feat(audit): add audit_log infrastructure and instrument AnnotationService
- V46 migration: audit_log table with indexes and append-only REVOKE - audit/ package: AuditKind enum (with Javadoc payloads), AuditLog entity, AuditLogRepository, AuditService (@Async on dedicated auditExecutor) - AsyncConfig: auditExecutor with CallerRunsPolicy and queueCapacity 50 - AnnotationService: ANNOTATION_CREATED on createAnnotation() only, deferred via afterCommit() when inside a transaction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
-- Append-only audit trail for domain-level archive activity.
|
||||
-- Enables dashboard queries (Family Pulse, activity feed, resume card) in #271.
|
||||
|
||||
CREATE TABLE audit_log (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
happened_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
-- ON DELETE SET NULL is by design: GDPR right-to-erasure. Deleted users' events
|
||||
-- retain their timestamp and kind but lose actor attribution.
|
||||
actor_id UUID REFERENCES app_users(id) ON DELETE SET NULL,
|
||||
kind VARCHAR(50) NOT NULL,
|
||||
document_id UUID REFERENCES documents(id) ON DELETE CASCADE,
|
||||
payload JSONB
|
||||
);
|
||||
|
||||
CREATE INDEX idx_audit_log_happened_at ON audit_log (happened_at DESC);
|
||||
CREATE INDEX idx_audit_log_document_id ON audit_log (document_id);
|
||||
CREATE INDEX idx_audit_log_actor_id ON audit_log (actor_id);
|
||||
CREATE INDEX idx_audit_log_kind ON audit_log (kind);
|
||||
|
||||
-- Enforce append-only at the database layer: the application role may INSERT
|
||||
-- but must not UPDATE or DELETE audit rows.
|
||||
REVOKE UPDATE, DELETE ON audit_log FROM app_user;
|
||||
Reference in New Issue
Block a user