-
Notifications
You must be signed in to change notification settings - Fork 25
Description
After all versions of a secret are deleted, the secret metadata remains in the backend storage indefinitely. This causes unbounded storage growth over time. A spike secret purge command is needed to permanently remove these empty secret entries.
Problem
When a user deletes all versions of a secret:
spike secret delete secrets/db/creds --all-versions
The secret's metadata (path, timestamps, etc.) remains in the backend with CurrentVersion == 0. Over time, this accumulates and wastes storage space.
Proposed Solution
Implement a spike secret purge command that:
- Scans all secrets in the backend
- Identifies secrets where CurrentVersion == 0 (all versions deleted)
- Uses the backend's Destroy() method to permanently remove them
- Reports how many secrets were purged
Usage
Interactive confirmation (default)
spike secret purge
Output: Found 42 empty secrets. Purge them? [y/N]
Skip confirmation
spike secret purge --force
Show what would be purged without actually purging
spike secret purge --dry-run
Output:
Would purge: secrets/old/api-key
Would purge: secrets/deprecated/token
Would purge: secrets/test/temp
Dry run: 3 secrets would be purged
Combined: preview then purge
spike secret purge --dry-run
spike secret purge --force
Future Enhancement
Consider adding time-based filtering:
Only purge secrets emptied more than 30 days ago
spike secret purge --older-than 30d
This allows operators to keep recently-deleted secrets recoverable for a grace period.
Implementation Notes
SDK Support
The spike-sdk-go already has the necessary building blocks:
- Value.IsEmpty() - Check if a secret has no versions
- KV.Destroy() - Permanently remove a secret entry
Backend Changes
SPIKE Nexus backend needs a corresponding Destroy() implementation:
- SQLite: DELETE FROM secrets WHERE path = ?
- Memory: delete(store, path)
- Lite: Similar to SQLite
API Endpoint
New endpoint needed:
- POST /v1/secrets/purge - Purge empty secrets
- Request body: { "force": bool, "dryRun": bool, "olderThan": duration }
- Response: { "purged": int, "paths": []string }
Alternatively, could be implemented as:
- DELETE /v1/secrets/{path}?destroy=true - For single secret destruction
- POST /v1/secrets/purge - For bulk purge operation
Authorization
Purge should require super permission or a new purge permission on the system path.
Files to Create/Modify
- app/pilot/internal/cmd/secret/purge.go - New CLI command
- app/nexus/internal/route/secret/purge.go - New API endpoint
- app/nexus/internal/state/backend/sqlite/persist/secret.go - Add Destroy() method
- app/nexus/internal/state/backend/memory/secret.go - Add Destroy() method
- app/nexus/internal/state/backend/lite/secret.go - Add Destroy() method
- spike-sdk-go/api/secret.go - Add Purge() method
- docs-src/content/usage/commands/secret.md - Document new command