feat(work-items): surface product governance matrix
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m37s
CD Pipeline / build-and-deploy (push) Successful in 5m21s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m37s
CD Pipeline / build-and-deploy (push) Successful in 5m21s
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -1469,6 +1469,61 @@ type SecurityCockpitRegistryReadback = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
type ProductGovernanceMatrixProduct = {
|
||||
product_id?: string | null;
|
||||
status?: string | null;
|
||||
canonical_repo?: string | null;
|
||||
prod_branch?: string | null;
|
||||
prod_sha_short?: string | null;
|
||||
dev_branch?: string | null;
|
||||
dev_sha_short?: string | null;
|
||||
ssh_refs_readable?: boolean | null;
|
||||
environment_split_ready?: boolean | null;
|
||||
owner_readiness_row_present?: boolean | null;
|
||||
visibility_readback?: string | null;
|
||||
public_ui_visible?: boolean | null;
|
||||
private_or_auth_only?: boolean | null;
|
||||
tokenless_http_status?: number | null;
|
||||
tokenless_404_is_visibility_auth?: boolean | null;
|
||||
backup_evidence_ref?: string | null;
|
||||
backup_evidence_state?: string | null;
|
||||
source_control_ready?: boolean | null;
|
||||
blockers?: string[] | null;
|
||||
next_gate?: string | null;
|
||||
};
|
||||
|
||||
type ProductGovernanceMatrixResponse = {
|
||||
schema_version?: string | null;
|
||||
status?: string | null;
|
||||
source_control_authority?: string | null;
|
||||
source_refs?: Record<string, string | null | undefined> | null;
|
||||
summary?: {
|
||||
product_count?: number | null;
|
||||
ready_product_count?: number | null;
|
||||
blocked_product_count?: number | null;
|
||||
canonical_repo_count?: number | null;
|
||||
ssh_verified_product_repo_count?: number | null;
|
||||
main_branch_present_product_repo_count?: number | null;
|
||||
dev_branch_present_product_repo_count?: number | null;
|
||||
dev_prod_environment_split_ready_count?: number | null;
|
||||
public_visible_product_repo_count?: number | null;
|
||||
private_or_auth_only_product_repo_count?: number | null;
|
||||
tokenless_http_404_private_or_auth_product_repo_count?: number | null;
|
||||
owner_readiness_row_present_count?: number | null;
|
||||
all_products_have_source_control_ready?: boolean | null;
|
||||
all_active_product_repos_have_owner_readiness_row?: boolean | null;
|
||||
all_expected_product_repos_have_dev_and_main?: boolean | null;
|
||||
backup_bundle_ready?: boolean | null;
|
||||
backup_bundle_expected_repo_count?: number | null;
|
||||
backup_evidence_linked_product_count?: number | null;
|
||||
backup_bundle_verified_product_count?: number | null;
|
||||
active_blocker_count?: number | null;
|
||||
} | null;
|
||||
products?: ProductGovernanceMatrixProduct[] | null;
|
||||
active_blockers?: string[] | null;
|
||||
next_action?: string | null;
|
||||
};
|
||||
|
||||
const COMMANDER_INSERTED_REQUIREMENT_FALLBACK: PriorityWorkOrderResponse = {
|
||||
summary: {
|
||||
active_p0_state: "blocked_reboot_auto_recovery_slo_not_ready",
|
||||
@@ -1824,6 +1879,7 @@ type Telemetry = {
|
||||
aiRouteStatus: AiRouteStatusResponse | null;
|
||||
reportSourceHealth: ReportSourceHealthResponse | null;
|
||||
priorityWorkOrder: PriorityWorkOrderResponse | null;
|
||||
productGovernanceMatrix: ProductGovernanceMatrixResponse | null;
|
||||
};
|
||||
|
||||
type AutomationAssetLedgerKey = "km" | "playbook" | "script" | "schedule" | "verifier";
|
||||
@@ -11276,6 +11332,181 @@ function MainlineWorkProgressStrip({
|
||||
);
|
||||
}
|
||||
|
||||
function ProductGovernanceMatrixPanel({
|
||||
matrix,
|
||||
loading,
|
||||
}: {
|
||||
matrix: ProductGovernanceMatrixResponse | null;
|
||||
loading: boolean;
|
||||
}) {
|
||||
const t = useTranslations("awooop.workItems.productGovernance");
|
||||
const summary = matrix?.summary;
|
||||
const products = (matrix?.products ?? []).slice(0, 6);
|
||||
const total = toCount(summary?.product_count ?? products.length);
|
||||
const ready = toCount(summary?.ready_product_count);
|
||||
const sshVerified = toCount(summary?.ssh_verified_product_repo_count);
|
||||
const devMainReady = toCount(summary?.dev_prod_environment_split_ready_count);
|
||||
const privateRepos = toCount(summary?.private_or_auth_only_product_repo_count);
|
||||
const backupLinked = toCount(summary?.backup_evidence_linked_product_count);
|
||||
const activeBlockers = toCount(summary?.active_blocker_count);
|
||||
const sourceReady =
|
||||
summary?.all_products_have_source_control_ready === true ||
|
||||
(total > 0 && ready === total && activeBlockers === 0);
|
||||
const metricCards = [
|
||||
{
|
||||
key: "products",
|
||||
label: t("metrics.products"),
|
||||
value: loading ? "--" : `${ready}/${total}`,
|
||||
icon: Database,
|
||||
tone: sourceReady ? "border-[#bfdcc4] bg-[#f2fbf3]" : "border-[#ead5bd] bg-[#fff8ef]",
|
||||
},
|
||||
{
|
||||
key: "ssh",
|
||||
label: t("metrics.ssh"),
|
||||
value: loading ? "--" : sshVerified,
|
||||
icon: GitBranch,
|
||||
tone: "border-[#c9d8ea] bg-[#eef5ff]",
|
||||
},
|
||||
{
|
||||
key: "devmain",
|
||||
label: t("metrics.devMain"),
|
||||
value: loading ? "--" : devMainReady,
|
||||
icon: GitPullRequest,
|
||||
tone: "border-[#d8d3c7] bg-white",
|
||||
},
|
||||
{
|
||||
key: "private",
|
||||
label: t("metrics.private"),
|
||||
value: loading ? "--" : privateRepos,
|
||||
icon: Lock,
|
||||
tone: "border-[#e6d0d0] bg-[#fff6f6]",
|
||||
},
|
||||
{
|
||||
key: "backup",
|
||||
label: t("metrics.backup"),
|
||||
value: loading ? "--" : backupLinked,
|
||||
icon: Archive,
|
||||
tone: "border-[#d5d6ea] bg-[#f6f6ff]",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section
|
||||
className="border border-[#e0ddd4] bg-white"
|
||||
data-testid="product-governance-matrix-panel"
|
||||
>
|
||||
<div className="grid gap-px bg-[#e0ddd4] xl:grid-cols-[minmax(260px,0.42fr)_minmax(0,1fr)]">
|
||||
<div className="bg-[#101411] p-4 text-white">
|
||||
<div className="inline-flex items-center gap-2 border border-[#315a39] bg-[#17241a] px-2 py-0.5 text-xs font-semibold text-[#b8e2bf]">
|
||||
<ShieldCheck className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
{t("eyebrow")}
|
||||
</div>
|
||||
<h3 className="mt-3 text-base font-semibold tracking-normal">
|
||||
{t("title")}
|
||||
</h3>
|
||||
<div className="mt-4 grid grid-cols-2 gap-2">
|
||||
<div className="border border-[#314034] bg-[#151b17] p-3">
|
||||
<div className="text-[11px] font-semibold text-[#9fa8a1]">
|
||||
{t("status")}
|
||||
</div>
|
||||
<div className="mt-1 text-sm font-semibold text-[#d8f5dc]">
|
||||
{loading ? "--" : sourceReady ? t("ready") : t("actionRequired")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="border border-[#314034] bg-[#151b17] p-3">
|
||||
<div className="text-[11px] font-semibold text-[#9fa8a1]">
|
||||
{t("authority")}
|
||||
</div>
|
||||
<div className="mt-1 font-mono text-sm font-semibold text-white">
|
||||
{matrix?.source_control_authority ?? "gitea"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p className="mt-3 text-xs leading-5 text-[#b8c0b9]">
|
||||
{t("subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-4">
|
||||
<div className="grid gap-2 md:grid-cols-5">
|
||||
{metricCards.map((metric) => {
|
||||
const Icon = metric.icon;
|
||||
return (
|
||||
<div key={metric.key} className={cn("border p-3", metric.tone)}>
|
||||
<div className="flex items-center justify-between gap-2 text-[11px] font-semibold text-[#5f5b52]">
|
||||
<span>{metric.label}</span>
|
||||
<Icon className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="mt-1 font-mono text-lg font-semibold text-[#141413]">
|
||||
{metric.value}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 grid gap-2 xl:grid-cols-3">
|
||||
{products.map((product) => {
|
||||
const rowReady = product.source_control_ready === true;
|
||||
return (
|
||||
<div
|
||||
key={product.product_id ?? product.canonical_repo}
|
||||
className={cn(
|
||||
"min-w-0 border p-3",
|
||||
rowReady
|
||||
? "border-[#bfdcc4] bg-[#f7fcf7]"
|
||||
: "border-[#ead5bd] bg-[#fff8ef]"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="min-w-0 truncate font-mono text-xs font-semibold text-[#141413]">
|
||||
{product.product_id}
|
||||
</div>
|
||||
<span
|
||||
className={cn(
|
||||
"border px-2 py-0.5 text-[11px] font-semibold",
|
||||
rowReady
|
||||
? "border-[#bfdcc4] bg-[#eef9f0] text-[#17602a]"
|
||||
: "border-[#ead5bd] bg-[#fff3e0] text-[#7a3d00]"
|
||||
)}
|
||||
>
|
||||
{rowReady ? t("ready") : t("actionRequired")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 truncate font-mono text-xs text-[#5f5b52]">
|
||||
{product.canonical_repo}
|
||||
</div>
|
||||
<div className="mt-2 grid grid-cols-2 gap-2 text-[11px] text-[#5f5b52]">
|
||||
<span className="truncate">
|
||||
{t("prod")} {product.prod_branch}:{product.prod_sha_short}
|
||||
</span>
|
||||
<span className="truncate">
|
||||
{t("dev")} {product.dev_branch}:{product.dev_sha_short}
|
||||
</span>
|
||||
<span className="truncate">
|
||||
{product.private_or_auth_only ? t("privateAuth") : t("publicVisible")}
|
||||
</span>
|
||||
<span className="truncate">
|
||||
{product.backup_evidence_state === "bundle_backup_verified"
|
||||
? t("backupVerified")
|
||||
: t("backupLinked")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 border border-[#c9d8ea] bg-[#eef5ff] p-3 text-xs leading-5 text-[#1f5b9b]">
|
||||
<span className="font-semibold">{t("nextAction")}</span>{" "}
|
||||
{loading ? "--" : matrix?.next_action ?? "--"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function CommanderInsertedRequirementsPanel({
|
||||
priority,
|
||||
loading,
|
||||
@@ -11706,6 +11937,7 @@ export default function AwoooPWorkItemsPage() {
|
||||
aiRouteStatus: null,
|
||||
reportSourceHealth: null,
|
||||
priorityWorkOrder: null,
|
||||
productGovernanceMatrix: null,
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [priorityWorkOrderReadback, setPriorityWorkOrderReadback] =
|
||||
@@ -11786,6 +12018,8 @@ export default function AwoooPWorkItemsPage() {
|
||||
projectId
|
||||
);
|
||||
const reportSourceHealthUrl = `${API_BASE}/api/v1/agents/agent-report-source-health`;
|
||||
const productGovernanceMatrixUrl =
|
||||
`${API_BASE}/api/v1/agents/product-governance-matrix-readback`;
|
||||
const priorityWorkOrderUrl = `${API_BASE}/api/v1/agents/awoooi-priority-work-order-readback`;
|
||||
const priorityWorkOrderPromise =
|
||||
fetchJson<PriorityWorkOrderResponse>(priorityWorkOrderUrl, 12000);
|
||||
@@ -11819,6 +12053,7 @@ export default function AwoooPWorkItemsPage() {
|
||||
callbackReplies,
|
||||
aiRouteStatus,
|
||||
reportSourceHealth,
|
||||
productGovernanceMatrix,
|
||||
priorityWorkOrder,
|
||||
] = await Promise.all([
|
||||
fetchJson<AutomationQualitySummary>(qualityUrl, 15000),
|
||||
@@ -11839,6 +12074,7 @@ export default function AwoooPWorkItemsPage() {
|
||||
fetchJson<CallbackRepliesWorkItemResponse>(callbackRepliesUrl, 12000),
|
||||
fetchJson<AiRouteStatusResponse>(aiRouteStatusUrl, 12000),
|
||||
fetchJson<ReportSourceHealthResponse>(reportSourceHealthUrl, 12000),
|
||||
fetchJson<ProductGovernanceMatrixResponse>(productGovernanceMatrixUrl, 12000),
|
||||
priorityWorkOrderPromise,
|
||||
]);
|
||||
|
||||
@@ -11888,6 +12124,7 @@ export default function AwoooPWorkItemsPage() {
|
||||
incidentTimeline,
|
||||
aiRouteStatus,
|
||||
reportSourceHealth,
|
||||
productGovernanceMatrix,
|
||||
priorityWorkOrder,
|
||||
});
|
||||
setLastUpdated(new Date());
|
||||
@@ -11991,6 +12228,11 @@ export default function AwoooPWorkItemsPage() {
|
||||
loading={priorityWorkOrderLoading && !priorityWorkOrder}
|
||||
/>
|
||||
|
||||
<ProductGovernanceMatrixPanel
|
||||
matrix={telemetry.productGovernanceMatrix}
|
||||
loading={loading && !telemetry.productGovernanceMatrix}
|
||||
/>
|
||||
|
||||
<SecurityMainlineCockpit
|
||||
priority={commanderInsertedRequirementWorkOrder}
|
||||
locale={locale}
|
||||
|
||||
Reference in New Issue
Block a user