Release and publication policy¶
Read before changing release, trusted CI, signing, promotion, or Pages workflows, or performing publication.
The complete Python CI job has a two-hour deadline covering locked dependency setup, the full suite, and runner cleanup. Local Python validation remains focused; the canonical CI check must complete successfully.
Trusted version refresh dispatches CI from protected main with the exact PR number, base SHA, and head SHA. Candidate
validation jobs remain read-only. Only separate no-checkout jobs may publish the canonical Version policy, Repository
checks, and Python tests commit statuses after revalidating the open same-repository PR and exact head/base. Preserve
the bot-only publication gate, visible run links, diagnostic names for bot-triggered pull_request jobs, and the active
ruleset contexts. Keep trusted dispatch and diagnostic pull-request runs in separate concurrency groups so diagnostic
work cannot cancel the trusted publisher. Never dispatch a candidate workflow revision with status-write permission.
Every workflow job that mutates gh-pages must use the shared atlaso-github-pages concurrency group with queue: max
and cancel-in-progress: false. Keep long prerequisite builds outside that job-level lock; acquire it before reading the
current Pages branch and retain it through the guarded publication push. Do not weaken existing signature, immutable
tag/release, monotonic-channel, or byte-idempotency checks when narrowing the lock scope.
Every Pages writer must also fail closed unless the shipped default stable manifest and signature exist in its final
tree. Appliance release and promotion workflows must re-fetch the published signed pointer and immutable release
manifest, verify the named trust key, and confirm CPython 3.14 compatibility after publication.
The trusted version workflow may update an internal pull request with GITHUB_TOKEN. GitHub can place the duplicate
pull_request workflow run created by that update behind an approval gate, so those diagnostic jobs use non-required
names. Automated branch updates request version refresh through a typed repository dispatch, which always uses the
workflow revision on protected main; there is no privileged manual-dispatch entry point.
The protected workflow then dispatches CI from main with the exact pull-request number, base SHA, and head SHA. Its
candidate validation jobs retain read-only permissions. Separate jobs that never check out candidate code revalidate
the open same-repository pull request and publish pending, success, failure, or error commit statuses named Version
policy, Repository checks, and Python tests, each linked to the trusted run. Those visible statuses are the
canonical contexts required by the main ruleset; a manual CI dispatch cannot publish them. Trusted dispatches and
diagnostic pull-request runs use separate concurrency groups, so a delayed diagnostic run cannot cancel trusted status
publication.
GitHub Pages writers serialize only their final mutation jobs through the shared atlaso-github-pages group. The group
uses queue: max with cancel-in-progress: false, preserving multiple pending documentation, appliance release,
Inventory Linux release, and promotion writers while keeping long prerequisite builds outside the Pages lock.
Release lifecycle contributions¶
Every successful same-repository main push CI run automatically starts Publish Python wheel. That separate
GitHub-hosted workflow has read-only repository permissions and publishes only the immutable Actions artifact
atlaso-wheel-vX.Y.Z-<full-sha> for 90 days. The artifact contains exactly one versioned Atlaso wheel and a canonical
identity document binding its source CI run ID and attempt, publisher run ID and attempt, version, commit, size, and
SHA-256 digest. Downstream consumption revalidates those exact attempts. It has no signing
material, GitHub Release/tag or Pages write authority, protected environment, self-hosted runner, or virtualization
access. Repeated artifacts for one version/commit must contain identical wheel bytes or the software consumer fails.
When identical retries coexist, the consumer stages each publisher-run artifact separately, validates its recorded
attempt, and preserves the earliest retained publisher run-and-attempt identity so an automatic retry cannot change the
inputs of an already published signed bundle.
Each successful automatic-main wheel handoff starts the separately protected Publish appliance release workflow.
The workflow requires the retained matching artifact, validates its GitHub run identities and
embedded build metadata, fails closed on collisions, and records that identity inside the signed appliance bundle. It
does not rebuild or substitute the application wheel. It retains the exact CPython 3.14 wheelhouse, signing,
immutable-tag/Release, Pages serialization, automatic development advancement, and live-verification gates. Manual
dispatch with the exact full SHA of a successful main push CI run remains available for idempotent recovery. After
the 90-day retention window, manually dispatch Replay Python wheel from main with the exact commit plus its
successful source CI run ID
and attempt. That admission workflow revalidates the evidence and current-main reachability without checking out or
executing the target, then emits only a one-day canonical replay request. Its completed workflow_run causes the
read-only Publish Python wheel workflow to revalidate the request and publish the replacement handoff. Replay does
not implicitly advance an older release; use the exact-SHA software-release dispatch for recovery. If the immutable
software Release already exists, that workflow verifies and reuses its signed
assets only after the replay wheel matches the bundled wheel byte for byte, preserving the original signed provenance
for channel recovery. Never rebuild or rename a wheel locally.
OVA and Hyper-V images use the separate manual lifecycle documented in the
virtualization artifact guide. A maintainer workstation creates and
smokes virtualization-vX.Y.Z-rc.N; protected hosted jobs sign it, and the exact bytes may become
virtualization-vX.Y.Z only after isolated Proxmox and KVM smoke. Never attach virtualization assets to vX.Y.Z,
advance an appliance-update channel from a virtualization workflow, or give signing material or write-capable tokens
to a self-hosted runner.