From 5a679e411229fddb26e4aeb23c2158b616979968 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 21 May 2026 09:36:29 +0800 Subject: [PATCH] feat(web): show GitHub readiness in AwoooP approvals --- apps/web/messages/en.json | 40 +++++++ apps/web/messages/zh-TW.json | 40 +++++++ .../app/[locale]/awooop/approvals/page.tsx | 111 +++++++++++++++++- docs/LOGBOOK.md | 14 +++ .../security/SECURITY-MIRROR-STATUS-ROLLUP.md | 2 + .../SECURITY-SUPPLY-CHAIN-PROGRESS.md | 6 +- ...ecurity-mirror-status-rollup.snapshot.json | 31 ++++- .../security-mirror-progress-guard.py | 56 +++++++++ 8 files changed, 296 insertions(+), 4 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 5badb005a..97d9710b9 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -4043,6 +4043,46 @@ "detail": "Wait for redacted owner decisions on webhooks, runners, deploy keys, branch protection / CODEOWNERS, and secret name parity." } } + }, + "githubPrimaryReadinessGate": { + "title": "GitHub Primary Readiness Approval Boundary", + "subtitle": "The approval queue only displays the owner-response gaps that block GitHub primary readiness. This is not GitHub primary approval and does not create repos, mutate refs, collect secret values, or disable Gitea.", + "badge": "Read-only approval boundary", + "responseLanesTitle": "Owner response lanes", + "boundaryLabel": "GitHub Primary Boundary", + "boundaryTitle": "No primary switch is approvable here", + "boundaryDetail": "This panel only brings the S4.9-S4.12 intake order into the approvals surface. All responses remain received=0 / accepted=0, with no approval record, no GitHub primary switch, no Gitea primary change, and no runtime gate.", + "openIwooos": "Open IwoooS", + "metrics": { + "giteaOwner": "Gitea owner", + "giteaOwnerDetail": "The five S4.9 owner attestation items are still not received / accepted.", + "githubTargetOwner": "GitHub target owner", + "githubTargetOwnerDetail": "The seven S4.10 target owner / visibility / canonical responses are still not accepted.", + "refsTruth": "Refs truth", + "refsTruthDetail": "The five S4.11 refs truth owner responses are still not accepted.", + "workflowSecretNames": "Workflow / secret names", + "workflowSecretNamesDetail": "The five S4.12 workflow / secret-name owner responses are still not accepted.", + "primaryReady": "Primary ready", + "primaryReadyDetail": "Still 0; approvals visibility is not primary cutover approval." + }, + "responseLanes": { + "giteaOwnerAttestation": { + "title": "Gitea inventory owner attestation", + "detail": "First confirm public-only / local gap, org / user endpoint, 110 adjacent source, canonical owner, and legacy disposition." + }, + "githubTargetOwner": { + "title": "GitHub target owner decision", + "detail": "Then confirm owner, visibility, and canonical target for the seven in-scope targets without creating repos automatically." + }, + "refsTruthOwner": { + "title": "Refs truth owner response", + "detail": "Next confirm main / dev truth, deprecated drift, release tags, and GitHub-only refs without syncing, deleting, or force-pushing refs." + }, + "workflowSecretOwner": { + "title": "Workflow / secret-name owner response", + "detail": "Finally confirm workflow, runner, deploy key, branch protection, CODEOWNERS, and secret names. Collect names only, never values." + } + } } }, "workItems": { diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index c39813aa6..65559bbf0 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -4044,6 +4044,46 @@ "detail": "等待 owner 對 webhook、runner、deploy key、branch protection / CODEOWNERS、secret name parity 做脫敏判定。" } } + }, + "githubPrimaryReadinessGate": { + "title": "GitHub Primary Readiness 審批邊界", + "subtitle": "審批佇列只顯示 GitHub primary 前置 owner response 缺口;這不是 GitHub primary approval,也不會建立 repo、改 refs、收 secret value 或停用 Gitea。", + "badge": "只讀審批邊界", + "responseLanesTitle": "Owner response lanes", + "boundaryLabel": "GitHub primary 邊界", + "boundaryTitle": "目前沒有可批准的 primary switch", + "boundaryDetail": "這個面板只把 S4.9-S4.12 的收件順序放到 approvals 視野;所有 response 仍為 received=0 / accepted=0,不建立 approval record、不切 GitHub primary、不改 Gitea primary,也不觸發 runtime gate。", + "openIwooos": "開啟 IwoooS", + "metrics": { + "giteaOwner": "Gitea owner", + "giteaOwnerDetail": "S4.9 的 5 個 owner attestation items 仍未 received / accepted。", + "githubTargetOwner": "GitHub target owner", + "githubTargetOwnerDetail": "S4.10 的 7 個 target owner / visibility / canonical responses 仍未 accepted。", + "refsTruth": "Refs truth", + "refsTruthDetail": "S4.11 的 5 類 refs truth owner responses 仍未 accepted。", + "workflowSecretNames": "Workflow / secret names", + "workflowSecretNamesDetail": "S4.12 的 5 類 workflow / secret 名稱 owner responses 仍未 accepted。", + "primaryReady": "Primary ready", + "primaryReadyDetail": "仍為 0;approvals 可見不等於可切 primary。" + }, + "responseLanes": { + "giteaOwnerAttestation": { + "title": "Gitea inventory owner attestation", + "detail": "先確認 public-only / local gap、org / user endpoint、110 adjacent source、canonical owner 與 legacy disposition。" + }, + "githubTargetOwner": { + "title": "GitHub target owner decision", + "detail": "再確認 7 個 in-scope targets 的 owner、visibility 與 canonical target,不自動建立 repo。" + }, + "refsTruthOwner": { + "title": "Refs truth owner response", + "detail": "接著確認 main / dev truth、deprecated drift、release tags 與 GitHub-only refs,不 sync / delete / force push。" + }, + "workflowSecretOwner": { + "title": "Workflow / secret name owner response", + "detail": "最後確認 workflow、runner、deploy key、branch protection、CODEOWNERS 與 secret 名稱;只收名稱,不收 value。" + } + } } }, "workItems": { diff --git a/apps/web/src/app/[locale]/awooop/approvals/page.tsx b/apps/web/src/app/[locale]/awooop/approvals/page.tsx index 8868f5ed0..cc7102074 100644 --- a/apps/web/src/app/[locale]/awooop/approvals/page.tsx +++ b/apps/web/src/app/[locale]/awooop/approvals/page.tsx @@ -18,6 +18,7 @@ import { ListChecks, SearchCheck, TriangleAlert, + GitBranch, } from "lucide-react"; import { cn } from "@/lib/utils"; import { Link } from "@/i18n/routing"; @@ -366,7 +367,7 @@ function SecurityOwnerResponseGatePanel() {

{t("boundaryLabel")}

{t("boundaryTitle")}

{t("boundaryDetail")}

-
+
approval_record_created=false owner_response_accepted_count=0 runtime_execution_authorized=false @@ -385,6 +386,113 @@ function SecurityOwnerResponseGatePanel() { ); } +function GitHubPrimaryReadinessApprovalBoundaryPanel() { + const t = useTranslations("awooop.approvals.githubPrimaryReadinessGate"); + const metrics = [ + { + label: t("metrics.giteaOwner"), + value: "0/5", + detail: t("metrics.giteaOwnerDetail"), + }, + { + label: t("metrics.githubTargetOwner"), + value: "0/7", + detail: t("metrics.githubTargetOwnerDetail"), + }, + { + label: t("metrics.refsTruth"), + value: "0/5", + detail: t("metrics.refsTruthDetail"), + }, + { + label: t("metrics.workflowSecretNames"), + value: "0/5", + detail: t("metrics.workflowSecretNamesDetail"), + }, + { + label: t("metrics.primaryReady"), + value: "0", + detail: t("metrics.primaryReadyDetail"), + }, + ]; + const responseLanes = [ + { phase: "S4.9", key: "giteaOwnerAttestation" }, + { phase: "S4.10", key: "githubTargetOwner" }, + { phase: "S4.11", key: "refsTruthOwner" }, + { phase: "S4.12", key: "workflowSecretOwner" }, + ]; + + return ( +
+
+
+
+ + {t("badge")} + +
+
+ {metrics.map((item) => ( +
+

{item.label}

+

{item.value}

+

{item.detail}

+
+ ))} +
+
+
+
+ {t("responseLanesTitle")} +
+
+ {responseLanes.map((item) => ( +
+ {item.phase} +
+

+ {t(`responseLanes.${item.key}.title`)} +

+

+ {t(`responseLanes.${item.key}.detail`)} +

+
+
+ ))} +
+
+
+

{t("boundaryLabel")}

+

{t("boundaryTitle")}

+

{t("boundaryDetail")}

+
+ approval_record_created=false + github_primary_approval_granted=false + owner_response_accepted_count=0 + repo_creation_authorized=false + refs_mutation_authorized=false + secret_value_collection_allowed=false + runtime_execution_authorized=false + action_buttons_allowed=false +
+ + {t("openIwooos")} +
+
+
+ ); +} + // ============================================================================= // Main Component // ============================================================================= @@ -553,6 +661,7 @@ export default function ApprovalsPage() { +