From 185173f09b0ad1e6283f8ddd7fb08b7108eace54 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Jun 2026 19:42:40 +0800 Subject: [PATCH] docs(security): add primary rollback owner handoff [skip ci] --- docs/LOGBOOK.md | 41 +++ ...ontrol_primary_rollback_adr_v1.schema.json | 153 +++++++++ .../SOURCE-CONTROL-PRIMARY-READINESS-GATE.md | 6 +- .../SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md | 77 ++++- ...ntrol-primary-readiness-gate.snapshot.json | 5 +- ...control-primary-rollback-adr.snapshot.json | 304 +++++++++++++++++- ...026-06-04-iwooos-security-governance-p0.md | 12 +- 7 files changed, 584 insertions(+), 14 deletions(-) diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index f220eb1a..ef571209 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,44 @@ +## 2026-06-04|IwoooS P1-5 Primary Rollback Owner Handoff + +**背景**:P1-4 已補 workflow / secret owner response handoff;本段接著補 P1-5 / S4.4 GitHub primary rollback ADR 的 owner handoff。目標是讓 7 個 in-scope repo 能用同一個只讀封套回覆 rollback owner、fallback role、trigger、pre-cutover / 1h / 24h validation window 與 follow-up owner;這不是 owner approval、不是 dry-run、不是 GitHub primary cutover,也不是 rollback execution。 + +**本輪完成**: +- 先 fast-forward 到 `d99e7366 feat(web): expose AwoooP run operator status chain`,再接上 deploy marker `9a965b66 chore(cd): deploy d99e736 [skip ci]`,保留另一個 Session 的 AwoooP runs operator status chain 與 CD 部署基準。 +- 更新 `SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md`:日期改為 2026-06-04,新增 P1-5 handoff 摘要、6 項送件前檢查、11 欄交接封套、7 個 repo response template 與送後不變條件。 +- 更新 `source-control-primary-rollback-adr.snapshot.json`:新增 `rollback_owner_handoff_package_ready=true`、`rollback_owner_handoff_completion_percent=100`、`rollback_owner_handoff_check_count=6`、`rollback_owner_handoff_packet_field_count=11`、7 個 repo owner response templates,並維持 received / accepted / rejected、owner approved、dry-run、active cutover 全部 `0`。 +- 更新 `source_control_primary_rollback_adr_v1.schema.json`:同步納入 `rollback_owner_handoff`、handoff preflight、handoff packet、repo templates 與 post-handoff invariants,避免 snapshot 與 schema 漂移。 +- 更新 `SOURCE-CONTROL-PRIMARY-READINESS-GATE.md` 與 `source-control-primary-readiness-gate.snapshot.json`:把 rollback ADR gate wording 對齊 P1-5 handoff,但 GitHub primary readiness gate 仍維持 `0`。 +- 更新 IwoooS P0/P1 主控總帳:P1 只讀重盤工作完成度從 `68%` 調到 `70%`;GitHub primary readiness、owner approval、dry-run、active cutover、runtime gate 不調高。 +- Guard 發現 `d99e7366` 新增的 AwoooP operator status chain 在 `apps/web/messages/en.json` 有 5 個英文狀態字串;本段依全站繁中鏡像規則改成繁中,`en.json` / `zh-TW.json` 差異歸零。 + +**完成度更新**: +- P1-5 Primary rollback owner handoff:`100%`。 +- P1 GitHub primary readiness 只讀重盤階段:`70%`。 +- Rollback owner response gate:`0%`,received / accepted / rejected 全部為 `0`。 +- Owner approved:`0`。 +- Dry-run completed:`0`。 +- Active cutover:`0`。 +- GitHub primary readiness gate:`0`。 +- Active runtime gate:`0`。 + +**驗證**: +- `python3 -m json.tool docs/security/source-control-primary-rollback-adr.snapshot.json`:通過。 +- `python3 -m json.tool docs/schemas/source_control_primary_rollback_adr_v1.schema.json`:通過。 +- `python3 -m json.tool docs/security/source-control-primary-readiness-gate.snapshot.json`:通過。 +- 本段自訂結構檢查:`PRIMARY_ROLLBACK_OWNER_HANDOFF_STRUCTURE_OK`。 +- i18n 鏡像檢查:`I18N_JSON_MIRROR_OK`。 +- `git diff --check`:通過。 +- `python3 scripts/security/source-control-owner-response-guard.py --root .`:`SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK`。 +- `python3 scripts/security/security-mirror-progress-guard.py --root .`:`SECURITY_MIRROR_PROGRESS_GUARD_OK`。 +- URL credential pattern 檢查:本段新增 diff 行無命中;檔案級掃描命中 LOGBOOK 歷史舊行的外洩檢查旗標,非本段新增 credential payload。 +- Schema validator 限制:本地沒有 Python `jsonschema` 與 Node AJV,未跑完整 JSON Schema validator;本段以 JSON parse、自訂結構檢查與既有 guard 補位。 +- Production 頁面檢查:本段 P1-5 主要是 docs / snapshot / schema / LOGBOOK;另含 5 個 i18n 鏡像字串修正,未改 layout 或資料鏈路。正式站頁面檢查若後續 CD 部署,需補 `/zh-TW/awooop/runs` desktop / mobile smoke;本段不宣稱新的 production 狀態,IwoooS `/zh-TW/iwooos` 沿用 P0 desktop / mobile live sanity 基準。 + +**目前邊界**: +- P1-5 handoff 只代表 rollback owner request package 可交接,不代表 request 已送出、owner 已回覆或 owner 已批准。 +- 不切 GitHub primary、不執行 rollback、不同步 / 刪除 refs、不 force push、不建立 repo、不改 visibility、不改 workflow / secret / runner、不停用 Gitea。 +- 未來即使 owner response 通過,也只能先更新 read-only rollback ADR、primary readiness wording、approval board 與 status rollup;真正 cutover / rollback 仍需獨立人工批准、dry-run、runtime gate、rollback plan 與 post-check。 + ## 2026-06-04|IwoooS P1-4 Workflow / Secret Owner Response Handoff **背景**:P1-3 已補 GitHub target owner response handoff;本段接著補 P1-4 / S4.12 workflow、webhook、runner、deploy key、branch protection / CODEOWNERS、repository secret name parity 的 owner response handoff。目標是只收名稱與脫敏 metadata,不收 secret value、hash、masked token、partial token 或任何可還原 credential material。 diff --git a/docs/schemas/source_control_primary_rollback_adr_v1.schema.json b/docs/schemas/source_control_primary_rollback_adr_v1.schema.json index cfa956f2..3909d2e7 100644 --- a/docs/schemas/source_control_primary_rollback_adr_v1.schema.json +++ b/docs/schemas/source_control_primary_rollback_adr_v1.schema.json @@ -15,6 +15,7 @@ "rollback_principles", "cutover_preconditions", "repo_rollback_plans", + "rollback_owner_handoff", "rollback_triggers", "validation_windows", "acceptance_rules", @@ -54,6 +55,14 @@ "owner_approved_count", "dry_run_completed_count", "active_cutover_count", + "rollback_owner_handoff_package_ready", + "rollback_owner_handoff_completion_percent", + "rollback_owner_handoff_check_count", + "rollback_owner_handoff_packet_field_count", + "rollback_owner_request_dispatch_authorized", + "rollback_owner_response_received_count", + "rollback_owner_response_accepted_count", + "rollback_owner_response_rejected_count", "rollback_execution_authorized", "github_primary_switch_authorized", "gitea_disable_authorized", @@ -67,6 +76,14 @@ "owner_approved_count": {"type": "integer", "minimum": 0}, "dry_run_completed_count": {"type": "integer", "minimum": 0}, "active_cutover_count": {"type": "integer", "minimum": 0}, + "rollback_owner_handoff_package_ready": {"type": "boolean"}, + "rollback_owner_handoff_completion_percent": {"type": "integer", "minimum": 0, "maximum": 100}, + "rollback_owner_handoff_check_count": {"type": "integer", "minimum": 0}, + "rollback_owner_handoff_packet_field_count": {"type": "integer", "minimum": 0}, + "rollback_owner_request_dispatch_authorized": {"type": "boolean", "const": false}, + "rollback_owner_response_received_count": {"type": "integer", "minimum": 0}, + "rollback_owner_response_accepted_count": {"type": "integer", "minimum": 0}, + "rollback_owner_response_rejected_count": {"type": "integer", "minimum": 0}, "rollback_execution_authorized": {"type": "boolean", "const": false}, "github_primary_switch_authorized": {"type": "boolean", "const": false}, "gitea_disable_authorized": {"type": "boolean", "const": false}, @@ -179,6 +196,142 @@ }, "minItems": 1 }, + "rollback_owner_handoff": { + "type": "object", + "required": [ + "status", + "package_ready", + "handoff_completion_percent", + "repo_template_count", + "preflight_checks", + "handoff_packet", + "repo_owner_response_templates", + "post_handoff_invariants" + ], + "properties": { + "status": {"type": "string", "enum": ["ready_not_dispatched"]}, + "package_ready": {"type": "boolean"}, + "handoff_completion_percent": {"type": "integer", "minimum": 0, "maximum": 100}, + "repo_template_count": {"type": "integer", "minimum": 0}, + "preflight_checks": { + "type": "array", + "items": { + "type": "object", + "required": ["check_id", "title", "completion_state", "current_status"], + "properties": { + "check_id": {"type": "string"}, + "title": {"type": "string"}, + "completion_state": {"type": "string", "enum": ["defined_not_dispatched"]}, + "current_status": {"type": "string"} + }, + "additionalProperties": false + }, + "minItems": 1 + }, + "handoff_packet": { + "type": "object", + "required": [ + "request_id", + "stage_id", + "prerequisite_gates", + "requested_repo_templates", + "recipient_role_or_team", + "required_response_fields", + "validation_window_refs", + "allowed_evidence_refs", + "forbidden_inputs", + "not_approval", + "request_dispatch_authorized" + ], + "properties": { + "request_id": {"type": "string"}, + "stage_id": {"type": "string"}, + "prerequisite_gates": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "requested_repo_templates": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "recipient_role_or_team": {"type": "string"}, + "required_response_fields": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "validation_window_refs": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "allowed_evidence_refs": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "forbidden_inputs": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "not_approval": {"type": "boolean"}, + "request_dispatch_authorized": {"type": "boolean", "const": false} + }, + "additionalProperties": false + }, + "repo_owner_response_templates": { + "type": "array", + "items": { + "type": "object", + "required": [ + "repo_key", + "github_repo", + "rollback_owner_status", + "fallback_role_confirmation_required", + "trigger_review_required", + "validation_window_refs", + "required_response_fields", + "response_received", + "response_accepted", + "primary_ready", + "execution_authorized" + ], + "properties": { + "repo_key": {"type": "string"}, + "github_repo": {"type": "string"}, + "rollback_owner_status": {"type": "string", "enum": ["waiting_owner_response"]}, + "fallback_role_confirmation_required": {"type": "boolean"}, + "trigger_review_required": {"type": "boolean"}, + "validation_window_refs": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "required_response_fields": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + }, + "response_received": {"type": "boolean"}, + "response_accepted": {"type": "boolean"}, + "primary_ready": {"type": "boolean", "const": false}, + "execution_authorized": {"type": "boolean", "const": false} + }, + "additionalProperties": false + }, + "minItems": 1 + }, + "post_handoff_invariants": { + "type": "array", + "items": {"type": "string"}, + "minItems": 1 + } + }, + "additionalProperties": false + }, "rollback_triggers": { "type": "array", "items": {"type": "string"}, diff --git a/docs/security/SOURCE-CONTROL-PRIMARY-READINESS-GATE.md b/docs/security/SOURCE-CONTROL-PRIMARY-READINESS-GATE.md index eae1a454..a91ab5d1 100644 --- a/docs/security/SOURCE-CONTROL-PRIMARY-READINESS-GATE.md +++ b/docs/security/SOURCE-CONTROL-PRIMARY-READINESS-GATE.md @@ -54,7 +54,7 @@ | refs truth / branch-tag parity | blocked | 3 個 mapped repos 仍有 refs drift;`awoooi` 已刷新到 Gitea heads `170` / GitHub heads `2`,S4.11 current classification 為 `194` refs review items;S4.11 owner response received / accepted 仍為 0 | | workflow / runner / secret name parity | missing evidence | S4.2 本機 evidence 已於 2026-06-04 刷新到 31 個 workflow files / 42 個 unique referenced secret names;仍缺 webhook、runner owner、deploy key、branch protection、repository secret parity;S4.12 owner response received / accepted 仍為 0 | | owner / visibility / canonical | pending review | GitHub target probe 仍是 5 個可讀、3 個 `not_found_or_private`;7 個 in-scope targets 仍需人工決策;S4.10 owner response received / accepted 仍為 0 | -| rollback ADR | pending review | S4.4 已建立 rollback ADR 草案;7 個 in-scope repos 仍需 owner approval、dry-run 與 validation window | +| rollback ADR | pending review | S4.4 / P1-5 已建立 rollback ADR 與 owner handoff;7 個 in-scope repos 仍需 owner response、owner approval、dry-run 與 validation window 驗收 | ## 3. AwoooP 可做 @@ -67,7 +67,7 @@ 7. 連到 `source_control_workflow_secret_name_inventory_v1` 與 2026-06-04 S4.2 local evidence,顯示 8 個 candidate repos、31 個 workflow files、42 個 unique referenced secret names 與仍缺的 webhook / runner / deploy key / branch protection / repository secret parity;只保存 secret 名稱與 owner,不保存 value。 8. 連到 S4.12 `source_control_workflow_secret_name_owner_response_v1` 顯示 1 個 owner response request packet、5 個 template statuses、3 個 audit event templates、5 個 redaction examples、6 個 collection checks、6 個 intake preflight checks、5 個 owner response templates、8 個 acceptance checks、10 個 rejection rules,且 received / accepted response 皆為 0、audit events emitted 仍為 0。 9. 連到 S4.13 `source_control_owner_response_validation_rollup_v1` 顯示四包 owner response validation 狀態:22 個 templates、10 個 cross-packet checks、6 條 evidence routing rules、8 個 display sections、7 條 state transition rules、9 個 reviewer checklist items、7 條 reviewer outcome lanes、4 個 reviewer audit event templates、5 個 reviewer audit display sections、6 個 reviewer audit collection checks、5 個 reviewer audit redaction examples、5 條 reviewer audit retention rules、6 個 reviewer audit retention checks、6 個 reviewer audit handoff packets、6 個 reviewer audit handoff checks、6 個 parallel session sync checks、6 條 parallel session conflict lanes、6 個 parallel session recovery checks、7 條 parallel session recovery outcome lanes、received / accepted / rejected response 皆為 0、reviewer audit emitted 仍為 0。 -10. 連到 `source_control_primary_rollback_adr_v1` 顯示 7 個 in-scope repos 的 rollback owner、trigger 與 validation window 草案。 +10. 連到 `source_control_primary_rollback_adr_v1` 顯示 7 個 in-scope repos 的 rollback owner handoff、trigger、fallback role 與 pre-cutover / 1h / 24h validation window 草案;P1-5 handoff package ready 但 received / accepted 仍為 0。 11. 把狀態寫入 Audit evidence 與 Operator Console。 ## 4. AwoooP 不可做 @@ -84,6 +84,6 @@ S4.0 只是把「切換前一定要看見什麼」先定義清楚。 -S4.4 已補上 rollback ADR 草案,但它只是 owner review 的資料包,不是切換批准。S4.7 已補上 Gitea coverage owner attestation,S4.9 已補上 Gitea owner response request packet、template status ledger、audit event templates、redaction examples、display sections、collection checks、收件包、preflight 與 outcome lanes,S4.10 已補上 GitHub target owner decision response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.11 已補上 refs truth owner response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.12 已補上 workflow / secret 名稱 owner response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.13 已補上四包 owner response validation rollup、evidence routing rules、display sections、state transition rules、reviewer checklist、reviewer outcome lanes、reviewer audit event templates、reviewer audit display sections、reviewer audit collection checks、reviewer audit redaction examples、reviewer audit retention rules、reviewer audit retention checks、reviewer audit handoff packets、handoff checks、parallel session sync checks、parallel session conflict lanes、parallel session recovery checks 與 parallel session recovery outcome lanes;它們只是 scope decision、response 收件提示、metadata audit template、脫敏範例、只讀收件檢查、只讀 preflight、只讀顯示順序、只讀 evidence routing、只讀狀態語義、人工審查提示、結果分類、脫敏稽核格式、稽核顯示邊界、只讀稽核檢查、安全 metadata 顯示範例、metadata retention 邊界、只讀 retention 驗證、跨 Session 只讀交接、交接消費檢查、平行 Session 同步檢查、衝突 lane、復原前檢查、復原結果分類與驗收框架,不是 audit production ingestion、migration approval、repo creation approval、visibility change approval、refs sync approval、delete approval、force-push approval、secret value collection approval、workflow modification approval 或 primary approval。`owner_approved_count=0`、`dry_run_completed_count=0`、`active_cutover_count=0`。 +S4.4 已補上 rollback ADR 草案,P1-5 已補上 7 個 in-scope repos 的 rollback owner handoff、fallback role confirmation、trigger review、validation window refs、送件前檢查與交接封套,但它仍只是 owner review 的資料包,不是切換批准。S4.7 已補上 Gitea coverage owner attestation,S4.9 已補上 Gitea owner response request packet、template status ledger、audit event templates、redaction examples、display sections、collection checks、收件包、preflight 與 outcome lanes,S4.10 已補上 GitHub target owner decision response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.11 已補上 refs truth owner response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.12 已補上 workflow / secret 名稱 owner response request packet、template status ledger、audit event templates、redaction examples、collection checks、intake preflight checks 與收件包,S4.13 已補上四包 owner response validation rollup、evidence routing rules、display sections、state transition rules、reviewer checklist、reviewer outcome lanes、reviewer audit event templates、reviewer audit display sections、reviewer audit collection checks、reviewer audit redaction examples、reviewer audit retention rules、reviewer audit retention checks、reviewer audit handoff packets、handoff checks、parallel session sync checks、parallel session conflict lanes、parallel session recovery checks 與 parallel session recovery outcome lanes;它們只是 scope decision、response 收件提示、metadata audit template、脫敏範例、只讀收件檢查、只讀 preflight、只讀顯示順序、只讀 evidence routing、只讀狀態語義、人工審查提示、結果分類、脫敏稽核格式、稽核顯示邊界、只讀稽核檢查、安全 metadata 顯示範例、metadata retention 邊界、只讀 retention 驗證、跨 Session 只讀交接、交接消費檢查、平行 Session 同步檢查、衝突 lane、復原前檢查、復原結果分類與驗收框架,不是 audit production ingestion、migration approval、repo creation approval、visibility change approval、refs sync approval、delete approval、force-push approval、secret value collection approval、workflow modification approval、rollback execution approval 或 primary approval。`rollback_owner_response_received_count=0`、`rollback_owner_response_accepted_count=0`、`owner_approved_count=0`、`dry_run_completed_count=0`、`active_cutover_count=0`。 這讓長期回到 GitHub 的方向可以繼續往前,但仍維持低摩擦:目前只 mirror、只顯示、只留痕,不執行。 diff --git a/docs/security/SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md b/docs/security/SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md index 55a87688..7df84213 100644 --- a/docs/security/SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md +++ b/docs/security/SOURCE-CONTROL-PRIMARY-ROLLBACK-ADR.md @@ -2,8 +2,8 @@ | 項目 | 內容 | |------|------| -| 日期 | 2026-05-13 | -| 狀態 | 草案,等待 owner review | +| 日期 | 2026-06-04 | +| 狀態 | 草案與 P1-5 rollback owner handoff 已整理,等待 owner review | | Schema | `docs/schemas/source_control_primary_rollback_adr_v1.schema.json` | | Snapshot | `docs/security/source-control-primary-rollback-adr.snapshot.json` | | 模式 | `rollback_adr_only` | @@ -11,11 +11,11 @@ ## 0. 核心結論 -S4.4 補上 GitHub primary cutover 前必備的 rollback ADR 草案。 +S4.4 補上 GitHub primary cutover 前必備的 rollback ADR 草案。2026-06-04 P1-5 再把逐 repo rollback owner handoff 補齊,讓 owner 可以用同一套欄位回覆 fallback 角色、trigger、1h / 24h 驗證窗口與 follow-up owner。 這不是 cutover plan,也不是 rollback 執行計畫。它只定義:每個 repo 在未來要切 GitHub primary 前,必須先有什麼 evidence、誰是 rollback owner、哪些狀況要停下來、以及切換後 1 小時 / 24 小時要看什麼。 -目前 `owner_approved_count=0`、`dry_run_completed_count=0`、`active_cutover_count=0`,所以 `primary_ready_count` 仍必須維持 0。 +目前 `owner_approved_count=0`、`rollback_owner_response_received_count=0`、`rollback_owner_response_accepted_count=0`、`dry_run_completed_count=0`、`active_cutover_count=0`,所以 `primary_ready_count` 仍必須維持 0。 ## 1. 摘要 @@ -28,10 +28,79 @@ S4.4 補上 GitHub primary cutover 前必備的 rollback ADR 草案。 | Owner approved | 0 | | Dry-run completed | 0 | | Active cutover | 0 | +| P1-5 rollback owner handoff package | `ready` | +| Handoff completion | `100%` | +| Handoff preflight checks | 6 | +| Handoff packet fields | 11 | +| Rollback owner response received / accepted / rejected | `0 / 0 / 0` | +| Rollback owner request dispatch authorized | `false` | | Rollback execution authorized | `false` | | GitHub primary switch authorized | `false` | | Gitea disable authorized | `false` | +## 1.0 2026-06-04 P1-5 Primary Rollback Owner Handoff + +本段把 S4.4 從「rollback ADR 草案已存在」推到「7 個 in-scope repo 的 rollback owner / fallback / trigger / validation window 可交接請 owner 回覆」。這是 handoff readiness,不是 request sent、不是 owner response received、不是 owner approval、不是 dry-run,也不是 GitHub primary cutover 或 rollback 執行批准。 + +| 指標 | 值 | +|------|----| +| P1-5 handoff package | ready | +| handoff completion | 100% | +| repo templates | 7 | +| preflight checks | 6 | +| handoff packet fields | 11 | +| request dispatch authorized | false | +| rollback owner response received | 0 | +| rollback owner response accepted | 0 | +| rollback owner response rejected | 0 | +| owner approved | 0 | +| dry-run completed | 0 | +| active cutover | 0 | +| GitHub primary switch authorized | false | + +### 1.0.1 送件前檢查 + +| 順序 | 檢查項 | 完成條件 | 目前狀態 | +|------|--------|----------|----------| +| 1 | source-control 基線同步 | 送件前確認 `gitea/main`、P1-2、P1-3、P1-4 與 S4.13 最新狀態 | 已定義,未送件 | +| 2 | 七個 in-scope repo | 只向 7 個 in-scope repo 收 rollback owner / fallback / trigger / validation 回覆 | 已定義,未送件 | +| 3 | fallback 角色保留 | 回覆必須確認 Gitea 或現行來源仍保留 fallback 角色 | 已定義,未送件 | +| 4 | validation window 對齊 | 每個 repo 必須對應 pre-cutover、1h、24h 三個驗證窗口 | 已定義,未送件 | +| 5 | metadata only | 只收 owner role/team、決策理由、脫敏 evidence ref 與 follow-up owner | 已定義,未送件 | +| 6 | 執行要求拒收 | primary switch、rollback execution、refs sync、workflow / secret 變更與 Gitea disable 全部 hard reject | 已定義,未送件 | + +### 1.0.2 交接封套欄位 + +| 欄位 | 內容規則 | +|------|----------| +| `request_id` | `p1_5_primary_rollback_owner_handoff` | +| `stage_id` | `S4.4` | +| `prerequisite_gates` | S4.9、P1-2、P1-3、P1-4、S4.13 只讀 handoff / validation rollup | +| `requested_repo_templates` | `awoooi`、`clawbot-v5`、`wooo-aiops`、`wooo-infra-config`、`ewoooc`、`bitan-pharmacy`、`tsenyang-website` | +| `recipient_role_or_team` | 只填 repo owner / release owner / fallback owner 的角色或團隊,不收個人 credential | +| `required_response_fields` | owner role/team、decision、decision reason、fallback role confirmation、rollback trigger scope、validation window owner、redacted evidence refs、followup owner | +| `validation_window_refs` | `pre_cutover_freeze_review`、`post_cutover_one_hour_observe`、`post_cutover_twenty_four_hour_review` | +| `allowed_evidence_refs` | 只引用 repo 內文件、snapshot、decision record id 或脫敏 metadata pointer | +| `forbidden_inputs` | token、secret、private key、runner token、webhook secret、repo write instruction、refs sync/delete instruction、primary switch、rollback execution、Gitea disable、active scan 或 host maintenance request | +| `not_approval` | 必須為 `true` | +| `request_dispatch_authorized` | 必須為 `false`,除非另有人工送件批准與 audit evidence | + +### 1.0.3 七個 repo response template + +| Repo | 需要 owner 回覆 | 驗證窗口 | 目前狀態 | +|------|----------------|----------|----------| +| `owenhytsai/awoooi` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/clawbot-v5` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/wooo-aiops` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/wooo-infra-config` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/ewoooc` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/bitan-pharmacy` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | +| `owenhytsai/tsenyang-website` | rollback owner、fallback role、trigger、validation owner、脫敏 evidence refs | pre-cutover / 1h / 24h | waiting owner response | + +### 1.0.4 送件後不變條件 + +即使後續 owner 實際回覆,也只能先進 intake preflight 與 reviewer validation。通過後可更新 read-only rollback ADR、primary readiness blocker wording、approval board 與 status rollup;不得直接切 GitHub primary、執行 rollback、sync / delete refs、force push、改 workflow / secret、啟用 runner、停用 Gitea、改主機或觸發 active scan。 + ## 2. Rollback 原則 1. GitHub primary 是長期方向,但每個 repo 必須先有 owner-approved rollback plan 才能進入 cutover review。 diff --git a/docs/security/source-control-primary-readiness-gate.snapshot.json b/docs/security/source-control-primary-readiness-gate.snapshot.json index 0b0a4197..323a7f83 100644 --- a/docs/security/source-control-primary-readiness-gate.snapshot.json +++ b/docs/security/source-control-primary-readiness-gate.snapshot.json @@ -155,12 +155,13 @@ "切換前後監控與驗證 gate 已定義" ], "current_gap": [ - "S4.4 已建立 rollback ADR 草案,但尚無 owner-approved decision record", - "7 個 in-scope repos 的 rollback owner、validation window 與 trigger 仍需人工審查", + "S4.4 / P1-5 已建立 rollback ADR 草案與 rollback owner handoff package,但尚無 owner-approved decision record", + "7 個 in-scope repos 的 rollback owner handoff templates、fallback role、validation window 與 trigger 已定義;rollback owner response received/accepted 仍為 0", "dry_run_completed_count=0,active_cutover_count=0,不得切換 GitHub primary" ], "allowed_now": [ "mirror rollback ADR 草案", + "mirror P1-5 rollback owner handoff package、preflight checks、handoff packet 與 repo templates", "列出 rollback evidence requirements", "讓 AwoooP mirror blocked state" ], diff --git a/docs/security/source-control-primary-rollback-adr.snapshot.json b/docs/security/source-control-primary-rollback-adr.snapshot.json index a186f655..3e402257 100644 --- a/docs/security/source-control-primary-rollback-adr.snapshot.json +++ b/docs/security/source-control-primary-rollback-adr.snapshot.json @@ -1,7 +1,7 @@ { "schema_version": "source_control_primary_rollback_adr_v1", "status": "draft_waiting_owner_review", - "date": "2026-05-13", + "date": "2026-06-04", "mode": "rollback_adr_only", "runtime_execution_authorized": false, "source_indexes": [ @@ -21,6 +21,14 @@ "owner_approved_count": 0, "dry_run_completed_count": 0, "active_cutover_count": 0, + "rollback_owner_handoff_package_ready": true, + "rollback_owner_handoff_completion_percent": 100, + "rollback_owner_handoff_check_count": 6, + "rollback_owner_handoff_packet_field_count": 11, + "rollback_owner_request_dispatch_authorized": false, + "rollback_owner_response_received_count": 0, + "rollback_owner_response_accepted_count": 0, + "rollback_owner_response_rejected_count": 0, "rollback_execution_authorized": false, "github_primary_switch_authorized": false, "gitea_disable_authorized": false, @@ -398,6 +406,300 @@ ] } ], + "rollback_owner_handoff": { + "status": "ready_not_dispatched", + "package_ready": true, + "handoff_completion_percent": 100, + "repo_template_count": 7, + "preflight_checks": [ + { + "check_id": "preflight-latest-source-control-baseline", + "title": "送件前確認 gitea/main、P1-2、P1-3、P1-4 與 S4.13 最新狀態", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + }, + { + "check_id": "preflight-seven-in-scope-repos-only", + "title": "只向 7 個 in-scope repos 收 rollback owner / fallback / trigger / validation 回覆", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + }, + { + "check_id": "preflight-fallback-role-kept", + "title": "回覆必須確認 Gitea 或現行來源仍保留 fallback 角色", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + }, + { + "check_id": "preflight-validation-windows-bound", + "title": "每個 repo 必須對應 pre-cutover、1h、24h 三個驗證窗口", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + }, + { + "check_id": "preflight-redacted-evidence-only", + "title": "只收 owner role/team、決策理由、脫敏 evidence ref 與 follow-up owner", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + }, + { + "check_id": "preflight-no-cutover-or-rollback-command", + "title": "primary switch、rollback execution、refs sync、workflow/secret 變更與 Gitea disable 全部拒收", + "completion_state": "defined_not_dispatched", + "current_status": "已定義,未送件" + } + ], + "handoff_packet": { + "request_id": "p1_5_primary_rollback_owner_handoff", + "stage_id": "S4.4", + "prerequisite_gates": [ + "S4.9 Gitea owner response gate", + "P1-2 Gitea authenticated inventory request handoff", + "P1-3 GitHub target owner response handoff", + "P1-4 workflow / secret owner response handoff", + "S4.13 owner response validation rollup" + ], + "requested_repo_templates": [ + "awoooi", + "clawbot-v5", + "wooo-aiops", + "wooo-infra-config", + "ewoooc", + "bitan-pharmacy", + "tsenyang-website" + ], + "recipient_role_or_team": "repo owner / release owner / fallback owner role only;不收個人 credential", + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "allowed_evidence_refs": [ + "docs/security/source-control-primary-readiness-gate.snapshot.json", + "docs/security/source-control-ref-truth-owner-response.snapshot.json", + "docs/security/github-target-owner-decision-response.snapshot.json", + "docs/security/source-control-workflow-secret-name-owner-response.snapshot.json", + "docs/security/source-control-owner-response-validation-rollup.snapshot.json" + ], + "forbidden_inputs": [ + "token value", + "secret value", + "private key", + "runner registration token", + "webhook secret", + "repo write instruction", + "refs sync or delete instruction", + "GitHub primary switch request", + "rollback execution request", + "Gitea disable or archive request", + "active scan or host maintenance request" + ], + "not_approval": true, + "request_dispatch_authorized": false + }, + "repo_owner_response_templates": [ + { + "repo_key": "awoooi", + "github_repo": "owenhytsai/awoooi", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "clawbot-v5", + "github_repo": "owenhytsai/clawbot-v5", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "wooo-aiops", + "github_repo": "owenhytsai/wooo-aiops", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "wooo-infra-config", + "github_repo": "owenhytsai/wooo-infra-config", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "ewoooc", + "github_repo": "owenhytsai/ewoooc", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "bitan-pharmacy", + "github_repo": "owenhytsai/bitan-pharmacy", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + }, + { + "repo_key": "tsenyang-website", + "github_repo": "owenhytsai/tsenyang-website", + "rollback_owner_status": "waiting_owner_response", + "fallback_role_confirmation_required": true, + "trigger_review_required": true, + "validation_window_refs": [ + "pre_cutover_freeze_review", + "post_cutover_one_hour_observe", + "post_cutover_twenty_four_hour_review" + ], + "required_response_fields": [ + "owner_role_or_team", + "decision", + "decision_reason", + "fallback_role_confirmation", + "rollback_trigger_scope", + "validation_window_owner", + "redacted_evidence_refs", + "followup_owner" + ], + "response_received": false, + "response_accepted": false, + "primary_ready": false, + "execution_authorized": false + } + ], + "post_handoff_invariants": [ + "request dispatch authorized 仍為 false,未送件前不得增加 request_sent_count。", + "owner response received / accepted / rejected 全部維持 0。", + "owner response 通過前不得把任何 repo 標記 primary_ready。", + "dry-run completed count 與 active cutover count 維持 0。", + "不得把 rollback owner handoff 當成 GitHub primary approval、rollback execution approval 或 Gitea disable approval。", + "未來即使 owner response 通過,也只能更新 read-only rollback ADR、primary readiness wording、approval board 與 status rollup。" + ] + }, "rollback_triggers": [ "main/dev SHA 或 tag parity 與 owner-approved truth 不一致", "workflow、webhook、runner、deploy key、branch protection 或 repository secret name parity evidence 不完整", diff --git a/docs/workplans/2026-06-04-iwooos-security-governance-p0.md b/docs/workplans/2026-06-04-iwooos-security-governance-p0.md index cc859fb7..7b0a9bd7 100644 --- a/docs/workplans/2026-06-04-iwooos-security-governance-p0.md +++ b/docs/workplans/2026-06-04-iwooos-security-governance-p0.md @@ -9,7 +9,7 @@ | 工作視窗 | IwoooS / AWOOOI 資安治理 P0 | | 本次乾淨 worktree | `/private/tmp/awoooi-iwooos-governance-p0-20260604` | | 本次分支 | `codex/iwooos-governance-p0-20260604` | -| 最新觀察到的 `gitea/main` | `8c9582f3 chore(cd): deploy b61ee9b [skip ci]` | +| 最新觀察到的 `gitea/main` | `9a965b66 chore(cd): deploy d99e736 [skip ci]` | | 前一個正式 IwoooS 候選基準 | code `7b8fc093`、deploy marker `45c63488`、LOGBOOK `02cadee6` | | 最新導航 IA 基準 | code `973fc7a4`、LOGBOOK `2555c811`、deploy marker `0260ec89` | | 禁止事項 | 不 force push、不 destructive git、不 SSH 修改主機、不 active scan、不收 secrets 明文、不把 AwoooP approval 當資安批准、不把 UI 可見當 runtime 授權 | @@ -23,7 +23,7 @@ | runtime landing | 40-45% | 否 | production 只讀頁存在,不等於 runtime ingestion 或 execution router | | active runtime gate | 0 | 否 | 必須維持 0,直到獨立人工批准、rollback、post-check 與 guard 成立 | | S4.9 owner response gate | 0% | 可在收到合格回覆後調整 | 目前只定義欄位、預檢、收件與驗收,不標記 received / accepted | -| GitHub primary readiness | 0 | 否 | primary gate 仍為 0;P1 只讀重盤工作本身目前約 68%,不代表可切 primary | +| GitHub primary readiness | 0 | 否 | primary gate 仍為 0;P1 只讀重盤工作本身目前約 70%,不代表可切 primary | | Kali 112 維護準備 | 只讀證據已納管,維護尚未開始 | 否 | 不更新套件、不重啟、不 hardening、不 active scan | | 111 / 168 開發主機納管 | observe-only mapping 已有,維護包需補強 | 可補文件,不調 runtime | 仍不 credentialed scan、不讀未授權資料、不自動修復 | | VibeWork 納入 IwoooS | 前端態勢已有 onboarding 欄位,產品邊界需補規範 | 可補文件 | 保留 VibeWork 獨立產品邊界 | @@ -155,9 +155,10 @@ S4.9 是目前 IwoooS 64% 能往前的第一優先 gate。驗收前所有 count | 全量 Gitea 專案版本盤點 | 25% | 目前仍是 public-only + 本機輔助 evidence | 需只讀 token / admin export;不使用 write credential | | 逐 repo refs truth queue | 100% | S4.11 current queue 已重產為 `194` refs review items:真相來源 `4`、deprecated / archive 候選 `142`、release tag `3`、GitHub-only `20` | 送 owner response;received / accepted 仍維持 0 | | Workflow / runner / secret parity owner response handoff | 100% | S4.12 已對齊 2026-06-04 local evidence,補 6 項 workflow / secret handoff preflight、9 欄 handoff packet 與送後不變條件;local secret names 校正為 `42` | 只收 redacted metadata,不收 value / hash / partial token;received / accepted 仍 0 | +| Primary rollback ADR owner handoff | 100% | S4.4 / P1-5 已補 6 項 rollback owner handoff preflight、11 欄 handoff packet、7 個 repo owner response templates 與送後不變條件 | `rollback_owner_response_received_count=0`、`owner_approved_count=0`、dry-run / active cutover 仍 0 | | GitHub primary cutover readiness | 0% | `primary_ready_count=0`、`github_primary_switch_authorized=false` | 需 owner、parity、rollback ADR、人工批准全部成立 | -P1 只讀重盤階段整體完成度:`68%`。它代表 freshness / inventory / handoff 工作進度,不代表 GitHub primary gate、authenticated inventory gate、workflow / secret parity complete、owner response accepted 或 runtime gate 提升。 +P1 只讀重盤階段整體完成度:`70%`。它代表 freshness / inventory / handoff 工作進度,不代表 GitHub primary gate、authenticated inventory gate、workflow / secret parity complete、owner response accepted、rollback approved、dry-run complete 或 runtime gate 提升。 ## 6.2 規範分析:已不符合、需新增、需調整 @@ -172,6 +173,7 @@ P1 只讀重盤階段整體完成度:`68%`。它代表 freshness / inventory / | 需要新增規範 | P1 page verification decision rule | 文件 / snapshot 更新不一定需要開頁;若宣稱 production 狀態或改前端才必須開頁 | 已保留驗證節點規則,本階段不改前端、不宣稱新 production | | 需要調整規範 | GitHub target probe wording | `not_found_or_private` 容易被誤讀成不存在 | 已在 primary gate 重申不可自動建立 repo、不可切 primary | | 需要調整規範 | Workflow / secret 名稱完成度 | local evidence 已有,但 webhook / runner / deploy key / branch protection / parity 仍缺 | 已改為 `missing_evidence`,不得說已完成 parity | +| 需要調整規範 | Rollback ADR owner readiness | 舊 ADR 有 fallback / trigger / window 摘要,但缺可交接的 owner response 封套與逐 repo template | 已補 P1-5 handoff package;received / accepted / approved 仍全部 0 | | 需要調整規範 | AwoooP 同步封包 | P1 要同步 refreshed counts、blocked gates、no-run 狀態,避免另一 Session 以舊 `117` heads / `141` items 繼續推進 | 本總帳與 LOGBOOK 會作為同步封包來源 | ## 6.3 P1 優先順序細化 @@ -182,7 +184,7 @@ P1 只讀重盤階段整體完成度:`68%`。它代表 freshness / inventory / | P1-2 | Gitea authenticated inventory request | 已補 2026-06-04 request handoff package;S4.9 owner response gate 作先行條件,只讀 token API / redacted admin export 二選一 | 只收 metadata,不保存 token value;received / accepted / imported 全部仍為 0 | | P1-3 | GitHub target owner response | 已補 2026-06-04 target owner handoff package;對 7 個 in-scope targets 收 owner / visibility / canonical 決策 | received / accepted 前仍全部 0;`not_found_or_private` 不代表不存在或可建立 | | P1-4 | Workflow / runner / secret parity evidence | 已補 2026-06-04 owner response handoff package;webhook、runner owner、deploy key、branch protection、CODEOWNERS、secret name parity 只收 redacted metadata | secret value、hash、masked token、partial token 仍拒收;received / accepted 前全部 0 | -| P1-5 | Primary rollback ADR 補強 | 逐 repo rollback owner、trigger、validation window、fallback role | ADR approved 前不切 primary | +| P1-5 | Primary rollback ADR 補強 | 已補 2026-06-04 rollback owner handoff package;逐 repo rollback owner、trigger、validation window、fallback role 進入可交接模板 | ADR approved 前不切 primary;received / accepted / approved 仍 0 | | P1-6 | AwoooP Session 同步 | 同步 commits、runs、production sanity、P1 refresh counts、gate 0 / false | 另一 Session 不再使用舊 refs count | | P1-7 | Kali 112 maintenance window 草案 | packages、`networking.service` failed、hardening 0/4、rollback、post-check | 文件草案,不執行 `apt upgrade` / restart / scan | | P1-8 | 111 / 168 開發主機 scope | scope、credential handling、rollback owner、validation 指標 | observe-only,不做 credentialed scan | @@ -212,6 +214,8 @@ P1 只讀重盤階段整體完成度:`68%`。它代表 freshness / inventory / | P1-3 JSON parse / structure check | `github-target-owner-decision-response.snapshot.json` 與 schema JSON parse 通過;本段自訂結構檢查 `GITHUB_TARGET_OWNER_HANDOFF_STRUCTURE_OK`;本地無 `jsonschema` / AJV,未跑完整 schema validator | | P1-4 Workflow / secret owner response handoff | S4.12 日期更新為 2026-06-04;補 6 項 workflow / secret handoff preflight、9 欄 handoff packet、送後不變條件;local referenced secret names 校正為 `42`;received / accepted / rejected 仍 0 | | P1-4 JSON parse / structure check | `source-control-workflow-secret-name-owner-response.snapshot.json` 與 schema JSON parse 通過;本段自訂結構檢查 `WORKFLOW_SECRET_OWNER_HANDOFF_STRUCTURE_OK`;本地無 `jsonschema` / AJV,未跑完整 schema validator | +| P1-5 Primary rollback owner handoff | S4.4 日期更新為 2026-06-04;補 6 項 rollback owner handoff preflight、11 欄 handoff packet、7 個 repo owner response templates 與送後不變條件;received / accepted / rejected、owner approved、dry-run、active cutover 仍 0 | +| P1-5 JSON parse / structure check | `source-control-primary-rollback-adr.snapshot.json` 與 schema JSON parse 通過;本段自訂結構檢查 `PRIMARY_ROLLBACK_OWNER_HANDOFF_STRUCTURE_OK`;本地無 `jsonschema` / AJV 時以 JSON parse、自訂結構檢查與既有 guard 補位 | | P1 JSON parse | `gitea-github-awoooi-inventory`、`github-target-probe`、`source-control-primary-readiness-gate`、`source-control-workflow-secret-name-local-evidence`、Gitea repo / search / org blocked snapshots 皆通過 | | P1 production 頁面檢查 | 本輪未改前端、未改 production 文案、未新增 deploy;不宣稱新的 production 狀態,沿用 P0 live sanity 作為基準 |