Skip to content

DR-108: The provenance register gains an append-only ingest-event history

DR-108: The provenance register gains an append-only ingest-event history

Section titled “DR-108: The provenance register gains an append-only ingest-event history”

source_documents.parent_id and .version have zero writers in TypeScript, Python and SQL. The /documents/[id]/diff version-pair branch is therefore unreachable in production and every document renders “This is the first version”. Found as a side-finding while wiring an unrelated column (id-407), and investigated as id-409.

The columns are not merely unwritten — a chain is unreachable by construction. The ratified admission writer resolve_or_mint_source_identity (20260703160100_id138_admission_identity_fn.sql) omits both from its INSERT column list, and mints id = uuid5(NS, 'sd:' || rel_path) with ON CONFLICT (id) DO NOTHING. A changed file at the same path resolves to the same row, by design — that stability is what makes the register a register.

Corpus-reframe R5, the only current statement of source_documents semantics, calls its rows the permanent provenance register: never deleted, meaningful once the bytes are discarded. Register semantics, not version-chain semantics. Current docs are otherwise silent on what a document version is.

The read surface is wide but shallow — 11 production sites plus an RPC pair, an api view and an MCP tool, with no hub symbol. Its origin is id-117, ratified roughly two weeks before the corpus reframe that superseded its premise.

Re-ingest history is recorded as an append-only ingest-event row on a separate register-history table, generalising the polymorphic verification_history shape DR-076 already names as the pattern for this class.

source_documents.parent_id/.version are not the ratified mechanism and are not adopted as one. The version-chain read surface is re-pointed at the new history, not deleted — it gains a real source of truth for the first time.

Decided on end-user value against the platform’s purpose, at the owner’s direction. The concrete need for a procurement SMB is “this tender pack was reissued with amendments — are my bid answers still valid?” That is a trust question about evidence, and it sits on the platform’s reason for existing: structured data an AI can cite. R1 already commits to citations degrading gracefully to the provenance register; “what changed on re-ingest” is the missing half of a promise already made.

  • (a) A new source_documents row chained by parent_id. Buys the same user value at much higher cost: it reopens DR-026 clause (i) and the SEED-CONTRACT uuid5-on-path identity formula, which is load-bearing.
  • (c) Nothing — the register records current state only. Cheapest, and defensible on the documents, which are silent here. Rejected on user value: for a tender-driven product, losing “has my evidence changed” is a real capability loss. The investigation rated deleting the reader LOW confidence precisely because the reframe had reasoned about records and concepts, never the evidence UI.
  • id-409 needs a spec chain before implementation: what counts as an ingest event, the row shape, and how the read surfaces compose it are all open.
  • parent_id’s place in id-399’s R8_PROTECTED_COLUMNS is now decidable but not decided — R8’s own text names origin type, locator, retention class, cadence and auth, and parent_id is not among them, so its protection is a conservative do-not-drop rather than a ratified column.
  • The source_documents table comment (“Each row is a specific version of a document. The parent_id chain links versions together.”) contradicts this ruling and should be corrected when the table is next touched.
  • app/api/cron/review-cadence/route.ts dropped its .is('superseded_by', null) guard, justified in-comment by “the existing parent_id version chain” — a chain that never forms. The ingest-event history is what a restored guard would read.