vaulted Textract JSON from Story 2482
→ claim one in-flight extraction version
→ project page text + LAYOUT blocks
→ mint deterministic, opaque anchor IDs
→ publish one current version
→ mark chunk/assertion artifacts from older versions stale
existing document_pages v1 → remains the only serving surface
documents.document_pages_v2 is a shadow fixture register.
There are no endpoints, DTO changes, or reads from the live document surface. T2a/T2b own the later atomic cutover.
| Table | Authority |
|---|---|
documents.extraction_versions |
Serializes re-extraction: at most one in_flight version and one canonical current version per document. |
documents.document_pages_v2 |
One row per page and extraction version: page text, generated search vector, and JSONB blocks carrying anchor, kind, text, bbox, confidence, and character offsets. |
documents.extraction_artifact_staleness |
An absence-means-fresh marker register. context.chunk and context.assertion are today's artifact kinds; later Deep Read envelopes and findings register by data, not a schema migration. |
firm_id, firm-leading indexes, forced RLS,
and composite foreign keys that keep a page or marker attached to the same firm's document and extraction version.
A second firm sees zero rows even when the first firm's rows exist.
test_er17_shadow_register_is_cross_firm_invisible commits one complete fixture for each of two firms, then proves firm B sees its own version, page, and staleness marker and zero rows from firm A.test_extraction_versions_allow_one_current_and_one_in_flight proves Postgres accepts one current plus one in-flight version, then rejects a second row in either state.The vault is the immutable observation; v2 pages are its deterministic address book. They are safe to rebuild, impossible to mix across firms, and deliberately invisible to serving code until the atomic cutover Story.