feat(mcp): run governed version lifecycle receipts
This commit is contained in:
@@ -187,7 +187,13 @@
|
||||
"lifecycle": {
|
||||
"title": "Version discovery to rollback loop",
|
||||
"subtitle": "Target discovery cadence: {cadence}; every version diff must pass replay and canary.",
|
||||
"runtimeState": "Current runtime state: {value}. Static policy is never presented as a running scheduler."
|
||||
"runtimeState": "Current runtime state: {value}. Static policy is never presented as a running scheduler.",
|
||||
"latestReceipt": "Latest durable execution receipt",
|
||||
"observed": "Observed",
|
||||
"changed": "Changed",
|
||||
"blocked": "Policy blocked",
|
||||
"errors": "Source errors",
|
||||
"pendingReceipt": "The controller is scheduled and awaiting its first production runtime receipt."
|
||||
},
|
||||
"security": {
|
||||
"title": "Enforced security boundaries",
|
||||
|
||||
@@ -187,7 +187,13 @@
|
||||
"lifecycle": {
|
||||
"title": "版本發現到回滾循環",
|
||||
"subtitle": "目標 discovery cadence:{cadence};每次 version diff 都必須走完整 replay 與 canary。",
|
||||
"runtimeState": "目前 runtime 狀態:{value}。此欄不會用靜態 policy 冒充已運行排程。"
|
||||
"runtimeState": "目前 runtime 狀態:{value}。此欄不會用靜態 policy 冒充已運行排程。",
|
||||
"latestReceipt": "最近一次持久化執行 receipt",
|
||||
"observed": "已觀測",
|
||||
"changed": "變更",
|
||||
"blocked": "Policy 阻擋",
|
||||
"errors": "來源錯誤",
|
||||
"pendingReceipt": "控制器已排程,等待第一筆 production runtime receipt。"
|
||||
},
|
||||
"security": {
|
||||
"title": "強制安全邊界",
|
||||
|
||||
@@ -77,6 +77,39 @@ interface RuntimeReadback {
|
||||
total_chunks: number
|
||||
sources: number
|
||||
}
|
||||
version_lifecycle?: {
|
||||
status: string
|
||||
controller_configured: boolean
|
||||
controller_owner: string
|
||||
lock_backend?: string
|
||||
interval_seconds: number
|
||||
latest_run?: {
|
||||
run_id: string
|
||||
trace_id: string
|
||||
work_item_id: string
|
||||
status: string
|
||||
candidate_count: number
|
||||
observed_count: number
|
||||
baseline_count: number
|
||||
changed_count: number
|
||||
policy_blocked_count: number
|
||||
error_count: number
|
||||
started_at: string
|
||||
ended_at?: string | null
|
||||
fresh: boolean
|
||||
} | null
|
||||
observations?: Array<{
|
||||
candidate_id: string
|
||||
catalog_source: string
|
||||
observed_version?: string | null
|
||||
discovery_status: string
|
||||
change_state: string
|
||||
lifecycle_terminal: string
|
||||
error_class?: string | null
|
||||
observed_at: string
|
||||
}>
|
||||
blockers?: string[]
|
||||
}
|
||||
federated_product_runtime_receipt_count?: number
|
||||
federated_product_runtime_receipt_expected?: number
|
||||
}
|
||||
@@ -226,6 +259,13 @@ export default function McpControlPlanePage({ params }: { params: { locale: stri
|
||||
const runtime = overview?.runtime
|
||||
const gateway = runtime?.gateway_audit_24h
|
||||
const rag = runtime?.rag
|
||||
const lifecycleRuntime = runtime?.version_lifecycle
|
||||
const lifecycleObservationByCandidate = useMemo(
|
||||
() => new Map(
|
||||
(lifecycleRuntime?.observations ?? []).map(row => [row.candidate_id, row]),
|
||||
),
|
||||
[lifecycleRuntime?.observations],
|
||||
)
|
||||
|
||||
return (
|
||||
<AppLayout locale={params.locale}>
|
||||
@@ -440,7 +480,14 @@ export default function McpControlPlanePage({ params }: { params: { locale: stri
|
||||
<td className="px-3 py-3 text-[#5f5b54]">{item.catalog_source}</td>
|
||||
<td className="px-3 py-3"><StatusBadge value={item.decision} /></td>
|
||||
<td className="px-3 py-3 text-[#5f5b54]">{item.scope}</td>
|
||||
<td className="px-3 py-3 text-[#5f5b54]">{item.version_state}</td>
|
||||
<td className="px-3 py-3 text-[#5f5b54]">
|
||||
<div>{lifecycleObservationByCandidate.get(item.capability_id)?.observed_version ?? item.version_state}</div>
|
||||
{lifecycleObservationByCandidate.has(item.capability_id) ? (
|
||||
<div className="mt-1 text-[10px] text-[#8a867e]">
|
||||
{lifecycleObservationByCandidate.get(item.capability_id)?.change_state.replaceAll('_', ' ')}
|
||||
</div>
|
||||
) : null}
|
||||
</td>
|
||||
<td className="px-3 py-3 text-[#5f5b54]">{item.digest_state} / {item.sbom_state} / {item.signature_state}</td>
|
||||
<td className="px-3 py-3">
|
||||
{item.deployment_allowed ? <CheckCircle2 className="h-4 w-4 text-[#2f7d54]" aria-label={t('external.allowed')} /> : <XCircle className="h-4 w-4 text-[#b2432d]" aria-label={t('external.blocked')} />}
|
||||
@@ -470,6 +517,25 @@ export default function McpControlPlanePage({ params }: { params: { locale: stri
|
||||
<div role="status" className="mt-4 rounded-xl border border-[#e8c77a] bg-[#fff9e9] p-3 text-xs leading-5 text-[#705219]">
|
||||
{t('lifecycle.runtimeState', { value: overview.version_lifecycle.runtime_state })}
|
||||
</div>
|
||||
{lifecycleRuntime?.latest_run ? (
|
||||
<div className="mt-3 rounded-xl border border-[#c8dfcf] bg-[#f2faf4] p-3 text-xs text-[#285a37]">
|
||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||
<span className="font-bold">{t('lifecycle.latestReceipt')}</span>
|
||||
<StatusBadge value={lifecycleRuntime.latest_run.status} />
|
||||
</div>
|
||||
<dl className="mt-3 grid grid-cols-2 gap-3 sm:grid-cols-4">
|
||||
<div><dt className="text-[#66816d]">{t('lifecycle.observed')}</dt><dd className="mt-1 text-lg font-bold">{lifecycleRuntime.latest_run.observed_count}/{lifecycleRuntime.latest_run.candidate_count}</dd></div>
|
||||
<div><dt className="text-[#66816d]">{t('lifecycle.changed')}</dt><dd className="mt-1 text-lg font-bold">{lifecycleRuntime.latest_run.changed_count}</dd></div>
|
||||
<div><dt className="text-[#66816d]">{t('lifecycle.blocked')}</dt><dd className="mt-1 text-lg font-bold">{lifecycleRuntime.latest_run.policy_blocked_count}</dd></div>
|
||||
<div><dt className="text-[#66816d]">{t('lifecycle.errors')}</dt><dd className="mt-1 text-lg font-bold">{lifecycleRuntime.latest_run.error_count}</dd></div>
|
||||
</dl>
|
||||
<p className="mt-3 break-all font-mono text-[10px] text-[#66816d]">{lifecycleRuntime.latest_run.work_item_id} · {lifecycleRuntime.latest_run.run_id}</p>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-3 rounded-xl border border-[#dedbd1] bg-[#fbfaf6] p-3 text-xs text-[#77736a]">
|
||||
{t('lifecycle.pendingReceipt')}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
|
||||
<article className="rounded-2xl border border-[#dedbd1] bg-white p-5" aria-labelledby="security-title">
|
||||
|
||||
Reference in New Issue
Block a user