Files
accounted/supabase/migrations/20260418130000_processing_history.sql
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

138 lines
5.2 KiB
SQL

-- Processing history (behandlingshistorik)
-- Append-only event log recording every legally significant act per BFNAR 2013:2 kap 8.
-- 7-year retention enforced at application layer (not DB trigger) to allow GDPR redaction.
-- Immutable: UPDATE blocked via audit_log_immutable() trigger.
--
-- seq ordering: BIGSERIAL assigns at statement time, not commit time.
-- Two concurrent transactions may produce seq values out of commit order.
-- For legally meaningful ordering, use occurred_at. seq is a cursor for polling.
-- =============================================================
-- 1. Event type reference table
-- =============================================================
-- Adding a new event type = INSERT, no ALTER TABLE required.
CREATE TABLE public.processing_event_types (
event_type TEXT PRIMARY KEY
);
ALTER TABLE public.processing_event_types ENABLE ROW LEVEL SECURITY;
-- Readable by all authenticated users (reference data)
CREATE POLICY "processing_event_types_select" ON public.processing_event_types
FOR SELECT USING (true);
-- Seed the v0.2 event catalog (28 types)
INSERT INTO public.processing_event_types (event_type) VALUES
-- Document stream
('DocumentIngested'),
('DocumentExtractionAttempted'),
('DocumentClassified'),
('DocumentRejected'),
('DocumentArchived'),
('DocumentSupersededByDuplicate'),
-- BankTransaction stream
('BankTransactionIngested'),
('BankTransactionEnriched'),
-- MatchProposal stream
('MatchAttemptedDeterministic'),
('MatchAttemptedLlm'),
('MatchConfirmed'),
('MatchRejected'),
-- Verifikation stream
('ForslagCreated'),
('ForslagMutated'),
('VerifikationCommitted'),
('RättelseverifikationIssued'),
('ForslagAbandoned'),
-- CounterpartyTemplate stream
('CounterpartyObserved'),
('TemplateStrengthened'),
('TemplateBroken'),
-- Period stream
('PeriodCloseInitiated'),
('PeriodClosed'),
('PeriodReopened'),
-- Migration stream
('MigrationInitiated'),
('MigrationValidated'),
('MigrationCommitted'),
-- System stream
('TimingCeilingTriggered'),
('RubricVersionPublished');
-- =============================================================
-- 2. Processing history table
-- =============================================================
CREATE TABLE public.processing_history (
event_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
seq BIGSERIAL UNIQUE NOT NULL,
company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE RESTRICT,
correlation_id UUID NOT NULL,
causation_id UUID REFERENCES public.processing_history(event_id),
aggregate_type TEXT NOT NULL CHECK (aggregate_type IN (
'Document',
'BankTransaction',
'MatchProposal',
'Verifikation',
'CounterpartyTemplate',
'Period',
'Migration',
'System'
)),
aggregate_id UUID NOT NULL,
event_type TEXT NOT NULL REFERENCES public.processing_event_types(event_type),
payload JSONB NOT NULL DEFAULT '{}',
payload_schema_version SMALLINT NOT NULL DEFAULT 1,
actor JSONB NOT NULL,
rubric_version TEXT,
occurred_at TIMESTAMPTZ NOT NULL,
appended_at TIMESTAMPTZ NOT NULL DEFAULT now()
-- No updated_at: append-only table
);
-- =============================================================
-- 3. Row-level security
-- =============================================================
ALTER TABLE public.processing_history ENABLE ROW LEVEL SECURITY;
-- SELECT: users can read their companies' processing history
CREATE POLICY "processing_history_select" ON public.processing_history
FOR SELECT USING (company_id IN (SELECT public.user_company_ids()));
-- No INSERT/UPDATE/DELETE policies for authenticated users.
-- Writes via service role client only.
-- =============================================================
-- 4. Indexes
-- =============================================================
-- Aggregate history: "full history of this document/transaction/verifikation"
CREATE INDEX idx_ph_aggregate
ON public.processing_history (company_id, aggregate_type, aggregate_id, seq);
-- Event type filtering: "all VerifikationCommitted events for this company"
CREATE INDEX idx_ph_company_event_type
ON public.processing_history (company_id, event_type, seq);
-- Time range: "all events for this company in March 2026" + retention cleanup
CREATE INDEX idx_ph_company_occurred
ON public.processing_history (company_id, occurred_at);
-- =============================================================
-- 5. Immutability trigger
-- =============================================================
-- Reuses audit_log_immutable() which unconditionally blocks all UPDATE operations.
CREATE TRIGGER processing_history_no_update
BEFORE UPDATE ON public.processing_history
FOR EACH ROW EXECUTE FUNCTION public.audit_log_immutable();
-- =============================================================
-- 6. Schema reload
-- =============================================================
NOTIFY pgrst, 'reload schema';