Firms list/create now uses hydrated generated hooks.
The firms list keeps the same dense admin UI, but its data path now matches the generated TanStack Query template that staff and support access will copy next.
What changed
firms/page.tsx creates a server query client, spreads adminListFirmsQueryOptions for the canonical key, overrides the query function with firmsGateway.list, then renders HydrationBoundary.
FirmsClient reads the same params through useAdminListFirms. The URL-driven nuqs table state remains the source for filters, sort, and pagination.
The create sheet provisions Clerk through a server action, submits the generated FirmCreateRequest through useAdminCreateFirm, and invalidates only after success.
Why no optimistic mutation
Firm lifecycle writes are privileged and audited. The admin operator sees server-confirmed state only: no onMutate, no speculative queryClient.setQueryData, and no form reset on rejection.
Template gaps closed
The firms BFF now forwards x-pramaan-* upstream identity headers so browser diagnostics can merge the live backend identity.
resolveRequestTraceId, validation errors, and header forwarding live in src/app/api/internal/_helpers.ts for #1482 and #1483 to reuse.
src/lib/query/invalidation.test.ts proves exact-key invalidation and firms collection invalidation by generated key head.
Retired path
listFirms no longer lives in the "use server"
action file. The firms-list Next fetch tag was removed; firm detail
tags are untouched for the later firm-detail migration.