Repository navigation
Managed Release Finalization And Open Decisions
The operator selected a guarantee for the ProjectBuddy managed release
workflow only. It includes a future managed path to promote an eligible
draft originally created by that workflow, with fresh verification before
publication. The operator selected managed-created drafts only; adoption
of an externally created draft is not part of this path. Direct
publication through a UI, CLI, or API outside that workflow is outside
the guarantee; this draft does not claim to prevent it. The current
release.yml implements neither the qualification verifier nor a
managed draft-promotion path.
The managed creation path retains the existing rejection of a version tag that predates its intent. A promotion may use a tag independently proven to belong to the same managed draft intent, if a tag exists; it must not accept an arbitrary pre-existing tag. Resolve the candidate SHA once and bind both the requested full tag ref and the release to it. Independently resolve any actual tag to its peeled commit, including an annotated tag where applicable; an unsupported, broken, mismatched, or unverifiable reference cannot pass. A concurrent actor creating the same tag remains a relevant interference with the managed path, even though that actor's own out-of-band publication is outside the guarantee.
The official release API
states that target_commitish is unused if the tag already exists.
Passing a resolved SHA as --target therefore does not close a tag
check/create race. The inspected sources do not establish when every
draft-creation path creates its tag. Gate draft creation and tag creation
independently, without assuming either order. If a tag is absent during
draft creation, do not claim a binding that has not been established;
before publication, either prove the actual tag target and protect it
through publication, or prove an equivalent atomic create-and-publish
binding. The latter is not established by the inspected sources. A
post-publication readback alone cannot prevent an already incorrect
publication.
The release API's
get-by-tag endpoint
describes published releases; a 404 there does not establish that a
draft is absent. Listing drafts requires sufficient access and complete
pagination, and pagination alone is not proof of a consistent snapshot
while the inventory changes. Unauthorized, incomplete, inconsistent, or
otherwise ambiguous inventories are UNKNOWN, not absence. The
Git reference API
also uses 422 for validation or abuse conditions; do not interpret
every 422 as an existing tag. The
CLI release documentation
describes separate draft, asset-upload, and publication requests when
assets are attached, and says immutability protections begin only after
publication if enabled. No current repository setting or atomicity across
GitHub and a separate evidence authority is established here.
Before any request that can create a draft, create a tag, or publish a release, retain an independently durable, recoverable intent. Its logical inventory includes a unique operation identity; repository identity; full tag ref; resolved candidate commit; operation kind; managed release ID when known; required proof identities and policy revision; and workflow run and attempt provenance. The private schema, authentication, durable authority, and GitHub-side attribution or exclusion mechanisms remain unselected. An intent does not itself prove that the remote side effect occurred or that it was performed by this request.
| State or condition | Required evidence and permitted progress |
|---|---|
PREPARED |
The exact intent and applicable proof are independently recoverable before dispatch. Missing authority or intent blocks the side effect. |
IN_FLIGHT |
A request may have been accepted. A timeout, canceled client, lost response, or indeterminate authorization result does not establish non-commit or terminality. |
DRAFT_RECORDED |
An independently identified managed release is confirmed as a draft and linked to its original intent and candidate. Verify any existing tag; do not assume that a draft necessarily created one. |
PUBLISHED_RECORDED |
Independently confirm the release ID, published state, actual tag target, and proof link under the selected finalization policy. Readback is necessary but cannot replace prevention of a pre-publication race. |
UNKNOWN or conflict |
Preserve the obligation, report it explicitly, and block dependent mutations and success until the exact outcome and possible late effects are reconciled. A confirmed conflict is FAIL; ambiguity is UNKNOWN. |
A matching tag name and SHA do not by themselves prove that an ambiguous request created that tag. Another actor may have created an identical ref. Likewise, a draft with the same tag is not necessarily the intended draft. No blind retry or new attempt may erase an unresolved request; retry only under a proven same-intent idempotency and fencing protocol, and authorize dependent mutations or success only after the outcome and possible late effects are reconciled. Such a protocol must bind the operation identity to the complete intended request and prevent duplicate or substituted effects; GitHub support for it has not been established. A proven successful earlier side effect still needs current proof revalidation before a later publication. Protect intent history and pending obligations against local rollback; a missing journal is not proof that no request was sent.
Two decisions remain open before a successor ADR or implementation:
-
GitHub administrator trust. Decide which GitHub principals can be
trusted not to alter the managed workflow, tags, evidence, and
enforcement during finalization. Host root's previously selected
trust is a separate boundary. Direct unmanaged publication remains
out of scope under either choice; interference with an in-scope
managed operation must still be addressed or leave it
UNKNOWN. - In-flight revocation ordering. A strict side-effect ordering would block an effect if revocation commits first, but needs a proven mechanism to order the independent authority and GitHub side effect. A committed-authorization cutoff could instead order revocation against a durable permit, but its consequences for a revocation after that cutoff and before actual publication must be explicitly chosen; it must not be silently treated as a post-publication event. Neither a preflight check, an ordinary cooperative lock, nor a post-publication read proves either policy. Address an LUnit proof reaching its existing 90-day limit during finalization as well.
Neither alternative is selected or proven. No production finalization implementation may be claimed safe until the threat model, ordering, permissions, recovery and late-request fencing are specified and their feasibility is verified.
For evidence revoked after a managed publication, the selected
response is to record and signal the affected release, block new managed
release operations, and require an operator response. Do not automatically
withdraw the published release. Preserve a protected release-to-proof
history and verify current revocation and incident state before another
managed release; unavailable or unverifiable state is UNKNOWN. The
monitoring mechanism, detection latency, operator authorization, and
conditions for clearing the block remain to be decided. Read-only
reconciliation and incident handling remain possible while releases are
blocked; no instantaneous detection or automatic unblock is claimed. The
incident record is separate from the six-field public qualification
summary and must not expose protected evidence or secrets.
The existing release procedure's asset review remains relevant, but this qualification design does not establish asset provenance, asset integrity, release-note integrity, or wiki and downstream-consumer promotion. Those claims require their own scope and evidence.