PR: #478: feat(filings): inline exhibit renumber + two-identity row [Story-1895] by @ankitmaheshwari-com
View PR →
Story-1895

Inline exhibit renumber + the two-identity row

Story-1886 shipped the Exhibit Register read-only, with two deferred halves blocked on the backend contract. The Story-1891 contract is now synced (codegen-sync #1894), so both are wired: counsel single-clicks an exhibit number to renumber it in place, and each row now shows the document's two identities together — the drafter's annexure label and the tribunal exhibit number on one row. No new contract fields invented; everything reads from the synced DocumentExhibitMarkingView and the renumber PATCH.

What shipped

Single-click inline renumber

The exhibit-number cell is now an ExhibitLabelCell: click the number → it becomes an input. Enter (or blur) saves via the generated useAppRenumberExhibitMarking PATCH; Escape cancels. On success the Exhibit Register query is invalidated so the row reconciles with the server (the service may normalize the label).

409 duplicate — inline, no crash

A label that collides with another marking in the same party series returns 409. The proxy passes the upstream ErrorResponse straight through; the cell keeps the editor open and shows the message inline under the field (role="alert"), so counsel picks another number without losing context.

True two-identity row

The Annexure column now renders marking.filingLabel (the drafter's "Annexure A", JOINed onto the marking view in Story-1891) beside the editable exhibit number. A standalone document with no annexure label shows —.

Human-only by contract

Renumber is a counsel act: the route is matters:write gated and the service stamps source='human'. There is no agent path in the UI — an agent can never reach the PATCH. The edit is audited server-side (exhibit_marking.renamed, old→new).

How the write threads through (BFF, HR-21, HR-22)

The browser only ever talks to /api/internal/*. The generated client PATCHes the absolute /app/…/exhibit-register/{markingId} path; toBrowserRoute in lib/kubb-client.ts maps it onto a new BFF proxy at the matching /api/internal path. That proxy parses the body with the generated exhibitMarkingRenumberRequestSchema (HR-21 trust-boundary parse), forwards through filingsGateway.renumberExhibitMarking (which re-asserts the DocumentExhibitMarkingView response), and passes a GatewayError — 409 included — straight back with its status. All contract types come from src/gen (HR-22); nothing hand-written.

Empty / zero first-run & privilege

A proceeding with no markings shows the existing empty state (no editable cells, no crash). The privilege gate is unchanged: privileged documents are dropped by the upstream JOIN (DR-2) and never reach the register, so the renumber path can only ever touch a tenderable, non-privileged marking. The read-only members case is enforced by the backend (matters:write → 403), surfaced inline like any other failure.

Files

Verify

pnpm typecheck (clean), pnpm lint (0 errors), pnpm build (green — new /exhibit-register/[markingId] route registered), pnpm test (full suite passing), and pnpm check:routes (registry fresh). i18n parity confirmed across en / hi; no raw color literals (semantic tokens + token-backed Tailwind only). Types imported from src/gen off current main — no codegen run.

Files changed

17 file(s), +483 / -31 lines

Path Role + -
messages/en.jsonConfig+5-2
messages/hi.jsonConfig+5-2
openapi/app-api.jsonConfig+32-0
src/app/api/internal/matters/[matterId]/proceedings/[proceedingId]/exhibit-register/[markingId]/route.tsApp route+92-0
src/components/matters/filings/exhibit-label-cell.tsxComponent+147-0
src/components/matters/filings/exhibit-register-table.stories.tsxComponent+29-13
src/components/matters/filings/exhibit-register-table.tsxComponent+19-5
src/components/matters/filings/filings-fixtures.tsComponent+4-0
src/components/matters/filings/filings-tab.tsxComponent+10-5
src/gen/schemas/documentListItem.jsonGenerated contract+16-0
src/gen/schemas/documentListResponse.jsonGenerated contract+16-0
src/gen/schemas/evidenceIndexManifest.jsonGenerated contract+16-0
src/gen/schemas/recordBootstrapResponse.jsonGenerated contract+16-0
src/gen/types/DocumentListItem.tsGenerated contract+13-0
src/gen/zod/documentListItemSchema.tsGenerated contract+19-0
src/lib/filings/gateway.tsLibrary+31-4
src/lib/kubb-client.tsLibrary+13-0