-- ── Relay operator audit (append-only roster mutation trail) ───────────────── -- One row per PUT/DELETE /operators/{pubkey} mutation. The roster is the -- deployment-wide root of trust and its mutations overwrite/remove in place; -- this append-only trail records who granted, elevated, or revoked whom, and -- when, so privilege changes are as auditable as the enforcement actions those -- principals perform. Written only inside the upsert/delete transactions; no -- UPDATE/DELETE path. CREATE TABLE relay_operator_audit ( id UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), actor_pubkey BYTEA NOT NULL CHECK (length(actor_pubkey) = 32), target_pubkey BYTEA NOT NULL CHECK (length(target_pubkey) = 32), op TEXT NOT NULL CHECK (op IN ('grant', 'revoke')), prev_role TEXT CHECK (prev_role IN ('operator', 'moderator')), new_role TEXT CHECK (new_role IN ('operator', 'moderator')), -- created_at is wall-clock occurrence time (clock_timestamp()), informational -- only — not monotonic, so it never establishes order. `seq` is the sole -- chronology key: mutations write their audit row under the serializing lock, -- so identity order equals the true privilege chain. Reads use ORDER BY seq. created_at TIMESTAMPTZ NOT NULL DEFAULT clock_timestamp(), seq BIGINT GENERATED ALWAYS AS IDENTITY ); CREATE INDEX idx_relay_operator_audit_target ON relay_operator_audit (target_pubkey, seq);