CREATE TABLE IF NOT EXISTS audit_logs ( id BIGINT GENERATED BY DEFAULT AS IDENTITY, actor_id BIGINT, actor_username VARCHAR(50), action SMALLINT NOT NULL, target_type SMALLINT, target_id VARCHAR(100), details JSONB, ip_address TEXT, user_agent TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, CHECK (details IS NULL OR jsonb_typeof(details) = 'object'), PRIMARY KEY (id, created_at) ) PARTITION BY RANGE (created_at); CREATE INDEX IF NOT EXISTS idx_audit_logs_actor_created ON audit_logs(actor_id, created_at DESC) WHERE actor_id IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_audit_logs_action_created ON audit_logs(action, created_at DESC); CREATE INDEX IF NOT EXISTS idx_audit_logs_target_created ON audit_logs(target_type, target_id, created_at DESC) WHERE target_type IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_audit_logs_ip_address ON audit_logs(ip_address) WHERE ip_address IS NOT NULL;