release: putImmutable — immutable now means immutable-while-present
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+6
−0
internal/release/release.go+6 −0
diff --git a/internal/release/release.go b/internal/release/release.go| index e76ec9743..82f305a35 100644 |
| --- a/internal/release/release.go |
| +++ b/internal/release/release.go |
| @@ -588,6 +588,12 @@ func Ship(ctx context.Context, s Store, acct string, m Manifest, files map[strin |
| // putImmutable claims a content-addressed key create-only; a lost race is |
| // fine iff the existing bytes are identical (idempotent re-ship), and an |
| // error otherwise (an immutable path must never change meaning). |
| +// |
| +// Since issue #136, "immutable" means immutable-WHILE-PRESENT: a release |
| +// object's bytes never change under its key, but retention (prune.go) and |
| +// whole-app purge (trash.go) may delete it. Create-only writes still refuse |
| +// to overwrite, and a re-ship of a pruned version is a NEW release that |
| +// happens to reuse the name. |
| func putImmutable(ctx context.Context, s Store, key string, body []byte) error { |
| _, err := s.Put(ctx, key, body, "") |
| if !errors.Is(err, ErrCASConflict) { |