diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index b91c9bfc..2ea8161c 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -5666,6 +5666,34 @@ } } }, + "s49RequestDraftPackage": { + "eyebrow": "S4.9 補件題目雷達", + "title": "五份負責人證明已整理成可交付草稿", + "subtitle": "此區只呈現要交給負責人確認的五個題目,將下一步拆成可掃描清單;目前仍未送出、未收件、未接受。", + "boundaryTitle": "草稿包邊界", + "items": { + "publicGap": { + "title": "公開庫與本地 Gitea 差異", + "body": "判定 wooo/clawbot-v5、wooo/wooo-aiops 是否納入這次清冊與遷移範圍。" + }, + "namespaceIdentity": { + "title": "wooo 命名空間身分", + "body": "確認 Gitea 內 wooo 應以 user、org 或雙軌盤點,避免 owner 判定漂移。" + }, + "adjacentScope": { + "title": "110 鄰近來源範圍", + "body": "逐項判定 bitan-pharmacy、momo-pro-system、tsenyang-website、wooo-infra-config 是否納入。" + }, + "canonicalOwner": { + "title": "正本來源與負責人", + "body": "為 in-scope repo 指定 owner、canonical source、GitHub target candidate 與 visibility reviewer。" + }, + "legacyDisposition": { + "title": "Legacy / 不可存取處置", + "body": "對 legacy、inaccessible 或 external repo 留下 disposition、理由與後續負責人。" + } + } + }, "immediateVisualMesh": { "eyebrow": "首屏資安網視覺模型", "title": "資安關聯視覺模型", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index b91c9bfc..2ea8161c 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -5666,6 +5666,34 @@ } } }, + "s49RequestDraftPackage": { + "eyebrow": "S4.9 補件題目雷達", + "title": "五份負責人證明已整理成可交付草稿", + "subtitle": "此區只呈現要交給負責人確認的五個題目,將下一步拆成可掃描清單;目前仍未送出、未收件、未接受。", + "boundaryTitle": "草稿包邊界", + "items": { + "publicGap": { + "title": "公開庫與本地 Gitea 差異", + "body": "判定 wooo/clawbot-v5、wooo/wooo-aiops 是否納入這次清冊與遷移範圍。" + }, + "namespaceIdentity": { + "title": "wooo 命名空間身分", + "body": "確認 Gitea 內 wooo 應以 user、org 或雙軌盤點,避免 owner 判定漂移。" + }, + "adjacentScope": { + "title": "110 鄰近來源範圍", + "body": "逐項判定 bitan-pharmacy、momo-pro-system、tsenyang-website、wooo-infra-config 是否納入。" + }, + "canonicalOwner": { + "title": "正本來源與負責人", + "body": "為 in-scope repo 指定 owner、canonical source、GitHub target candidate 與 visibility reviewer。" + }, + "legacyDisposition": { + "title": "Legacy / 不可存取處置", + "body": "對 legacy、inaccessible 或 external repo 留下 disposition、理由與後續負責人。" + } + } + }, "immediateVisualMesh": { "eyebrow": "首屏資安網視覺模型", "title": "資安關聯視覺模型", diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index e719b59d..dfdb76f8 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -63,6 +63,14 @@ type EvidenceUnlockQueueItem = { tone: 'steady' | 'warn' | 'locked' } +type S49RequestDraftPackageItem = { + key: string + template: string + status: string + icon: typeof ShieldCheck + tone: 'steady' | 'warn' | 'locked' +} + type FastProgressItem = { key: string value: string @@ -966,6 +974,27 @@ const evidenceUnlockQueueBoundaries = [ 'not_authorization=true', ] +const s49RequestDraftPackageItems: S49RequestDraftPackageItem[] = [ + { key: 'publicGap', template: 'D1', status: '草稿', icon: Radar, tone: 'warn' }, + { key: 'namespaceIdentity', template: 'D2', status: '草稿', icon: Network, tone: 'warn' }, + { key: 'adjacentScope', template: 'D3', status: '草稿', icon: Server, tone: 'warn' }, + { key: 'canonicalOwner', template: 'D4', status: '草稿', icon: GitBranch, tone: 'warn' }, + { key: 'legacyDisposition', template: 'D5', status: '草稿', icon: FileText, tone: 'warn' }, +] + +const s49RequestDraftPackageBoundaries = [ + 's4_9_owner_attestation_request_draft_frontstage_card_count=5', + 's4_9_owner_attestation_request_draft_template_ready_count=5', + 's4_9_owner_attestation_request_sent=false', + 's4_9_owner_attestation_owner_response_received_count=0', + 's4_9_owner_attestation_owner_response_accepted_count=0', + 's4_9_owner_attestation_runtime_gate_opened=false', + 'runtime_execution_authorized=false', + 'active_runtime_gate_count=0', + 'action_buttons_allowed=false', + 'not_authorization=true', +] + const fastProgressItems: FastProgressItem[] = [ { key: 'done', value: '7 頁', icon: CheckCircle2, tone: 'steady' }, { key: 'kali112', value: '只讀通過', icon: ShieldCheck, tone: 'warn' }, @@ -10392,6 +10421,125 @@ function IwoooSEvidenceUnlockQueueBoard() { ) } +function IwoooSS49RequestDraftPackageBoard() { + const t = useTranslations('iwooos.s49RequestDraftPackage') + const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const } + + return ( + + + + + + + {t('eyebrow')} + + {t('title')} + {t('subtitle')} + + + + {s49RequestDraftPackageItems.map(item => { + const Icon = item.icon + return ( + + + {item.template} + + + {item.status} + + {t(`items.${item.key}.title` as never)} + + + {t(`items.${item.key}.body` as never)} + + + ) + })} + + + + + + {t('boundaryTitle')} + + + {s49RequestDraftPackageBoundaries.map(item => ( + + {item} + + ))} + + + + + ) +} + function IwoooSImmediateVisualMeshBoard() { const t = useTranslations('iwooos.immediateVisualMesh') const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const } @@ -16871,6 +17019,7 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) { + diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index a03a617a..9ef5640f 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,54 @@ +## 2026-06-01|IwoooS S4.9 補件題目雷達落地 + +**背景**: + +- 前一階段已把 S4.9 Gitea 清冊負責人補件整理成五份可交付草稿,但前台只顯示「草稿 5」仍不夠具體。 +- 使用者需要在 IwoooS 第一層直接看懂卡在哪五個題目,而不是從大量文字或文件裡推理。 +- 本階段仍維持初期資安框架原則:只做可視化、read-only evidence 與人工 gate;不啟動 Kali 掃描、SSH 修復、主機更新、repo 變更或 runtime execution。 + +**本次調整**: + +- `apps/web/src/app/[locale]/iwooos/page.tsx`: + - 新增 `IwoooSS49RequestDraftPackageBoard`,把 S4.9 五個負責人補件題目提升成首層可掃描雷達。 + - 五張題目卡分別對應 D1 公開庫與本地 Gitea 差異、D2 wooo 命名空間身分、D3 110 鄰近來源範圍、D4 正本來源與負責人、D5 legacy / 不可存取處置。 + - 明確顯示 `request_sent=false`、`owner_response_received_count=0`、`owner_response_accepted_count=0`、`active_runtime_gate_count=0`、`action_buttons_allowed=false`。 +- `apps/web/messages/zh-TW.json` / `apps/web/messages/en.json`: + - 新增 `iwooos.s49RequestDraftPackage` 文案;英文語系維持繁中文案鏡像。 + - 文案定位為產品化資安工作台,不把對話內容或內部溝通語氣放進正式頁面。 +- `docs/security/iwooos-posture-projection.snapshot.json`: + - 新增 `s4_9_request_draft_package_*` summary 與五筆題目卡機器證據。 + - 鎖定 `draft_status=ready_not_sent`、`runtime_execution_authorized=false`、`not_authorization=true`。 +- `docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json`: + - 新增 `request_draft_template_ready_count=5`、`frontstage_package_visible=true`、`frontstage_card_count=5`。 +- `docs/security/security-mirror-status-rollup.snapshot.json`: + - 新增 S2.160 台帳,標記這是 framework detail,不是 headline percent 或 runtime delta。 +- `scripts/security/security-mirror-progress-guard.py`: + - 新增 S4.9 前台雷達 guard,防止五張題目卡被誤讀成已送出、已收到、已接受、已審批或已開執行期 gate。 + +**驗證**: + +- `python3 -m json.tool apps/web/messages/zh-TW.json` +- `python3 -m json.tool apps/web/messages/en.json` +- `cmp -s apps/web/messages/zh-TW.json apps/web/messages/en.json` +- `python3 -m json.tool docs/security/iwooos-posture-projection.snapshot.json` +- `python3 -m json.tool docs/security/security-mirror-status-rollup.snapshot.json` +- `python3 -m json.tool docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json` +- `git diff --check` +- `python3 scripts/security/source-control-owner-response-guard.py --root .` → `SOURCE_CONTROL_OWNER_RESPONSE_GUARD_OK` +- `python3 scripts/security/security-mirror-progress-guard.py --root .` → `SECURITY_MIRROR_PROGRESS_GUARD_OK` +- `pnpm --dir apps/web exec tsc --noEmit --tsBuildInfoFile /tmp/iwooos-s49-frontstage-radar-20260601.tsbuildinfo` +- `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 pnpm --dir apps/web run build` +- Browser / Playwright local visual verification: + - Desktop `1440x1100`:S4.9 雷達存在、五張題目卡存在、必要邊界字串存在、內部對話語氣不存在、horizontal overflow `0`。 + - Mobile `390x844`:S4.9 雷達存在、五張題目卡存在、必要邊界字串存在、內部對話語氣不存在、horizontal overflow `0`。 + +**目前整體進度(本階段完成後)**: + +- 完整 IwoooS / 資安網總進度:維持 `61%`;這次把卡點具體化為五張可掃描題目卡,不是假性提高總進度。 +- 框架 / 治理 / 文件 / schema / read-only evidence:約 `86-88%`;S4.9 草稿題目已能被前台、snapshot 與 guard 同步看見。 +- Runtime ingestion / GitHub primary / AwoooP production landing:約 `40-45%`;`request_sent_count=0`、`owner_response_received_count=0`、`owner_response_accepted_count=0`、`active_runtime_gate_count=0`。 +- Kali `192.168.0.112` 與開發主機 `192.168.0.111` / `192.168.0.168` 仍維持已納入框架、未啟動掃描 / 修復 / 更新 / 重啟的邊界。 + ## 2026-06-01|Docker 診斷型 PlayBook 自修復守門落地 **背景**: diff --git a/docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json b/docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json index 8ea8ba56..47c2385d 100644 --- a/docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json +++ b/docs/security/gitea-inventory-owner-attestation-request-draft.snapshot.json @@ -7,11 +7,14 @@ "runtime_execution_authorized": false, "source_packet": "docs/security/GITEA-INVENTORY-OWNER-ATTESTATION-RESPONSE.md", "source_snapshot": "docs/security/gitea-inventory-owner-attestation-response.snapshot.json", - "summary": { - "request_draft_package_ready": true, - "request_draft_template_count": 5, - "request_sent": false, - "request_sent_count": 0, + "summary": { + "request_draft_package_ready": true, + "request_draft_template_count": 5, + "request_draft_template_ready_count": 5, + "frontstage_package_visible": true, + "frontstage_card_count": 5, + "request_sent": false, + "request_sent_count": 0, "recipients_confirmed_count": 0, "owner_response_received_count": 0, "owner_response_accepted_count": 0, diff --git a/docs/security/iwooos-posture-projection.snapshot.json b/docs/security/iwooos-posture-projection.snapshot.json index 28f64084..ba6d8de1 100644 --- a/docs/security/iwooos-posture-projection.snapshot.json +++ b/docs/security/iwooos-posture-projection.snapshot.json @@ -63,6 +63,13 @@ "evidence_unlock_queue_accepted_count": 0, "evidence_unlock_queue_github_primary_ready_count": 0, "evidence_unlock_queue_runtime_gate_count": 0, + "s4_9_request_draft_package_first_layer": true, + "s4_9_request_draft_package_card_count": 5, + "s4_9_request_draft_package_template_ready_count": 5, + "s4_9_request_draft_package_request_sent_count": 0, + "s4_9_request_draft_package_owner_response_received_count": 0, + "s4_9_request_draft_package_owner_response_accepted_count": 0, + "s4_9_request_draft_package_runtime_gate_count": 0, "visual_command_dashboard_widget_count": 14, "visual_command_dashboard_first_layer": true, "visual_command_dashboard_default_visible": false, @@ -493,6 +500,83 @@ "not_authorization": true } ], + "s4_9_request_draft_package_items": [ + { + "item_id": "publicGap", + "display_order": 1, + "source_template_id": "response-public-only-vs-local-gitea-gap", + "template_label": "D1", + "display_mode": "first_screen_s4_9_request_draft_package", + "draft_status": "ready_not_sent", + "request_sent_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "runtime_gate_count": 0, + "runtime_execution_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "item_id": "namespaceIdentity", + "display_order": 2, + "source_template_id": "response-org-user-endpoint-identity", + "template_label": "D2", + "display_mode": "first_screen_s4_9_request_draft_package", + "draft_status": "ready_not_sent", + "request_sent_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "runtime_gate_count": 0, + "runtime_execution_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "item_id": "adjacentScope", + "display_order": 3, + "source_template_id": "response-internal-110-adjacent-scope", + "template_label": "D3", + "display_mode": "first_screen_s4_9_request_draft_package", + "draft_status": "ready_not_sent", + "request_sent_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "runtime_gate_count": 0, + "runtime_execution_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "item_id": "canonicalOwner", + "display_order": 4, + "source_template_id": "response-repo-owner-canonical-scope", + "template_label": "D4", + "display_mode": "first_screen_s4_9_request_draft_package", + "draft_status": "ready_not_sent", + "request_sent_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "runtime_gate_count": 0, + "runtime_execution_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + }, + { + "item_id": "legacyDisposition", + "display_order": 5, + "source_template_id": "response-legacy-or-inaccessible-disposition", + "template_label": "D5", + "display_mode": "first_screen_s4_9_request_draft_package", + "draft_status": "ready_not_sent", + "request_sent_count": 0, + "owner_response_received_count": 0, + "owner_response_accepted_count": 0, + "runtime_gate_count": 0, + "runtime_execution_authorized": false, + "action_buttons_allowed": false, + "not_authorization": true + } + ], "first_progress_unlock_path_steps": [ { "step_id": "owner_response_scope", diff --git a/docs/security/security-mirror-status-rollup.snapshot.json b/docs/security/security-mirror-status-rollup.snapshot.json index 728d8cb7..4bde37d0 100644 --- a/docs/security/security-mirror-status-rollup.snapshot.json +++ b/docs/security/security-mirror-status-rollup.snapshot.json @@ -2389,6 +2389,18 @@ "runtime_delta": false, "execution_authorized": false, "not_authorization": true + }, + { + "delta_id": "s2_160_iwooos_s49_request_draft_frontstage_radar", + "display_order": 189, + "completed_stage": "S2.160 IwoooS S4.9 補件題目雷達", + "progress_axis": "framework_detail", + "headline_percent_delta": 0, + "framework_delta_visible": true, + "why_headline_unchanged": "IwoooS 只把 S4.9 五個負責人補件題目提升成首層可掃描雷達,顯示 D1 公開庫與本地 Gitea 差異、D2 wooo 命名空間身分、D3 110 鄰近來源範圍、D4 正本來源與負責人、D5 legacy / 不可存取處置;s4_9_owner_attestation_request_draft_frontstage_card_count=5、s4_9_owner_attestation_request_draft_template_ready_count=5、s4_9_owner_attestation_request_sent=false、s4_9_owner_attestation_owner_response_received_count=0、s4_9_owner_attestation_owner_response_accepted_count=0、runtime_execution_authorized=false、active_runtime_gate_count=0、action_buttons_allowed=false,不把前台雷達當請求送出、負責人回覆收到、審查接受、審批紀錄、掃描、修復、部署、主機更新、GitHub primary 切換或 Gitea 停用。", + "runtime_delta": false, + "execution_authorized": false, + "not_authorization": true } ], "next_safe_actions": [ diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index a8fa3ba5..dc7ec640 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -749,6 +749,7 @@ def validate(root: Path) -> None: "s2_157_iwooos_progress_evidence_rail", "s2_158_iwooos_evidence_unlock_queue", "s2_159_iwooos_s49_request_draft_package", + "s2_160_iwooos_s49_request_draft_frontstage_radar", ] assert_equal( "progress_delta_ledger.delta_ids", @@ -1738,6 +1739,31 @@ def validate(root: Path) -> None: iwooos_projection["summary"]["evidence_unlock_queue_runtime_gate_count"], 0, ) + assert_true( + "iwooos_projection.summary.s4_9_request_draft_package_first_layer", + iwooos_projection["summary"]["s4_9_request_draft_package_first_layer"], + ) + assert_equal( + "iwooos_projection.summary.s4_9_request_draft_package_card_count", + iwooos_projection["summary"]["s4_9_request_draft_package_card_count"], + 5, + ) + assert_equal( + "iwooos_projection.summary.s4_9_request_draft_package_template_ready_count", + iwooos_projection["summary"]["s4_9_request_draft_package_template_ready_count"], + 5, + ) + for count_key in [ + "s4_9_request_draft_package_request_sent_count", + "s4_9_request_draft_package_owner_response_received_count", + "s4_9_request_draft_package_owner_response_accepted_count", + "s4_9_request_draft_package_runtime_gate_count", + ]: + assert_equal( + f"iwooos_projection.summary.{count_key}", + iwooos_projection["summary"][count_key], + 0, + ) assert_equal( "iwooos_projection.summary.all_product_coverage_snapshot_default_summary_mode", iwooos_projection["summary"]["all_product_coverage_snapshot_default_summary_mode"], @@ -3304,6 +3330,20 @@ def validate(root: Path) -> None: s49_request_draft["summary"]["request_draft_template_count"], len(expected_s4_9_owner_response_request_template_ids), ) + assert_equal( + "s49_request_draft.summary.request_draft_template_ready_count", + s49_request_draft["summary"]["request_draft_template_ready_count"], + len(expected_s4_9_owner_response_request_template_ids), + ) + assert_true( + "s49_request_draft.summary.frontstage_package_visible", + s49_request_draft["summary"]["frontstage_package_visible"], + ) + assert_equal( + "s49_request_draft.summary.frontstage_card_count", + s49_request_draft["summary"]["frontstage_card_count"], + len(expected_s4_9_owner_response_request_template_ids), + ) assert_false("s49_request_draft.summary.request_sent", s49_request_draft["summary"]["request_sent"]) assert_equal("s49_request_draft.summary.request_sent_count", s49_request_draft["summary"]["request_sent_count"], 0) assert_equal( @@ -12793,6 +12833,68 @@ def validate(root: Path) -> None: "iwooos_projection.evidence_unlock_queue_items.workflowSecrets.secret_plaintext_collection_allowed", workflow_secrets_queue_item["secret_plaintext_collection_allowed"], ) + expected_s4_9_request_draft_package_item_ids = [ + "publicGap", + "namespaceIdentity", + "adjacentScope", + "canonicalOwner", + "legacyDisposition", + ] + s4_9_request_draft_package_items = iwooos_projection["s4_9_request_draft_package_items"] + assert_equal( + "iwooos_projection.s4_9_request_draft_package_items.ids", + [item["item_id"] for item in s4_9_request_draft_package_items], + expected_s4_9_request_draft_package_item_ids, + ) + assert_equal( + "iwooos_projection.s4_9_request_draft_package_items.display_order", + [item["display_order"] for item in s4_9_request_draft_package_items], + list(range(1, len(expected_s4_9_request_draft_package_item_ids) + 1)), + ) + assert_equal( + "iwooos_projection.s4_9_request_draft_package_items.source_template_ids", + [item["source_template_id"] for item in s4_9_request_draft_package_items], + expected_s4_9_owner_response_request_template_ids, + ) + assert_equal( + "iwooos_projection.s4_9_request_draft_package_items.template_labels", + [item["template_label"] for item in s4_9_request_draft_package_items], + ["D1", "D2", "D3", "D4", "D5"], + ) + for item in s4_9_request_draft_package_items: + assert_equal( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.display_mode", + item["display_mode"], + "first_screen_s4_9_request_draft_package", + ) + assert_equal( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.draft_status", + item["draft_status"], + "ready_not_sent", + ) + for count_key in [ + "request_sent_count", + "owner_response_received_count", + "owner_response_accepted_count", + "runtime_gate_count", + ]: + assert_equal( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.{count_key}", + item[count_key], + 0, + ) + assert_false( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.runtime_execution_authorized", + item["runtime_execution_authorized"], + ) + assert_false( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.action_buttons_allowed", + item["action_buttons_allowed"], + ) + assert_true( + f"iwooos_projection.s4_9_request_draft_package_items.{item['item_id']}.not_authorization", + item["not_authorization"], + ) for text in [ 'data-testid="iwooos-first-screen-depth-map-board"', 'data-testid="iwooos-first-screen-depth-map-layers"', @@ -12924,6 +13026,53 @@ def validate(root: Path) -> None: iwooos_projection_page, text, ) + for text in [ + 'data-testid="iwooos-s49-request-draft-package-board"', + 'data-testid="iwooos-s49-request-draft-package-items"', + 'data-testid="iwooos-s49-request-draft-package-boundaries"', + "IwoooSS49RequestDraftPackageBoard", + "s49RequestDraftPackageItems", + "s49RequestDraftPackageBoundaries", + "publicGap", + "namespaceIdentity", + "adjacentScope", + "canonicalOwner", + "legacyDisposition", + ]: + assert_text_contains( + "iwooos_page.s49_request_draft_package", + iwooos_projection_page, + text, + ) + assert_text_before( + "iwooos_page.evidence_unlock_queue_before_s49_request_draft_package", + iwooos_projection_page, + "", + "", + ) + assert_text_before( + "iwooos_page.s49_request_draft_package_before_immediate_visual_mesh", + iwooos_projection_page, + "", + "", + ) + for text in [ + "s4_9_owner_attestation_request_draft_frontstage_card_count=5", + "s4_9_owner_attestation_request_draft_template_ready_count=5", + "s4_9_owner_attestation_request_sent=false", + "s4_9_owner_attestation_owner_response_received_count=0", + "s4_9_owner_attestation_owner_response_accepted_count=0", + "s4_9_owner_attestation_runtime_gate_opened=false", + "runtime_execution_authorized=false", + "active_runtime_gate_count=0", + "action_buttons_allowed=false", + "not_authorization=true", + ]: + assert_text_contains( + "iwooos_page.s49_request_draft_package_boundary", + iwooos_projection_page, + text, + ) assert_text_contains( "iwooos_page.focus_deck_testid", iwooos_projection_page,
{t('subtitle')}
+ {t(`items.${item.key}.body` as never)} +
+ {item} +