Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ __pycache__/
.archive-w1d1/
.ciw/
env-defs/
.scratch/
15 changes: 10 additions & 5 deletions governance/evidence-query.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
# 源 3 butler Cloudbird-Software/.github @ butler-ledger governance/butler/shadow-evidence.jsonl
# 源 4 elevation Cloudbird-Software/.github @ elevation-ledger governance/elevation/shadow-evidence.jsonl
# (W2-C4 JIT 提权裁决/收回记录——subject 可查询即 AC-9c 锚点)
# 源 5 tickets Cloudbird-Software/cnb-bridge @ tickets-ledger tickets.jsonl
# (W2-C1 内网调度器短票据 grant/revoke——AC-5b 统一账本;Go 发射器产出,
# 链形态与 evidence_shadow.py 逐字节兼容,金向量锚定)
#
# 用法:
# bash governance/evidence-query.sh [--card owner/repo#n] [--json] # --json=汇总行也走 stdout
Expand Down Expand Up @@ -70,20 +73,22 @@ fi
DRILL_OK=0; fetch_file "Cloudbird-Software/.github" "drill-ledger" "governance/drill/shadow-evidence.jsonl" "$TMP/drill.jsonl" && DRILL_OK=1 || [[ $? -eq 1 ]] || exit 2
BUTLER_OK=0; fetch_file "Cloudbird-Software/.github" "butler-ledger" "governance/butler/shadow-evidence.jsonl" "$TMP/butler.jsonl" && BUTLER_OK=1 || [[ $? -eq 1 ]] || exit 2
ELEV_OK=0; fetch_file "Cloudbird-Software/.github" "elevation-ledger" "governance/elevation/shadow-evidence.jsonl" "$TMP/elev.jsonl" && ELEV_OK=1 || [[ $? -eq 1 ]] || exit 2
TICKET_OK=0; fetch_file "Cloudbird-Software/cnb-bridge" "tickets-ledger" "tickets.jsonl" "$TMP/tickets.jsonl" && TICKET_OK=1 || [[ $? -eq 1 ]] || exit 2

# ---- 逐源验链 + 归并输出(链断=exit 3:不可信数据不出结果) ----
export CARD_FILTER JSON_ONLY DRILL_OK BUTLER_OK ELEV_OK
python3 - "$DIR/evidence_shadow.py" "$SRC_METER" "$TMP/drill.jsonl" "$TMP/butler.jsonl" "$TMP/elev.jsonl" "$TMP" <<'PYEOF'
export CARD_FILTER JSON_ONLY DRILL_OK BUTLER_OK ELEV_OK TICKET_OK
python3 - "$DIR/evidence_shadow.py" "$SRC_METER" "$TMP/drill.jsonl" "$TMP/butler.jsonl" "$TMP/elev.jsonl" "$TMP/tickets.jsonl" "$TMP" <<'PYEOF'
import glob, json, os, sys

sys.path.insert(0, os.path.dirname(os.path.abspath(sys.argv[1])))
import evidence_shadow # noqa: E402 验链与 CI-Workflows 侧同源语义

metering_dir, drill_f, butler_f, elev_f, tmp = sys.argv[2:7]
metering_dir, drill_f, butler_f, elev_f, tickets_f, tmp = sys.argv[2:8]
sources = {"metering": sorted(glob.glob(os.path.join(metering_dir, "shadow-evidence-*.jsonl"))),
"drill": [drill_f] if os.environ.get("DRILL_OK") == "1" else [],
"butler": [butler_f] if os.environ.get("BUTLER_OK") == "1" else [],
"elevation": [elev_f] if os.environ.get("ELEV_OK") == "1" else []}
"elevation": [elev_f] if os.environ.get("ELEV_OK") == "1" else [],
"tickets": [tickets_f] if os.environ.get("TICKET_OK") == "1" else []}
errs, recs = [], []
for src, files in sources.items():
for f in files:
Expand All @@ -106,7 +111,7 @@ for r in out:

summary = {
"total": len(out),
"by_source": {s: sum(1 for r in out if r["source"] == s) for s in ("metering", "drill", "butler", "elevation")},
"by_source": {s: sum(1 for r in out if r["source"] == s) for s in ("metering", "drill", "butler", "elevation", "tickets")},
"by_tenant": {},
"by_card_top": {},
}
Expand Down
3 changes: 2 additions & 1 deletion governance/providers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ entries:
# 三面分离:本二条目=执行面资产申报(判定锚点恒在 GitHub CI,不随池增减改变)
- name: self-cloud-pool
kind: compute # 自有云内网算力池(公网服务器+云电脑池)
entry: 服务器调度器(W2-C1 落地;过渡期=PM 会话经公网服务器驱动云电脑池)
entry: 服务器调度器 v0=cnb-bridge 仓 selfcloud/(W2-C1 已落地:Job Contract
消费+短票据签发+egress allowlist+无状态约束执法;RUNBOOK §5)
placement: server-anchored(池化以服务器为锚,ADR-0103 决策 4)
secrets: [] # 凭据一律走内网域 Vault(本条目零 org secret——分域边界)
catalog: governance/assets-register.yaml(资产归属/额度/license 边界)
Expand Down
61 changes: 49 additions & 12 deletions governance/tests/test-evidence-shadow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,39 @@ python3 "$DIR/governance/evidence_shadow.py" append --file "$ESHADOW" --event-fi
python3 "$DIR/governance/evidence_shadow.py" verify --file "$ESHADOW" >/dev/null \
&& pass "elevation 影子验链绿" || fail "elevation 影子链断"

# ---- evidence-query 四源统一查询(AC-4a:归并 + 验链 + fail-closed) ----
# ---- tickets 短票据事件(W2-C1 / AC-5b:evidence-query 第 5 源,subject 可查询) ----
TICKETS="$TMP/tickets.jsonl"
cat >"$TMP/tk1.json" <<'EOF'
{"ts": "2026-08-29T00:00:00Z", "kind": "approval", "action": "ticket.grant", "verdict": "pass",
"subject": {"card": "Cloudbird-Software/.github#412", "tenant": "cloudbird-internal"},
"actor": {"identity": "selfcloud-scheduler", "role": "bot"},
"payload": "{\"job_id\": \"job-t1\", \"ttl_minutes\": 30}"}
EOF
cat >"$TMP/tk2.json" <<'EOF'
{"ts": "2026-08-29T00:30:00Z", "kind": "approval", "action": "ticket.revoke", "verdict": "pass",
"subject": {"card": "Cloudbird-Software/.github#412", "tenant": "cloudbird-internal"},
"actor": {"identity": "selfcloud-scheduler", "role": "bot"},
"payload": "{\"job_id\": \"job-t1\", \"reason\": \"ttl-expired\"}"}
EOF
python3 "$DIR/governance/evidence_shadow.py" append --file "$TICKETS" --event-file "$TMP/tk1.json" >/dev/null \
&& python3 "$DIR/governance/evidence_shadow.py" append --file "$TICKETS" --event-file "$TMP/tk2.json" >/dev/null \
&& python3 "$DIR/governance/evidence_shadow.py" verify --file "$TICKETS" >/dev/null \
&& pass "tickets 影子验链绿(grant/revoke 双事件)" || fail "tickets 影子链断"

# ---- evidence-query 五源统一查询(AC-4a:归并 + 验链 + fail-closed) ----
GHSTUB="$TMP/gh-stub"
mkdir -p "$TMP/fixtures"
# fixture:metering=周分片列表($SHADOW);drill/butler/elevation=各自影子(独立成链)
python3 - "$SHADOW" "$DSHADOW" "$BUTLER_SHADOW" "$ESHADOW" "$TMP/fixtures" <<'PYEOF'
# fixture:metering=周分片列表($SHADOW);drill/butler/elevation=各自影子(独立成链);tickets=短票据链
python3 - "$SHADOW" "$DSHADOW" "$BUTLER_SHADOW" "$ESHADOW" "$TICKETS" "$TMP/fixtures" <<'PYEOF'
import base64, json, sys
shadow, dshadow, bshadow, eshadow, fixdir = sys.argv[1:6]
shadow, dshadow, bshadow, eshadow, tickets, fixdir = sys.argv[1:7]
b64 = lambda p: base64.b64encode(open(p, "rb").read()).decode()
json.dump([{"type": "file", "name": "shadow-evidence-2026-W35.jsonl", "content": b64(shadow)}],
open(f"{fixdir}/metering-list.json", "w"))
json.dump({"type": "file", "content": b64(dshadow)}, open(f"{fixdir}/drill.json", "w"))
json.dump({"type": "file", "content": b64(bshadow)}, open(f"{fixdir}/butler.json", "w"))
json.dump({"type": "file", "content": b64(eshadow)}, open(f"{fixdir}/elev.json", "w"))
json.dump({"type": "file", "content": b64(tickets)}, open(f"{fixdir}/tickets.json", "w"))
PYEOF
cat >"$GHSTUB" <<'STUBEOF'
#!/usr/bin/env bash
Expand All @@ -185,9 +205,14 @@ case "$url" in
cat "$F/butler.json" ;;
"repos/Cloudbird-Software/.github/contents/governance/elevation/shadow-evidence.jsonl?ref=elevation-ledger")
if [[ "${GH_STUB_ELEV_MISSING:-}" == "1" ]]; then
echo 'gh: No commit found for the ref elevation-ledger (HTTP 404)' >&2; exit 1
echo "gh: No commit found for the ref elevation-ledger (HTTP 404)" >&2; exit 1
fi
cat "$F/elev.json" ;;
"repos/Cloudbird-Software/cnb-bridge/contents/tickets.jsonl?ref=tickets-ledger")
if [[ "${GH_STUB_TICKETS_MISSING:-}" == "1" ]]; then
echo "gh: No commit found for the ref tickets-ledger (HTTP 404)" >&2; exit 1
fi
cat "$F/tickets.json" ;;
*) echo "gh-stub: 意外 URL $url" >&2; exit 1 ;;
esac
STUBEOF
Expand All @@ -196,10 +221,10 @@ nlines() { grep -c . <<<"$1" || true; } # 非空行计数(wc 对空 herestrin
QOUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/q.err"); QRC=$?
N=$(nlines "$QOUT")
[[ $QRC -eq 0 && "$N" -eq 6 ]] && pass "统一查询归并四源(6 条,rc=0)" || fail "统一查询(rc=$QRC 行=$N)"
[[ $QRC -eq 0 && "$N" -eq 8 ]] && pass "统一查询归并五源(8 条,rc=0)" || fail "统一查询(rc=$QRC 行=$N)"
grep -q '"source":"metering"' <<<"$QOUT" && grep -q '"source":"drill"' <<<"$QOUT" && grep -q '"source":"butler"' <<<"$QOUT" \
&& grep -q '"source":"elevation"' <<<"$QOUT" \
&& pass "四源标记齐全(source 字段)" || fail "source 标记缺失"
&& grep -q '"source":"elevation"' <<<"$QOUT" && grep -q '"source":"tickets"' <<<"$QOUT" \
&& pass "五源标记齐全(source 字段)" || fail "source 标记缺失"
grep -q '^SUMMARY ' "$TMP/q.err" && grep -Eq '"metering": ?2' "$TMP/q.err" \
&& pass "分源统计(stderr SUMMARY)" || fail "SUMMARY 统计缺失"
# --card 过滤:metering 影子绑 #407,drill/butler 哨兵 #0,elevation 绑 #415
Expand All @@ -213,28 +238,40 @@ EOUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub \
EN=$(nlines "$EOUT")
[[ $ERC -eq 0 && "$EN" -eq 1 ]] && grep -q '"source":"elevation"' <<<"$EOUT" \
&& pass "AC-9c elevation 记录 subject 可查询(#415 → 1 条)" || fail "elevation 查询(rc=$ERC 行=$EN)"
# AC-5b:短票据 grant/revoke 事件按 subject 可查询(#412 → 2 条,source=tickets)
TQOUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub \
bash "$DIR/governance/evidence-query.sh" --card Cloudbird-Software/.github#412 2>/dev/null); TQRC=$?
TQN=$(nlines "$TQOUT")
[[ $TQRC -eq 0 && "$TQN" -eq 2 ]] && grep -q '"source":"tickets"' <<<"$TQOUT" \
&& grep -q '"ticket.grant"' <<<"$TQOUT" && grep -q '"ticket.revoke"' <<<"$TQOUT" \
&& pass "AC-5b tickets 短票据事件 subject 可查询(#412 → 2 条)" || fail "tickets 查询(rc=$TQRC 行=$TQN)"
# 源缺席(404):过渡期合法,非红(须在篡改 fixture 生成前跑——桩对篡改片优先回放)
MOUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub GH_STUB_BUTLER_MISSING=1 \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/m.err"); MRC=$?
MN=$(nlines "$MOUT")
[[ $MRC -eq 0 && "$MN" -eq 5 ]] && pass "butler 源缺席(404)→ 跳过非红(5 条)" || fail "源缺席误红(rc=$MRC 行=$MN)"
[[ $MRC -eq 0 && "$MN" -eq 7 ]] && pass "butler 源缺席(404)→ 跳过非红(7 条)" || fail "源缺席误红(rc=$MRC 行=$MN)"
# 源缺席(404 第二报文形态——账本分支未建 "No ref found"):同跳过非红
# (2026-08-29 波次通道实测回归:该形态曾被误判"非 404"→ INFRA exit 2)
ROUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub GH_STUB_BUTLER_MISSING=2 \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/r.err"); RRC=$?
RN=$(nlines "$ROUT")
[[ $RRC -eq 0 && "$RN" -eq 5 ]] && pass "源缺席(No ref found 分支未建)→ 跳过非红(5 条)" || fail "分支未建误红(rc=$RRC 行=$RN)"
[[ $RRC -eq 0 && "$RN" -eq 7 ]] && pass "源缺席(No ref found 分支未建)→ 跳过非红(7 条)" || fail "分支未建误红(rc=$RRC 行=$RN)"
# 源缺席(404 第三报文形态——分支缺失 "No commit found for the ref",本地实测
# 真实报文):按 HTTP 404 状态码判定后同跳过非红
COUT2=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub GH_STUB_BUTLER_MISSING=3 \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/c2.err"); C2RC=$?
C2N=$(nlines "$COUT2")
[[ $C2RC -eq 0 && "$C2N" -eq 5 ]] && pass "源缺席(No commit found for the ref)→ 跳过非红(5 条)" || fail "分支缺失误红(rc=$C2RC 行=$C2N)"
[[ $C2RC -eq 0 && "$C2N" -eq 7 ]] && pass "源缺席(No commit found for the ref)→ 跳过非红(7 条)" || fail "分支缺失误红(rc=$C2RC 行=$C2N)"
# 源缺席(elevation 第 4 源分支未建——"No commit found"):同跳过非红
EOUT2=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub GH_STUB_ELEV_MISSING=1 \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/e2.err"); E2RC=$?
E2N=$(nlines "$EOUT2")
[[ $E2RC -eq 0 && "$E2N" -eq 5 ]] && pass "elevation 源缺席(分支未建)→ 跳过非红(5 条)" || fail "elevation 缺席误红(rc=$E2RC 行=$E2N)"
[[ $E2RC -eq 0 && "$E2N" -eq 7 ]] && pass "elevation 源缺席(分支未建)→ 跳过非红(7 条)" || fail "elevation 缺席误红(rc=$E2RC 行=$E2N)"
# tickets 第 5 源缺席(分支未建):同跳过非红(REMOVAL 语义:源消失≠链断)
TKOUT=$(GH="$GHSTUB" GH_STUB_FIXTURES="$TMP/fixtures" GH_TOKEN=stub GH_STUB_TICKETS_MISSING=1 \
bash "$DIR/governance/evidence-query.sh" 2>"$TMP/tk.err"); TKRC=$?
TKQN=$(nlines "$TKOUT")
[[ $TKRC -eq 0 && "$TKQN" -eq 6 ]] && pass "tickets 源缺席(分支未建)→ 跳过非红(6 条)" || fail "tickets 缺席误红(rc=$TKRC 行=$TKQN)"
# 负向:任一源链断 → exit 3 且 stdout 零输出(不可信数据不出结果)
python3 - "$TMP/fixtures" <<'PYEOF'
import base64, json, sys
Expand Down