ALTER TABLE staff_outbox ADD COLUMN IF NOT EXISTS subject_type TEXT; ALTER TABLE staff_outbox ADD COLUMN IF NOT EXISTS subject_id VARCHAR(26); ALTER TABLE staff_outbox ADD COLUMN IF NOT EXISTS actor_type TEXT; ALTER TABLE staff_outbox ADD COLUMN IF NOT EXISTS actor_id VARCHAR(26); UPDATE staff_outbox SET subject_type = COALESCE(subject_type, payload #>> '{subject,type}', 'staff.Unknown'), subject_id = COALESCE(subject_id, payload #>> '{subject,id}', id), actor_type = COALESCE(actor_type, payload #>> '{actor,type}', 'service'), actor_id = COALESCE(actor_id, payload #>> '{actor,id}', correlation_id) WHERE subject_type IS NULL OR subject_id IS NULL OR actor_type IS NULL OR actor_id IS NULL; ALTER TABLE staff_outbox ALTER COLUMN subject_type SET NOT NULL; ALTER TABLE staff_outbox ALTER COLUMN subject_id SET NOT NULL; ALTER TABLE staff_outbox ALTER COLUMN actor_type SET NOT NULL; ALTER TABLE staff_outbox ALTER COLUMN actor_id SET NOT NULL; ALTER TABLE staff_outbox DROP CONSTRAINT IF EXISTS staff_outbox_subject_id_check; ALTER TABLE staff_outbox ADD CONSTRAINT staff_outbox_subject_id_check CHECK (subject_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_outbox DROP CONSTRAINT IF EXISTS staff_outbox_actor_type_check; ALTER TABLE staff_outbox ADD CONSTRAINT staff_outbox_actor_type_check CHECK (actor_type IN ('user', 'service')); ALTER TABLE staff_outbox DROP CONSTRAINT IF EXISTS staff_outbox_actor_id_check; ALTER TABLE staff_outbox ADD CONSTRAINT staff_outbox_actor_id_check CHECK (actor_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_outbox DROP CONSTRAINT IF EXISTS staff_outbox_correlation_id_check; ALTER TABLE staff_outbox ADD CONSTRAINT staff_outbox_correlation_id_check CHECK (correlation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_outbox DROP CONSTRAINT IF EXISTS staff_outbox_causation_id_check; ALTER TABLE staff_outbox ADD CONSTRAINT staff_outbox_causation_id_check CHECK (causation_id IS NULL OR causation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_inbox DROP CONSTRAINT IF EXISTS staff_inbox_event_id_check; ALTER TABLE staff_inbox ADD CONSTRAINT staff_inbox_event_id_check CHECK (event_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_inbox DROP CONSTRAINT IF EXISTS staff_inbox_tenant_id_check; ALTER TABLE staff_inbox ADD CONSTRAINT staff_inbox_tenant_id_check CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_inbox DROP CONSTRAINT IF EXISTS staff_inbox_correlation_id_check; ALTER TABLE staff_inbox ADD CONSTRAINT staff_inbox_correlation_id_check CHECK (correlation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_inbox DROP CONSTRAINT IF EXISTS staff_inbox_causation_id_check; ALTER TABLE staff_inbox ADD CONSTRAINT staff_inbox_causation_id_check CHECK (causation_id IS NULL OR causation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_idempotency_keys DROP CONSTRAINT IF EXISTS staff_idempotency_keys_tenant_id_check; ALTER TABLE staff_idempotency_keys ADD CONSTRAINT staff_idempotency_keys_tenant_id_check CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_audit_log DROP CONSTRAINT IF EXISTS staff_audit_log_id_check; ALTER TABLE staff_audit_log ADD CONSTRAINT staff_audit_log_id_check CHECK (id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_audit_log DROP CONSTRAINT IF EXISTS staff_audit_log_tenant_id_check; ALTER TABLE staff_audit_log ADD CONSTRAINT staff_audit_log_tenant_id_check CHECK (tenant_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_audit_log DROP CONSTRAINT IF EXISTS staff_audit_log_actor_id_check; ALTER TABLE staff_audit_log ADD CONSTRAINT staff_audit_log_actor_id_check CHECK (actor_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_audit_log DROP CONSTRAINT IF EXISTS staff_audit_log_entity_id_check; ALTER TABLE staff_audit_log ADD CONSTRAINT staff_audit_log_entity_id_check CHECK (entity_id IS NULL OR entity_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); ALTER TABLE staff_audit_log DROP CONSTRAINT IF EXISTS staff_audit_log_correlation_id_check; ALTER TABLE staff_audit_log ADD CONSTRAINT staff_audit_log_correlation_id_check CHECK (correlation_id ~ '^[0-9A-HJKMNP-TV-Z]{26}$'); DROP POLICY IF EXISTS staff_audit_tenant_isolation ON staff_audit_log; DROP POLICY IF EXISTS staff_audit_tenant_select ON staff_audit_log; DROP POLICY IF EXISTS staff_audit_tenant_insert ON staff_audit_log; CREATE POLICY staff_audit_tenant_select ON staff_audit_log FOR SELECT USING (tenant_id = current_setting('app.tenant_id', true)); CREATE POLICY staff_audit_tenant_insert ON staff_audit_log FOR INSERT WITH CHECK ( tenant_id = current_setting('app.tenant_id', true) AND actor_id = current_setting('app.user_id', true) ); DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'krona_staff_app') THEN GRANT USAGE ON SCHEMA public TO krona_staff_app; GRANT SELECT, INSERT, UPDATE, DELETE ON staff_outbox, staff_inbox, staff_idempotency_keys TO krona_staff_app; GRANT SELECT, INSERT ON staff_audit_log TO krona_staff_app; REVOKE UPDATE, DELETE, TRUNCATE ON staff_audit_log FROM krona_staff_app; END IF; END $$;