diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 7d0331a4..f8065296 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -6,6 +6,7 @@ - 新增 `scripts/security/telegram-notification-egress-inventory.py`,repo-only 掃描 `.gitea/workflows`、`scripts/ops`、`scripts/ci`、`apps/api/src`;不讀 secret、不送 Telegram、不改 workflow / script。 - 新增 `docs/security/telegram-notification-egress-inventory.snapshot.json` 與 `docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md`。 - `security-mirror-progress-guard.py` 已鎖住 Telegram egress snapshot:`direct_bot_api_call_count=18`、`direct_bot_api_file_count=11`、workflow `13`、ops script `4`、API direct `1`、`gateway_normalized_callsite_count=56`、`gateway_final_exit_formatter_present_count=1`。 +- 新增 `scripts/security/telegram-notification-egress-owner-request-draft.py`、`docs/security/telegram-notification-egress-owner-request-draft.snapshot.json` 與 `docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md`,把 11 個 direct egress 檔案聚成 11 份人工送件前 owner request 草稿:workflow `6`、ops script `4`、API direct `1`。 - direct egress 目前分布: - Gitea workflow:`.gitea/workflows/cd.yaml`、`cd-dev.yaml`、`code-review.yaml`、`deploy-alerts.yaml`、`e2e-health.yaml`、`run-migration.yml` - Ops script:`scripts/ops/docker-health-monitor.sh`、`pg-backup.sh`、`dr-drill.sh`、`backup-from-110.sh` @@ -13,15 +14,17 @@ **邊界**: - 這是 notification egress inventory / owner gate,不是 workflow 修改、script 修改、`channel_hub.py` 重構、Telegram 實發、Bot API call、secret 讀取、chat route 變更、production deploy 或 runtime gate。 -- owner response received / accepted、formatter convergence accepted、redaction contract accepted、delivery receipt accepted、direct Bot API migration authorized、Telegram send authorized、workflow / script modification authorized、secret collection、raw payload storage、production write、runtime gate、action button 全部維持 `0 / false`。 +- request sent、recipient confirmed、audit event emitted、owner response received / accepted、formatter convergence accepted、redaction contract accepted、delivery receipt accepted、direct Bot API migration authorized、Telegram send authorized、workflow / script modification authorized、secret collection、raw payload storage、production write、runtime gate、action button 全部維持 `0 / false`。 - direct Bot API call count 大於 0 代表仍有已知旁路風險;不得把 API 內部 formatter 完成誤判成全域通知出口已完全治理。 **驗證**: - `python3 scripts/security/telegram-notification-egress-inventory.py --root . --generated-at 2026-06-18T22:30:00+08:00 --output docs/security/telegram-notification-egress-inventory.snapshot.json`:`TELEGRAM_NOTIFICATION_EGRESS_INVENTORY_OK direct_calls=18 files=11 workflow=13 ops=4 api=1 runtime_gate=0`。 +- `python3 scripts/security/telegram-notification-egress-owner-request-draft.py --root . --generated-at 2026-06-18T22:45:00+08:00 --output docs/security/telegram-notification-egress-owner-request-draft.snapshot.json`:`TELEGRAM_NOTIFICATION_EGRESS_OWNER_REQUEST_DRAFT_OK drafts=11 workflow=6 ops=4 api=1 sent=0 runtime_gate=0`。 - `python3 -m json.tool docs/security/telegram-notification-egress-inventory.snapshot.json`:通過。 **完成度同步**: - Telegram notification egress inventory / guard:`100%`。 +- Telegram notification egress owner request draft:`100%`。 - Direct Bot API formatter convergence:`0%`,需 owner response / maintenance window 後分批處理。 - AI 自動化告警產品化:通知出口治理從「API final-exit formatter」推進到「repo-wide egress inventory」;下一步是 owner response package 與 migration plan。 - IwoooS headline 仍維持 `64%`,active runtime gate 仍 `0`。 diff --git a/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md b/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md index 026bc6a6..a5b74e84 100644 --- a/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md +++ b/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md @@ -86,6 +86,7 @@ Host / runner 資源告警的第一版落地: 通知出口旁路清冊: - `docs/security/telegram-notification-egress-inventory.snapshot.json` 目前固定 repo 內 `18` 個 direct Bot API `sendMessage`,分布為 Gitea workflow `13`、ops script `4`、API direct path `1`。 +- `docs/security/telegram-notification-egress-owner-request-draft.snapshot.json` 已將上述 direct egress 檔案聚成 `11` 份人工送件前草稿,request sent 仍為 `0`。 - 這些 direct egress 可能繞過 TelegramGateway formatter、dedup、outbound mirror、KM / PlayBook / Verifier 與 no-false-green gate;因此只能視為已知待治理 surface,不能視為已完成收斂。 - 清冊階段只允許保存 path、line、redacted excerpt、owner 欄位與 reviewer gate;不送 Telegram、不讀 Bot token、不保存 chat secret、不改 workflow / script、不開 runtime gate。 - 後續每個 direct egress 要收斂前,都必須補 owner route、message shape、redaction contract、formatter convergence plan、delivery receipt、fallback mode、rollback owner 與 post-check evidence。 diff --git a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md index 5a0e4be1..a6ac0ee7 100644 --- a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md +++ b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md @@ -50,6 +50,8 @@ 2026-06-18 再新增 `docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md` 與 `docs/security/telegram-notification-egress-inventory.snapshot.json`,把 repo 內 direct Telegram Bot API `sendMessage` 旁路固定成 notification egress 清冊。固定 `direct_bot_api_call_count=18`、`direct_bot_api_file_count=11`、workflow `13`、ops script `4`、API direct `1`、`gateway_normalized_callsite_count=56`、`gateway_final_exit_formatter_present_count=1`、`required_owner_field_count=18`、`reviewer_check_count=14`、`outcome_lane_count=9`、`blocked_action_count=22`。此更新只表示旁路已可重跑盤點;owner response、formatter convergence accepted、delivery receipt accepted、workflow / script modification、Telegram send、Bot API call、secret collection、production write、runtime gate 與 action button 仍全部為 `0 / false`。 +同日再新增 `docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md` 與 `docs/security/telegram-notification-egress-owner-request-draft.snapshot.json`,將 11 個 direct egress 檔案轉成人工送件前草稿。固定 `request_draft_count=11`、workflow `6`、ops script `4`、API direct `1`、`required_owner_field_count=19`、`preflight_check_count=16`、`outcome_lane_count=9`、`forbidden_payload_count=14`、`blocked_action_count=26`;request sent、recipient confirmed、owner response accepted、formatter convergence accepted、Telegram send、Bot API call、workflow / script modification、API sender refactor、secret collection、production write、runtime gate 與 action button 仍全部為 `0 / false`。 + ## 1.2c 2026-06-18 Backup / Restore / Escrow 事故後回讀計畫 已新增 `docs/security/BACKUP-RESTORE-POST-INCIDENT-READBACK-PLAN.md` 與 `docs/security/backup-restore-post-incident-readback-plan.snapshot.json`,將 38 個 backup / restore / escrow / retention surface 轉成事故後回讀計畫。固定 `readback_candidate_count=38`、`write_capable_readback_candidate_count=27`、`live_evidence_required_readback_candidate_count=38`、`restore_drill_readback_required_candidate_count=38`、`offsite_or_escrow_readback_required_candidate_count=20`、`retention_or_remote_delete_readback_required_candidate_count=17`、`required_readback_field_count=34`、`reviewer_check_count=32`、`outcome_lane_count=11`、`blocked_action_count=51`,讓 `backup_restore_credential` 從 `64%` 推進到 `66%`,高價值配置平均維持 `71%`,需 live evidence 類別仍為 `9`。 diff --git a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md index 79fe42a7..26ebeb50 100644 --- a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md +++ b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md @@ -89,6 +89,8 @@ 此更新只表示 `.gitea/workflows`、`scripts/ops` 與 `apps/api/src/services/channel_hub.py` 的 direct egress 已可重跑盤點,不代表已遷移。owner response received / accepted、formatter convergence accepted、redaction contract accepted、delivery receipt accepted、direct Bot API migration authorized、Telegram send、Bot API call、workflow / script modification、secret collection、raw payload storage、production write、runtime gate 仍全部為 `0 / false`。 +同日再新增 `telegram_notification_egress_owner_request_draft_v1`,將 11 個 direct egress 檔案轉成人工送件前 owner request 草稿。固定 `request_draft_count=11`、`workflow_request_draft_count=6`、`ops_script_request_draft_count=4`、`api_direct_request_draft_count=1`、`required_owner_field_count=19`、`preflight_check_count=16`、`outcome_lane_count=9`、`forbidden_payload_count=14`、`blocked_action_count=26`。request sent、recipient confirmed、audit event emitted、owner response accepted、formatter convergence accepted、break-glass fallback accepted、Telegram send、Bot API call、workflow / script modification、API sender refactor、secret collection、raw payload storage、production write、runtime gate 仍全部為 `0 / false`。 + ### 0.3d 2026-06-15 Public / Admin / API runtime config 變更證據驗收 `public_runtime_config_change_evidence_acceptance_v1` 已把公開產品頁、AwoooP 後台、API / CORS、frontend env、Sentry tunnel、webhook / callback 與跨產品 runtime route 轉成 metadata-only 變更證據驗收只讀帳本。固定 `candidates=6`、`c0=5`、`c1=1`、`write_capable=6`、`source_refs=20`、`required_evidence_fields=21`、`reviewer_checks=21`、`outcome_lanes=8`、`blocked_actions=32`。 diff --git a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md index 93d99b2e..73c92b3c 100644 --- a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md +++ b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md @@ -94,6 +94,8 @@ 同步邊界:IwoooS headline 維持 `64%`,active runtime gate 維持 `0`;direct Bot API migration authorized、Telegram send authorized、Bot API call authorized、workflow modification authorized、script modification authorized、secret value collection、raw payload storage、production write、runtime gate 與 action buttons 全部仍為 `0 / false`。本段只更新文件、snapshot、guard 與通知模型,不改 workflow、不重構 API、不呼叫 Telegram、不讀 Bot token、不 dispatch workflow、不觸發部署。 +同日再新增 `telegram_notification_egress_owner_request_draft_v1`,把 11 個 direct egress 檔案轉成人工送件前草稿。固定 `request_draft_count=11`、workflow `6`、ops script `4`、API direct `1`、`required_owner_field_count=19`、`preflight_check_count=16`、`outcome_lane_count=9`、`forbidden_payload_count=14`、`blocked_action_count=26`。這是 handoff envelope,不是 request sent、recipient confirmed、audit event emitted、owner response accepted、formatter convergence accepted、workflow / script modification、API sender refactor、Telegram send、Bot API call、secret collection、production write 或 runtime gate。 + ## 0.00aaa 2026-06-15 K8s / ArgoCD GitOps 變更證據驗收 本輪把 K8s / ArgoCD 從 owner response acceptance 推進到 GitOps 變更證據驗收只讀帳本:`k8s_argocd_change_evidence_acceptance_v1` 固定 `candidates=4`、`c0=3`、`write_capable=4`、`required_evidence_fields=18`、`reviewer_checks=18`、`outcome_lanes=8`、`blocked_actions=28`,並讓 `k8s_production_gitops` 只讀治理成熟度 `62% -> 64%`,高價值配置平均只讀成熟度仍維持 `68%`。這是 metadata-only 收件驗收,不是 change evidence received / accepted、runtime approval package、ArgoCD API read、ArgoCD sync、kubectl action、Helm upgrade、NetworkPolicy apply、NodePort change、RBAC change、live cluster read、production write 或 runtime gate。 diff --git a/docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md b/docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md index 0590947a..cee5eabb 100644 --- a/docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md +++ b/docs/security/TELEGRAM-NOTIFICATION-EGRESS-INVENTORY.md @@ -104,7 +104,8 @@ Reviewer 必須確認: ## 8. 下一步 -1. 先把 Gitea workflow 13 個 direct send 分成 CD / code-review / migration / health 類,決定哪些改走 AWOOI Alertmanager / TelegramGateway,哪些保留為 break-glass fallback。 -2. `scripts/ops/docker-health-monitor.sh`、`pg-backup.sh`、`dr-drill.sh`、`backup-from-110.sh` 需要 owner 確認 API 離線 fallback 的訊息形狀與 redaction contract。 -3. `apps/api/src/services/channel_hub.py` 的 interim Telegram path 需要評估是否改走 TelegramGateway 或至少套同一個 normalization / mirror / receipt 契約。 -4. 每個遷移都必須單獨做 owner approval、maintenance window、rollback owner、no-secret-value evidence 與 post-check;不得用本清冊直接改 workflow 或送 Telegram。 +1. `docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md` 已把 11 個 direct egress 檔案聚成 11 份人工送件前草稿;request sent 仍為 `0`。 +2. 先把 Gitea workflow 13 個 direct send 分成 CD / code-review / migration / health 類,決定哪些改走 AWOOI Alertmanager / TelegramGateway,哪些保留為 break-glass fallback。 +3. `scripts/ops/docker-health-monitor.sh`、`pg-backup.sh`、`dr-drill.sh`、`backup-from-110.sh` 需要 owner 確認 API 離線 fallback 的訊息形狀與 redaction contract。 +4. `apps/api/src/services/channel_hub.py` 的 interim Telegram path 需要評估是否改走 TelegramGateway 或至少套同一個 normalization / mirror / receipt 契約。 +5. 每個遷移都必須單獨做 owner approval、maintenance window、rollback owner、no-secret-value evidence 與 post-check;不得用本清冊直接改 workflow 或送 Telegram。 diff --git a/docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md b/docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md new file mode 100644 index 00000000..4c9fab00 --- /dev/null +++ b/docs/security/TELEGRAM-NOTIFICATION-EGRESS-OWNER-REQUEST-DRAFT.md @@ -0,0 +1,101 @@ +# Telegram 通知出口 Owner Request 草稿 + +| 項目 | 內容 | +|------|------| +| 日期 | 2026-06-18 | +| 狀態 | `owner_request_draft_ready_no_dispatch_no_runtime_action` | +| 工具 | `scripts/security/telegram-notification-egress-owner-request-draft.py` | +| Snapshot | `docs/security/telegram-notification-egress-owner-request-draft.snapshot.json` | +| Source snapshot | `docs/security/telegram-notification-egress-inventory.snapshot.json` | +| 模式 | metadata-only;不送 request、不確認 recipient、不送 Telegram、不改 workflow / script | +| runtime gate | `0` | + +## 1. 目的 + +`telegram_notification_egress_inventory_v1` 已確認 repo 內仍有 `18` 個 direct Bot API `sendMessage` call site,分散在 `11` 個檔案。這份 Owner Request 草稿把 call site 依檔案聚合成 `11` 份人工送件前草稿,要求 owner 判定每個通知出口要如何收斂: + +- 改走 `TelegramGateway` final-exit formatter。 +- 改走 AWOOI Alertmanager / webhook 入口,再由 TelegramGateway 發送。 +- 保留為明確的 break-glass fallback,但必須有訊息形狀、redaction、delivery receipt 與 no-false-green gate。 + +本文件不是 request sent,也不是批准修改 workflow、script、API sender 或 Telegram route。 + +## 2. 固定數字 + +| 指標 | 數值 | 解讀 | +|------|------|------| +| `source_direct_bot_api_call_count` | `18` | 來源清冊中的 direct send call site | +| `source_direct_bot_api_file_count` | `11` | 來源清冊中的 direct send 檔案 | +| `request_draft_count` | `11` | 每個檔案一份 owner request 草稿 | +| `workflow_request_draft_count` | `6` | Gitea workflow 草稿 | +| `ops_script_request_draft_count` | `4` | ops script 草稿 | +| `api_direct_request_draft_count` | `1` | API direct sender 草稿 | +| `request_field_count` | `27` | 草稿 envelope 欄位 | +| `required_owner_field_count` | `19` | owner 必填欄位 | +| `preflight_check_count` | `16` | 送件前預檢 | +| `outcome_lane_count` | `9` | 收件結果分流 | +| `forbidden_payload_count` | `14` | 禁止提交的 payload 類型 | +| `blocked_action_count` | `26` | 草稿階段禁止動作 | + +所有 request sent、recipient confirmed、audit event emitted、owner response received / accepted、formatter convergence accepted、delivery receipt accepted、break-glass fallback accepted、direct Bot API migration authorized、Telegram send、Bot API call、workflow / script modification、API sender refactor、secret collection、raw payload storage、production write、runtime gate 與 action button 都維持 `0 / false`。 + +## 3. Owner 必填欄位 + +每份草稿至少需要 owner 提供: + +1. `owner_role_or_team` +2. `routing_purpose` +3. `current_sender` +4. `target_chat_route` +5. `message_shape_contract` +6. `redaction_contract` +7. `formatter_convergence_decision` +8. `gateway_or_alertmanager_target` +9. `break_glass_fallback_decision` +10. `delivery_receipt_ref` +11. `dedup_or_fingerprint_plan` +12. `fallback_or_degraded_mode` +13. `migration_or_exception_reason` +14. `maintenance_window` +15. `rollback_owner` +16. `postcheck_evidence_ref` +17. `no_secret_value_attestation` +18. `no_raw_payload_attestation` +19. `no_false_green_attestation` + +Owner 回覆只能提供 metadata / ref,不得包含 Bot token、chat secret、secret hash、partial token、masked token、authorization header、raw message payload、raw workflow log、raw action log、未脫敏截圖、內部工作視窗逐字稿、private namespace、未脫敏內部路徑或內網 IP。 + +## 4. Preflight checks + +送件前必須確認: + +- source inventory 是目前版本,且 draft count 與 direct file count 一致。 +- owner role、route purpose、message shape、redaction contract、formatter convergence decision 都存在。 +- break-glass fallback 必須顯式標示;不能把 fallback 當主路徑偷渡。 +- delivery receipt、dedup / fingerprint、maintenance window、rollback owner 與 post-check evidence 都已指定。 +- no-secret-value、no-raw-payload、no-false-green attestation 都存在。 +- runtime gate 維持 0;草稿不能送 Telegram、dispatch workflow、修改 script 或重構 API sender。 + +## 5. Outcome lanes + +| Lane | 說明 | +|------|------| +| `draft_waiting_owner_dispatch` | 草稿待人工送件,request sent 仍為 0 | +| `request_owner_route_supplement` | 缺 owner、route、purpose | +| `request_formatter_convergence_supplement` | 缺 formatter convergence decision 或 target | +| `request_break_glass_fallback_supplement` | 缺 fallback decision 或 exception reason | +| `request_redaction_or_receipt_supplement` | 缺 redaction contract、receipt 或 dedup plan | +| `quarantine_secret_or_raw_payload` | 收到 secret / raw payload / raw log 時隔離 | +| `reject_false_green_claim` | 把 CD success、route 200、UI 可見或 Telegram 送達當驗收時拒收 | +| `ready_for_manual_dispatch` | 草稿 metadata 完整,可由人工送件 | +| `waiting_runtime_gate` | 即使回覆 accepted,runtime send / 修改仍需獨立批准 | + +## 6. 禁止動作 + +此草稿階段禁止送 owner request、確認 recipient、emit audit event、送 Telegram、呼叫 Bot API、改 workflow、改 script、重構 API sender、改 chat route、改 Bot token、讀 secret store、收 secret value / hash / partial token / chat id secret、保存 raw message payload / 未脫敏 log、workflow dispatch、production deploy、把 CD success / route 200 / UI 可見當 delivery receipt、跳過 formatter convergence、跳過 redaction contract、開 runtime gate 或新增 action button。 + +## 7. 下一步 + +1. 人工確認送件對象與 route owner 後,才可把這 11 份草稿送出;送出本身需另有 audit event,不由本 snapshot 代替。 +2. 收到 owner response 後,先做 intake preflight:欄位完整、無 secret value、無 raw payload、無 false-green claim。 +3. 通過 reviewer 後,才可為每個 surface 建 migration plan;workflow / script / API sender 修改仍需獨立維護窗口、rollback owner 與 production post-check。 diff --git a/docs/security/telegram-notification-egress-owner-request-draft.snapshot.json b/docs/security/telegram-notification-egress-owner-request-draft.snapshot.json new file mode 100644 index 00000000..ec03a94c --- /dev/null +++ b/docs/security/telegram-notification-egress-owner-request-draft.snapshot.json @@ -0,0 +1,1809 @@ +{ + "schema_version": "telegram_notification_egress_owner_request_draft_v1", + "generated_at": "2026-06-18T22:45:00+08:00", + "git_commit": "8cbedfe4", + "status": "owner_request_draft_ready_no_dispatch_no_runtime_action", + "mode": "metadata_only_no_secret_value_no_telegram_send_no_workflow_change", + "source_snapshot": "docs/security/telegram-notification-egress-inventory.snapshot.json", + "source_schema_version": "telegram_notification_egress_inventory_v1", + "source_status": "inventory_ready_no_runtime_action", + "summary": { + "source_direct_bot_api_call_count": 18, + "source_direct_bot_api_file_count": 11, + "request_draft_count": 11, + "workflow_request_draft_count": 6, + "ops_script_request_draft_count": 4, + "ci_script_request_draft_count": 0, + "api_direct_request_draft_count": 1, + "request_field_count": 27, + "required_owner_field_count": 19, + "preflight_check_count": 16, + "outcome_lane_count": 9, + "forbidden_payload_count": 14, + "blocked_action_count": 26, + "request_sent_count": 0, + "recipient_confirmed_count": 0, + "audit_event_emitted_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "formatter_convergence_accepted_count": 0, + "redaction_contract_accepted_count": 0, + "delivery_receipt_accepted_count": 0, + "break_glass_fallback_accepted_count": 0, + "direct_bot_api_migration_authorized_count": 0, + "telegram_send_authorized_count": 0, + "bot_api_call_authorized_count": 0, + "workflow_modification_authorized_count": 0, + "script_modification_authorized_count": 0, + "api_sender_refactor_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "raw_payload_storage_allowed_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0 + }, + "execution_boundaries": { + "runtime_execution_authorized": false, + "owner_request_send_authorized": false, + "recipient_confirmation_authorized": false, + "audit_event_emit_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + "request_drafts": [ + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_cd_dev_yaml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/cd-dev.yaml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 3, + "line_refs": [ + 54, + 241, + 262 + ], + "line_hash_refs": [ + "f503c2c0f61100a9", + "c41f88fbca91a4b9", + "eaa9a6cb8326dc79" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_cd_yaml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/cd.yaml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 5, + "line_refs": [ + 113, + 305, + 1203, + 1552, + 1575 + ], + "line_hash_refs": [ + "b57e6587a106976b", + "19c1de8d67af874a", + "6ef020c2b6eac91f", + "d029b95242f39c03", + "d62c45a8595984fc" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_code_review_yaml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/code-review.yaml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 2, + "line_refs": [ + 137, + 216 + ], + "line_hash_refs": [ + "a7ebbd735dad5ab2", + "f10f7782dc7c8125" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_deploy_alerts_yaml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/deploy-alerts.yaml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 69 + ], + "line_hash_refs": [ + "79e83190f68f27c9" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_e2e_health_yaml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/e2e-health.yaml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 98 + ], + "line_hash_refs": [ + "d73ce94678f970a9" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:_gitea_workflows_run_migration_yml", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": ".gitea/workflows/run-migration.yml", + "surface_kind": "gitea_workflow_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 210 + ], + "line_hash_refs": [ + "934a8dd69fca99b3" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:apps_api_src_services_channel_hub_py", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": "apps/api/src/services/channel_hub.py", + "surface_kind": "api_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 1138 + ], + "line_hash_refs": [ + "9e418fa74c83815a" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:scripts_ops_backup_from_110_sh", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": "scripts/ops/backup-from-110.sh", + "surface_kind": "ops_script_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 64 + ], + "line_hash_refs": [ + "ff5ffbeca44d679b" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:scripts_ops_docker_health_monitor_sh", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": "scripts/ops/docker-health-monitor.sh", + "surface_kind": "ops_script_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 90 + ], + "line_hash_refs": [ + "6611406903bc7d65" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:scripts_ops_dr_drill_sh", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": "scripts/ops/dr-drill.sh", + "surface_kind": "ops_script_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 63 + ], + "line_hash_refs": [ + "b7cf532f3c5509fc" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "request_draft_id": "telegram_notification_egress_owner_request:scripts_ops_pg_backup_sh", + "source_inventory_schema_version": "telegram_notification_egress_inventory_v1", + "source_path": "scripts/ops/pg-backup.sh", + "surface_kind": "ops_script_direct_bot_api", + "direct_call_count": 1, + "line_refs": [ + 52 + ], + "line_hash_refs": [ + "8268f3d6f14d66a3" + ], + "request_fields": [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization" + ], + "required_owner_fields": [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation" + ], + "preflight_checks": [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero" + ], + "outcome_lanes": [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate" + ], + "forbidden_payloads": [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip" + ], + "blocked_actions": [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button" + ], + "request_sent": false, + "recipient_confirmed": false, + "audit_event_emitted": false, + "owner_response_received": false, + "owner_response_accepted": false, + "formatter_convergence_accepted": false, + "redaction_contract_accepted": false, + "delivery_receipt_accepted": false, + "break_glass_fallback_accepted": false, + "direct_bot_api_migration_authorized": false, + "telegram_send_authorized": false, + "bot_api_call_authorized": false, + "workflow_modification_authorized": false, + "script_modification_authorized": false, + "api_sender_refactor_authorized": false, + "secret_value_collection_allowed": false, + "raw_payload_storage_allowed": false, + "production_write_authorized": false, + "runtime_gate": false, + "action_buttons_allowed": false, + "not_authorization": true + } + ], + "operator_interpretation": [ + "This is a draft packet for manual owner dispatch; request_sent_count remains 0.", + "Each file-level draft must decide whether the path converges to TelegramGateway, AWOOI Alertmanager, or a documented break-glass fallback.", + "No workflow, script, API, secret, Telegram, or production action is authorized by this snapshot." + ] +} 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 f87b9a5e..715731ce 100644 --- a/docs/workplans/2026-06-04-iwooos-security-governance-p0.md +++ b/docs/workplans/2026-06-04-iwooos-security-governance-p0.md @@ -82,7 +82,7 @@ | P0-3 | AwoooP 同步封包 | 100% | 已送至 AwoooP 平行工作 thread `019e9154-7d5e-7b72-85be-c9d97e43ecc9`;後續仍需每次推版前重新 fetch / fast-forward | 本文件、thread send readback、mirror checklist readback | | P0-4 | production live sanity 節點 | 100% | desktop / mobile / 展開區塊 / overflow / action href 檢查已完成 | Playwright production sanity 通過 | | P0-5 | LOGBOOK 與完成度更新 | 100% | D2 comments-only、D2 AIOps sample、D2 Code Review 候選分類與 D2 AwoooP Runs fallback 皆已回填;可見 / bundle 變更皆已補 local / production desktop + mobile smoke | `docs/LOGBOOK.md` readback | -| P0-6 | Telegram 監控告警 / 通知出口治理 | outbound 主鏈路 100%;靜音 / recurrence slice 88%;通知出口清冊 100%;direct Bot API convergence 0% | Alertmanager 缺 project context、既有 approval 收斂告警靜音、AI 分析中重複告警靜音皆已修復並正式 smoke;`TelegramGateway` final-exit formatter 已完成 host / multi-signal 卡片化;本輪新增 direct Bot API egress inventory,固定 workflow 13、ops script 4、API direct 1,後續需 owner response 後分批收斂,不得把 API formatter 完成誤判成全域完成 | API health、Telegram health、API pod Alertmanager smoke、production logs `converged_alert_recurrence_sent`、`telegram-notification-egress-inventory.snapshot.json` | +| P0-6 | Telegram 監控告警 / 通知出口治理 | outbound 主鏈路 100%;靜音 / recurrence slice 88%;通知出口清冊 100%;owner request draft 100%;direct Bot API convergence 0% | Alertmanager 缺 project context、既有 approval 收斂告警靜音、AI 分析中重複告警靜音皆已修復並正式 smoke;`TelegramGateway` final-exit formatter 已完成 host / multi-signal 卡片化;本輪新增 direct Bot API egress inventory,固定 workflow 13、ops script 4、API direct 1,並聚成 11 份 owner request 草稿;後續需 owner response 後分批收斂,不得把 API formatter 完成誤判成全域完成 | API health、Telegram health、API pod Alertmanager smoke、production logs `converged_alert_recurrence_sent`、`telegram-notification-egress-inventory.snapshot.json`、`telegram-notification-egress-owner-request-draft.snapshot.json` | | P0-7 | Telegram 批准後執行真相鏈止血 | 100% | no-action approval 不再顯示批准 / 執行中;可執行修復 approval 會寫入 `auto_repair_executions`、KM 與 verifier;下一步補 MCP evidence / PlayBook trust 產生真正修復候選 | 目標 pytest `125 passed`、py_compile、guard、production health、API / worker rollout、production pod classifier readback | | P0-8 | Telegram no-action 人工處置包與操作入口 | 100% | no-action 卡片已新增人工處置包、證據補齊清單、AwoooP 修復候選建立步驟、verifier / KM / PlayBook 回寫提醒,並改成 `處置包`、`重診`、`歷史`、`靜默`、`真相鏈`、`Runs` 鍵盤;舊訊息不 retroactive 改寫 | 目標 pytest `64 passed + 44 passed`、py_compile、guard、production health、API / worker rollout、production pod render / keyboard smoke | | P0-9 | MCP evidence -> PlayBook 修復候選產生 | D5 `88%`;Approvals ledger `100%`;Runs ledger desktop `100%`;Alerts ledger desktop / mobile `100%` | 已補 webhook fallback 先建立 incident,再收 MCP evidence、查 approved PlayBook、檢查 trust / command safety、產生 medium approval candidate 與 verifier plan;D1 追加通用兜底 PlayBook / 診斷型命令不可誤當修復、阻擋理由繁中化;D2 在缺候選時產生 `repair_candidate_draft_package_v1`、`playbook_draft_required`、下一步與必填欄位;D3 新增 `awooop_repair_candidate_draft_work_item_v1` read-only projection 與 Telegram `工作項目` deeplink;D4 讓 AwoooP Work Items 詳細呈現 PlayBook 草案處置板、必填欄位、阻擋原因、下一步、Runs / 審批連結;D5 新增 `repair_candidate_coverage_gap_v1`,讓 blocked result 帶出 coverage key、target kind、blocking stage、必收 MCP evidence refs、PlayBook template fields 與 runtime 0 / false 邊界;Approvals / Runs / Alerts 已新增 `資產沉澱` 欄或焦點矩陣,可直接看到 KM / PlayBook / 腳本 / 排程 / Verifier 的完成與卡點;下一步要補 Runs mobile smoke,並把同一總帳接到正式 Telegram 告警卡、Observability 與 Tenants,用真實告警驗證 approval -> execution -> verifier -> KM / PlayBook 回寫 | Approvals code `dafe5342` 已隨 deploy marker `42c08ece` 正式站 desktop / mobile smoke;Runs code `11c2b5d4` 已隨 deploy marker `8b6ab87c` 正式站 desktop DOM smoke;Alerts code `10cd6167` 已隨 deploy marker `d36d764a` 正式站 desktop / mobile DOM smoke;P2-407 API production readback `overall_completion_percent=100`;status-chain 後續仍必須看到 tool call、PlayBook id、risk gate、repair candidate、verifier plan | diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 1831c1e1..9270ef82 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -231,6 +231,9 @@ def validate(root: Path) -> None: telegram_notification_egress_inventory = load_json( security_dir / "telegram-notification-egress-inventory.snapshot.json" ) + telegram_notification_egress_owner_request_draft = load_json( + security_dir / "telegram-notification-egress-owner-request-draft.snapshot.json" + ) public_runtime_config_change_evidence_acceptance = load_json( security_dir / "public-runtime-config-change-evidence-acceptance.snapshot.json" ) @@ -21630,6 +21633,146 @@ def validate(root: Path) -> None: f"telegram_notification_egress_inventory.{item['egress_surface_id']}.{false_key}", item[false_key], ) + assert_equal( + "telegram_notification_egress_owner_request_draft.schema", + telegram_notification_egress_owner_request_draft["schema_version"], + "telegram_notification_egress_owner_request_draft_v1", + ) + assert_equal( + "telegram_notification_egress_owner_request_draft.status", + telegram_notification_egress_owner_request_draft["status"], + "owner_request_draft_ready_no_dispatch_no_runtime_action", + ) + assert_equal( + "telegram_notification_egress_owner_request_draft.mode", + telegram_notification_egress_owner_request_draft["mode"], + "metadata_only_no_secret_value_no_telegram_send_no_workflow_change", + ) + expected_telegram_egress_owner_request_summary = { + "source_direct_bot_api_call_count": 18, + "source_direct_bot_api_file_count": 11, + "request_draft_count": 11, + "workflow_request_draft_count": 6, + "ops_script_request_draft_count": 4, + "ci_script_request_draft_count": 0, + "api_direct_request_draft_count": 1, + "request_field_count": 27, + "required_owner_field_count": 19, + "preflight_check_count": 16, + "outcome_lane_count": 9, + "forbidden_payload_count": 14, + "blocked_action_count": 26, + "request_sent_count": 0, + "recipient_confirmed_count": 0, + "audit_event_emitted_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "formatter_convergence_accepted_count": 0, + "redaction_contract_accepted_count": 0, + "delivery_receipt_accepted_count": 0, + "break_glass_fallback_accepted_count": 0, + "direct_bot_api_migration_authorized_count": 0, + "telegram_send_authorized_count": 0, + "bot_api_call_authorized_count": 0, + "workflow_modification_authorized_count": 0, + "script_modification_authorized_count": 0, + "api_sender_refactor_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "raw_payload_storage_allowed_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0, + } + for key, expected in expected_telegram_egress_owner_request_summary.items(): + assert_equal( + f"telegram_notification_egress_owner_request_draft.summary.{key}", + telegram_notification_egress_owner_request_draft["summary"][key], + expected, + ) + expected_telegram_egress_request_paths = [ + ".gitea/workflows/cd-dev.yaml", + ".gitea/workflows/cd.yaml", + ".gitea/workflows/code-review.yaml", + ".gitea/workflows/deploy-alerts.yaml", + ".gitea/workflows/e2e-health.yaml", + ".gitea/workflows/run-migration.yml", + "apps/api/src/services/channel_hub.py", + "scripts/ops/backup-from-110.sh", + "scripts/ops/docker-health-monitor.sh", + "scripts/ops/dr-drill.sh", + "scripts/ops/pg-backup.sh", + ] + assert_equal( + "telegram_notification_egress_owner_request_draft.source_paths", + [item["source_path"] for item in telegram_notification_egress_owner_request_draft["request_drafts"]], + expected_telegram_egress_request_paths, + ) + for key, value in telegram_notification_egress_owner_request_draft["execution_boundaries"].items(): + if key == "not_authorization": + assert_true(f"telegram_notification_egress_owner_request_draft.execution_boundaries.{key}", value) + else: + assert_false(f"telegram_notification_egress_owner_request_draft.execution_boundaries.{key}", value) + for item in telegram_notification_egress_owner_request_draft["request_drafts"]: + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.request_fields", + len(item["request_fields"]), + 27, + ) + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.required_owner_fields", + len(item["required_owner_fields"]), + 19, + ) + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.preflight_checks", + len(item["preflight_checks"]), + 16, + ) + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.outcome_lanes", + len(item["outcome_lanes"]), + 9, + ) + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.forbidden_payloads", + len(item["forbidden_payloads"]), + 14, + ) + assert_equal( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.blocked_actions", + len(item["blocked_actions"]), + 26, + ) + assert_true( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.not_authorization", + item["not_authorization"], + ) + for false_key in [ + "request_sent", + "recipient_confirmed", + "audit_event_emitted", + "owner_response_received", + "owner_response_accepted", + "formatter_convergence_accepted", + "redaction_contract_accepted", + "delivery_receipt_accepted", + "break_glass_fallback_accepted", + "direct_bot_api_migration_authorized", + "telegram_send_authorized", + "bot_api_call_authorized", + "workflow_modification_authorized", + "script_modification_authorized", + "api_sender_refactor_authorized", + "secret_value_collection_allowed", + "raw_payload_storage_allowed", + "production_write_authorized", + "runtime_gate", + "action_buttons_allowed", + ]: + assert_false( + f"telegram_notification_egress_owner_request_draft.{item['request_draft_id']}.{false_key}", + item[false_key], + ) assert_equal( "public_runtime_config_change_evidence_acceptance.schema", public_runtime_config_change_evidence_acceptance["schema_version"], diff --git a/scripts/security/telegram-notification-egress-owner-request-draft.py b/scripts/security/telegram-notification-egress-owner-request-draft.py new file mode 100644 index 00000000..77245afb --- /dev/null +++ b/scripts/security/telegram-notification-egress-owner-request-draft.py @@ -0,0 +1,339 @@ +#!/usr/bin/env python3 +"""Build owner request drafts for Telegram notification egress surfaces. + +The draft groups direct Bot API sendMessage call sites by file path. It creates +metadata-only handoff envelopes and never sends requests, calls Telegram, reads +secrets, or modifies workflows/scripts. +""" + +from __future__ import annotations + +import argparse +import json +import subprocess +import sys +from collections import defaultdict +from datetime import datetime, timedelta, timezone +from pathlib import Path +from typing import Any + + +TAIPEI = timezone(timedelta(hours=8)) + +SOURCE_SNAPSHOT = Path("docs/security/telegram-notification-egress-inventory.snapshot.json") + +REQUEST_FIELDS = [ + "request_draft_id", + "source_inventory_schema_version", + "source_path", + "surface_kind", + "direct_call_count", + "line_refs", + "line_hash_refs", + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", + "not_authorization", +] + +REQUIRED_OWNER_FIELDS = [ + "owner_role_or_team", + "routing_purpose", + "current_sender", + "target_chat_route", + "message_shape_contract", + "redaction_contract", + "formatter_convergence_decision", + "gateway_or_alertmanager_target", + "break_glass_fallback_decision", + "delivery_receipt_ref", + "dedup_or_fingerprint_plan", + "fallback_or_degraded_mode", + "migration_or_exception_reason", + "maintenance_window", + "rollback_owner", + "postcheck_evidence_ref", + "no_secret_value_attestation", + "no_raw_payload_attestation", + "no_false_green_attestation", +] + +PREFLIGHT_CHECKS = [ + "source_inventory_current", + "owner_role_present", + "route_purpose_present", + "message_shape_contract_present", + "redaction_contract_present", + "formatter_convergence_decision_present", + "break_glass_fallback_explicit", + "delivery_receipt_metadata_present", + "dedup_or_fingerprint_present", + "maintenance_window_present_for_change", + "rollback_owner_present", + "postcheck_evidence_present", + "no_secret_value_attested", + "no_raw_payload_attested", + "no_false_green_attested", + "runtime_gate_stays_zero", +] + +OUTCOME_LANES = [ + "draft_waiting_owner_dispatch", + "request_owner_route_supplement", + "request_formatter_convergence_supplement", + "request_break_glass_fallback_supplement", + "request_redaction_or_receipt_supplement", + "quarantine_secret_or_raw_payload", + "reject_false_green_claim", + "ready_for_manual_dispatch", + "waiting_runtime_gate", +] + +FORBIDDEN_PAYLOADS = [ + "bot_token_value", + "chat_secret_value", + "secret_hash", + "partial_token", + "masked_token", + "authorization_header", + "raw_message_payload", + "raw_workflow_log", + "raw_action_log", + "raw_screenshot_with_secret", + "internal_work_window_transcript", + "private_namespace", + "unredacted_internal_path", + "unredacted_private_ip", +] + +BLOCKED_ACTIONS = [ + "send_owner_request", + "confirm_recipient", + "emit_audit_event", + "telegram_send", + "bot_api_call", + "workflow_modification", + "script_modification", + "api_sender_refactor", + "change_chat_route", + "change_bot_token", + "read_secret_store", + "collect_secret_value", + "collect_secret_hash", + "collect_partial_token", + "collect_chat_id_secret", + "store_raw_message_payload", + "store_unredacted_log", + "workflow_dispatch", + "production_deploy", + "accept_cd_success_as_delivery_receipt", + "accept_route_200_as_notification_delivery", + "accept_ui_visible_as_notification_acceptance", + "skip_formatter_convergence", + "skip_redaction_contract", + "open_runtime_gate", + "add_action_button", +] + + +def git_short_sha(root: Path) -> str: + try: + result = subprocess.run( + ["git", "rev-parse", "--short", "HEAD"], + cwd=root, + check=True, + capture_output=True, + text=True, + ) + return result.stdout.strip() + except Exception: + return "unknown" + + +def load_json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + +def request_id_for(path: str) -> str: + safe = path.replace("/", "_").replace(".", "_").replace("-", "_") + return f"telegram_notification_egress_owner_request:{safe}" + + +def build_report(root: Path, generated_at: str | None = None) -> dict[str, Any]: + generated = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds") + source_path = root / SOURCE_SNAPSHOT + source = load_json(source_path) + grouped: dict[str, list[dict[str, Any]]] = defaultdict(list) + for item in source["direct_bot_api_calls"]: + grouped[item["path"]].append(item) + + request_drafts: list[dict[str, Any]] = [] + for path in sorted(grouped): + calls = sorted(grouped[path], key=lambda item: item["line"]) + surface_kind = calls[0]["surface_kind"] + request_drafts.append( + { + "request_draft_id": request_id_for(path), + "source_inventory_schema_version": source["schema_version"], + "source_path": path, + "surface_kind": surface_kind, + "direct_call_count": len(calls), + "line_refs": [item["line"] for item in calls], + "line_hash_refs": [item["line_hash"] for item in calls], + "request_fields": REQUEST_FIELDS, + "required_owner_fields": REQUIRED_OWNER_FIELDS, + "preflight_checks": PREFLIGHT_CHECKS, + "outcome_lanes": OUTCOME_LANES, + "forbidden_payloads": FORBIDDEN_PAYLOADS, + "blocked_actions": BLOCKED_ACTIONS, + "request_sent": False, + "recipient_confirmed": False, + "audit_event_emitted": False, + "owner_response_received": False, + "owner_response_accepted": False, + "formatter_convergence_accepted": False, + "redaction_contract_accepted": False, + "delivery_receipt_accepted": False, + "break_glass_fallback_accepted": False, + "direct_bot_api_migration_authorized": False, + "telegram_send_authorized": False, + "bot_api_call_authorized": False, + "workflow_modification_authorized": False, + "script_modification_authorized": False, + "api_sender_refactor_authorized": False, + "secret_value_collection_allowed": False, + "raw_payload_storage_allowed": False, + "production_write_authorized": False, + "runtime_gate": False, + "action_buttons_allowed": False, + "not_authorization": True, + } + ) + + workflow_drafts = [item for item in request_drafts if item["surface_kind"] == "gitea_workflow_direct_bot_api"] + ops_drafts = [item for item in request_drafts if item["surface_kind"] == "ops_script_direct_bot_api"] + ci_drafts = [item for item in request_drafts if item["surface_kind"] == "ci_script_direct_bot_api"] + api_drafts = [item for item in request_drafts if item["surface_kind"] == "api_direct_bot_api"] + + return { + "schema_version": "telegram_notification_egress_owner_request_draft_v1", + "generated_at": generated, + "git_commit": git_short_sha(root), + "status": "owner_request_draft_ready_no_dispatch_no_runtime_action", + "mode": "metadata_only_no_secret_value_no_telegram_send_no_workflow_change", + "source_snapshot": SOURCE_SNAPSHOT.as_posix(), + "source_schema_version": source["schema_version"], + "source_status": source["status"], + "summary": { + "source_direct_bot_api_call_count": source["summary"]["direct_bot_api_call_count"], + "source_direct_bot_api_file_count": source["summary"]["direct_bot_api_file_count"], + "request_draft_count": len(request_drafts), + "workflow_request_draft_count": len(workflow_drafts), + "ops_script_request_draft_count": len(ops_drafts), + "ci_script_request_draft_count": len(ci_drafts), + "api_direct_request_draft_count": len(api_drafts), + "request_field_count": len(REQUEST_FIELDS), + "required_owner_field_count": len(REQUIRED_OWNER_FIELDS), + "preflight_check_count": len(PREFLIGHT_CHECKS), + "outcome_lane_count": len(OUTCOME_LANES), + "forbidden_payload_count": len(FORBIDDEN_PAYLOADS), + "blocked_action_count": len(BLOCKED_ACTIONS), + "request_sent_count": 0, + "recipient_confirmed_count": 0, + "audit_event_emitted_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "formatter_convergence_accepted_count": 0, + "redaction_contract_accepted_count": 0, + "delivery_receipt_accepted_count": 0, + "break_glass_fallback_accepted_count": 0, + "direct_bot_api_migration_authorized_count": 0, + "telegram_send_authorized_count": 0, + "bot_api_call_authorized_count": 0, + "workflow_modification_authorized_count": 0, + "script_modification_authorized_count": 0, + "api_sender_refactor_authorized_count": 0, + "secret_value_collection_allowed_count": 0, + "raw_payload_storage_allowed_count": 0, + "production_write_authorized_count": 0, + "runtime_gate_count": 0, + "action_button_count": 0, + }, + "execution_boundaries": { + "runtime_execution_authorized": False, + "owner_request_send_authorized": False, + "recipient_confirmation_authorized": False, + "audit_event_emit_authorized": False, + "telegram_send_authorized": False, + "bot_api_call_authorized": False, + "workflow_modification_authorized": False, + "script_modification_authorized": False, + "api_sender_refactor_authorized": False, + "secret_value_collection_allowed": False, + "raw_payload_storage_allowed": False, + "production_write_authorized": False, + "action_buttons_allowed": False, + "not_authorization": True, + }, + "request_drafts": request_drafts, + "operator_interpretation": [ + "This is a draft packet for manual owner dispatch; request_sent_count remains 0.", + "Each file-level draft must decide whether the path converges to TelegramGateway, AWOOI Alertmanager, or a documented break-glass fallback.", + "No workflow, script, API, secret, Telegram, or production action is authorized by this snapshot.", + ], + } + + +def validate(root: Path) -> None: + report = build_report(root) + if report["summary"]["request_draft_count"] != report["summary"]["source_direct_bot_api_file_count"]: + raise SystemExit("BLOCKED telegram egress owner request draft: file/draft count mismatch") + if report["summary"]["runtime_gate_count"] != 0: + raise SystemExit("BLOCKED telegram egress owner request draft: runtime gate must stay 0") + + +def main() -> None: + parser = argparse.ArgumentParser(description="Build Telegram notification egress owner request draft") + parser.add_argument("--root", default=".", help="repository root") + parser.add_argument("--output", help="write JSON snapshot") + parser.add_argument("--generated-at", help="fixed generated_at timestamp") + args = parser.parse_args() + + root = Path(args.root).resolve() + report = build_report(root, args.generated_at) + payload = json.dumps(report, ensure_ascii=False, indent=2) + "\n" + if args.output: + Path(args.output).write_text(payload, encoding="utf-8") + else: + sys.stdout.write(payload) + + print( + "TELEGRAM_NOTIFICATION_EGRESS_OWNER_REQUEST_DRAFT_OK " + f"drafts={report['summary']['request_draft_count']} " + f"workflow={report['summary']['workflow_request_draft_count']} " + f"ops={report['summary']['ops_script_request_draft_count']} " + f"api={report['summary']['api_direct_request_draft_count']} " + f"sent={report['summary']['request_sent_count']} " + f"runtime_gate={report['summary']['runtime_gate_count']}", + file=sys.stderr, + ) + + +if __name__ == "__main__": + main()