feat(db): schema bootstrap with append-only audit_log table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
-- Append-only audit log. One database == one organization, so there is no org_id.
|
||||
CREATE TABLE audit_log (
|
||||
seq BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
actor_kind TEXT NOT NULL CHECK (actor_kind IN ('user', 'system')),
|
||||
actor_id UUID,
|
||||
action TEXT NOT NULL CHECK (action IN ('created', 'updated', 'deleted')),
|
||||
entity_type TEXT NOT NULL,
|
||||
entity_id UUID NOT NULL,
|
||||
changes JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||||
CONSTRAINT actor_id_matches_kind CHECK (
|
||||
(actor_kind = 'user' AND actor_id IS NOT NULL) OR
|
||||
(actor_kind = 'system' AND actor_id IS NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX audit_log_entity_idx ON audit_log (entity_type, entity_id, seq);
|
||||
|
||||
-- Enforce append-only at the database level: reject any UPDATE or DELETE.
|
||||
CREATE OR REPLACE FUNCTION audit_log_reject_mutation() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
RAISE EXCEPTION 'audit_log is append-only; % is not permitted', TG_OP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER audit_log_immutable
|
||||
BEFORE UPDATE OR DELETE ON audit_log
|
||||
FOR EACH ROW EXECUTE FUNCTION audit_log_reject_mutation();
|
||||
Reference in New Issue
Block a user