feat(web): show GitHub readiness in IwoooS
This commit is contained in:
@@ -2837,6 +2837,44 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceControlReadiness": {
|
||||
"title": "GitHub Primary Readiness",
|
||||
"subtitle": "The long-term Gitea-to-GitHub direction is shown as read-only readiness: candidate repos, owner responses, refs truth, workflow / secret names, and rollback ADR must all be present before primary_ready_count can be reviewed.",
|
||||
"gateLabel": "Readiness gate",
|
||||
"guardLabel": "Still forbidden",
|
||||
"items": {
|
||||
"candidateRepos": {
|
||||
"title": "Candidate repo inventory",
|
||||
"body": "8 candidate repos and 7 in-scope repos are visible for inventory and owner-evidence alignment only.",
|
||||
"guard": "No GitHub repo creation or visibility changes."
|
||||
},
|
||||
"primaryReady": {
|
||||
"title": "primary_ready_count remains 0",
|
||||
"body": "No repo has passed target, refs, workflow / secret name, and rollback readiness yet.",
|
||||
"guard": "No GitHub primary switch and no Gitea disablement."
|
||||
},
|
||||
"ownerResponses": {
|
||||
"title": "Owner responses are still waiting",
|
||||
"body": "S4.9-S4.12 include 22 templates; received=0 and accepted=0.",
|
||||
"guard": "Do not treat request-ready as response accepted."
|
||||
},
|
||||
"refsTruth": {
|
||||
"title": "Refs truth is not accepted",
|
||||
"body": "main / dev truth, release tags, and deprecated refs still need owner decisions.",
|
||||
"guard": "No refs push, delete, or force push."
|
||||
},
|
||||
"workflowSecrets": {
|
||||
"title": "Workflow / secret names are incomplete",
|
||||
"body": "Workflow, runner, webhook, and secret-name parity evidence is still missing for 7 in-scope repos.",
|
||||
"guard": "Collect names and owners only, never secret values."
|
||||
},
|
||||
"rollbackAdr": {
|
||||
"title": "Rollback ADR is not approved",
|
||||
"body": "Rollback owner, validation window, and trigger details still need human review for 7 in-scope repos.",
|
||||
"guard": "No cutover dry-run and no primary switch."
|
||||
}
|
||||
}
|
||||
},
|
||||
"awooopReadOnlyLandingReadiness": {
|
||||
"title": "AwoooP Read-Only Landing Readiness",
|
||||
"subtitle": "S2.51 turns the AwoooP main-line read-only consumption path for IwoooS / security mirror state into an intake readiness board. This is landing readiness, not production_landing_enabled, and it does not connect an execution router.",
|
||||
|
||||
@@ -2838,6 +2838,44 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceControlReadiness": {
|
||||
"title": "GitHub Primary Readiness",
|
||||
"subtitle": "把 Gitea 轉 GitHub 的長期方向拆成只讀 readiness:候選 repo、owner response、refs truth、workflow / secret 名稱與 rollback ADR 都要到齊,才會重估 primary_ready_count。",
|
||||
"gateLabel": "Readiness gate",
|
||||
"guardLabel": "仍禁止",
|
||||
"items": {
|
||||
"candidateRepos": {
|
||||
"title": "候選 repo 清冊",
|
||||
"body": "8 個 candidate repos、7 個 in-scope,目前只做清冊與 owner evidence 對齊。",
|
||||
"guard": "不建立 GitHub repo、不改 visibility。"
|
||||
},
|
||||
"primaryReady": {
|
||||
"title": "primary_ready_count 仍為 0",
|
||||
"body": "尚無 repo 通過 target、refs、workflow / secret 名稱與 rollback readiness。",
|
||||
"guard": "不切 GitHub primary、不停用 Gitea。"
|
||||
},
|
||||
"ownerResponses": {
|
||||
"title": "Owner response 仍等待",
|
||||
"body": "S4.9-S4.12 共 22 個 templates,目前 received=0、accepted=0。",
|
||||
"guard": "不把 request-ready 當 response accepted。"
|
||||
},
|
||||
"refsTruth": {
|
||||
"title": "Refs truth 尚未接受",
|
||||
"body": "main / dev truth、release tags、deprecated refs 仍需 owner 判定。",
|
||||
"guard": "不 push、delete、force push refs。"
|
||||
},
|
||||
"workflowSecrets": {
|
||||
"title": "Workflow / secret 名稱未完成",
|
||||
"body": "7 個 in-scope repos 的 workflow、runner、webhook、secret name parity 還缺 evidence。",
|
||||
"guard": "只收名稱與 owner,不收 secret value。"
|
||||
},
|
||||
"rollbackAdr": {
|
||||
"title": "Rollback ADR 未批准",
|
||||
"body": "7 個 in-scope repos 的 rollback owner、驗證窗口與 trigger 尚待人工審查。",
|
||||
"guard": "不 dry-run cutover、不切 primary。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"awooopReadOnlyLandingReadiness": {
|
||||
"title": "AwoooP 只讀 Landing Readiness",
|
||||
"subtitle": "S2.51 把 AwoooP 主線要如何只讀消費 IwoooS / security mirror 狀態整理成接入準備面板。這是 landing readiness,不是 production landing enabled,也不接 execution router。",
|
||||
|
||||
@@ -66,6 +66,14 @@ type OwnerResponseNextActionFocusItem = {
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
type SourceControlReadinessItem = {
|
||||
key: string
|
||||
gate: string
|
||||
value: string
|
||||
icon: typeof ShieldCheck
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
type S49OwnerResponsePreflightCheck = {
|
||||
key: string
|
||||
check: string
|
||||
@@ -406,6 +414,15 @@ const ownerResponseNextActionFocusItems: OwnerResponseNextActionFocusItem[] = [
|
||||
{ key: 'workflowSecretOwnerResponse', focus: 'S4.12', icon: Lock, tone: 'locked' },
|
||||
]
|
||||
|
||||
const sourceControlReadinessItems: SourceControlReadinessItem[] = [
|
||||
{ key: 'candidateRepos', gate: 'S4.0', value: '8 / 7', icon: GitBranch, tone: 'warn' },
|
||||
{ key: 'primaryReady', gate: 'S4.0', value: '0', icon: Lock, tone: 'locked' },
|
||||
{ key: 'ownerResponses', gate: 'S4.13', value: '0 / 22', icon: ClipboardCheck, tone: 'warn' },
|
||||
{ key: 'refsTruth', gate: 'S4.11', value: '0', icon: SearchCheck, tone: 'locked' },
|
||||
{ key: 'workflowSecrets', gate: 'S4.12', value: '0 / 7', icon: FileWarning, tone: 'warn' },
|
||||
{ key: 'rollbackAdr', gate: 'S4.4', value: '0', icon: FileText, tone: 'locked' },
|
||||
]
|
||||
|
||||
const s49OwnerResponsePreflightChecks: S49OwnerResponsePreflightCheck[] = [
|
||||
{ key: 'knownAttestationItem', check: 'P1', icon: SearchCheck, tone: 'warn' },
|
||||
{ key: 'requiredOwnerFields', check: 'P2', icon: ListChecks, tone: 'warn' },
|
||||
@@ -1075,6 +1092,38 @@ function OwnerResponseNextActionFocusCard({ item }: { item: OwnerResponseNextAct
|
||||
)
|
||||
}
|
||||
|
||||
function SourceControlReadinessCard({ item }: { item: SourceControlReadinessItem }) {
|
||||
const t = useTranslations('iwooos.sourceControlReadiness')
|
||||
const Icon = item.icon
|
||||
const textWrap = { overflowWrap: 'anywhere' as const, wordBreak: 'break-word' as const }
|
||||
return (
|
||||
<div style={{ ...band, minHeight: 184, padding: 16, ...textWrap }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
|
||||
<Icon size={18} color={toneColors[item.tone]} />
|
||||
<span style={{ fontSize: 11, color: '#87867f' }}>{t('gateLabel')}</span>
|
||||
</div>
|
||||
<span style={{ fontSize: 11, color: toneColors[item.tone] }}>{item.gate}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: 28, fontWeight: 700, color: '#141413', marginTop: 12, lineHeight: 1 }}>
|
||||
{item.value}
|
||||
</div>
|
||||
<h2 style={{ fontSize: 14, margin: '10px 0 6px', color: '#141413' }}>
|
||||
{t(`items.${item.key}.title` as never)}
|
||||
</h2>
|
||||
<p style={{ fontSize: 12, lineHeight: 1.55, color: '#6f6d66', margin: 0, ...textWrap }}>
|
||||
{t(`items.${item.key}.body` as never)}
|
||||
</p>
|
||||
<div style={{ marginTop: 10, display: 'grid', gap: 5 }}>
|
||||
<div style={{ fontSize: 11, color: '#87867f' }}>{t('guardLabel')}</div>
|
||||
<div style={{ fontSize: 11, color: toneColors[item.tone], lineHeight: 1.45, ...textWrap }}>
|
||||
{t(`items.${item.key}.guard` as never)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function S49OwnerResponsePreflightCard({ item }: { item: S49OwnerResponsePreflightCheck }) {
|
||||
const t = useTranslations('iwooos.s49OwnerResponsePreflight')
|
||||
const Icon = item.icon
|
||||
@@ -2400,6 +2449,26 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style={{ marginBottom: 14 }} data-testid="iwooos-source-control-readiness-board">
|
||||
<div style={{ marginBottom: 14 }}>
|
||||
<h2 style={{ fontSize: 16, margin: 0 }}>{t('sourceControlReadiness.title')}</h2>
|
||||
<p style={{ fontSize: 12, color: '#6f6d66', margin: '6px 0 0', lineHeight: 1.55 }}>
|
||||
{t('sourceControlReadiness.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
{sourceControlReadinessItems.map(item => (
|
||||
<SourceControlReadinessCard key={item.key} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style={{ marginBottom: 14 }}>
|
||||
<div style={{ marginBottom: 14 }}>
|
||||
<h2 style={{ fontSize: 16, margin: 0 }}>{t('awooopReadOnlyLandingReadiness.title')}</h2>
|
||||
|
||||
Reference in New Issue
Block a user