# =====================================================================
# 系统体检包V1.0·18项检查规则（SSOT权威源）
# 本文件是 checkup.ps1 / checkup.sh / 检查清单.md 的唯一权威依据
# 修改本文件必须同步三处脚本实现并重出SHA256SUMS.txt（万有AI工程规范·SSOT）
# 总分=100 · P0红线4项（N2/S2/O4/X1）· Docker三件适用性N/A归一化
# =====================================================================
package:
  id: wanyou-checkup
  version: "1.0"
  schema_version: "1.0"
  stance: read_only_offline   # 五条铁律之一·脚本实现必须一致
  scoring:
    formula: "earned / eligible * 100"
    grades: { green: 85, yellow: 70, red_below: 70 }
    red_card_rule: "P0项终态=未通过或未知(cannot_detect·或问答补测后仍无法确认)均触发红牌→结论最高黄·暂缓上线·未知项标注'?未知'·唯N/A豁免(非容器系统S2剔除不触发)·宁严勿松:分数高不能洗白安全未知"
scan_limits:
  max_depth: 4
  max_file_bytes: 524288      # 512KB
  max_files: 2000
  exclude_dirs: [node_modules, .git, dist, build, vendor, __pycache__, venv, .venv, .next, .nuxt, .output, coverage]
text_exts: [py, js, ts, jsx, tsx, go, java, php, rb, rs, c, cpp, h, cs, yaml, yml, json, toml, ini, cfg, conf, env, sh, bash, ps1, psm1, md, txt, sql, html, vue, properties]

items:
  - id: N1
    name: git版本管理
    category: 规范性
    level: P1
    score: 5
    detect: "path:.git存在 且 git rev-parse HEAD 可解析"
    qa_question: "系统是否纳入版本管理（git或其他）？改动能否回溯？"
    remediation: "在项目根目录执行 git init 并完成首次提交；此后任何改动先commit再部署。"
    cannot_detect_hint: "git未安装或目录不可读时转问答"

  - id: N2
    name: 敏感文件忽略
    category: 规范性
    level: P0
    score: 8
    detect: ".gitignore 含覆盖 .env 的规则 且 git ls-files 中不存在真实env文件（.env/.env.production等·排除*.example/*.template/*.sample）"
    qa_question: "有没有把含密码/密钥的配置文件提交进过仓库（哪怕后来删了）？"
    remediation: "在.gitignore加入 .env 与 .env.*（保留 !*.example）；若历史中提交过真实密钥，必须立即轮换所有泄露密钥。"

  - id: N3
    name: 依赖锁定
    category: 规范性
    level: P1
    score: 5
    detect: "存在任一：package-lock.json|pnpm-lock.yaml|yarn.lock|poetry.lock|Pipfile.lock|requirements.txt|go.sum|Cargo.lock"
    qa_question: "依赖版本是否锁定、能否在新机器上可复现安装？"
    remediation: "npm用package-lock.json并commit；Python用pip freeze>requirements.txt或poetry.lock。"

  - id: N4
    name: README
    category: 规范性
    level: P1
    score: 3
    detect: "README* 存在且非空"
    qa_question: "新人拿到代码能否看懂这是什么、怎么跑？"
    remediation: "补README：项目是什么/技术栈/本地跑通三步/联系谁。"

  - id: N5
    name: 部署文档
    category: 规范性
    level: P1
    score: 4
    detect: "DEPLOY*|部署*.md|docs/deploy*|docs/deployment* 存在"
    qa_question: "换一台全新机器，照文档能从零部署吗？演练过吗？"
    remediation: "写部署文档：环境要求/依赖安装/配置项清单/启动命令/验证方法；并真实演练一遍。"

  - id: N6
    name: 环境配置分离
    category: 规范性
    level: P1
    score: 6
    detect: ".env.example|.env.template|.env.sample|env.example|config.example.* 存在"
    qa_question: "配置（数据库地址/密钥/端口）与代码是否分离？换环境改配置还是改代码？"
    remediation: "建立.env.example模板（只含键名+占位值），真实值只放本地.env（且已被N2的gitignore盖住）。"

  - id: S1
    name: 健康检查
    category: 稳定性
    level: P1
    score: 7
    applies_if: docker
    detect: "Dockerfile含HEALTHCHECK 或 compose含healthcheck: 或代码中存在/health|/healthz路由"
    qa_question: "服务假死时能被自动发现吗？健康检查端点测过吗？"
    remediation: "容器化：Dockerfile加HEALTHCHECK或compose加healthcheck；非容器：暴露/health端点并接入监控探活。"

  - id: S2
    name: 容器非root运行
    category: 稳定性
    level: P0
    score: 7
    applies_if: docker
    detect: "Dockerfile存在USER指令且非USER root"
    qa_question: ""
    remediation: "Dockerfile末尾加 USER appuser（先useradd创建）；注意预先chown应用目录。"

  - id: S3
    name: 重启策略与资源上限
    category: 稳定性
    level: P1
    score: 6
    applies_if: docker
    detect: "compose含restart:(unless-stopped|always) 且 含mem_limit|deploy.resources|cpus"
    qa_question: "容器/进程崩了会自动拉起吗？有没有内存CPU上限防止挤兑整台机器？"
    remediation: "compose服务加 restart: unless-stopped；加 mem_limit 与 cpus 上限（防内存泄漏拖垮宿主机全部服务）。"

  - id: S4
    name: 自动化测试
    category: 稳定性
    level: P2
    score: 5
    detect: "tests/|test/|__tests__/ 目录 或 test_*.py|*.test.ts|*.spec.js 文件存在"
    qa_question: "改代码后怎么知道没改坏核心功能？跑过完整测试吗？"
    remediation: "为核心路径补最小测试集（成功路径+3个异常路径），先跑通再谈覆盖率和框架选型。"

  - id: O1
    name: 备份机制
    category: 运维面
    level: P1
    score: 6
    detect: "文件名或内容含 备份|backup|bak 的脚本/文档/定时任务痕迹"
    qa_question: "数据库每天自动备份吗？备份存在另一台机器吗？恢复演练过吗？"
    remediation: "每日自动备份+异地存放（与生产不同机）；每季度做一次真实恢复演练。"

  - id: O2
    name: 回滚预案
    category: 运维面
    level: P1
    score: 6
    detect: "内容含 回滚|rollback 的文档或脚本"
    qa_question: "新版本出问题怎么退回旧版？退回步骤实际演练过吗？"
    remediation: "部署采用备份式替换（旧版本先mv归档再上新的），并在部署文档写明回滚命令。"

  - id: O3
    name: 版本锚
    category: 运维面
    level: P2
    score: 3
    detect: "VERSION|CHANGELOG* 存在 或 git tag数量≥1"
    qa_question: "现在线上跑的是哪个版本？说得出锚吗？"
    remediation: "每次发布打git tag或写CHANGELOG；部署时把commit号写入镜像/版本文件。"

  - id: O4
    name: 危险命令扫描
    category: 运维面
    level: P0
    score: 8
    detect: "部署类脚本(sh/bash/ps1/yml/Dockerfile)中 rm -rf 后接 绝对路径|变量|~|/* ，或Windows rd /s /q 接盘符根"
    qa_question: "部署脚本里有没有'先删光再全量替换'类操作？误删过吗？"
    remediation: "禁用全量删除替换：改为增量替换+mv备份式归档（GL-04纪律）；删除命令必须带明确具体路径并二次确认。"

  - id: O5
    name: 日志与监控
    category: 运维面
    level: P2
    score: 3
    detect: "logging|log4j|serilog|winston|pino|日志 等配置痕迹"
    qa_question: "出问题时你怎么知道？错误日志去哪看？有人盯着吗？"
    remediation: "统一错误日志落盘+定期查看节拍（哪怕每天人工看一次）；关键服务接入探活。"

  - id: X1
    name: 密钥硬编码
    category: 安全红线
    level: P0
    score: 10
    detect: "文本文件匹配私钥块|AWS_AK|sk-前缀长key|password/secret/token=字面量；排除*.example|*.template|*.sample|*test*与占位符(your_*,xxx+,changeme,${},<占位>)"
    qa_question: "代码里有没有写死过任何真实密码/APIkey？（测试库的也算）"
    remediation: "全部改env注入；已写死过的key立即去服务商后台轮换（旧key作废）——删代码不等于作废。"

  - id: X2
    name: 调试态暴露
    category: 安全红线
    level: P1
    score: 5
    detect: "DEBUG\\s*=\\s*True|APP_DEBUG\\s*=\\s*true|debug:\\s*true（生产配置/启动面）"
    qa_question: "生产环境开着调试模式吗？错误页会把堆栈给用户看吗？"
    remediation: "生产配置显式关DEBUG；错误页只给通用文案，堆栈只进日志。"

  - id: X3
    name: 依赖漏洞审计
    category: 安全红线
    level: P1
    score: 3
    detect: "检测到npm生态(node lock)或Python生态(requirements)时置transfer_to_qa"
    qa_question: "（AI体检员引导学员在其机器执行：npm audit 或 pip-audit）扫描出多少高危？修了吗？"
    remediation: "npm audit fix / pip-audit后按建议升级；高危项必须处理，不能只记录。"
