import { MigrationInterface, QueryRunner } from 'typeorm'; export class PhaseAAuditEvents1786548002000 implements MigrationInterface { name = 'PhaseAAuditEvents1786548002000'; public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` CREATE TABLE audit_events ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), occurred_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, actor_user_id uuid, actor_username varchar(80), action varchar(100) NOT NULL, entity_type varchar(100), entity_id varchar(255), request_id varchar(128), source varchar(32) NOT NULL, ip inet, user_agent text, before_data jsonb, after_data jsonb, metadata jsonb, CONSTRAINT fk_audit_events_actor_user FOREIGN KEY (actor_user_id) REFERENCES users(id) ON DELETE SET NULL, CONSTRAINT chk_audit_events_json_objects CHECK ( (before_data IS NULL OR jsonb_typeof(before_data) = 'object') AND (after_data IS NULL OR jsonb_typeof(after_data) = 'object') AND (metadata IS NULL OR jsonb_typeof(metadata) = 'object') ) ) `); await queryRunner.query(` CREATE INDEX idx_audit_events_occurred_at ON audit_events (occurred_at DESC) `); await queryRunner.query(` CREATE INDEX idx_audit_events_actor_user_id ON audit_events (actor_user_id) `); await queryRunner.query(` CREATE INDEX idx_audit_events_action ON audit_events (action) `); await queryRunner.query(` CREATE INDEX idx_audit_events_entity ON audit_events (entity_type, entity_id) `); await queryRunner.query(` CREATE INDEX idx_audit_events_request_id ON audit_events (request_id) `); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query('DROP TABLE audit_events'); } }