docs(security): mark next owner response candidate

This commit is contained in:
Your Name
2026-05-18 09:42:54 +08:00
parent 94bb6f5f07
commit 68e0cd7b2e
14 changed files with 189 additions and 9 deletions

View File

@@ -1,3 +1,18 @@
## 2026-05-18 | 資安供應鏈 S4.13Next Collection Candidate
**背景**S4.13 已有 4 條 missing response lanes 與 4 步 collection order本輪補上單一 `next_collection_candidate`,讓 AwoooP 只顯示下一包建議收件,而不是把整串順序誤讀成 approval queue 或 execution queue。
**完成**
- `source_control_owner_response_validation_rollup_v1` schema 新增 optional `next_collection_candidate`
- `source-control-owner-response-validation-rollup.snapshot.json` 標示目前下一個建議收件為 S4.9 Gitea owner attestation response需要 5 個 Gitea coverage attestation itemsreceived / accepted 仍為 0。
- `source-control-owner-response-guard.py` 反查 `next_collection_candidate` 必須等於 collection order 第 1 步,且 `execution_authorized=false``not_approval=true`
- 更新 S4.13 人讀文件、AwoooP checklist、status rollup、readiness、manifest、progress 與 handoff。
**仍禁止**
- 不把 next collection candidate 當成 approval、runtime gate、repo / refs / workflow / secret / runner 執行授權或 GitHub primary approval。
- 不提前接受 S4.10 / S4.11 / S4.12 response。
- 不收 token value、secret value、private key、cookie、session 或未脫敏 payload。
## 2026-05-18 | 資安供應鏈 S4.13Owner Response Collection Order
**背景**S4.13 已能顯示 4 條 missing response lanes本輪補上建議收件順序讓 AwoooP 可以把下一個 owner response 工作排清楚,但仍不把收件順序變成 approval queue 或 execution queue。

View File

@@ -286,6 +286,53 @@
},
"minItems": 1
},
"next_collection_candidate": {
"type": "object",
"description": "AwoooP 可顯示的單一下一步 owner response 收件項目;此欄位只提示 reviewer 下一包 response不是 approval queue 或 execution queue。",
"required": [
"order",
"lane_id",
"display_status",
"source_contract",
"required_packet",
"required_response_template_count",
"received_response_count",
"accepted_response_count",
"minimum_response",
"awooop_display_mode",
"why_next",
"blocked_until_received",
"execution_authorized",
"not_approval",
"still_forbidden"
],
"properties": {
"order": {"type": "integer", "minimum": 1},
"lane_id": {"type": "string"},
"display_status": {"type": "string", "enum": ["next_owner_response_required"]},
"source_contract": {"type": "string"},
"required_packet": {"type": "string"},
"required_response_template_count": {"type": "integer", "minimum": 0},
"received_response_count": {"type": "integer", "minimum": 0},
"accepted_response_count": {"type": "integer", "minimum": 0},
"minimum_response": {
"type": "array",
"items": {"type": "string"},
"minItems": 1
},
"awooop_display_mode": {"type": "string", "enum": ["display_next_collection_item_only"]},
"why_next": {"type": "string"},
"blocked_until_received": {"type": "boolean", "const": true},
"execution_authorized": {"type": "boolean", "const": false},
"not_approval": {"type": "boolean", "const": true},
"still_forbidden": {
"type": "array",
"items": {"type": "string"},
"minItems": 1
}
},
"additionalProperties": false
},
"allowed_outputs": {
"type": "array",
"items": {"type": "string"},

View File

@@ -42,7 +42,7 @@ AwoooP 初期不得直接啟動掃描、不得呼叫 Codex patch runner、不得
| `security_mirror_quarantine_v1` | AwoooP 鏡像隔離契約 | Operator Console、Audit | mirror-only | 只隔離驗收失敗 payload、顯示 recovery request 與 retry gate不作 runtime blocker |
| `security_mirror_dry_run_v1` | AwoooP 鏡像 dry-run 報告契約 | Operator Console、Audit | mirror-only | 只回報接入演練結果,且必須包含 progress guard、owner response guard 與 latest local validation不得轉成 production ingestion |
| `security_mirror_status_rollup_v1` | AwoooP 鏡像狀態彙整契約 | Operator Console、Runtime State、Audit | mirror-only | 只顯示階段狀態、58% 進度估算、下一個 gate 與禁止事項;不得視為 runtime authorization |
| `source_control_owner_response_validation_rollup_v1` | S4.9 / S4.10 / S4.11 / S4.12 owner response validation rollup | Operator Console、Source-control review、Audit | mirror-only | 只顯示四包 response packets、22 個 templates、missing response lanes、owner response collection order、10 個 cross-packet checks、quarantine rules 與 latest local validation不得視為 approval 或 runtime gate |
| `source_control_owner_response_validation_rollup_v1` | S4.9 / S4.10 / S4.11 / S4.12 owner response validation rollup | Operator Console、Source-control review、Audit | mirror-only | 只顯示四包 response packets、22 個 templates、missing response lanes、owner response collection order、next collection candidate、10 個 cross-packet checks、quarantine rules 與 latest local validation不得視為 approval 或 runtime gate |
| `coding_task_v1` | Code Review / Codex Security / manual review | Approval candidate、Channel Event、Audit | suggest-only | 不自動開 patch runner、不自動 merge |
| `source_control_migration_event_v1` | Gitea/GitHub branch/tag/SHA diff | Supply-chain evidence、Approval candidate | mirror-only | 不觸發 deploy、不切換 primary |
| `gitea_repo_inventory_v1` | Gitea org/user repo list 或管理匯出 | Supply-chain evidence、migration matrix | mirror-only | 顯示 public-only evidence、S4.5 authenticated/admin export request、S4.6 redacted import acceptance、S4.7 owner coverage attestation 與 S4.9 owner response 收件包;不保存 token value、不刪除或停用 Gitea repo |

View File

@@ -56,6 +56,8 @@ AwoooP 顯示 S4.13 時,應把 `missing_response_lanes` 當成 Operator Consol
建議顯示 `owner_response_collection_order` 作為下一步收件順序:先 S4.9 Gitea scope / canonical owner再 S4.10 GitHub target owner / visibility / canonical再 S4.11 refs truth最後 S4.12 workflow / secret name parity。這只是 review 順序,不是 approval queue 或 execution queue。
可同步顯示 `next_collection_candidate`,目前只指向 S4.9 Gitea owner attestation response需要 5 個 Gitea coverage attestation items、received / accepted 皆為 0、顯示模式為 `display_next_collection_item_only`。這個欄位只提示下一包 response不是 approval也不代表 S4.10 / S4.11 / S4.12 可被提前接受。
## 1. Session 分工
### AwoooP 主線 Session

View File

@@ -32,7 +32,7 @@
| GitHub primary rollback ADR | S4.4 已建立7 個 in-scope rollback drafts、0 個 owner approved、0 個 dry-run completed、0 個 active cutover |
| Gitea inventory | S4.5 已補認證清冊匯出請求S4.6 已補匯入驗收契約S4.7 已補 owner coverage attestationS4.8 已把既有 Gitea queue/gate/review packet/follow-up gate 對齊 attestation 先行S4.9 已補 owner response 收件包;目前 status=`partial_waiting_authenticated_inventory`、未認證公開範圍 repos 2 個、本機可見 Gitea unique repos 4 個、匯出來源選項 2 類、匯入驗收 payload 0 筆、owner attestation items 5 個、收到 attestation 0 筆、owner response 0 筆、敏感 payload 必須隔離、允許收集 token value=false |
| Workflow / secret name inventory | S4.1 已建立S4.2 補 4 個 repos、31 個 workflow files、43 個 referenced secret names 的 local evidenceS4.3 補 7 個 repos、5 類 lanes 的 redacted export requestS4.12 補 5 個 owner response templates0 個 inventory complete、禁止收集 secret value、禁止 write token |
| Owner response validation | S4.13 已建立;四包 owner response 目前 received/accepted 皆為 04 條 missing response lanes4 步 collection order 可供 AwoooP 直接顯示latest local validation 為 `SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK`,不代表 owner response 已收到或任何執行授權 |
| Owner response validation | S4.13 已建立;四包 owner response 目前 received/accepted 皆為 04 條 missing response lanes4 步 collection order 與 next collection candidate 可供 AwoooP 直接顯示;下一個建議收件為 S4.9 Gitea owner attestationlatest local validation 為 `SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK`,不代表 owner response 已收到或任何執行授權 |
| Dry-run | `contract_defined_not_executed`;已納入 `CHECK_PROGRESS_GUARD``CHECK_OWNER_RESPONSE_GUARD`latest local validation 為 `repo_snapshot_guard_pass`,仍不代表 production ingestion |
| Runtime actions | `false` |
| Payload ingestion | `false` |

View File

@@ -36,7 +36,7 @@
| `security_mirror_acceptance_v1` | mirror-only | AwoooP 只讀鏡像接入驗收 checks | `security-mirror-acceptance.snapshot.json` |
| `security_mirror_quarantine_v1` | mirror-only | AwoooP 鏡像驗收失敗隔離與 retry gate | `security-mirror-quarantine.snapshot.json` |
| `security_mirror_dry_run_v1` | mirror-only | AwoooP 鏡像接入演練回報格式 | `security-mirror-dry-run.snapshot.json` |
| `security_mirror_status_rollup_v1` | mirror-only | AwoooP / Security Supply Chain 跨 Session 狀態總覽S4.13 owner response validation rollup | `security-mirror-status-rollup.snapshot.json` / `source-control-owner-response-validation-rollup.snapshot.json` |
| `security_mirror_status_rollup_v1` | mirror-only | AwoooP / Security Supply Chain 跨 Session 狀態總覽S4.13 owner response validation rollup 與 next collection candidate | `security-mirror-status-rollup.snapshot.json` / `source-control-owner-response-validation-rollup.snapshot.json` |
| `coding_task_v1` | suggest-only | Code Review 接 Codex patch-only | 無正式 snapshot |
| `source_control_migration_event_v1` | mirror-only | Gitea/GitHub refs 差異 | `gitea-github-awoooi``clawbot-v5``wooo-aiops` |
| `gitea_repo_inventory_v1` | mirror-only | Gitea repo inventoryS4.5 已補認證清冊匯出請求S4.6 已補匯入驗收契約S4.7 已補 owner coverage attestationS4.9 已補 owner response 收件包 | public-only / blocked endpoint / S4.5 export request / S4.6 import acceptance / S4.7 coverage attestation / S4.9 response snapshots |

View File

@@ -59,7 +59,7 @@ python3 scripts/security/security-mirror-progress-guard.py
| S4.2 Workflow / Secret 名稱 local evidence | 完成草案 | 已建立 local read-only collector 與 snapshot7 個 local repos visible、4 個 local evidence repos、31 個 workflow files、43 個 referenced secret names、secret value detected=false | 補 webhook / deploy key / branch protection / repository secret parity 的 redacted evidence仍不可切 primary |
| S4.3 Workflow / Secret 名稱 redacted export request | 完成草案 | 已建立 export request schema / snapshot / 人讀版7 個 in-scope repos、5 類 export laneswebhook、runner、deploy key、branch protection / CODEOWNERS、repository secret name paritywrite token allowed=false | repo owner 或未來只讀 API 依 request 補 redacted export仍不可收 secret value、不可修改 GitHub/Gitea |
| S4.12 Workflow / Secret Name Owner Response 收件包 | 完成草案 | 已建立 owner response schema / snapshot / 人讀版5 個 response templates、8 個 acceptance checks、10 個 rejection rules、candidate repos 8、in-scope repos 7、received response 0、accepted 0、execution authorized=false | owner 依模板回覆 webhook、runner、deploy key、branch protection / CODEOWNERS、repository secret name parityresponse 通過只更新 read-only inventory / export request / readiness wording不代表收 secret value、改 workflow、啟用 runner 或 primary approval |
| S4.13 Source Control Owner Response Validation Rollup | 完成草案 | 已建立 validation rollup schema / snapshot / 人讀版;彙整 S4.9 / S4.10 / S4.11 / S4.12 四包 response packets、4 條 missing response lanes、4 步 owner response collection order、22 個 response templates、10 個 cross-packet checks、40 個 rejection rules、received / accepted / rejected response 皆為 0、execution authorized=falselatest local validation 為 `SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK` | AwoooP 可顯示四包 owner response 驗收總覽、缺口摘要、建議收件順序與 quarantine rulesrollup 不代表 approval、runtime gate、repo / refs / workflow / secret / runner 執行授權或 primary approval |
| S4.13 Source Control Owner Response Validation Rollup | 完成草案 | 已建立 validation rollup schema / snapshot / 人讀版;彙整 S4.9 / S4.10 / S4.11 / S4.12 四包 response packets、4 條 missing response lanes、4 步 owner response collection order、next collection candidate、22 個 response templates、10 個 cross-packet checks、40 個 rejection rules、received / accepted / rejected response 皆為 0、execution authorized=falselatest local validation 為 `SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK` | AwoooP 可顯示四包 owner response 驗收總覽、缺口摘要、建議收件順序、下一個建議收件項目與 quarantine rulesrollup 不代表 approval、runtime gate、repo / refs / workflow / secret / runner 執行授權或 primary approval |
| S4.4 GitHub Primary rollback ADR | 完成草案 | 已建立 rollback ADR schema / snapshot / 人讀版7 個 in-scope rollback drafts、0 owner approved、0 dry-run completed、0 active cutover | repo owner 審查 rollback owner、validation window 與 triggers仍不可切 primary 或執行 rollback |
| S4.5 Gitea 認證清冊匯出請求 | 完成草案 | 已建立匯出請求 schema / snapshot / 人讀版;目前未認證公開範圍 repo 2 個、本機可見 Gitea unique repo 4 個、覆蓋缺口 2 個、匯出來源選項 2 類;允許收集 token value=false | repo owner 依只讀 token API 或已脫敏管理匯出補私有 / 內部全量 repo list仍不可保存 token、不可 write Gitea、不可 refs sync |
| S4.6 Gitea 認證清冊匯入驗收契約 | 完成草案 | 已建立匯入驗收 schema / snapshot / 人讀版;目前 received payload 0、accepted 0、rejected 0定義 10 個驗收檢查、10 個拒收規則與 4 個 quarantine lanes | owner 提供脫敏 payload 後先驗收 / 拒收 / 隔離;仍不可把驗收當 primary approval |

View File

@@ -80,6 +80,18 @@ S4.13 不新增第 36 個主 contract不新增 approval item不啟用 runt
這個順序只讓 AwoooP 顯示下一個建議收件項目,不是 approval queue、不是 execution queue也不授權任何 repo、refs、workflow、secret、runner 或 primary 動作。
## 2.3 下一個建議收件項目
| 欄位 | 內容 |
|------|------|
| 下一步 | S4.9 Gitea owner attestation response |
| 需要回覆 | 5 個 Gitea coverage attestation items |
| 顯示模式 | `display_next_collection_item_only` |
| 目前 received / accepted | `0 / 0` |
| 仍禁止 | 不收 token value、不寫 Gitea、不 sync refs、不切 GitHub primary |
`next_collection_candidate` 只讓 AwoooP Operator Console 顯示「現在先收 S4.9」。它不是批准、不是執行排程,也不是後續 S4.10 / S4.11 / S4.12 已可接受的訊號。
## 3. Cross-Packet 驗收規則
1. 四個 source response packets 都必須可解析,且 summary 欄位存在。

View File

@@ -203,7 +203,7 @@
"docs/security/SECURITY-MIRROR-STATUS-ROLLUP.md",
"docs/security/SOURCE-CONTROL-OWNER-RESPONSE-VALIDATION-ROLLUP.md"
],
"notes": "提供 AwoooP / Security Supply Chain 跨 Session 狀態總覽、下一個 gate 與禁止事項S4.13 owner response validation rollup 可 mirror 四個 response packets、22 個 templates、received=0、accepted=0不授權執行。"
"notes": "提供 AwoooP / Security Supply Chain 跨 Session 狀態總覽、下一個 gate 與禁止事項S4.13 owner response validation rollup 可 mirror 四個 response packets、22 個 templates、received=0、accepted=0、next_collection_candidate=S4.9;不授權執行。"
},
{
"contract": "coding_task_v1",

View File

@@ -143,8 +143,8 @@
{
"phase_id": "S4_migration_execution",
"state": "not_started",
"current_result": "GitHub primary 是長期方向source_control_primary_readiness_gate_v1 已定義 8 個 candidate repos、7 個 in-scope blocked repos、0 個 primary readyS4.1 已定義 workflow / secret 名稱 inventory 契約S4.2 已補 local evidenceS4.3 已補 redacted export requestS4.4 已補 rollback ADR 草案S4.5 已補 Gitea authenticated inventory export requestS4.6 已補 redacted import acceptanceS4.7 已補 owner coverage attestation requestS4.9 已補 Gitea owner response intake packetS4.10 已補 GitHub target owner decision response intake packetS4.11 已補 refs truth owner response intake packetS4.12 已補 workflow / secret 名稱 owner response intake packetS4.13 已補四包 owner response validation rollup彙整 22 個 templates、received=0、accepted=0但 inventory status 仍 partialGitHub target / refs truth / workflow-secret response 仍 0 筆。",
"next_gate": "依 S4.13 先集中檢查四包 owner response validation 狀態,再依 S4.9 收到並驗收 S4.7 Gitea owner response、依 S4.10 收到並驗收 7 個 GitHub target owner / visibility / canonical response、依 S4.11 收到並驗收 5 個 refs truth owner response templates、依 S4.12 收到並驗收 5 個 workflow / secret 名稱 owner response templates、authenticated inventory payload 通過 S4.6 驗收、rollback ADR owner approval 與逐 repo 人工批准。"
"current_result": "GitHub primary 是長期方向source_control_primary_readiness_gate_v1 已定義 8 個 candidate repos、7 個 in-scope blocked repos、0 個 primary readyS4.1 已定義 workflow / secret 名稱 inventory 契約S4.2 已補 local evidenceS4.3 已補 redacted export requestS4.4 已補 rollback ADR 草案S4.5 已補 Gitea authenticated inventory export requestS4.6 已補 redacted import acceptanceS4.7 已補 owner coverage attestation requestS4.9 已補 Gitea owner response intake packetS4.10 已補 GitHub target owner decision response intake packetS4.11 已補 refs truth owner response intake packetS4.12 已補 workflow / secret 名稱 owner response intake packetS4.13 已補四包 owner response validation rollup彙整 22 個 templates、received=0、accepted=0並標示 next_collection_candidate=S4.9但 inventory status 仍 partialGitHub target / refs truth / workflow-secret response 仍 0 筆。",
"next_gate": "依 S4.13 先集中檢查四包 owner response validation 狀態,AwoooP 只顯示 next_collection_candidate=S4.9 Gitea owner attestation再依 S4.9 收到並驗收 S4.7 Gitea owner response、依 S4.10 收到並驗收 7 個 GitHub target owner / visibility / canonical response、依 S4.11 收到並驗收 5 個 refs truth owner response templates、依 S4.12 收到並驗收 5 個 workflow / secret 名稱 owner response templates、authenticated inventory payload 通過 S4.6 驗收、rollback ADR owner approval 與逐 repo 人工批准。"
}
],
"next_safe_actions": [
@@ -401,7 +401,7 @@
"S4.10 只新增 GitHub target owner decision response 收件包response_template_count=7、received_response_count=0、accepted_response_count=0不把 response packet 當 repo creation、visibility change、refs sync 或 GitHub primary approval。",
"S4.11 只新增 refs truth owner response 收件包response_template_count=5、received_response_count=0、accepted_response_count=0不把 response packet 當 refs sync、delete、force push 或 GitHub primary approval。",
"S4.12 只新增 workflow / secret 名稱 owner response 收件包response_template_count=5、received_response_count=0、accepted_response_count=0不把 response packet 當 secret value collection、workflow modification、GitHub hosted runner enablement 或 GitHub primary approval。",
"S4.13 只新增 owner response validation rollupresponse_packet_count=4、template_count=22、received_response_count=0、accepted_response_count=0、cross_packet_check_count=10不把 rollup 當 approval、runtime gate 或 execution authorization。"
"S4.13 只新增 owner response validation rollupresponse_packet_count=4、template_count=22、received_response_count=0、accepted_response_count=0、cross_packet_check_count=10、next_collection_candidate=S4.9,不把 rollup 當 approval、runtime gate 或 execution authorization。"
],
"forbidden_actions": [
"start_kali_scan",

View File

@@ -346,7 +346,7 @@
"sync_refs",
"store_secret_value"
],
"notes": "定義 AwoooP 與 Security Supply Chain Session 的共同狀態摘要S4.13 已補 owner response validation rollup彙整 S4.9/S4.10/S4.11/S4.12 共 22 個 response templates、received=0、accepted=0只顯示階段、下一個 gate 與禁止事項,不授權執行。"
"notes": "定義 AwoooP 與 Security Supply Chain Session 的共同狀態摘要S4.13 已補 owner response validation rollup彙整 S4.9/S4.10/S4.11/S4.12 共 22 個 response templates、received=0、accepted=0、next_collection_candidate=S4.9;只顯示階段、下一個 gate 與禁止事項,不授權執行。"
},
{
"contract": "coding_task_v1",

View File

@@ -305,6 +305,7 @@
"mirror_owner_response_validation_rollup",
"display_cross_packet_counts",
"display_missing_owner_response_lanes",
"display_next_collection_candidate",
"route_invalid_response_to_quarantine",
"update_read_only_readiness_wording_after_accepted_response"
],
@@ -466,6 +467,34 @@
]
}
],
"next_collection_candidate": {
"order": 1,
"lane_id": "s4_9_gitea_inventory_owner_attestation_response",
"display_status": "next_owner_response_required",
"source_contract": "gitea_inventory_owner_attestation_response_v1",
"required_packet": "docs/security/GITEA-INVENTORY-OWNER-ATTESTATION-RESPONSE.md",
"required_response_template_count": 5,
"received_response_count": 0,
"accepted_response_count": 0,
"minimum_response": [
"public-only/local gap disposition",
"org/user endpoint disposition",
"110 adjacent source scope",
"canonical owner",
"legacy/inaccessible disposition"
],
"awooop_display_mode": "display_next_collection_item_only",
"why_next": "S4.9 是後續 GitHub target、refs truth 與 workflow / secret parity 判定的前置 scope / canonical owner 來源;未收到前不得推進後續 source-control owner response 接受狀態。",
"blocked_until_received": true,
"execution_authorized": false,
"not_approval": true,
"still_forbidden": [
"store_token_value",
"write_gitea_repo",
"sync_refs",
"switch_github_primary"
]
},
"latest_local_validation": {
"status": "repo_snapshot_guard_pass",
"date": "2026-05-18",

View File

@@ -87,6 +87,34 @@ def validate(root: Path) -> None:
assert_false("owner_rollup.github_primary_switch_authorized", owner_summary["github_primary_switch_authorized"])
assert_false("owner_rollup.action_buttons_allowed", owner_summary["action_buttons_allowed"])
next_candidate = owner_rollup["next_collection_candidate"]
assert_equal("owner_rollup.next_collection_candidate.order", next_candidate["order"], 1)
assert_equal(
"owner_rollup.next_collection_candidate.lane_id",
next_candidate["lane_id"],
"s4_9_gitea_inventory_owner_attestation_response",
)
assert_equal(
"owner_rollup.next_collection_candidate.display_status",
next_candidate["display_status"],
"next_owner_response_required",
)
assert_equal(
"owner_rollup.next_collection_candidate.required_response_template_count",
next_candidate["required_response_template_count"],
5,
)
assert_equal("owner_rollup.next_collection_candidate.received_response_count", next_candidate["received_response_count"], 0)
assert_equal("owner_rollup.next_collection_candidate.accepted_response_count", next_candidate["accepted_response_count"], 0)
assert_equal(
"owner_rollup.next_collection_candidate.awooop_display_mode",
next_candidate["awooop_display_mode"],
"display_next_collection_item_only",
)
assert_true("owner_rollup.next_collection_candidate.blocked_until_received", next_candidate["blocked_until_received"])
assert_false("owner_rollup.next_collection_candidate.execution_authorized", next_candidate["execution_authorized"])
assert_true("owner_rollup.next_collection_candidate.not_approval", next_candidate["not_approval"])
owner_local_validation = owner_rollup["latest_local_validation"]
assert_equal("owner_rollup.latest_local_validation.status", owner_local_validation["status"], "repo_snapshot_guard_pass")
assert_equal("owner_rollup.latest_local_validation.scope", owner_local_validation["scope"], "repo_snapshot_only")

View File

@@ -136,6 +136,7 @@ def validate(root: Path) -> None:
lane_by_id = {lane["lane_id"]: lane for lane in rollup["validation_lanes"]}
missing_lane_by_id = {lane["lane_id"]: lane for lane in rollup["missing_response_lanes"]}
collection_order_by_id = {item["lane_id"]: item for item in rollup["owner_response_collection_order"]}
next_collection_candidate = rollup["next_collection_candidate"]
total_templates = 0
total_acceptance_checks = 0
total_rejection_rules = 0
@@ -195,6 +196,52 @@ def validate(root: Path) -> None:
assert_equal("missing_response_lanes.count", len(missing_lane_by_id), len(LANES))
assert_equal("owner_response_collection_order.count", len(collection_order_by_id), len(LANES))
first_lane = LANES[0]
first_collection_item = collection_order_by_id[first_lane["lane_id"]]
first_missing_lane = missing_lane_by_id[first_lane["lane_id"]]
assert_equal("next_collection_candidate.order", next_collection_candidate["order"], 1)
assert_equal("next_collection_candidate.lane_id", next_collection_candidate["lane_id"], first_lane["lane_id"])
assert_equal(
"next_collection_candidate.display_status",
next_collection_candidate["display_status"],
"next_owner_response_required",
)
assert_equal(
"next_collection_candidate.source_contract",
next_collection_candidate["source_contract"],
first_missing_lane["source_contract"],
)
assert_equal(
"next_collection_candidate.required_packet",
next_collection_candidate["required_packet"],
first_collection_item["required_packet"],
)
assert_equal(
"next_collection_candidate.required_response_template_count",
next_collection_candidate["required_response_template_count"],
first_lane["expected_templates"],
)
assert_equal("next_collection_candidate.received_response_count", next_collection_candidate["received_response_count"], 0)
assert_equal("next_collection_candidate.accepted_response_count", next_collection_candidate["accepted_response_count"], 0)
assert_equal(
"next_collection_candidate.minimum_response",
next_collection_candidate["minimum_response"],
first_collection_item["minimum_response"],
)
assert_equal(
"next_collection_candidate.awooop_display_mode",
next_collection_candidate["awooop_display_mode"],
"display_next_collection_item_only",
)
assert_true("next_collection_candidate.blocked_until_received", next_collection_candidate["blocked_until_received"])
assert_false("next_collection_candidate.execution_authorized", next_collection_candidate["execution_authorized"])
assert_true("next_collection_candidate.not_approval", next_collection_candidate["not_approval"])
assert_equal(
"next_collection_candidate.still_forbidden",
next_collection_candidate["still_forbidden"],
first_collection_item["still_forbidden"],
)
local_validation = rollup["latest_local_validation"]
assert_equal("rollup.latest_local_validation.status", local_validation["status"], "repo_snapshot_guard_pass")
assert_equal("rollup.latest_local_validation.scope", local_validation["scope"], "repo_snapshot_only")