CONCEPT Cited by 1 source
Publish-time immutability¶
Publish-time immutability is the semantics in which a composite software artifact — a release, a package version, a container tag — is locked at the moment of publication so no actor (including the original publisher) can later modify, replace, or delete its contents. It is a publish-time one-way door: the decision to make this release immutable is committed atomically with the release itself.
Distinguished from related immutability shapes:
| Shape | Locked at | Scope | Who can unlock |
|---|---|---|---|
| Publish-time immutability (this page) | publish | composite (tag + assets + metadata) | nobody, for the life of the release |
| Immutable object storage | write | single blob / object | nobody — objects are individually WORM |
| Retention policy | time-based | per-object or per-bucket | policy admin (time-bounded) |
| Mutable-with-audit | write | any | anyone; audit log preserved |
The difference matters for supply-chain policy. An object-lock guarantee (S3 Object Lock, Azure Blob immutability) protects a single blob. A retention policy is a temporal rule. Publish-time immutability protects a coherent named aggregate — the specific thing a consumer names when they say "version 1.4.2 of this software" — across the blob, the name that points to it (the Git tag), and the metadata bundle.
Canonical instance: GitHub immutable releases (2025-10-28)¶
GitHub's GA feature is the wiki's canonical production instance:
- Lock scope: assets + Git tag + release metadata, as one aggregate.
- Lock trigger: publishing the release while the repo/org setting is on.
- Unlock mechanism: none — "disabling immutability doesn't affect releases created while it was enabled."
- Enforcement surface: GitHub's own release/tag-update code paths reject modifications on immutable releases.
- Off-platform verification: a release attestation in Sigstore bundle format ships with the release, so mirrors and air-gapped consumers can verify integrity without re-contacting GitHub.
(Source: sources/2025-10-31-github-immutable-releases-ga)
Why publish-time and not later¶
Publish-time is the only time the publisher's intent is unambiguous. "I am publishing version X with these bytes" is a deliberate act. Any later modification — even by the same account — is by definition a different intent ("I want the bytes for X to now be Y"). Immutability refuses to execute that second intent: if the assets for X need to change, a new release Y has to be published.
The alternative — retention-policy or mutable-with-audit immutability — can't distinguish "legitimate correction" from "compromised-account asset swap" at policy-evaluation time, so it provides weaker supply-chain guarantees.
Why non-retroactive disable is definitional¶
The "once immutable, always immutable" property is not a GitHub implementation quirk — it is what makes publish-time immutability meaningful. If disabling the setting retroactively unlocked prior releases, then an attacker with control of the setting toggle (an admin credential, a compromised OAuth app with org-admin scope) could swap any release's assets after the fact, and downstream consumers' prior verifications would be invalidated. Non-retroactive disable pushes the trust boundary from is this setting currently on? to was this setting on at publish time? — a historical fact that the attestation itself encodes.
Architectural implications¶
-
Scope must be new-artifacts-only on rollout. Applying publish-time immutability to an existing catalogue would either require re-publishing every release (operational nightmare, breaks existing consumers' cached hashes) or treating old releases as retroactively-immutable (captures back-catalogue errors no one can fix). GitHub's "existing releases remain mutable unless republished" is the standard dodge — backward compatibility via scope-to-new-objects.
-
Control-plane enforcement, data-plane outputs. The repo/org setting that enforces immutability is a control-plane invariant; the attestation bundle is the data-plane output. Consumers verify the data-plane output without re-reading the control-plane state.
-
Composes with tag protection and attestation, not competes. Publish-time immutability is the policy. concepts/tag-protection is one of its enforcement clauses (tag can't be re-pointed). concepts/release-attestation is the portable receipt.
Seen in¶
- sources/2025-10-31-github-immutable-releases-ga — GitHub Releases GA, 2025-10-28.
Related¶
- concepts/immutable-object-storage — blob-level immutability; the primitive underneath asset locking.
- concepts/tag-protection — the Git-ref clause of publish-time immutability.
- concepts/release-attestation — the portable cryptographic witness.
- systems/github-releases — the canonical production implementation.
- patterns/sigstore-bundle-attestation — the reusable verification shape.