Skip to content

Expose asynchronous Service deletion lifecycle consistently in the CLI #25

Description

@rcyw

Summary

Make the asynchronous Service deletion lifecycle explicit and machine-readable across axern service delete, service get, and service list.

The current control-plane model already persists ServiceDeletionStatus, and an exact service get <id> can retrieve a deleted Service. The CLI output layer, however, drops deletion_status; the delete command always prints Service deleted, even though deletion is asynchronous; and the list help does not explain that its default view excludes terminal Services or that --status deleted is the audit lookup path.

This made a successful HK acceptance look like a failed deletion check: service list and agent list no longer showed the Service, while service get <id> showed status=deleted and a deletion-completed latest event. Automation had to infer lifecycle completion from the event because the persisted deletion phase was absent from CLI JSON.

Current behavior

  • axern service delete <id> calls the asynchronous delete API once, then unconditionally prints Service deleted: <id>.
  • axern service get <id> -o json uses a CLI-specific ServiceJSON projection that omits the proto's Service.deletion_status field.
  • axern service list defaults to the active/non-terminal view.
  • axern service list --status deleted already retrieves deleted audit records, but this is not discoverable from the command description.
  • Exact service get <id> remains available after deletion, which is the desired audit behavior until admin service purge is explicitly invoked.

Relevant code:

  • apps/cli/internal/commands/service/command.go
  • apps/cli/internal/output/service_json.go
  • sdk/proto/axern/control/service/v1/service_types.proto

Long-term direction

Keep deletion asynchronous and keep terminal Services hidden from the default list. Make those semantics explicit rather than adding a second list mechanism or a compatibility output path.

  1. Add a typed deletion lifecycle projection to CLI Service JSON, derived directly from ServiceDeletionStatus.
  2. Include deletion phase, volume disposition, claim IDs, message, and completion timestamp when present.
  3. Change the immediate human-readable delete result to state that deletion was requested unless the returned Service is already complete.
  4. Add --wait and --wait-timeout to service delete, using the persisted deletion phase as the completion contract rather than the latest event text.
  5. Document in service list --help that the default view excludes terminal records and that --status deleted retrieves them.
  6. Keep service get <id> as the exact audit lookup and admin service purge <id> as the only permanent record removal path.

Acceptance criteria

  • service get <id> -o json exposes a stable deletion_status object whenever the control plane returns one.
  • service delete <id> no longer reports an asynchronous request as unconditionally completed.
  • service delete <id> --wait --wait-timeout <duration> returns successfully only after SERVICE_DELETION_PHASE_COMPLETE; timeout and lifecycle errors return non-zero.
  • service list --help describes the terminal-record default and gives --status deleted as the retrieval path.
  • Table and JSON output distinguish deleting from deletion-complete without parsing event messages.
  • Tests cover request-only deletion, waited completion, timeout, JSON projection, and explicit deleted-status listing.
  • Public API, persisted lifecycle semantics, default list behavior, and purge authorization remain unchanged.

Non-goals

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestgoPull requests that update go code

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions