fix(web): surface IwoooS S4.9 draft radar
All checks were successful
CD Pipeline / tests (push) Successful in 1m19s
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / build-and-deploy (push) Successful in 4m26s
CD Pipeline / post-deploy-checks (push) Successful in 3m15s

This commit is contained in:
Your Name
2026-06-01 20:17:18 +08:00
parent 6b38f7b44a
commit fa29f856b0
8 changed files with 509 additions and 5 deletions

View File

@@ -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": "資安關聯視覺模型",

View File

@@ -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": "資安關聯視覺模型",

View File

@@ -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 (
<section
data-testid="iwooos-s49-request-draft-package-board"
style={{ marginBottom: 14, maxWidth: '100%', overflow: 'hidden' }}
>
<div style={{ ...band, padding: 14, background: '#fffdf8', borderColor: '#ead9bf' }}>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 260px), 1fr))',
gap: 10,
}}
>
<div
style={{
border: '0.5px solid #ead9bf',
borderRadius: 8,
background: '#fff',
padding: 13,
minWidth: 0,
display: 'grid',
alignContent: 'center',
alignSelf: 'start',
gap: 8,
}}
>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, color: '#8a4f1c', fontSize: 12, fontWeight: 800 }}>
<ClipboardCheck size={16} color="#b65f1b" />
{t('eyebrow')}
</div>
<h2 style={{ margin: 0, fontSize: 18, lineHeight: 1.25, color: '#141413', ...textWrap }}>{t('title')}</h2>
<p style={{ margin: 0, fontSize: 12, lineHeight: 1.55, color: '#6f4f32', ...textWrap }}>{t('subtitle')}</p>
</div>
<div
data-testid="iwooos-s49-request-draft-package-items"
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 150px), 1fr))',
gap: 8,
minWidth: 0,
}}
>
{s49RequestDraftPackageItems.map(item => {
const Icon = item.icon
return (
<div
key={item.key}
data-testid={`iwooos-s49-request-draft-package-item-${item.key}`}
style={{
border: '0.5px solid #e8c9ad',
borderRadius: 8,
background: '#fff',
padding: 10,
minHeight: 128,
display: 'grid',
gap: 7,
minWidth: 0,
}}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
<span style={{ color: toneColors[item.tone], fontSize: 11, fontWeight: 800 }}>{item.template}</span>
<Icon size={15} color={toneColors[item.tone]} />
</div>
<div style={{ fontSize: 16, lineHeight: 1, fontWeight: 800, color: toneColors[item.tone] }}>{item.status}</div>
<h3 style={{ margin: 0, fontSize: 12.5, lineHeight: 1.25, color: '#141413', ...textWrap }}>
{t(`items.${item.key}.title` as never)}
</h3>
<p style={{ margin: 0, fontSize: 10.6, lineHeight: 1.45, color: '#6f6d66', ...textWrap }}>
{t(`items.${item.key}.body` as never)}
</p>
</div>
)
})}
</div>
</div>
<details
data-testid="iwooos-s49-request-draft-package-boundaries"
style={{
marginTop: 10,
border: '0.5px solid #ead9bf',
borderRadius: 8,
background: '#fff',
padding: '7px 10px',
}}
>
<summary style={{ cursor: 'pointer', fontSize: 12, fontWeight: 700, color: '#6f4f32' }}>
{t('boundaryTitle')}
</summary>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 6, marginTop: 9 }}>
{s49RequestDraftPackageBoundaries.map(item => (
<code
key={item}
style={{
border: '0.5px solid #f1e5d6',
borderRadius: 8,
padding: '6px 8px',
color: '#6f4f32',
fontSize: 11,
lineHeight: 1.4,
background: '#fffdf8',
overflowWrap: 'anywhere',
}}
>
{item}
</code>
))}
</div>
</details>
</div>
</section>
)
}
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 } }) {
<IwoooSFirstScreenDepthMapBoard />
<IwoooSProgressEvidenceRailBoard />
<IwoooSEvidenceUnlockQueueBoard />
<IwoooSS49RequestDraftPackageBoard />
<IwoooSImmediateVisualMeshBoard />
<IwoooSTopologyAtlasBoard />

View File

@@ -1,3 +1,54 @@
## 2026-06-01IwoooS 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-01Docker 診斷型 PlayBook 自修復守門落地
**背景**

View File

@@ -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,

View File

@@ -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",

View File

@@ -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": [

View File

@@ -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,
"<IwoooSEvidenceUnlockQueueBoard />",
"<IwoooSS49RequestDraftPackageBoard />",
)
assert_text_before(
"iwooos_page.s49_request_draft_package_before_immediate_visual_mesh",
iwooos_projection_page,
"<IwoooSS49RequestDraftPackageBoard />",
"<IwoooSImmediateVisualMeshBoard />",
)
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,