PR: #468: feat(matters): Import-into-matter sheet — W1 brownfield import [Story-1858] by @ankitmaheshwari-com
View PR →
Story-1858 · app lane · RFD-DOC-001 · W1 brownfield import

Import into <matter> — drop your whole case into the Record

~99% of lawyers onboard by importing a years-long case at once. W1 is the front door that must absorb chaos without fear. You open Import from inside a matter, so the matter is the container — no picker, no forced classification. Drop a folder, a ZIP, or a pile of files; everything enters this matter's Evidentiary Record. The "wow" (sort, OCR, annexure-split) lives downstream on the Record — W1 shows upload accountability only.

What shipped

How uploads wire to the ledger

StepPathStatus
Mint import (expected_count derived server-side)generated appCreateDocumentImport → /api/internal/matters/{id}/documents/imports → gateway → functions ledgerLive (real endpoint)
Presign upload (binds importItemId)server action → presignDocumentUploadLive
Transfer bytesbrowser → S3 (direct PUT, progress)Live
Finalize → lands on Record + ledger item accountedserver action → finalizeDocumentUploadLive

All upstream calls ride the shared gateway, so traceparent / correlation propagate automatically (pramaan-docs ADR-104 / ADR-065). No OTel SDK, manual spans, or ad-hoc headers were added on this surface.

System-boundary status (seam closed)

The ledger endpoints shipped on main (functions Story-1855, PR #496). This PR is wired to the real backend, not a fixture (AGENTS.md "done = system boundary"):

  • The OpenAPI mirror was synced from pramaan-functions origin/main and pnpm codegen run — src/gen now carries ImportCreateRequest/Response, appCreateDocumentImport, and the new presign.importItemId.
  • Mint goes through the generated client + the BFF proxy; the request is contract-validated at the proxy (HR-21) and the response in the gateway (assertContract, HR-21/22).
  • No stub remains. The provisional local schema and the document-imports placeholder route were deleted; the legal-lexicon stub was deleted and the notice now consumes the merged Story-1854 module.
  • Mint is required (no best-effort fallback): the real mint runs first and owns the completeness denominator. If it fails nothing is enqueued — the failure is surfaced with the trace_id and counsel retries. (The presign still accepts a null importItemId for a future loose-file path, but the W1 flow always mints first.)
  • The W1 source bucket (Client/Opponent/Other) is a client-side display hint for V1 — distinct from the ledger's selection source_kind; the V1 ledger contract does not persist the declared bucket.

Reconciliation note

The issue AC listed per-file stages "uploaded → scanned → extracting". The canonical mockup (mockups/W1.md, 2026-06-28) supersedes that: W1 = upload only — scan/OCR/index move to the Record. Per repo doctrine (linked mockup > pasted brief), W1 shows transfer progress only; processing facts belong to the Record / matter-detail page.

Verification

Files changed

68 file(s), +3552 / -185 lines

Path Role + -
messages/en.jsonConfig+20-0
messages/hi.jsonConfig+20-0
openapi/app-api.jsonConfig+517-0
openapi/permission-map.jsonConfig+16-0
src/app/api/internal/matters/[matterId]/documents/imports/route.tsApp route+83-0
src/components/matters/evidentiary-record-notice.tsxComponent+47-0
src/components/matters/import-into-matter-sheet.stories.tsxComponent+122-0
src/components/matters/import-into-matter-sheet.tsxComponent+123-0
src/components/matters/import-sheet-presentation.tsComponent+42-0
src/components/matters/intake-upload-sheet.stories.tsxComponent+0-83
src/components/matters/intake-upload-sheet.tsxComponent+0-83
src/components/matters/live-matter-documents-page.tsxComponent+10-4
src/components/matters/upload-dropzone.tsxComponent+68-12
src/components/matters/use-document-upload-queue.tsComponent+22-3
src/components/matters/use-matter-import.tsComponent+133-0
src/gen/client/appCreateDocumentImport.tsGenerated contract+73-0
src/gen/client/appGetMatterImportCompleteness.tsGenerated contract+63-0
src/gen/client/index.tsGenerated contract+2-0
src/gen/hooks/index.tsGenerated contract+12-0
src/gen/hooks/useAppCreateDocumentImport.tsGenerated contract+156-0
src/gen/hooks/useAppGetMatterImportCompleteness.tsGenerated contract+131-0
src/gen/hooks/useAppGetMatterImportCompletenessSuspense.tsGenerated contract+133-0
src/gen/index.tsGenerated contract+91-0
src/gen/schemas/documentPresignUploadRequest.jsonGenerated contract+5-0
src/gen/schemas/importCreateRequest.jsonGenerated contract+61-0
src/gen/schemas/importCreateResponse.jsonGenerated contract+88-0
src/gen/schemas/importDroppedReason.jsonGenerated contract+35-0
src/gen/schemas/importItemInput.jsonGenerated contract+37-0
src/gen/schemas/importItemInputKind.jsonGenerated contract+7-0
src/gen/schemas/importItemState.jsonGenerated contract+15-0
src/gen/schemas/importItemView.jsonGenerated contract+35-0
src/gen/schemas/importSourceKind.jsonGenerated contract+7-0
src/gen/schemas/importStatus.jsonGenerated contract+6-0
src/gen/schemas/matterImportCompletenessResponse.jsonGenerated contract+106-0
src/gen/types/AppCreateDocumentImport.tsGenerated contract+77-0
src/gen/types/AppGetMatterImportCompleteness.tsGenerated contract+71-0
src/gen/types/DocumentPresignUploadRequest.tsGenerated contract+4-0
src/gen/types/ImportCreateRequest.tsGenerated contract+25-0
src/gen/types/ImportCreateResponse.tsGenerated contract+47-0
src/gen/types/ImportDroppedReason.tsGenerated contract+29-0
src/gen/types/ImportItemInput.tsGenerated contract+38-0
src/gen/types/ImportItemInputKind.tsGenerated contract+13-0
src/gen/types/ImportItemState.tsGenerated contract+20-0
src/gen/types/ImportItemView.tsGenerated contract+29-0
src/gen/types/ImportSourceKind.tsGenerated contract+13-0
src/gen/types/ImportStatus.tsGenerated contract+12-0
src/gen/types/MatterImportCompletenessResponse.tsGenerated contract+65-0
src/gen/types/index.tsGenerated contract+44-0
src/gen/zod/appCreateDocumentImportSchema.tsGenerated contract+96-0
src/gen/zod/appGetMatterImportCompletenessSchema.tsGenerated contract+88-0
src/gen/zod/documentPresignUploadRequestSchema.tsGenerated contract+7-0
src/gen/zod/importCreateRequestSchema.tsGenerated contract+38-0
src/gen/zod/importCreateResponseSchema.tsGenerated contract+44-0
src/gen/zod/importDroppedReasonSchema.tsGenerated contract+30-0
src/gen/zod/importItemInputKindSchema.tsGenerated contract+17-0
src/gen/zod/importItemInputSchema.tsGenerated contract+48-0
src/gen/zod/importItemStateSchema.tsGenerated contract+25-0
src/gen/zod/importItemViewSchema.tsGenerated contract+28-0
src/gen/zod/importSourceKindSchema.tsGenerated contract+17-0
src/gen/zod/importStatusSchema.tsGenerated contract+14-0
src/gen/zod/index.tsGenerated contract+33-0
src/gen/zod/matterImportCompletenessResponseSchema.tsGenerated contract+56-0
src/lib/kubb-client.tsLibrary+12-0
src/lib/matters/folder-drop.test.tsLibrary+63-0
src/lib/matters/folder-drop.tsLibrary+80-0
src/lib/matters/gateway.tsLibrary+32-0
src/lib/matters/import-source.tsLibrary+33-0
src/lib/matters/upload-queue.tsLibrary+18-0