[PR #359] feat(image): expose the published image catalog #380

Open
opened 2026-10-29 14:22:48 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/kvcache-ai/AgentENV/pull/359
Author: @Primary33
Created: 10/11/2026
Status: 🔄 Open

Base: main ← Head: feat/image-catalog


📝 Commits (2)

  • 6e1cb01 feat: build and publish reusable images with the CLI
  • 580e3dc feat: list inspect and delete published images

📊 Changes

33 files changed (+6616 additions, -208 deletions)

View changed files

📝 crates/aenv/src/commands/build.rs (+221 -66)
📝 crates/aenv/src/main.rs (+1 -1)
📝 docs/src/concepts/sandboxes/starting.md (+84 -1)
📝 scripts/buildkit/test.py (+59 -0)
➕ services/gateway/internal/image_build_test.go (+136 -0)
📝 services/gateway/internal/metrics.go (+15 -1)
📝 services/gateway/internal/routes.go (+5 -1)
📝 services/gateway/internal/routes_test.go (+9 -1)
📝 services/gateway/internal/server.go (+31 -2)
➕ src/api/generated/src/apis/images.rs (+300 -0)
📝 src/api/generated/src/apis/mod.rs (+1 -0)
📝 src/api/generated/src/models.rs (+1571 -1)
📝 src/api/generated/src/server/mod.rs (+1552 -0)
📝 src/api/impls/image_build.rs (+636 -65)
📝 src/api/impls/image_build/cleanup.rs (+45 -6)
📝 src/api/impls/image_build/tests.rs (+592 -3)
📝 src/api/impls/image_build/transport.rs (+44 -1)
📝 src/api/impls/image_build/worker.rs (+5 -5)
📝 src/api/impls/mod.rs (+1 -0)
📝 src/api/openapi.yml (+363 -1)

...and 13 more files

📄 Description

What

Expose repository-backed GET /images, GET /images/{digest}, and DELETE /images/{digest} for published images, plus GET /images/tags and DELETE /images/tags/{tag} for image tags.

Why

Users need to inspect and remove image catalog entries and tags without invalidating running sandboxes or snapshots that already reference the shared layers.

Design proposal: #378.

Depends on image builds (#347). Review this feature only. Rebase onto main after #347 merges.

Scope and non-goals

Catalog and tag-management API and gateway routes, document collections for images and tags, and standalone image lifecycle tests. Deleting an image does not reclaim layers or delete the tags that point to it.

Design and behavior changes

  • Paginate image summaries with GET /images; retrieve the full published description by canonical SHA256 identity with GET /images/{digest}.
  • Delete the catalog entry while retaining shared layers used by existing sandboxes and snapshots.
  • Reject subsequent launches by a deleted image digest; preserve active sandboxes, resume, fork, and snapshot restore.
  • Paginate tags in name:tag order with GET /images/tags, using the same cursor rules as GET /images. DELETE /images/tags/{tag} is idempotent and never deletes the image.
  • Deleting an image leaves its tags in place; resolving such a tag fails until it is moved or deleted.
  • After #370 the catalog uses DocumentCollection::Images / ImageTags with the generic list_documents and delete_document, so the OSS- and POSIX-specific list/delete methods from the previous revision are gone and no backend code changes. Their OSS mock-S3 round-trip test went with them; the catalog logic is now covered by backend-independent tests.

Compatibility and operations

  • Public API or generated protocol: additive /images, /images/{digest}, /images/tags, and DELETE /images/tags/{tag}.
  • Configuration or defaults: none; the endpoints use the existing repository configuration.
  • Snapshot manifest, artifact layout, or storage format: none beyond #347. Deletion removes documents, not shared layer objects.
  • Upgrade and rollback: upgrade the gateway and server together.
  • Host requirements, permissions, ports, or dependencies: N/A.

Validation

Rebased onto 87c1df3. Run on a Linux test host as a non-root user with isolated state:

  • make fmt: reported src/image/oci_image.rs from d243f6e, which fails the same check on main, and the line wrapping of one test array in src/image/resolver.rs, which was then rewrapped exactly as rustfmt printed it.
  • make clippy: clean with -A clippy::manual_pattern_char_comparison, needed only for that same main line.
  • make test-unit
  • Relevant Rust tests (see below)
  • make -C services test and make -C services fmt-check vet
  • Generated server regenerated with openapi-generator 7.22.0 (rust-axum), as make agentenv-server does
  • Documentation updated

Commands and results:

cargo test --locked -p aenv                                   passed
cargo test --locked -p agentenv --lib <filter>                passed for image::, types::, repository::,
                                                              api::impls::image_build, api::proxy, volume::
go test ./... (services/)                                     passed
scripts/buildkit/test.py (full suite, 10 tests) against an
  isolated single-node server built from this branch          10 passed in 308 s

The native image test covers canonical digest identity, tagging during the build, cold starts by digest and by aenv/ tag, rejection of both after image deletion, tag deletion, and continued operation, resume, fork isolation, and snapshot restore for existing sandboxes.

Skipped checks and reasons: make test-unit (capability and ublk suites are unaffected).

Risks and reviewer notes

Review catalog and tag deletion semantics, dangling tags after image deletion, and the independence of previously captured sandbox state. CI's fmt and clippy jobs fail on main until the oci_image.rs line is fixed there.

Checklist

  • The PR contains one coherent change and no unrelated formatting or refactoring.
  • New behavior is covered by tests, or I explained why testing is impractical.
  • Logs and examples contain no credentials, tokens, or private registry information.
  • I did not manually edit generated code without updating its source and regenerating it.

🔄 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/359 **Author:** [@Primary33](https://github.com/Primary33) **Created:** 10/11/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/image-catalog` --- ### 📝 Commits (2) - [`6e1cb01`](https://github.com/kvcache-ai/AgentENV/commit/6e1cb016e5b38e05c328740914b821b77abf7fc0) feat: build and publish reusable images with the CLI - [`580e3dc`](https://github.com/kvcache-ai/AgentENV/commit/580e3dcd3af450c3632aed814203320edeee2e95) feat: list inspect and delete published images ### 📊 Changes **33 files changed** (+6616 additions, -208 deletions) <details> <summary>View changed files</summary> 📝 `crates/aenv/src/commands/build.rs` (+221 -66) 📝 `crates/aenv/src/main.rs` (+1 -1) 📝 `docs/src/concepts/sandboxes/starting.md` (+84 -1) 📝 `scripts/buildkit/test.py` (+59 -0) ➕ `services/gateway/internal/image_build_test.go` (+136 -0) 📝 `services/gateway/internal/metrics.go` (+15 -1) 📝 `services/gateway/internal/routes.go` (+5 -1) 📝 `services/gateway/internal/routes_test.go` (+9 -1) 📝 `services/gateway/internal/server.go` (+31 -2) ➕ `src/api/generated/src/apis/images.rs` (+300 -0) 📝 `src/api/generated/src/apis/mod.rs` (+1 -0) 📝 `src/api/generated/src/models.rs` (+1571 -1) 📝 `src/api/generated/src/server/mod.rs` (+1552 -0) 📝 `src/api/impls/image_build.rs` (+636 -65) 📝 `src/api/impls/image_build/cleanup.rs` (+45 -6) 📝 `src/api/impls/image_build/tests.rs` (+592 -3) 📝 `src/api/impls/image_build/transport.rs` (+44 -1) 📝 `src/api/impls/image_build/worker.rs` (+5 -5) 📝 `src/api/impls/mod.rs` (+1 -0) 📝 `src/api/openapi.yml` (+363 -1) _...and 13 more files_ </details> ### 📄 Description ## What Expose repository-backed `GET /images`, `GET /images/{digest}`, and `DELETE /images/{digest}` for published images, plus `GET /images/tags` and `DELETE /images/tags/{tag}` for image tags. ## Why Users need to inspect and remove image catalog entries and tags without invalidating running sandboxes or snapshots that already reference the shared layers. ## Related issue Design proposal: #378. Depends on image builds (#347). [Review this feature only](https://github.com/Primary33/AgentENV/compare/6e1cb016e5b38e05c328740914b821b77abf7fc0...580e3dcd3af450c3632aed814203320edeee2e95). Rebase onto `main` after #347 merges. ## Scope and non-goals Catalog and tag-management API and gateway routes, document collections for images and tags, and standalone image lifecycle tests. Deleting an image does not reclaim layers or delete the tags that point to it. ## Design and behavior changes - Paginate image summaries with `GET /images`; retrieve the full published description by canonical SHA256 identity with `GET /images/{digest}`. - Delete the catalog entry while retaining shared layers used by existing sandboxes and snapshots. - Reject subsequent launches by a deleted image digest; preserve active sandboxes, resume, fork, and snapshot restore. - Paginate tags in `name:tag` order with `GET /images/tags`, using the same cursor rules as `GET /images`. `DELETE /images/tags/{tag}` is idempotent and never deletes the image. - Deleting an image leaves its tags in place; resolving such a tag fails until it is moved or deleted. - After #370 the catalog uses `DocumentCollection::Images` / `ImageTags` with the generic `list_documents` and `delete_document`, so the OSS- and POSIX-specific list/delete methods from the previous revision are gone and no backend code changes. Their OSS mock-S3 round-trip test went with them; the catalog logic is now covered by backend-independent tests. ## Compatibility and operations - Public API or generated protocol: additive `/images`, `/images/{digest}`, `/images/tags`, and `DELETE /images/tags/{tag}`. - Configuration or defaults: none; the endpoints use the existing repository configuration. - Snapshot manifest, artifact layout, or storage format: none beyond #347. Deletion removes documents, not shared layer objects. - Upgrade and rollback: upgrade the gateway and server together. - Host requirements, permissions, ports, or dependencies: N/A. ## Validation Rebased onto `87c1df3`. Run on a Linux test host as a non-root user with isolated state: - [x] `make fmt`: reported `src/image/oci_image.rs` from `d243f6e`, which fails the same check on `main`, and the line wrapping of one test array in `src/image/resolver.rs`, which was then rewrapped exactly as rustfmt printed it. - [x] `make clippy`: clean with `-A clippy::manual_pattern_char_comparison`, needed only for that same `main` line. - [ ] `make test-unit` - [x] Relevant Rust tests (see below) - [x] `make -C services test` and `make -C services fmt-check vet` - [x] Generated server regenerated with openapi-generator 7.22.0 (`rust-axum`), as `make agentenv-server` does - [x] Documentation updated Commands and results: ```text cargo test --locked -p aenv passed cargo test --locked -p agentenv --lib <filter> passed for image::, types::, repository::, api::impls::image_build, api::proxy, volume:: go test ./... (services/) passed scripts/buildkit/test.py (full suite, 10 tests) against an isolated single-node server built from this branch 10 passed in 308 s ``` The native image test covers canonical digest identity, tagging during the build, cold starts by digest and by `aenv/` tag, rejection of both after image deletion, tag deletion, and continued operation, resume, fork isolation, and snapshot restore for existing sandboxes. Skipped checks and reasons: `make test-unit` (capability and ublk suites are unaffected). ## Risks and reviewer notes Review catalog and tag deletion semantics, dangling tags after image deletion, and the independence of previously captured sandbox state. CI's fmt and clippy jobs fail on `main` until the `oci_image.rs` line is fixed there. ## Checklist - [x] The PR contains one coherent change and no unrelated formatting or refactoring. - [x] New behavior is covered by tests, or I explained why testing is impractical. - [x] Logs and examples contain no credentials, tokens, or private registry information. - [x] I did not manually edit generated code without updating its source and regenerating it. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#380
No description provided.