{
  "$schema": "https://bestaiskill.com/schemas/agent-install/2.json",
  "skill": "storage-analyzer",
  "built": "2026-10-26",
  "control_level": 4,
  "control_level_label": "L4 高权限",
  "capabilities": [
    "execute_command",
    "network",
    "write_file"
  ],
  "required_controls": {
    "agent": [
      "sandbox_recommended",
      "graded_authorization"
    ],
    "admin": [
      "approval_process",
      "rollback_support",
      "full_audit"
    ]
  },
  "evidence": [
    {
      "file": "scripts/",
      "summary": "Executes local scripts or commands: scripts/scan.py (read-only scan, calls system commands like du/df/diskutil via subprocess without disk writes)"
    },
    {
      "file": "网络端点",
      "summary": "Declares external network access: Local loopback only: http://127.0.0.1:<random_port>/ serving the report page and POST /action (Host header must strictly match 127.0.0.1/localhost)"
    },
    {
      "file": "本地工作目录",
      "summary": "File I/O and artifact output: /tmp/storage_scan.json (scan results), user-specified analysis JSON (written by agent), report HTML (written in static mode)"
    }
  ],
  "verification": {
    "method": "第二遍独立重读 + 反查：① 文件清单核对（SKILL.md + scripts/{scan,server,build_report}.py + assets/report_template.html + references/{macos,windows}.md）；② 把 scan.py 全文与 server.py 全文当作代码审读，确认「扫描侧无写操作/无删除」「服务侧删除受三套白名单约束」；③ token 扫描：公网 URL 零命中（唯一 URL 是 http://127.0.0.1:%d/），凭证类零命中（无 API key/环境变量），subprocess 调用点逐个核对（du/df/osascript/open/explorer）；④ 核对 SKILL.md 的「安全模型」表述与 server.py 的 load() 实现是否一致（rm/trash/open 三集合的构造规则）；⑤ 核对「静态模式无删除按钮」在 build_report.py 与模板中确有机制（DELETE 配置写 null）；⑥ 夸大检查：description 声称「扫描全程只读」「可起本地服务在网页上一键删除」与实现一致；Windows 未实测已由 skill 自己声明。",
    "second_pass": [
      {
        "item": "扫描器确实只读",
        "status": "ok",
        "detail": "scan.py 只用 os.scandir/os.listdir/du/df/diskutil 等读取与统计；无 open(...,\"w\")、无 shutil.rmtree/os.remove、无 mkdir；docstring 明写 STRICTLY READ-ONLY。"
      },
      {
        "item": "服务侧白名单构造与文档一致",
        "status": "ok",
        "detail": "load() 中：green.trash_paths → rm/trash/open 三集合；yellow.trash_paths 只进 trash+open；yellow.path（存在时）只进 open；red.app_paths（存在时）只进 open——与 SKILL.md「三套白名单，权限从严到宽」逐条对应。"
      },
      {
        "item": "删除请求的多重校验",
        "status": "ok",
        "detail": "do_POST 依次校验：Host ∈ {127.0.0.1, localhost}、token 相等、mode ∈ {rm,trash,open}、每个 path realpath 后必须在对应白名单、且必须在 HOME 或 /Applications 之下（删除类白名单不含 /Applications）。"
      },
      {
        "item": "回收站删除的实现",
        "status": "ok",
        "detail": "macOS: osascript `tell application \"Finder\" to delete (POSIX file ...)`，失败回退 shutil.move 到 ~/.Trash；Windows: ctypes 调 SHFileOperationW，fFlags 含 FOF_ALLOWUNDO（进回收站）。"
      },
      {
        "item": "无公网请求",
        "status": "ok",
        "detail": "全目录 URL 扫描仅命中 http://127.0.0.1:%d/（服务自述地址）；无 CDN、无遥测、无第三方 API。"
      },
      {
        "item": "无凭证读取",
        "status": "ok",
        "detail": "API_KEY/token/secret 扫描：唯一 token 变量是 secrets.token_urlsafe(24) 生成的会话 token，非用户凭证；无 env 读取、无 keychain、无配置文件读取。"
      },
      {
        "item": "静态报告确实没有删除能力",
        "status": "ok",
        "detail": "build_report.py 把 __DELETE_CONFIG__ 替换为 \"null\"；模板里的 fetch(DELETE.endpoint, ...) 只有在服务模式下注入 token/endpoint 才可用（SKILL.md 的排障段落也这么说）。"
      },
      {
        "item": "零第三方依赖",
        "status": "ok",
        "detail": "三个脚本 import 仅 json/os/secrets/shutil/subprocess/sys/time/webbrowser/http.server/re/ctypes；无 requirements/pip 指令。"
      },
      {
        "item": "Windows 未实测声明",
        "status": "ok",
        "detail": "SKILL.md「平台状态」写明 Windows「代码已写…但**未在真实 Windows 上实测**」，并要求首次在 Windows 跑时核对路径、scandir 大小与回收站删除。"
      },
      {
        "item": "分级与按钮的对应关系",
        "status": "ok",
        "detail": "「🟢 项给「移到废纸篓」(可逆) +「直接删除」…🟡 项给「在访达打开」+（有安全子路径时）「移到废纸篓」」+「红灯不给删除/卸载按钮」在 SKILL.md 与 server.py 白名单规则里一致。"
      },
      {
        "item": "commit / 元数据",
        "status": "ok",
        "detail": "pin 目录 HEAD＝48e8ba527f0be55f77772debb979c92f06acf5c0（与任务表一致）；GitHub API：stars 20687、pushed_at 2026-09-13T06:39:20Z、仓库 spdx=MIT；skill 目录内无独立 LICENSE。"
      }
    ],
    "level": 1,
    "level_label": "V1 已固定",
    "commit": "48e8ba527f0be55f77772debb979c92f06acf5c0",
    "sha256": "b8b3f5bde010e27b9b4895926911eea06db32746aec96d73b5ce676ff7dd3d07",
    "reviewed_by": null,
    "reviewed_at": null
  },
  "assessed_at": "2026-10-25",
  "method_version": "2.0",
  "mirror": {
    "archive": "https://skillpub.pages.dev/r2/v/2026-09-15/storage-analyzer.tar.gz",
    "sha256": "b8b3f5bde010e27b9b4895926911eea06db32746aec96d73b5ce676ff7dd3d07",
    "commit": "48e8ba527f0be55f77772debb979c92f06acf5c0"
  },
  "original": {
    "github": "https://github.com/KKKKhazix/khazix-skills/tree/main/storage-analyzer",
    "path": "storage-analyzer",
    "commit": "48e8ba527f0be55f77772debb979c92f06acf5c0"
  }
}