synops/migrations/020_belongs_to_access_propagation.sql
vegard 5dfaeff53c Valider fase 3–4: fiks belongs_to-tilgangspropagering og mottakssortering
Validering av fase 3 (frontend) og fase 4 (tilgangskontroll) avdekket to bugs:

1. belongs_to-access-gap: Når en belongs_to-edge opprettes ETTER at
   noen allerede har tilgang til foreldrenoden, fikk ikke barnenoden
   tilgangsoppføringer i node_access-matrisen. F.eks. kunne Vegard (eier
   av en kommunikasjonsnode) ikke se innhold opprettet av Claude med
   belongs_to-edge til den noden.

   Løsning: Ny PG-funksjon propagate_belongs_to_access() som kopierer
   forelderens tilgangsrader til barnet. Kalles fra maskinrommet ved
   opprettelse av belongs_to-edges (create_node m/context, create_edge,
   create_communication m/context). Retroaktiv fiks for eksisterende data.

2. Mottaksflate-sortering: Brukte .microsSinceUnixEpoch (SpacetimeDB-
   BigInt-arv) på vanlig number-felt, ga alltid 0n → ingen sortering.
   Fikset til direkte number-sammenligning.

Verifisert: SvelteKit + maskinrommet bygger og kjører. PG-skjema, OIDC,
WebSocket/NOTIFY, RLS-policies, team-transitivitet og visibility fungerer.
2026-03-18 14:41:20 +00:00

51 lines
1.8 KiB
PL/PgSQL

-- Migrasjon 020: Propager tilgang ved nye belongs_to-edges
--
-- Når en belongs_to-edge opprettes mellom barn og forelder, skal alle
-- som allerede har tilgang til forelderen også få tilgang til barnet.
-- recompute_access håndterer dette i steg 2 for access-granting edges,
-- men ikke for belongs_to-edges som opprettes etter at tilgang allerede er gitt.
CREATE OR REPLACE FUNCTION propagate_belongs_to_access(
p_child_id UUID,
p_parent_id UUID
) RETURNS void LANGUAGE plpgsql AS $$
BEGIN
-- For alle som har tilgang til forelder: gi samme tilgang til barnet
INSERT INTO node_access (subject_id, object_id, access, via_edge)
SELECT na.subject_id, p_child_id, na.access, na.via_edge
FROM node_access na
WHERE na.object_id = p_parent_id
ON CONFLICT (subject_id, object_id)
DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access),
via_edge = CASE
WHEN EXCLUDED.access > node_access.access THEN EXCLUDED.via_edge
ELSE node_access.via_edge
END;
END;
$$;
-- Retroaktivt: fiks eksisterende belongs_to-edges der tilgang mangler.
-- Finn barn som har belongs_to-edge til forelder, men der forelderens
-- tilgangssubjekter ikke har tilgang til barnet.
DO $$
DECLARE
r RECORD;
BEGIN
FOR r IN
SELECT e.source_id AS child_id, e.target_id AS parent_id
FROM edges e
WHERE e.edge_type = 'belongs_to'
AND EXISTS (
SELECT 1 FROM node_access na
WHERE na.object_id = e.target_id
AND NOT EXISTS (
SELECT 1 FROM node_access na2
WHERE na2.subject_id = na.subject_id
AND na2.object_id = e.source_id
)
)
LOOP
PERFORM propagate_belongs_to_access(r.child_id, r.parent_id);
END LOOP;
END;
$$;