PR: #451: feat(page-card): gen:catalog authority generator + check:catalog gate [Story-1785] by @ankitmaheshwari-com
View PR →
Story-1785

gen:catalog — the Page Card authority generator + check:catalog gate

The Page Card permission authority used to be hand-declared in permissions.ts (a six-string BACKEND_PERMISSIONS list with an "interim, replace when gen:catalog lands" note). This change builds that generator: pnpm gen:catalog derives the authority from the backend's own artifacts (openapi/permission-map.json + openapi/app-api.json) into one committed file, and check:catalog fails CI on a stale artifact or on a Page Card operation claiming a permission the backend does not enforce. No hand-authored authority remains.

What changed

One generator, two inputs, one artifact

scripts/page-card/gen-catalog.ts reads the backend permission-map.json + app-api.json via the same sibling-read resolution as kubb.config (LI-6: env override → sibling working tree → vendored mirror), and emits src/lib/surface-registry/page-card/generated-authority.ts.

Two derived sets

ENFORCED_OPERATION_PERMISSIONS = every distinct needs string actually enforced on a backend op (matters:read, matters:write, clients:write, settings:write). BACKEND_PERMISSIONS = the read+write namespace expanded from those (each <ns>:write implies its browse / resolver <ns>:read, RFD D-8) — reproducing the old six strings, but generated.

Stricter op gate (AC #2)

findCatalogViolations now validates an operation.needs against the enforced set (∈ permission-map), while a card's read / resolver permission is validated against the namespace. A card op claiming a real-but-not -enforced string (e.g. clients:read) is now rejected.

OpenAPI cross-check

The second input does real work: every app operation the permission-map names must exist as an operationId in app-api.json — catching a permission-map that has drifted from the contract (190/190 today).

Where it lives

Verify

pnpm gen:catalog   # regenerate; output is committed
pnpm check:catalog # freshness + op-needs subset, green
pnpm lint
pnpm typecheck
pnpm test
pnpm build

Coverage in generated-authority.test.ts (freshness, namespace expansion, OpenAPI cross-check, the stricter op gate) plus the existing catalog.test.ts / listing-surface.test.ts proofs.

Non-goal (RFD-AGT-004): this builds the authority half only. The component / dto_bindings catalog and the settings-catalog ListingSurface view cards are the S-D3 schema-extension follow-on — view config (columns, filters, labels) is not in the OpenAPI.

Files changed

9 file(s), +2175 / -60 lines

Path Role + -
.github/workflows/ci.ymlWorkflow+8-4
openapi/AGENTS.mdSource+14-9
openapi/permission-map.jsonConfig+1786-0
package.jsonConfig+2-1
scripts/page-card/gen-catalog.tsScript+189-0
src/lib/surface-registry/page-card/catalog.tsLibrary+37-19
src/lib/surface-registry/page-card/generated-authority.test.tsLibrary+78-0
src/lib/surface-registry/page-card/generated-authority.tsLibrary+30-0
src/lib/surface-registry/page-card/permissions.tsLibrary+31-27