ADR 0049: Release publication requires newest eligible exact-SHA provider evidence¶
- Status: Accepted
- Date: 2026-08-13
Context¶
The release and runtime-image workflows independently react to the same tag and can mutate PyPI and GHCR. Required real-live evidence was documented but not consumed by either workflow. Existing behavioral JSON assemblers are useful diagnostics, but accept caller-selected inputs and cannot authenticate their workflow run or containing artifact.
Decision¶
One manual Release candidate evidence workflow runs on exact master. Its
fixed native terminal job publishes one attempt-specific closed artifact. A
read-only publication verifier first authenticates the paired tag runs and
freezes the eligible evidence set to exact-SHA dispatches whose provider
created_at is no later than the shared publication cutoff. It selects the
unique maximum provider created_at in that set before inspecting the run's
current attempt or status. Equal maximum values are ambiguous and fail closed.
The verifier then reads that run's current run_attempt, requires success,
binds its terminal job through the GitHub check suite to the same attempt, and
validates the unique unexpired artifact under bounded resource and strict JSON
rules. Rerunning an older dispatch cannot change dispatch order, while a new
post-cutoff dispatch is ignored for the frozen tag.
Both tag-triggered publication workflows invoke this verifier in preflight and
again inside every mutation-capable job immediately before its first external
write: release attestation, PyPI publication, GitHub Release creation,
digest-only GHCR publication with attestations, and GHCR alias promotion. A
multi-write block does not run a separate gate before each attestation; its
later attest writes remain in the same gated block, with no intervening
checked-out repository code able to change evidence authority. A newer
eligible failed, cancelled, pending, missing, malformed, or expired
dispatch for the same exact commit blocks; an older eligible PASS is never a
fallback. A dispatch created after the provider cutoff cannot supersede or
deny the already-frozen tag. A different tagged commit requires its own
evidence. Later master advancement does not invalidate evidence for frozen
commit C.
PyPI is an additional non-transactional boundary inside the package publisher.
Its upload API accepts files individually, while the pinned publishing action's
skip-existing behavior continues after an existing filename. Therefore the
fresh provider gate alone is insufficient for a safe same-version resume. The
ordinary publisher performs a second fail-closed check immediately before the
action: it rehashes the exact eight local candidates, reads each of the four
exact-version PyPI JSON endpoints, and requires every visible file to be an
exact non-yanked candidate by filename, SHA-256, and size. The only accepted
states are a fully absent release or an exact candidate subset; unexpected,
duplicate, conflicting, malformed, oversized, or unavailable state blocks
before upload.
The second gate writes a deterministic closed receipt before the publishing
action. It binds repository, tagged commit, release tag, fixed workflow path,
positive run ID/attempt asserted against GitHub environment values, raw
candidate-inventory digest, all endpoint observations, and all candidate
classifications. skip-existing: true is retained only as mechanics for that
proved exact subset, never as authority to ignore a conflict. Post-publication
byte verification remains defense in depth. A concurrent conflicting upload
between the final observation and the action is an unavoidable external race;
it blocks downstream steps when detected but may require a new patch version
because accepted PyPI files cannot be rolled back.
The verifier remains stdlib-only because the OIDC publisher job deliberately does not check out or install repository/application code. Shared closed JSON, error, receipt, and candidate contracts are factored once; local inventory and PyPI transport are separate adapters; the CLI composes policy. This small source-free bundle avoids both dependency installation at the privileged boundary and duplicated validation logic while keeping each module below the repository size thresholds.
The time boundary is provider-owned, not tagger-authored. For both
.github/workflows/release.yml and
.github/workflows/runtime-image.yml, the verifier requires exactly one
tag-push run with the exact repository, workflow path, tag, commit, and push
event. The calling run must also match its exact positive run ID and attempt and
still be in_progress. The earlier of the two provider created_at values is
the immutable publication cutoff. Only evidence dispatches created no later
than that instant are eligible; the selected execution must also have
completed, its terminal check must have completed, and its artifact must have
been created by the cutoff. Later evidence dispatches are ignored. Artifact
retention is availability, not permanent durability.
Every successful verification receipt retains the complete publication pair,
not only the calling run. The pair is exactly the release.yml and
runtime-image.yml identities sorted by workflow path; every closed entry
contains only workflow path, positive run ID, positive run attempt, and
provider creation time. The caller must match its corresponding entry, the
serialized cutoff must equal the exact minimum creation time, and a tagged
SHA-256 binds the canonical JSON bytes of the ordered pair. The retained
receipt can therefore reproduce its cutoff decision without later GitHub API
history.
Paired-run discovery absorbs only provider indexing latency. By default each
gate performs an initial observation plus at most 30 ten-second waits (31
observations and about 300 seconds of sleep budget, excluding request time).
Every observation re-fetches and re-authenticates the caller's exact current
run detail, then lists both fixed workflow paths. Runs for another tag are
ignored. Only zero exact-tag matches
for a path and mutable current-run run_attempt/updated_at detail/list
projection drift are retryable. A malformed exact match, more than one exact
match, or immutable current-run id/created_at drift fails immediately.
Persistent mutable projection drift fails after the same bounded poll.
The authoritative native_transfer campaign is a strict real_local superset
and derives claims only from observed inputs. Disabled placeholder assemblers
remain disabled. Its 25,000-row stress evidence fixes every required phase at a
minimum 500 rows/s and rejects rates that are inconsistent with the producer's
three-decimal duration and two-decimal rate rounding. No custom check,
checks: write, publication token, OIDC, or protected environment is granted
to the producer.
Consequences¶
- A tag without current exact-SHA evidence fails before PyPI and GHCR work.
- Package release has no manual dispatch; only the paired tag-push workflows can enter publication, and each authenticates the other provider run.
- Both irreversible DAGs independently verify the same bytes and identity.
- A partial PyPI retry is machine-admitted only for an exact immutable public candidate subset and leaves an attempt-bound PASS/FAIL receipt.
- Reruns are fail-closed. Before tagging, artifact deletion or expiry requires
a new campaign on the then-current
mastercandidate. After the tag-run cutoff is frozen, post-cutoff evidence cannot replace lost authority; recovery requires a newly reviewed version and tag. - Raw live certification and legacy evidence-pack APIs remain compatible but diagnostic.
- Tag creation remains a maintainer action; workflow code blocks publication, while repository tag rules are the separate preventive control.