#!/bin/bash # zy-evidence-gate.sh — 提交检测站 v1.0(冰朔20260827整改令) # 正本:TC-TCS核心卷/TCS-PROTOCOL-ZY001-EVIDENCE-GATE-0001.tcs # 模式:参照FlagOS平台提交流——证据不全=驳回;证据齐→自动唤起核查Agent验真→PASS才执行→回执落盘。 # 用法: # zy-evidence-gate.sh submit --action A --claim C --source-desc S --evidence-file F --quote Q --then "CMD" # zy-evidence-gate.sh hook (PreToolUse 拦截:敏感工程命令无 @EV- 票号即驳回) # zy-evidence-gate.sh verify (全量票据审计) set -uo pipefail W="/Volumes/JZAO/铸渊-ICE-GL-ZY001" EV="$W/BRIDGE/evidence" TICKETS="$EV/tickets" VERIFY_AGENT="$W/BRIDGE/tools/zy-evidence-verify.mjs" mkdir -p "$TICKETS" "$EV/sources" die() { echo "EVIDENCE-GATE ✗ $1" >&2; [ $# -gt 1 ] && echo " $2" >&2; exit 1; } ok() { echo "EVIDENCE-GATE ✓ $1"; } sha256() { /usr/bin/shasum -a 256 "$1" | awk '{print $1}'; } next_ticket_id() { local d n id d=$(date +%Y%m%d) n=$(ls "$TICKETS" 2>/dev/null | grep -c "^EV-$d" || true) printf 'EV-%s-%04d' "$d" $((n + 1)) } case "${1:-}" in submit) shift ACTION=""; CLAIM=""; SOURCE_DESC=""; EVIDENCE_FILE=""; QUOTE=""; THEN_CMD="" while [ $# -gt 0 ]; do case "$1" in --action) ACTION="$2"; shift 2;; --claim) CLAIM="$2"; shift 2;; --source-desc) SOURCE_DESC="$2"; shift 2;; --evidence-file) EVIDENCE_FILE="$2"; shift 2;; --quote) QUOTE="$2"; shift 2;; --then) THEN_CMD="$2"; shift 2;; *) die "USAGE" "submit --action --claim --source-desc --evidence-file --quote --then CMD";; esac done # ① 四要素齐全性(缺=猜) [ -n "$ACTION" ] && [ -n "$CLAIM" ] && [ -n "$SOURCE_DESC" ] && [ -n "$EVIDENCE_FILE" ] && [ -n "$QUOTE" ] && [ -n "$THEN_CMD" ] \ || die "REJECTED_NO_EVIDENCE" "动作/主张/来源/证据文件/引文/命令 六件缺一——拿不出证据=猜的,驳回。" # ② 出票并自动唤起核查 Agent TID=$(next_ticket_id) TP="$TICKETS/$TID.json" ABS_EV="$EVIDENCE_FILE" case "$ABS_EV" in /*) ;; *) ABS_EV="$W/$EVIDENCE_FILE";; esac [ -r "$ABS_EV" ] || die "REJECTED_EVIDENCE_MISSING" "证据文件不存在: ${ABS_EV}(先把原文落盘再谈提交)" ESHA=$(sha256 "$ABS_EV") python3 - "$TP" "$TID" "$ACTION" "$CLAIM" "$SOURCE_DESC" "$EVIDENCE_FILE" "$ESHA" "$QUOTE" "$THEN_CMD" <<'PY' import json,sys tp,tid,action,claim,sd,evf,esha,quote,cmd=sys.argv[1:10] json.dump({"ticket":tid,"action":action,"claim":claim,"source_desc":sd, "evidence_file":evf,"evidence_sha256":esha,"quote":quote,"command":cmd, "status":"PENDING_AUDIT"},open(tp,"w"),ensure_ascii=False,indent=1) PY AUDIT_OUT=$(node "$VERIFY_AGENT" "$TP" 2>&1) AUDIT_RC=$? if [ $AUDIT_RC -ne 0 ]; then echo "$AUDIT_OUT" >&2 die "REJECTED_BY_AUDIT_AGENT" "核查Agent判定证据不实——提交驳回,票据已留痕: $TP" fi echo "$AUDIT_OUT" | tail -n +2 | head -8 # ③ 核查通过 → 执行提交 → 回执 RECEIPT="RE-$(date +%Y%m%d-%H%M%S)-$(printf '%s' "$THEN_CMD" | shasum -a 256 | awk '{print substr($1,1,8)}')" python3 - "$TP" "$RECEIPT" <<'PY' import json,sys tp,r=sys.argv[1:3] t=json.load(open(tp)); t["receipt"]=r; t["status"]="EXECUTED" json.dump(t,open(tp,"w"),ensure_ascii=False,indent=1) PY if eval "$THEN_CMD"; then ok "$TID 核查PASS已执行 | 回执 $RECEIPT | $ACTION" else die "COMMAND_FAILED" "命令执行失败(票据 $TID 已留痕,证据链仍有效)" fi ;; hook) # PreToolUse:敏感工程命令必须内联 @EV-xxxx 票号且该票核查PASS INPUT=$(cat) CMD_LINE=$(printf '%s' "$INPUT" | python3 -c 'import json,sys try: d=json.load(sys.stdin) print(d.get("tool_input",{}).get("command","")) except Exception: print("")' 2>/dev/null) SENSITIVE='zip |git (commit|push|tag)|pip3? install|curl .*(-X|--request) *(POST|PUT|DELETE)|cp .*Desktop|mv .*Desktop|rm -' if printf '%s' "$CMD_LINE" | grep -qE "$SENSITIVE"; then TID=$(printf '%s' "$CMD_LINE" | grep -oE '@EV-[0-9]{8}-[0-9]{4}' | head -1 | sed 's/^@//') if [ -z "$TID" ]; then echo "【证据门 ✗ 拦截】敏感工程命令未携带证据票号(@EV-YYYYMMDD-NNNN)。" >&2 echo "流程:证据原文先落盘 BRIDGE/evidence/sources/ → zy-evidence-gate.sh submit 出票(自动核查)→ 命令内引用 @票号。拿不出证据=猜的=驳回。" >&2 exit 2 fi TP="$TICKETS/$TID.json" ST=$(python3 -c "import json;print(json.load(open('$TP'))['status'])" 2>/dev/null || echo "MISSING") if [ "$ST" != "VERIFIED" ] && [ "$ST" != "EXECUTED" ]; then echo "【证据门 ✗ 拦截】票号 $TID 不存在或未通过核查(状态:${ST})。先走 submit 流程拿有效票。" >&2 exit 2 fi fi exit 0 ;; verify) FAIL=0; N=0 for tp in "$TICKETS"/EV-*.json; do [ -f "$tp" ] || continue N=$((N+1)) node "$VERIFY_AGENT" "$tp" >/dev/null 2>&1 || { echo "FAIL $tp"; FAIL=$((FAIL+1)); } done echo "EVIDENCE-GATE verify: $N 票, $FAIL 失败" [ $FAIL -eq 0 ] ;; *) die "USAGE" "zy-evidence-gate.sh submit|hook|verify";; esac