Skip to content

Add ak quarantine hold, and document the quarantine commands shipped in v1.2.0 #156

Description

@brandonrc

Corrected 2026-07-28. The original body of this issue was substantially wrong. It claimed the CLI had no quarantine support at all. It does, and has since v1.2.0. The corrected scope is below; see the comment thread for what changed and why.

Summary

ak quarantine shipped in v1.2.0 with status, release, and reject. Two gaps remain:

  1. There is no hold subcommand, despite the backend exposing an admin quarantine-now endpoint.
  2. The command shipped undocumented. It is absent from the README command list and never got a CHANGELOG entry.

What already exists

src/commands/quarantine.rs (404 lines), added in 32c0aa6 "feat: add quarantine CLI command coverage (#102)" on 2026-07-09. Wired into src/cli.rs and src/commands/mod.rs, with 17 passing tests covering clap parsing, wiremock-backed handler behaviour, and two insta snapshots.

Implemented today:

ak quarantine status <artifact-id>
ak quarantine release <artifact-id>
ak quarantine reject <artifact-id> [--reason "..."]

Gap 1: no hold subcommand

origin/main of the backend registers four quarantine routes:

.route("/:artifact_id", get(get_quarantine_status))
.route("/:artifact_id/quarantine", post(quarantine_artifact))   // admin: quarantine now
.route("/:artifact_id/release", post(release_artifact))
.route("/:artifact_id/reject", post(reject_artifact))

The CLI covers three of the four. POST /:artifact_id/quarantine has no CLI equivalent, so placing a manual admin hold is the one quarantine operation with no command.

Proposed:

ak quarantine hold <artifact-id> --reason "..."

Implementation notes:

  • Verify the request body shape and whether the reason is required against backend/src/api/handlers/quarantine.rs on origin/main.
  • Match the conventions of the three existing subcommands, including their test style.
  • Check whether the vendored SDK's ClientQuarantineExt exposes the quarantine-now operation. If the vendored SDK is stale relative to the backend, use the same raw HTTP path the sibling commands use rather than blocking on an SDK regen.

Gap 2: undocumented

ak quarantine is missing from the README command list and has no CHANGELOG entry, so it shipped in v1.2.0 with no user-facing documentation. completion.rs needs no change; it derives from the clap tree via Cli::command().

Explicitly out of scope

ak quarantine list is not implementable. The backend has no endpoint listing quarantined artifacts; all four routes are keyed by a single artifact_id. This needs a backend counterpart first and should be filed separately if wanted.

Do not make --reason required on reject. RejectRequest.reason is Option<String> on the backend ("Optional reason for rejection"), and the shipped command correctly mirrors that. Changing it would be a breaking change to a released command.

Note on API path drift

The running 1.6.0-demo-fix build exposes the admin hold at POST /api/v1/quarantine/{artifact_id} (verified live, HTTP 200), while origin/main exposes it at POST /api/v1/quarantine/{artifact_id}/quarantine. The endpoint was renamed after that image was built. Implement against origin/main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions