0005: Poll publishes, push proposes, one ingest path¶
- Status:
Accepted
- Date:
2026-10-19
Context¶
Records arrive two ways: the published or default branch of a source, and CI pipelines on feature branches. A pushed proposal must never overwrite what is published, and both paths must parse, validate and hash identically so approval evidence carries over.
Decision¶
Polling reads only each registration’s published_ref and writes
published rows.
Push intake (PUT/POST /api/v1/candidates) writes only
candidate rows and refuses the literal published ref.
Both go through app.services.ingest
(prepare_document then ingest_document).
Published rows are unique per (source_id, project, path);
candidates per (source_id, project, record_key, ref).
Consequences¶
A push can never create, replace or delete a published row.
Identical bytes produce the same digest on both paths, which makes promotion work (0006: Bind approval to identity and content digest).
For
published_ref: "@project-default"the real default branch is unknown without a source call, which intake never makes, so a push to that branch is stored as a candidate. Polling still owns the published row.