#!/bin/bash # mm-review · maomao-fifth-domain pre-receive 自动审核 · 铸渊 2026-08-06 # ⊢ 明文密钥必拦 ⊢ 破坏现有必拦 ⊢ 写入窗口必验 ⊢ 每次写入留痕 LOG_DIR=/srv/guanghu/mm-gz-001/access/logs GRANTS=/srv/guanghu/mm-gz-001/access/grants.json PUSHER="${GITEA_PUSHER_NAME:-unknown}" VERDICT=PASS REASONS=() COMMITS=0 REFSLIST="" PUSHER_ATTR="" ZERO=0000000000000000000000000000000000000000 mkdir -p "$LOG_DIR" active_grant() { python3 - "$GRANTS" <<'PY' import json,sys,datetime try: g=json.load(open(sys.argv[1])) except Exception: print("none"); sys.exit() now=datetime.datetime.now(datetime.timezone.utc) for x in g: if x.get("status")=="active": try: exp=datetime.datetime.fromisoformat(x["expiresAt"]) except Exception: continue if exp>now: print(x.get("persona","persona")); sys.exit() print("none") PY } while read -r old new ref; do REFSLIST="$REFSLIST $ref" branch=${ref#refs/heads/} if [ "$new" = "$ZERO" ]; then case "$branch" in guanghu/main|deploy) VERDICT=REJECT; REASONS+=("禁止删除受保护分支: $branch");; esac continue fi if [ "$PUSHER" = "mm-writer" ]; then W=$(active_grant) if [ "$W" = "none" ]; then VERDICT=REJECT REASONS+=("无有效写入窗口(3小时授权已过期或未申请)。人格体请先 POST https://maomao.guanghulab.com/api/access-request 申请,等苍耳审批") continue fi PUSHER_ATTR="$W" fi if [ "$old" != "$ZERO" ]; then if ! git merge-base --is-ancestor "$old" "$new" 2>/dev/null; then VERDICT=REJECT; REASONS+=("禁止历史重写(非快进推送): $branch") continue fi fi for c in $(git rev-list "$old".."$new" 2>/dev/null || git rev-list -n 20 "$new" 2>/dev/null); do COMMITS=$((COMMITS+1)) for f in $(git diff-tree --root --no-commit-id --name-only --diff-filter=AM -r "$c" 2>/dev/null | head -60); do if git show "$c:$f" 2>/dev/null | head -c 400000 | grep -qE "sk-[A-Za-z0-9]{16,}|AKIA[A-Z0-9]{16}|-----BEGIN [A-Z ]*PRIVATE KEY-----|gh[pousr]_[A-Za-z0-9]{20,}|xox[baprs]-[A-Za-z0-9-]{10,}|(api[_-]?key|apikey|secret[_-]?key|access[_-]?token|password|passwd)[\"']?[[:space:]]*[:=][[:space:]]*[\"'][A-Za-z0-9+/=_.-]{12,}"; then VERDICT=REJECT; REASONS+=("文件疑似包含明文密钥: $f(提交 ${c:0:8})。密钥必须移出仓库") fi done if [ "$PUSHER" != "maomao" ]; then for f in $(git diff-tree --root --no-commit-id --name-only --diff-filter=D -r "$c" 2>/dev/null); do case "$f" in REPO-MAP.hdlp|GLW-ENTRY.hdlp|INDEX.hdlp|README.md|AGENTS.md|guanghu-nodes/MM-GZ-001/machine/NAVIGATION.json|guanghu-nodes/MM-GZ-001/recovery/WAKE-UP-ROUTE.json|guanghu-nodes/MM-GZ-001/personas/registry.json) VERDICT=REJECT; REASONS+=("人格体不得删除入口文件: $f");; esac done fi done done python3 - "$LOG_DIR" "$PUSHER" "$PUSHER_ATTR" "$VERDICT" "$COMMITS" "$REFSLIST" "$(printf '%s|' "${REASONS[@]}")" <<'PY' import json,sys,datetime,os logdir,pusher,attr,verdict,commits,refs,reasons=sys.argv[1:8] rec={"ts":datetime.datetime.now(datetime.timezone.utc).isoformat(), "pusher":pusher,"persona":attr or None,"verdict":verdict, "commits":int(commits),"refs":refs.split(), "reasons":[r for r in reasons.split("|") if r]} os.makedirs(logdir,exist_ok=True) p=os.path.join(logdir,"PUSH-%s.json"%datetime.datetime.now().strftime("%Y%m%dT%H%M%S%f")) open(p,"w").write(json.dumps(rec,ensure_ascii=False,indent=1)) PY if [ "$VERDICT" = "REJECT" ]; then echo "── 守望自动审核:REJECT ──" for r in "${REASONS[@]}"; do echo " ✗ $r"; done exit 1 fi echo "── 守望自动审核:PASS($COMMITS 提交 · 推送者 $PUSHER${PUSHER_ATTR:+ · 人格 $PUSHER_ATTR})──" exit 0