Release-Channel Ref-Minting Contract — Names over a Single Identity Anchor¶
Status: living design document. The backend contract for the naming layer of [[release-channels]] — the twin of [[release-channel-materialization-contract]] (projection layer). Small by construction: once the single-anchor invariant holds, ref-minting carries almost no semantic burden. Iterate it here.
Implementation is gated. Shares the materialization contract's prerequisite (a store-resident identity to name). This document existing is not a trigger to build.
What a ref is anchored to (the whole question, already answered)¶
A forge release projection needs a ref to hang on. When the trigger that produces an identity is
itself a ref (a pushed rc-{version} tag), the anchor exists. When it is not — a branch push, a
schedule — the backend mints a backing ref (e.g. dev-{sha:8}).
The only question ref-minting could raise is "what is the ref anchored to?" — and the single-anchor invariant ([[release-channels]] Invariant 6) already answers it:
A ref is a naming pointer to a certified set — the release identity ([[release-channels]] Invariant 6). It names an identity, never "a release" and never "a store entry."
That collapses the dual-graph risk (ref → release vs ref → certified set) before it can appear.
A ref is an index entry in the naming layer; the identity it names is the certified set, held by no
storage system in particular.
The rule (one sentence)¶
A minted ref binds a name to a certified set (the identity); it carries no bytes, no trust, and no identity of its own.
Conformance (each a test target — most are the single anchor, restated at the naming layer)¶
- R1 — Names, never anchors identity. Resolving a ref yields the certified set (a digest set), never a forge-, tag-, store-, or manifest-resident object. (Invariant 6 at the naming layer.)
- R2 — Carrier, not identity. Deleting or recreating a ref (on prune, or alias repoint) changes distribution, never identity. The certified set is unaffected by what happens to the ref.
- R3 — Binds to an exact certified set. The ref→identity binding names one certification, identified by the identity digest (the equality primitive, [[release-channels]] watch-list). The binding is reproducible: resolve the same ref, get the same certified set.
- R4 — Idempotent. The same trigger for the same identity mints the same ref binding to the same
certified set — never a divergent one. (
verifyequality holds across re-runs.) - R5 — No trust surface. Verification never consults a ref; it resolves ref → certified set and
verifies there. A ref cannot be a
verifyinput. (Same family as [[persistence-identity]]: a handle locates, it does not bless.) - R6 — Not release lineage. A channel ref must never be read as a human release tag. Traced:
the
tag_sourcessearch path and changelog boundary are already safe (pattern-scoped to semver; a non-semverdev-{sha:8}matches neither). The actual exposure is the unfilteredgitstate.ExactTagAtHEADscan (headAtTag,ci/context.golocal fallback). Under the single anchor this is no longer a semantic edge case — it is one rule: don't confuse the naming index with the identity space. Guard:ExactTagAtHEADand its callers must ignore channel refs (restrict totag_sources-matching refs, or exclude the channel namespace).
Naming discipline (inherited, not re-decided)¶
dev-{sha:8} — hyphen, mirrors docker, user-defined pattern. The + build-metadata stays in the
archive filename, never the ref ([[release-channels]] Locked decisions). A ref name may encode
provenance (a sha) for readability, but it resolves to a certified set, never to the commit — R1.
Prerequisite (shared)¶
Ref-minting has nothing to bind to until the certified output set is store-resident — the same
blob-capable-persistence prerequisite as [[release-channel-materialization-contract]]
(PersistenceKind has no blob variant; cas is OCI-layout-only). R3/R4 also presume the identity
digest (the deferred serialization spec). No new prerequisite of its own.
Acceptance¶
Satisfied when: resolving any minted ref yields the certified set it names, idempotently
(R3/R4); verify consults only that identity, never the ref (R5); and ExactTagAtHEAD-class scans
exclude channel refs (R6). At that point both backend contracts are closed and the Commit 1…N
staging plan in [[release-channels]] derives mechanically.