[PR #32] [CLOSED] fix(snapshot): isolate registry publications on delete #130

Closed
opened 2026-10-29 14:20:01 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/kvcache-ai/AgentENV/pull/32
Author: @catyans
Created: 7/28/2026
Status: ❌ Closed

Base: main ← Head: fix/snapshot-publication-delete-safety-pr


📝 Commits (2)

  • ab03c3c fix(snapshot): isolate registry publications on delete
  • 3780276 fix(snapshot): hide durable deletion tombstones

📊 Changes

6 files changed (+182 additions, -58 deletions)

View changed files

📝 src/snapshot/repository/backends/common/acr/manifest.rs (+31 -0)
📝 src/snapshot/repository/backends/common/acr/publisher.rs (+28 -9)
📝 src/snapshot/repository/backends/oss/repository.rs (+87 -49)
📝 src/snapshot/repository/backends/posixfs/catalog.rs (+1 -0)
📝 src/snapshot/repository/interfaces.rs (+4 -0)
📝 src/snapshot/types/snapshot.rs (+31 -0)

📄 Description

Summary

  • add the exact snapshot publication tag to the top-level OCI manifest annotations;
  • make rootfs and attached-drive manifest digests publication-specific while preserving layer and config blob deduplication;
  • delete external registry publications before removing the durable OSS catalog record;
  • persist a reader-invisible deletion tombstone before external cleanup;
  • keep publication metadata and alias retry handles available when cleanup fails;
  • reject invalid persisted repoBlobUrl metadata instead of treating cleanup as successful.

Motivation

OCI registries delete manifests by content digest. Previously, two snapshot
publications with the same config and OverlayBD layer descriptors produced the
same manifest bytes and digest. Deleting either publication by digest could
therefore invalidate tags owned by another snapshot.

The manifest now includes:

{
  "annotations": {
    "io.agentenv.snapshot.tag": "agentenv-snapshot-<snapshot-id>"
  }
}

Attached drives use their complete generated publication tag. Only the small
manifest object becomes unique; config and layer blobs remain content-addressed
and shared.

Deletion semantics

Before external cleanup begins, the OSS record is durably marked deleting.
Public get, list, and alias resolution hide this tombstone, while internal
deletion lookup retains access by ID or alias to the publication metadata
needed for retry. Manifest deletion already treats registry 404 Not Found as
success, so retries after partially completed cleanup remain idempotent.

If external cleanup fails, the alias, tombstoned catalog record, and snapshot
artifacts are retained. The alias is removed only after external cleanup and
catalog deletion succeed.

Verification

Validated on an Alibaba Cloud Linux 3 node with Rust 1.97.1:

cargo fmt --all -- --check
cargo test -p agentenv snapshot::repository::backends::common::acr::manifest::tests
cargo test -p agentenv snapshot::repository::backends::common::acr::publisher::tests
cargo test -p agentenv deleting
cargo clippy -p agentenv --all-targets -- -D warnings

The new tests verify that identical layers with different publication tags
produce different manifest digests, invalid persisted repository metadata fails
cleanup, legacy records deserialize without a tombstone, and deleting records
are hidden from readers.

Fixes #16.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/kvcache-ai/AgentENV/pull/32 **Author:** [@catyans](https://github.com/catyans) **Created:** 7/28/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/snapshot-publication-delete-safety-pr` --- ### 📝 Commits (2) - [`ab03c3c`](https://github.com/kvcache-ai/AgentENV/commit/ab03c3c881a4af117e29cde77e7fa806ab79df81) fix(snapshot): isolate registry publications on delete - [`3780276`](https://github.com/kvcache-ai/AgentENV/commit/3780276d4f1d1415f6b569ee42d54270f5e5aa28) fix(snapshot): hide durable deletion tombstones ### 📊 Changes **6 files changed** (+182 additions, -58 deletions) <details> <summary>View changed files</summary> 📝 `src/snapshot/repository/backends/common/acr/manifest.rs` (+31 -0) 📝 `src/snapshot/repository/backends/common/acr/publisher.rs` (+28 -9) 📝 `src/snapshot/repository/backends/oss/repository.rs` (+87 -49) 📝 `src/snapshot/repository/backends/posixfs/catalog.rs` (+1 -0) 📝 `src/snapshot/repository/interfaces.rs` (+4 -0) 📝 `src/snapshot/types/snapshot.rs` (+31 -0) </details> ### 📄 Description ## Summary - add the exact snapshot publication tag to the top-level OCI manifest annotations; - make rootfs and attached-drive manifest digests publication-specific while preserving layer and config blob deduplication; - delete external registry publications before removing the durable OSS catalog record; - persist a reader-invisible deletion tombstone before external cleanup; - keep publication metadata and alias retry handles available when cleanup fails; - reject invalid persisted `repoBlobUrl` metadata instead of treating cleanup as successful. ## Motivation OCI registries delete manifests by content digest. Previously, two snapshot publications with the same config and OverlayBD layer descriptors produced the same manifest bytes and digest. Deleting either publication by digest could therefore invalidate tags owned by another snapshot. The manifest now includes: ```json { "annotations": { "io.agentenv.snapshot.tag": "agentenv-snapshot-<snapshot-id>" } } ``` Attached drives use their complete generated publication tag. Only the small manifest object becomes unique; config and layer blobs remain content-addressed and shared. ## Deletion semantics Before external cleanup begins, the OSS record is durably marked `deleting`. Public `get`, `list`, and alias resolution hide this tombstone, while internal deletion lookup retains access by ID or alias to the publication metadata needed for retry. Manifest deletion already treats registry `404 Not Found` as success, so retries after partially completed cleanup remain idempotent. If external cleanup fails, the alias, tombstoned catalog record, and snapshot artifacts are retained. The alias is removed only after external cleanup and catalog deletion succeed. ## Verification Validated on an Alibaba Cloud Linux 3 node with Rust 1.97.1: ```text cargo fmt --all -- --check cargo test -p agentenv snapshot::repository::backends::common::acr::manifest::tests cargo test -p agentenv snapshot::repository::backends::common::acr::publisher::tests cargo test -p agentenv deleting cargo clippy -p agentenv --all-targets -- -D warnings ``` The new tests verify that identical layers with different publication tags produce different manifest digests, invalid persisted repository metadata fails cleanup, legacy records deserialize without a tombstone, and deleting records are hidden from readers. Fixes #16. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-29 14:20:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kvcache-ai/AgentENV#130
No description provided.