Register platform loading template governance

This commit is contained in:
rcourtman
2026-06-12 13:38:05 +01:00
parent f90ae48814
commit 0109361296
3 changed files with 136 additions and 0 deletions
@@ -2393,6 +2393,11 @@ Docker, Kubernetes, Proxmox, Standalone, TrueNAS, vSphere, and future platform
feature tables; source-specific consumers own only the empty-state icon, title,
description, and actions. Platform feature tables must not import
`EmptyState` directly or recreate a `Card`-wrapped empty-state shell.
Platform table loading states are registry-backed too.
`PlatformTableLoadingState` owns the repeated table-card compact
`role="status"` loading row for platform pages and tables; platform consumers
own only the title and description copy. Platform feature surfaces must not
recreate the `TableCard` plus compact status-row shell locally.
Filter bars are registry-backed too. `FilterBar` owns resource-list filtering
as a catalog of `FilterDef` entries, while `filterChipStatusDot` owns the
small leading status-dot glyph used by filter options. Page and feature
@@ -114,6 +114,29 @@
"scripts/shared-template-audit.mjs"
]
},
{
"id": "platform-table-loading-state",
"category": "platform-table-loading-state",
"summary": "Platform page and table loading states must compose PlatformTableLoadingState instead of recreating local TableCard status rows.",
"canonical": {
"path": "src/features/platformPage/sharedPlatformPage.tsx",
"export": "PlatformTableLoadingState"
},
"requiredConsumers": [
{ "path": "src/features/docker/DockerPageSurface.tsx" },
{ "path": "src/features/kubernetes/KubernetesPageSurface.tsx" },
{ "path": "src/features/proxmox/ProxmoxPageSurface.tsx" },
{ "path": "src/features/standalone/StandalonePageSurface.tsx" },
{ "path": "src/features/truenas/TrueNASPageSurface.tsx" },
{ "path": "src/features/truenas/TrueNASProtectionTable.tsx" },
{ "path": "src/features/vmware/VmwarePageSurface.tsx" }
],
"proof": [
"src/components/shared/SharedPrimitives.guardrails.test.ts",
"src/features/platformPage/__tests__/platformOverviewLayout.guardrails.test.ts",
"scripts/shared-template-audit.mjs"
]
},
{
"id": "filter-bar-catalog-shell",
"category": "filter-bar",
@@ -217,6 +240,31 @@
"scripts/shared-template-audit.mjs"
]
},
{
"id": "platform-table-loading-state-local-status-row",
"category": "platform-table-loading-state",
"summary": "Platform feature loading states must compose PlatformTableLoadingState instead of recreating the compact TableCard status row locally.",
"canonical": {
"path": "src/features/platformPage/sharedPlatformPage.tsx",
"export": "PlatformTableLoadingState"
},
"scopes": [
"src/features/docker",
"src/features/kubernetes",
"src/features/proxmox",
"src/features/standalone",
"src/features/truenas",
"src/features/vmware"
],
"extensions": [".tsx"],
"allPatterns": ["role=\"status\"", "px-3 py-2 text-xs text-muted"],
"legacyReason": "Retired migration debt. Platform table loading states must use PlatformTableLoadingState; no compact local status-row exceptions are currently allowed.",
"allowedPaths": [],
"proof": [
"src/components/shared/SharedPrimitives.guardrails.test.ts",
"scripts/shared-template-audit.mjs"
]
},
{
"id": "filter-bar-consumer-legacy-page-controls",
"category": "filter-bar",
@@ -92,8 +92,15 @@ import webInterfaceUrlFieldStateSource from '@/components/shared/useWebInterface
import webInterfaceNameLinkSource from '@/components/shared/WebInterfaceNameLink.tsx?raw';
import inlineDetailTableRowSource from '@/components/shared/InlineDetailTableRow.tsx?raw';
import sharedTemplateRegistrySource from '../../../scripts/shared-template-registry.json?raw';
import dockerPageSurfaceSource from '@/features/docker/DockerPageSurface.tsx?raw';
import kubernetesPageSurfaceSource from '@/features/kubernetes/KubernetesPageSurface.tsx?raw';
import proxmoxPageSurfaceSource from '@/features/proxmox/ProxmoxPageSurface.tsx?raw';
import standalonePageSurfaceSource from '@/features/standalone/StandalonePageSurface.tsx?raw';
import sharedPlatformPageSource from '@/features/platformPage/sharedPlatformPage.tsx?raw';
import platformResourceDetailTableRowSource from '@/features/platformPage/PlatformResourceDetailTableRow.tsx?raw';
import truenasPageSurfaceSource from '@/features/truenas/TrueNASPageSurface.tsx?raw';
import truenasProtectionTableSource from '@/features/truenas/TrueNASProtectionTable.tsx?raw';
import vmwarePageSurfaceSource from '@/features/vmware/VmwarePageSurface.tsx?raw';
import upgradeNavigationSource from '@/utils/upgradeNavigation.ts?raw';
import guestRowSource from '@/components/Workloads/GuestRow.tsx?raw';
import workloadsTableSource from '@/components/Workloads/WorkloadsTable.tsx?raw';
@@ -1065,6 +1072,82 @@ describe('shared primitive guardrails', () => {
}
});
it('keeps platform table loading states on the shared status-row template', () => {
const registry = JSON.parse(sharedTemplateRegistrySource) as {
rules?: Array<{
id: string;
canonical?: { path?: string; export?: string };
requiredConsumers?: Array<{ path?: string }>;
}>;
patternGuards?: Array<{
id: string;
canonical?: { path?: string; export?: string };
allPatterns?: string[];
scopes?: string[];
allowedPaths?: string[];
}>;
};
const registeredRule = registry.rules?.find(
(rule) => rule.id === 'platform-table-loading-state',
);
const registeredGuard = registry.patternGuards?.find(
(guard) => guard.id === 'platform-table-loading-state-local-status-row',
);
const requiredConsumerPaths = [
'src/features/docker/DockerPageSurface.tsx',
'src/features/kubernetes/KubernetesPageSurface.tsx',
'src/features/proxmox/ProxmoxPageSurface.tsx',
'src/features/standalone/StandalonePageSurface.tsx',
'src/features/truenas/TrueNASPageSurface.tsx',
'src/features/truenas/TrueNASProtectionTable.tsx',
'src/features/vmware/VmwarePageSurface.tsx',
];
expect(registeredRule?.canonical?.path).toBe(
'src/features/platformPage/sharedPlatformPage.tsx',
);
expect(registeredRule?.canonical?.export).toBe('PlatformTableLoadingState');
expect(registeredRule?.requiredConsumers?.map((consumer) => consumer.path)).toEqual(
expect.arrayContaining(requiredConsumerPaths),
);
expect(registeredGuard?.canonical?.path).toBe(
'src/features/platformPage/sharedPlatformPage.tsx',
);
expect(registeredGuard?.canonical?.export).toBe('PlatformTableLoadingState');
expect(registeredGuard?.allPatterns).toEqual([
'role="status"',
'px-3 py-2 text-xs text-muted',
]);
expect(registeredGuard?.allowedPaths ?? []).toHaveLength(0);
expect(registeredGuard?.scopes).toEqual(
expect.arrayContaining([
'src/features/docker',
'src/features/kubernetes',
'src/features/proxmox',
'src/features/standalone',
'src/features/truenas',
'src/features/vmware',
]),
);
expect(sharedPlatformPageSource).toContain('export function PlatformTableLoadingState');
expect(sharedPlatformPageSource).toContain('role="status"');
expect(sharedPlatformPageSource).toContain('px-3 py-2 text-xs text-muted');
for (const source of [
dockerPageSurfaceSource,
kubernetesPageSurfaceSource,
proxmoxPageSurfaceSource,
standalonePageSurfaceSource,
truenasPageSurfaceSource,
truenasProtectionTableSource,
vmwarePageSurfaceSource,
]) {
expect(source).toContain('PlatformTableLoadingState');
expect(source).not.toContain('<div class="px-3 py-2 text-xs text-muted" role="status">');
}
});
it('keeps platform row-detail disclosure controls on the shared toggle primitive', () => {
const registry = JSON.parse(sharedTemplateRegistrySource) as {
requiredPatternGuards?: Array<{