feat(web): add IwoooS coverage matrix
This commit is contained in:
@@ -1135,6 +1135,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"coverage": {
|
||||
"title": "Coverage and Boundary Matrix",
|
||||
"subtitle": "Groups the 10 existing security surfaces into four responsibility planes so IwoooS can show where to read signals, human control, governance audit, and engineering review.",
|
||||
"groups": {
|
||||
"signals": {
|
||||
"title": "Signals and Exposure",
|
||||
"body": "Collects security, compliance, alert, error, and UX audit signals; observations stay visible without becoming blockers."
|
||||
},
|
||||
"humanControl": {
|
||||
"title": "Human Control Boundary",
|
||||
"body": "Keeps HITL, multi-sig, and AwoooP approvals visible; runtime gates still require human decisions."
|
||||
},
|
||||
"governanceAudit": {
|
||||
"title": "Governance and Audit",
|
||||
"body": "Governance events, SLOs, remediation queues, and operation logs are evidence surfaces, not execution authorization."
|
||||
},
|
||||
"engineeringReview": {
|
||||
"title": "Engineering Review",
|
||||
"body": "Code Review remains a non-blocking review pipeline for risk grading and coding follow-up, not deploy approval."
|
||||
}
|
||||
},
|
||||
"conflicts": {
|
||||
"title": "Overlap and Conflict Controls",
|
||||
"subtitle": "The same security signal can appear on multiple pages. IwoooS only organizes entrypoints and does not change ownership or authority.",
|
||||
"preserveOwnership": {
|
||||
"title": "Preserve Route Ownership",
|
||||
"body": "Each route remains owned by its original page and API contract; IwoooS does not move write authority."
|
||||
},
|
||||
"noRuntimeLift": {
|
||||
"title": "No Runtime Lift",
|
||||
"body": "The coverage matrix can show coverage and gaps, but cannot create scan, execute, repair, or blocking gates."
|
||||
},
|
||||
"codeReviewNotDeployGate": {
|
||||
"title": "Code Review Is Not Deploy Approval",
|
||||
"body": "AI Code Review can grade risk and propose coding follow-up, but cannot become deploy approval by itself."
|
||||
},
|
||||
"awooopNotSecurityApproval": {
|
||||
"title": "AwoooP Approval Is Not Security Approval",
|
||||
"body": "The AwoooP approval queue can show human gate state, but security gates still require decision records and follow-up runtime gates."
|
||||
},
|
||||
"kaliNotCalled": {
|
||||
"title": "Frontend Index Does Not Call Kali",
|
||||
"body": "Kali 112 remains observe-only; active scan or /execute must go through human approval and follow-up gates."
|
||||
}
|
||||
}
|
||||
},
|
||||
"nextGate": {
|
||||
"title": "Next High-level Gate",
|
||||
"body": "S4.9 Gitea owner attestation response is the recommended next owner evidence. Headline progress should only increase after owner responses, redacted payload ingestion, active runtime gates, or GitHub primary readiness actually change."
|
||||
|
||||
@@ -1136,6 +1136,52 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"coverage": {
|
||||
"title": "覆蓋與邊界矩陣",
|
||||
"subtitle": "把 10 個既有資安頁面分成四個責任面,讓 IwoooS 能說清楚哪裡看訊號、哪裡做人工控制、哪裡看治理稽核、哪裡看工程審查。",
|
||||
"groups": {
|
||||
"signals": {
|
||||
"title": "訊號與暴露面",
|
||||
"body": "集中安全、合規、告警、錯誤與 UX 稽核訊號;只顯示風險,不把觀察結果直接升成阻擋。"
|
||||
},
|
||||
"humanControl": {
|
||||
"title": "人工控制邊界",
|
||||
"body": "保留 HITL、multi-sig 與 AwoooP approvals 的人控位置;沒有人工決策就不啟動 runtime gate。"
|
||||
},
|
||||
"governanceAudit": {
|
||||
"title": "治理與稽核",
|
||||
"body": "治理事件、SLO、補救佇列與操作日誌用來看流程證據,不把 audit event 當執行授權。"
|
||||
},
|
||||
"engineeringReview": {
|
||||
"title": "工程審查",
|
||||
"body": "Code Review 維持 non-blocking review pipeline,用於風險分級與後續修復建議,不直接等同 deploy approval。"
|
||||
}
|
||||
},
|
||||
"conflicts": {
|
||||
"title": "重疊與衝突控制",
|
||||
"subtitle": "同一個資安訊號可能在多個頁面出現,IwoooS 只做入口整理,不改變原始頁面的責任與權限。",
|
||||
"preserveOwnership": {
|
||||
"title": "保留原頁 owner",
|
||||
"body": "每個 route 繼續由原本頁面與 API contract 負責,IwoooS 不搬移資料寫入權。"
|
||||
},
|
||||
"noRuntimeLift": {
|
||||
"title": "不把只讀索引升成 runtime",
|
||||
"body": "coverage matrix 只能顯示覆蓋與缺口,不建立 scan、execute、repair 或 blocking gate。"
|
||||
},
|
||||
"codeReviewNotDeployGate": {
|
||||
"title": "Code Review 不等於部署批准",
|
||||
"body": "AI Code Review 可以提供風險分級與 coding follow-up,但不能直接變成 deploy approval。"
|
||||
},
|
||||
"awooopNotSecurityApproval": {
|
||||
"title": "AwoooP approvals 不等於資安批准",
|
||||
"body": "AwoooP 審批佇列可顯示人控狀態,但資安 gate 仍需對應決策紀錄與 follow-up runtime gate。"
|
||||
},
|
||||
"kaliNotCalled": {
|
||||
"title": "前端索引不呼叫 Kali",
|
||||
"body": "Kali 112 維持 observe-only;任何 active scan 或 /execute 都必須走人工批准與後續 gate。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nextGate": {
|
||||
"title": "下一個高層 Gate",
|
||||
"body": "S4.9 Gitea owner attestation response 是目前建議先收的 owner evidence。任何 headline 提升都要等 owner response、redacted payload ingestion、active runtime gate 或 GitHub primary readiness 有真實變化。"
|
||||
|
||||
@@ -48,6 +48,19 @@ type SecuritySurface = {
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
type CoverageGroup = {
|
||||
key: string
|
||||
count: string
|
||||
icon: typeof ShieldCheck
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
surfaces: string
|
||||
}
|
||||
|
||||
type ConflictControl = {
|
||||
key: string
|
||||
tone: 'steady' | 'warn' | 'locked'
|
||||
}
|
||||
|
||||
const postureMetrics: PostureMetric[] = [
|
||||
{ key: 'overall', value: '58%', tone: 'warn' },
|
||||
{ key: 'framework', value: '80-85%', tone: 'steady' },
|
||||
@@ -86,6 +99,45 @@ const existingSecuritySurfaces: SecuritySurface[] = [
|
||||
{ key: 'codeReview', href: '/code-review', icon: SearchCheck, tone: 'warn' },
|
||||
]
|
||||
|
||||
const coverageGroups: CoverageGroup[] = [
|
||||
{
|
||||
key: 'signals',
|
||||
count: '5',
|
||||
icon: Radar,
|
||||
tone: 'warn',
|
||||
surfaces: '/security-compliance, /security, /compliance, /alerts, /errors',
|
||||
},
|
||||
{
|
||||
key: 'humanControl',
|
||||
count: '2',
|
||||
icon: Lock,
|
||||
tone: 'locked',
|
||||
surfaces: '/authorizations, /awooop/approvals',
|
||||
},
|
||||
{
|
||||
key: 'governanceAudit',
|
||||
count: '2',
|
||||
icon: ListChecks,
|
||||
tone: 'steady',
|
||||
surfaces: '/governance, /alert-operation-logs',
|
||||
},
|
||||
{
|
||||
key: 'engineeringReview',
|
||||
count: '1',
|
||||
icon: SearchCheck,
|
||||
tone: 'warn',
|
||||
surfaces: '/code-review',
|
||||
},
|
||||
]
|
||||
|
||||
const conflictControls: ConflictControl[] = [
|
||||
{ key: 'preserveOwnership', tone: 'steady' },
|
||||
{ key: 'noRuntimeLift', tone: 'locked' },
|
||||
{ key: 'codeReviewNotDeployGate', tone: 'warn' },
|
||||
{ key: 'awooopNotSecurityApproval', tone: 'locked' },
|
||||
{ key: 'kaliNotCalled', tone: 'locked' },
|
||||
]
|
||||
|
||||
const evidenceItems = [
|
||||
'iwooos-posture-projection.snapshot.json',
|
||||
'security-rollout-policy.snapshot.json',
|
||||
@@ -239,6 +291,48 @@ function SurfaceCard({ item, locale }: { item: SecuritySurface; locale: string }
|
||||
)
|
||||
}
|
||||
|
||||
function CoverageCard({ item }: { item: CoverageGroup }) {
|
||||
const t = useTranslations('iwooos.coverage')
|
||||
const Icon = item.icon
|
||||
return (
|
||||
<div style={{ ...band, minHeight: 154, padding: 16 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12 }}>
|
||||
<Icon size={18} color={toneColors[item.tone]} />
|
||||
<span style={{ fontSize: 24, fontWeight: 700, color: toneColors[item.tone] }}>{item.count}</span>
|
||||
</div>
|
||||
<h2 style={{ fontSize: 14, margin: '12px 0 6px', color: '#141413' }}>{t(`groups.${item.key}.title` as never)}</h2>
|
||||
<p style={{ fontSize: 12, lineHeight: 1.55, color: '#6f6d66', margin: 0 }}>
|
||||
{t(`groups.${item.key}.body` as never)}
|
||||
</p>
|
||||
<div style={{ fontSize: 11, color: '#87867f', marginTop: 10, lineHeight: 1.45 }}>{item.surfaces}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ConflictRow({ item, index }: { item: ConflictControl; index: number }) {
|
||||
const t = useTranslations('iwooos.coverage.conflicts')
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '34px minmax(0, 1fr)',
|
||||
gap: 10,
|
||||
alignItems: 'start',
|
||||
padding: '10px 0',
|
||||
borderBottom: index === conflictControls.length - 1 ? 'none' : '0.5px solid #eee9dd',
|
||||
}}
|
||||
>
|
||||
<ToneDot tone={item.tone} />
|
||||
<div>
|
||||
<div style={{ fontSize: 13, fontWeight: 700, color: '#141413' }}>{t(`${item.key}.title` as never)}</div>
|
||||
<div style={{ fontSize: 11, color: '#6f6d66', marginTop: 3, lineHeight: 1.45 }}>
|
||||
{t(`${item.key}.body` as never)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function IwoooSPage({ params }: { params: { locale: string } }) {
|
||||
const t = useTranslations('iwooos')
|
||||
|
||||
@@ -273,6 +367,41 @@ export default function IwoooSPage({ params }: { params: { locale: string } }) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))',
|
||||
gap: 14,
|
||||
marginBottom: 14,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div style={{ marginBottom: 14 }}>
|
||||
<h2 style={{ fontSize: 16, margin: 0 }}>{t('coverage.title')}</h2>
|
||||
<p style={{ fontSize: 12, color: '#6f6d66', margin: '6px 0 0', lineHeight: 1.55 }}>
|
||||
{t('coverage.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))',
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
{coverageGroups.map(item => <CoverageCard key={item.key} item={item} />)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ ...band, padding: 16 }}>
|
||||
<h2 style={{ fontSize: 15, margin: 0 }}>{t('coverage.conflicts.title')}</h2>
|
||||
<p style={{ fontSize: 12, color: '#6f6d66', margin: '6px 0 8px', lineHeight: 1.55 }}>
|
||||
{t('coverage.conflicts.subtitle')}
|
||||
</p>
|
||||
{conflictControls.map((item, index) => <ConflictRow key={item.key} item={item} index={index} />)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section
|
||||
style={{
|
||||
display: 'grid',
|
||||
|
||||
Reference in New Issue
Block a user