Add `prune` operation to v2 API standard operations
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
## Background
Backend.AI accumulates DB records of terminal-state entities over time (terminated sessions/kernels, delete-complete vfolders, etc.) along with their RBAC associations in association_scopes_entities. There is currently no first-class operation to clean these records in a controlled, audited way. This epic introduces a standard prune operation in v2 API to address this.
## Goal
Add `prune` as the 7th standard operation in v2 API, alongside `create`, `get`, `search`, `update`, `delete`, and `purge`. prune is a bulk sweep that removes records matching a hardcoded terminal-state condition per entity, optionally bounded by a time argument.
`prune` is distinct from `purge`: purge hard-deletes a single specific instance by ID, while prune sweeps all qualifying records of an entity type.
## Scope
### Per-entity prune endpoints
`POST /api/rest/v2/{entity}/prune`
- Terminal-state condition is hardcoded per entity (caller cannot override via status filter).
- Optional `until` / `before` argument bounded by an entity-specific timestamp column (e.g., terminated_at for session/kernel, deleted_at for vfolder).
- Optional `limit` argument to cap rows processed per call.
- RBAC cascade option (default **ON**): when ON, matching rows in association_scopes_entities are deleted in the same transaction (association first, entity second).
- Response shape: `{count: int, ids: [UUID, ...]`}.
### Standalone RBAC prune endpoint
`POST /api/rest/v2/rbac/prune`
- Removes orphan rows in association_scopes_entities whose (entity_type, entity_id) no longer exists in the target entity table.
- No filter args other than `limit`.
- Requires a registry mapping `entity_type` -> target table for polymorphic lookup.
- Acts as a safety net; under normal operation, per-entity prune (RBAC cascade ON by default) keeps orphans from accumulating.
### Common requirements
- **Authorization**: superadmin only (`admin_only`).
- **Scope**: global (no domain/project scoping).
- **Audit log**: each prune call records caller, entity type, `until` argument, count, and id list.
- **Concurrency**: single transaction with `DELETE ... RETURNING`; PostgreSQL row locks naturally serialize concurrent callers.
- **CLI**: each prune endpoint exposed via `./bai` v2 CLI.
## Out of scope
- Background sweepers / cron-based automatic pruning (operator-triggered only).
- Retention policies (immediate prune; no "wait N days after termination" logic).
- Per-instance hard-delete via prune (use `purge`).
- Recovery / undo of pruned records.
## Initial target entities
- Session / Kernel (terminal: `terminated`).
- vfolder (terminal: `delete-complete`).
- Additional entities to be enumerated as child stories.
## Open items for child stories
- Per-entity terminal-state condition and timestamp column for `until` filter.
- `entity_type` -> table registry for RBAC orphan prune.
- CLI flag naming for the RBAC cascade option.
JIRA Issue: BA-5935
Contributor guide
Assessment
This issue has not been assessed yet.