Å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.
138 lines
5.2 KiB
SQL
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';
|