Files
wrenn/db/migrations/20260324220743_audit_logs.sql
pptx704 1be30034bd Add audit log infrastructure and GET /v1/audit-logs endpoint
Introduces an append-only audit trail for all user and system actions:
sandbox lifecycle (create/pause/resume/destroy/auto-pause), snapshots,
team rename, API key create/revoke, member add/remove/leave/role_update,
and BYOC host add/delete/marked_down/marked_up.

- New audit_logs table (migration) with team_id, actor, resource,
  action, scope (team|admin), status (success|info|warning|error),
  metadata, and created_at
- AuditLogger (internal/audit) with named fire-and-forget methods per
  event; system actor used for background events (HostMonitor, TTL reaper)
- GET /v1/audit-logs: JWT-only, cursor pagination (max 200), multi-value
  filters for resource_type and action (comma-sep or repeated params);
  members see team-scoped events only, admins/owners see all
- AuthContext extended with APIKeyID + APIKeyName so API key requests
  record meaningful actor identity
- HostMonitor wired with AuditLogger for auto-pause and host marked_down
2026-03-25 05:15:16 +06:00

29 lines
1.5 KiB
SQL

-- +goose Up
CREATE TABLE audit_logs (
id TEXT PRIMARY KEY,
team_id TEXT NOT NULL,
actor_type TEXT NOT NULL, -- 'user', 'api_key', 'system'
actor_id TEXT, -- user_id or api_key_id; NULL for system
actor_name TEXT, -- display name snapshotted at write time; NULL for system
resource_type TEXT NOT NULL, -- 'sandbox', 'snapshot', 'team', 'api_key', 'member', 'host'
resource_id TEXT, -- primary ID of the affected resource; NULL when not applicable
action TEXT NOT NULL, -- 'create', 'pause', 'resume', 'destroy', 'delete', 'rename',
-- 'revoke', 'add', 'remove', 'leave', 'role_update',
-- 'marked_down', 'marked_up'
scope TEXT NOT NULL, -- 'team' or 'admin'
status TEXT NOT NULL, -- 'success', 'info', 'warning', 'error'
metadata JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Primary access pattern: team feed sorted newest-first with cursor pagination.
CREATE INDEX idx_audit_logs_team_time ON audit_logs (team_id, created_at DESC);
-- Secondary index: filtered by resource_type and action within a team.
CREATE INDEX idx_audit_logs_team_resource ON audit_logs (team_id, resource_type, action, created_at DESC);
-- +goose Down
DROP TABLE audit_logs;