diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 7fad94e13..8cd7f8b33 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -2753,6 +2753,39 @@ "guard": "Faster cadence does not loosen safety; runtime and source-control cutover still need human gates." } } + }, + "ownerResponseNextActionFocus": { + "title": "Owner Response Next-Action Focus", + "subtitle": "S2.47 makes the owner-response work that can actually move the 58% headline explicit: collect S4.9 Gitea owner attestation first, then GitHub targets, refs truth, and workflow / secret names. This is display-only: no chasing, autofill, or received marking.", + "focusLabel": "Next focus", + "nextLabel": "Evidence to inspect", + "guardLabel": "Still forbidden", + "items": { + "giteaOwnerAttestation": { + "title": "Collect S4.9 Gitea owner attestation first", + "body": "Confirm Gitea coverage, public-only / local gaps, org/user endpoint, 110 adjacent source, canonical owner, and legacy disposition.", + "next": "Owner must answer the 5 redacted evidence refs in GITEA-INVENTORY-OWNER-ATTESTATION-RESPONSE.", + "guard": "received=0; accepted=0; no token value storage, Gitea writes, refs sync, or primary switch." + }, + "githubTargetOwnerDecision": { + "title": "Handle S4.10 GitHub target decisions next", + "body": "Confirm each GitHub target owner, visibility, canonical disposition, and not_found_or_private handling.", + "next": "After S4.9 is accepted, collect the 7 target responses from GITHUB-TARGET-OWNER-DECISION-RESPONSE.", + "guard": "No GitHub repo creation, visibility change, refs sync, or target response as primary approval." + }, + "refsTruthOwnerResponse": { + "title": "Resolve S4.11 refs truth after that", + "body": "Clarify main/dev truth, deprecated drift, release tags, and GitHub-only refs so migration does not treat stale refs as truth.", + "next": "Repo owners must decide the 141 ref review items per repo / per ref.", + "guard": "No fetch, push, refs deletion, force push, or history rewrite." + }, + "workflowSecretOwnerResponse": { + "title": "Complete S4.12 workflow / secret names last", + "body": "Fill webhook, runner, deploy key, branch protection / CODEOWNERS, and repository secret name parity gaps.", + "next": "Collect names, owners, and redacted parity evidence only so GitHub readiness has verifiable gaps.", + "guard": "No secret value collection, workflow mutation, runner enablement, or write token use." + } + } } }, "tickets": { diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index a07023d71..3077eb554 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -2754,6 +2754,39 @@ "guard": "節奏加快不等於放寬安全;runtime 與 source-control cutover 仍需人工 gate。" } } + }, + "ownerResponseNextActionFocus": { + "title": "Owner Response 下一步收件焦點", + "subtitle": "S2.47 將下一個真正能推動 58% 的 owner response 工作排清楚:先收 S4.9 Gitea owner attestation,再依序處理 GitHub target、refs truth、workflow / secret name。這裡只顯示收件焦點,不催收、不代填、不標記 received。", + "focusLabel": "下一步焦點", + "nextLabel": "要看的 evidence", + "guardLabel": "仍禁止", + "items": { + "giteaOwnerAttestation": { + "title": "S4.9 Gitea owner attestation 先收", + "body": "先確認 Gitea 覆蓋範圍、public-only / local gap、org/user endpoint、110 adjacent source、canonical owner 與 legacy disposition。", + "next": "需要 owner 依 GITEA-INVENTORY-OWNER-ATTESTATION-RESPONSE 回覆 5 個脫敏 evidence refs。", + "guard": "received=0;accepted=0;不保存 token value、不寫 Gitea、不 sync refs、不切 primary。" + }, + "githubTargetOwnerDecision": { + "title": "S4.10 GitHub target 決策接續", + "body": "確認每個 GitHub target 的 owner、visibility、canonical disposition 與 not_found_or_private 處理方式。", + "next": "S4.9 通過後,才依 GITHUB-TARGET-OWNER-DECISION-RESPONSE 收 7 個 target responses。", + "guard": "不建立 GitHub repo、不改 visibility、不同步 refs、不把 target response 當 primary approval。" + }, + "refsTruthOwnerResponse": { + "title": "S4.11 Refs truth 再判定", + "body": "釐清 main/dev truth、deprecated drift、release tag 與 GitHub-only refs,避免 migration 時把舊 refs 誤當真相。", + "next": "需要 repo owner 對 141 個 ref review items 做單 repo / 單 ref 判定。", + "guard": "不 fetch、不 push、不 delete refs、不 force push、不 rewrite history。" + }, + "workflowSecretOwnerResponse": { + "title": "S4.12 Workflow / secret 名稱最後補齊", + "body": "補 webhook、runner、deploy key、branch protection / CODEOWNERS、repository secret name parity。", + "next": "只收名稱、owner 與脫敏 parity evidence,讓 GitHub readiness 有可驗證缺口表。", + "guard": "不收 secret value、不改 workflow、不啟用 runner、不使用 write token。" + } + } } }, "tickets": { diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index 579d301ac..ccb7bf857 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -38,6 +38,13 @@ type ProgressAccelerationLane = { tone: 'steady' | 'warn' | 'locked' } +type OwnerResponseNextActionFocusItem = { + key: string + focus: string + icon: typeof ShieldCheck + tone: 'steady' | 'warn' | 'locked' +} + type Pillar = { key: string icon: typeof ShieldCheck @@ -323,6 +330,13 @@ const progressAccelerationLanes: ProgressAccelerationLane[] = [ { key: 'cadenceCompression', lane: 'PAL6', icon: CheckCircle2, tone: 'steady' }, ] +const ownerResponseNextActionFocusItems: OwnerResponseNextActionFocusItem[] = [ + { key: 'giteaOwnerAttestation', focus: 'S4.9', icon: ClipboardCheck, tone: 'warn' }, + { key: 'githubTargetOwnerDecision', focus: 'S4.10', icon: GitBranch, tone: 'warn' }, + { key: 'refsTruthOwnerResponse', focus: 'S4.11', icon: SearchCheck, tone: 'warn' }, + { key: 'workflowSecretOwnerResponse', focus: 'S4.12', icon: Lock, tone: 'locked' }, +] + const posturePillars: Pillar[] = [ { key: 'exposure', icon: Radar, tone: 'warn' }, { key: 'sourceControl', icon: GitBranch, tone: 'warn' }, @@ -832,6 +846,38 @@ function ProgressAccelerationLaneCard({ item }: { item: ProgressAccelerationLane ) } +function OwnerResponseNextActionFocusCard({ item }: { item: OwnerResponseNextActionFocusItem }) { + const t = useTranslations('iwooos.ownerResponseNextActionFocus') + const Icon = item.icon + return ( +
+ {t(`items.${item.key}.body` as never)} +
+{t(`groups.${item.key}.body` as never)}
-+ {t('ownerResponseNextActionFocus.subtitle')} +
+