From c6fe7c2dd768cc47bc43d517b94776523ecf17c8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 12 Jun 2026 12:14:45 +0800 Subject: [PATCH] =?UTF-8?q?docs(security):=20=E5=BC=B7=E5=8C=96=20S4.9=20o?= =?UTF-8?q?wner=20response=20=E5=9F=BA=E6=BA=96=E4=B8=80=E8=87=B4=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...9-OWNER-RESPONSE-GATE-CURRENT-GAP-AUDIT.md | 5 ++-- ...ONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md | 2 +- ...r-response-validation-rollup.snapshot.json | 6 ++--- .../source-control-owner-response-guard.py | 25 +++++++++++++++++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/security/S4-9-OWNER-RESPONSE-GATE-CURRENT-GAP-AUDIT.md b/docs/security/S4-9-OWNER-RESPONSE-GATE-CURRENT-GAP-AUDIT.md index e1bf0216..2fb672fe 100644 --- a/docs/security/S4-9-OWNER-RESPONSE-GATE-CURRENT-GAP-AUDIT.md +++ b/docs/security/S4-9-OWNER-RESPONSE-GATE-CURRENT-GAP-AUDIT.md @@ -3,7 +3,7 @@ | 項目 | 內容 | |------|------| | 日期 | 2026-06-12 | -| 基準 | `gitea/main=b17a28c2 feat(governance): 新增報表 runtime 啟動前閘門` | +| 基準 | `gitea/main=7cea7ef0 docs(logbook): 記錄 IwoooS 修正候選卡驗證 [skip ci]` | | 範圍 | S4.9 Gitea owner attestation response gate 與 S4.13 owner response validation rollup | | 模式 | 只讀 committed snapshot / 文件稽核 | | 不可誤讀 | 不是 request sent、不是 owner response received、不是 accepted、不是 repo / refs / workflow / secret / runtime 授權 | @@ -30,7 +30,7 @@ S4.9 的基礎規範已存在,且已能被 `source-control-owner-response-guar | 缺口 | 影響 | 下一步 | |------|------|--------| -| P0 主控總帳與缺口稽核基準需跟上最新 `gitea/main` | 平行 Session 已推進 P2-403I/J/K、Public Gateway Preflight、SRE 戰情室路由、Knowledge Base tenant context 與報表 runtime 啟動前閘門;舊 commit 基準會讓新 Session 誤判下一步 | 本輪已更新到 `b17a28c2`;後續每次推送前仍需 fetch、讀 LOGBOOK 最新段落與同步 runs / deploy marker | +| P0 主控總帳與缺口稽核基準需跟上最新 `gitea/main` | 平行 Session 已推進 P2-403I/J/K、Public Gateway Preflight、SRE 戰情室路由、Knowledge Base tenant context、報表 runtime 啟動前閘門、IwoooS 審查後修正候選卡與 S4.13 rollup 口徑修正;舊 commit 基準會讓新 Session 誤判下一步 | 本輪已更新到 `7cea7ef0`,最新 deploy marker 為 `8a8843e3`;後續每次推送前仍需 fetch、讀 LOGBOOK 最新段落與同步 runs / deploy marker | | S4.9 gate 仍只有 request-ready,沒有 owner response | IwoooS 64% 不能因規範存在而往前解鎖 | 維持 `0%`,只準備收件缺口,不調高 progress | | S4.13 rollup 文件曾殘留舊模板總數 | Snapshot 已是 `5 + 9 + 5 + 5 = 24`,但文件仍可能寫成 `22`,會造成 reviewer 誤判 S4.10 目標數 | 已同步文件並把 `source-control-owner-response-guard.py` 納入文件一致性檢查 | | request packet 的欄位名稱存在同義詞 | `affected_repos`、`affected_sources`、`affected_repos_or_sources_or_namespace`、`evidence_refs` 與使用者要求的 `affected_scope`、`redacted_evidence_refs` 容易在 UI / handoff 中混用 | 已補 `S4-9-CANONICAL-OWNER-RESPONSE-ENVELOPE.md`,後續顯示層以六欄 canonical envelope 呈現;source templates 可保留細分欄位 | @@ -88,6 +88,7 @@ S4.9 的基礎規範已存在,且已能被 `source-control-owner-response-guar | S4.9 現況缺口稽核 | 100% | 已列出已符合、仍不符合、需新增、需調整、五題回覆與 0 / false 邊界 | | S4.9 canonical owner response envelope | 100% | 已補六欄信封、alias 映射、五題投影、quarantine-first 與 reviewer checklist | | S4.9 owner response gate | 0% | 沒有收到 owner response,不得調高 | +| S4.9 基準與日期一致性 | 100% | 已跟到 `gitea/main=7cea7ef0` 與 deploy marker `8a8843e3`,並要求 guard 擋下過期基準、過期日期與舊模板公式 | | S4.13 rollup 文件一致性 | 100% | 已把 `22` 舊口徑修正為 `24`,並由 guard 檢查 | | IwoooS 整體 | 維持 64% | 只讀稽核不改 runtime readiness | | active runtime gate | 0 | 不變 | diff --git a/docs/security/SOURCE-CONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md b/docs/security/SOURCE-CONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md index c01c4331..b608abbf 100644 --- a/docs/security/SOURCE-CONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md +++ b/docs/security/SOURCE-CONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md @@ -111,7 +111,7 @@ S4.13 不新增第 36 個主 contract,不新增 approval item,不啟用 runt AwoooP 顯示 S4.9 時,應同步讀取 `gitea-inventory-owner-attestation-response.snapshot.json` 的 1 個 owner response request packet、5 個 template statuses、3 個 audit event templates、5 個 redaction examples、8 個 display sections、6 個 collection checks、6 個 intake preflight checks 與 5 個 outcome lanes;request packet 只提示 owner 要填什麼與不得貼什麼,template statuses 只逐項顯示 waiting / request ready,audit event templates 只定義 request shown / response received metadata / outcome classified 的脫敏 metadata 欄位且目前 0 emitted,redaction examples 只提供安全回覆形狀,display sections 只固定只讀 UI 順序,collection checks 只維持 request / received / accepted 狀態分離,preflight / outcome 只分類可審、補證、隔離、拒收或等待,不代表 owner response accepted 或 AwoooP production ingestion 已啟用。 -### 2.3.1 2026-06-04 S4.9 Current Intake Readiness +### 2.3.1 2026-06-12 S4.9 Current Intake Readiness S4.9 目前已具備可直接照表收件與預檢的準備度,但尚未收到任何 owner response。這個狀態應顯示在 AwoooP 操作控制台作為下一個收件焦點,不得變成 approval queue 或 execution queue。 diff --git a/docs/security/source-control-owner-response-validation-rollup.snapshot.json b/docs/security/source-control-owner-response-validation-rollup.snapshot.json index 9229bb04..866c6c3d 100644 --- a/docs/security/source-control-owner-response-validation-rollup.snapshot.json +++ b/docs/security/source-control-owner-response-validation-rollup.snapshot.json @@ -1,7 +1,7 @@ { "schema_version": "source_control_owner_response_validation_rollup_v1", "status": "draft_waiting_owner_responses", - "date": "2026-06-04", + "date": "2026-06-12", "mode": "owner_response_validation_rollup_only", "runtime_execution_authorized": false, "source_contracts": [ @@ -200,7 +200,7 @@ "check_id": "template_counts_match", "title": "response template count 必須與各 source packet summary 一致", "required": true, - "pass_condition": "5 + 7 + 5 + 5 = 22", + "pass_condition": "5 + 9 + 5 + 5 = 24", "failure_lane": "mirror_quarantine", "execution_authorized": false }, @@ -2242,7 +2242,7 @@ }, "latest_local_validation": { "status": "repo_snapshot_guard_pass", - "date": "2026-06-04", + "date": "2026-06-12", "scope": "repo_snapshot_only", "command": "python3 scripts/security/source-control-owner-response-guard.py --root .", "result": "SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK", diff --git a/scripts/security/source-control-owner-response-guard.py b/scripts/security/source-control-owner-response-guard.py index 524a5bb4..7bece72a 100755 --- a/scripts/security/source-control-owner-response-guard.py +++ b/scripts/security/source-control-owner-response-guard.py @@ -13,6 +13,10 @@ from pathlib import Path from typing import Any +EXPECTED_ROLLUP_DATE = "2026-06-12" +EXPECTED_TEMPLATE_COUNT_FORMULA = "5 + 9 + 5 + 5 = 24" +STALE_TEMPLATE_COUNT_FORMULA = "5 + 7 + 5 + 5 = 22" + LANES = [ { "lane_id": "s4_9_gitea_inventory_owner_attestation_response", @@ -498,13 +502,16 @@ def validate_markdown_consistency(security_dir: Path) -> None: encoding="utf-8" ) - assert_contains("rollup_doc.total_template_formula", rollup_doc, "5 + 9 + 5 + 5 = 24") + assert_contains("rollup_doc.date", rollup_doc, EXPECTED_ROLLUP_DATE) + assert_contains("rollup_doc.total_template_formula", rollup_doc, EXPECTED_TEMPLATE_COUNT_FORMULA) assert_contains("rollup_doc.total_template_display", rollup_doc, "24 templates") - assert_not_contains("rollup_doc.stale_formula", rollup_doc, "5 + 7 + 5 + 5 = 22") + assert_not_contains("rollup_doc.stale_date", rollup_doc, "2026-06-04") + assert_not_contains("rollup_doc.stale_formula", rollup_doc, STALE_TEMPLATE_COUNT_FORMULA) assert_not_contains("rollup_doc.stale_display", rollup_doc, "22 templates") assert_contains("gap_audit_doc.latest_baseline_present", gap_audit_doc, "gitea/main=") assert_not_contains("gap_audit_doc.stale_baseline_b615", gap_audit_doc, "b615bde5") assert_not_contains("gap_audit_doc.stale_baseline_f1bad", gap_audit_doc, "f1bad81d") + assert_not_contains("gap_audit_doc.stale_baseline_b17a", gap_audit_doc, "b17a28c2") assert_contains("gap_audit_doc.rollup_consistency", gap_audit_doc, "S4.13 rollup 文件一致性") @@ -515,6 +522,7 @@ def validate(root: Path) -> None: rollup_summary = rollup["summary"] assert_equal("rollup.status", rollup["status"], "draft_waiting_owner_responses") + assert_equal("rollup.date", rollup["date"], EXPECTED_ROLLUP_DATE) assert_false("rollup.runtime_execution_authorized", rollup["runtime_execution_authorized"]) assert_equal("rollup.response_packet_count", rollup_summary["response_packet_count"], len(LANES)) assert_equal("rollup.validation_lane_count", rollup_summary["validation_lane_count"], len(LANES)) @@ -1130,6 +1138,18 @@ def validate(root: Path) -> None: assert_equal("missing_response_lanes.count", len(missing_lane_by_id), len(LANES)) assert_equal("owner_response_collection_order.count", len(collection_order_by_id), len(LANES)) + cross_packet_checks = {item["check_id"]: item for item in rollup["cross_packet_acceptance_checks"]} + assert_equal( + "cross_packet_acceptance_checks.template_counts_match.pass_condition", + cross_packet_checks["template_counts_match"]["pass_condition"], + EXPECTED_TEMPLATE_COUNT_FORMULA, + ) + assert_not_contains( + "rollup.snapshot.stale_template_count_formula", + json.dumps(rollup, ensure_ascii=False), + STALE_TEMPLATE_COUNT_FORMULA, + ) + evidence_routing_rules = rollup["owner_response_evidence_routing_rules"] assert_equal( "owner_response_evidence_routing_rules.ids", @@ -1826,6 +1846,7 @@ def validate(root: Path) -> None: local_validation = rollup["latest_local_validation"] assert_equal("rollup.latest_local_validation.status", local_validation["status"], "repo_snapshot_guard_pass") + assert_equal("rollup.latest_local_validation.date", local_validation["date"], EXPECTED_ROLLUP_DATE) assert_equal("rollup.latest_local_validation.scope", local_validation["scope"], "repo_snapshot_only") assert_equal("rollup.latest_local_validation.result", local_validation["result"], "SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK") assert_equal("rollup.latest_local_validation.received_response_count", local_validation["received_response_count"], 0)