#!/usr/bin/env bash
# 查 ClawHub skill 的扫描状态 —— 权威 REST API 不依赖 GUI / HTML scrape。
#
# 使用：
#   ./scripts/check-clawhub-scan.sh                    # 查 latest of acong-tech-xiangqin
#   ./scripts/check-clawhub-scan.sh 0.6.1              # 查指定版本
#   ./scripts/check-clawhub-scan.sh 0.6.1 other-slug   # 换 slug
#
# 退出码：0=clean；1=suspicious/malware/异常
# CLAWHUB_TOKEN env 可选（没有也能查公开 version.security，moderation 需要 token）。
set -euo pipefail

VERSION="${1:-}"
SLUG="${2:-acong-tech-xiangqin}"
AUTH_HDR=""
if [ -n "${CLAWHUB_TOKEN:-}" ]; then
  AUTH_HDR="Authorization: Bearer $CLAWHUB_TOKEN"
fi

_curl() {
  if [ -n "$AUTH_HDR" ]; then
    curl -sS -H "$AUTH_HDR" "$1"
  else
    curl -sS "$1"
  fi
}

TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT

# 拿 latest 如果没传
if [ -z "$VERSION" ]; then
  _curl "https://clawhub.ai/api/v1/skills/$SLUG" > "$TMPDIR/top.json"
  VERSION=$(python3 -c "import json;print(json.load(open('$TMPDIR/top.json'))['latestVersion']['version'])")
fi

echo "→ skill: $SLUG v$VERSION"

_curl "https://clawhub.ai/api/v1/skills/$SLUG/versions/$VERSION" > "$TMPDIR/ver.json"
# moderation 对匿名返非 JSON "Moderation details unavailable"；token 时返 JSON
_curl "https://clawhub.ai/api/v1/skills/$SLUG/moderation" > "$TMPDIR/mod.json" 2>/dev/null || true

python3 - "$TMPDIR/ver.json" "$TMPDIR/mod.json" <<'PY'
import json, sys

ver = json.load(open(sys.argv[1]))
# moderation 可选（匿名返非 JSON）
try:
    mod = json.load(open(sys.argv[2]))
except (json.JSONDecodeError, FileNotFoundError):
    mod = {}

sec = ver.get('version', {}).get('security', {}) or {}
scanners = sec.get('scanners') or {}
vt = scanners.get('vt')
llm = scanners.get('llm') or {}
m = mod.get('moderation', {}) or {}

print(f"  security.status:      {sec.get('status', '?')}")
print(f"  security.hasWarnings: {sec.get('hasWarnings', False)}")
print(f"  scanners.vt:          {vt if vt else 'pending'}")
print(f"  scanners.llm:         {llm.get('verdict', '?')} (confidence {llm.get('confidence', '?')})")
if m:
    print(f"  moderation.verdict:        {m.get('verdict', '?')}")
    print(f"  moderation.isSuspicious:   {m.get('isSuspicious', '?')}")
    print(f"  moderation.isMalwareBlocked: {m.get('isMalwareBlocked', '?')}")
else:
    print("  (moderation 需要 CLAWHUB_TOKEN；以 security.status 为准)")

# gating 逻辑
# - 主：version.security.status （llm + vt 综合）
# - 辅：moderation 如果能拿到就一并判
if m.get('isMalwareBlocked'):
    print("\n✗ MALWARE BLOCKED"); sys.exit(1)
if m and m.get('isSuspicious'):
    print(f"\n✗ SUSPICIOUS: reasonCodes={m.get('reasonCodes', [])}")
    print(f"  VT URL: {sec.get('virustotalUrl')}")
    sys.exit(1)
if sec.get('status') and sec.get('status') != 'clean':
    print(f"\n✗ security.status={sec.get('status')} (not clean)")
    print(f"  VT URL: {sec.get('virustotalUrl')}")
    sys.exit(1)
# llm verdict 如果已回且不 benign → fail
verdict = llm.get('verdict')
if verdict and verdict not in ('benign', None):
    print(f"\n✗ LLM verdict={verdict}")
    sys.exit(1)
print("\n✓ clean")
PY
