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.
This commit is contained in:
parent
773569759c
commit
5dfaeff53c
4 changed files with 85 additions and 7 deletions
|
|
@ -67,11 +67,7 @@
|
|||
}
|
||||
|
||||
// Sort by created_at descending
|
||||
nodes.sort((a, b) => {
|
||||
const ta = a.createdAt?.microsSinceUnixEpoch ?? 0n;
|
||||
const tb = b.createdAt?.microsSinceUnixEpoch ?? 0n;
|
||||
return tb > ta ? 1 : tb < ta ? -1 : 0;
|
||||
});
|
||||
nodes.sort((a, b) => (b.createdAt ?? 0) - (a.createdAt ?? 0));
|
||||
|
||||
return nodes;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -595,6 +595,16 @@ pub async fn create_node(
|
|||
"belongs_to-edge opprettet (kontekst-arv)"
|
||||
);
|
||||
|
||||
// Propager tilgang: alle som har tilgang til ctx_id får tilgang til node_id
|
||||
if let Err(e) = sqlx::query("SELECT propagate_belongs_to_access($1, $2)")
|
||||
.bind(node_id)
|
||||
.bind(ctx_id)
|
||||
.execute(&state.db)
|
||||
.await
|
||||
{
|
||||
tracing::error!("propagate_belongs_to_access feilet: {e}");
|
||||
}
|
||||
|
||||
Some(edge_id)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -881,6 +891,18 @@ pub async fn create_edge(
|
|||
internal_error("Databasefeil ved opprettelse av edge")
|
||||
})?;
|
||||
|
||||
// Propager tilgang ved belongs_to: alle som har tilgang til target (forelder) får tilgang til source (barn)
|
||||
if req.edge_type == "belongs_to" {
|
||||
if let Err(e) = sqlx::query("SELECT propagate_belongs_to_access($1, $2)")
|
||||
.bind(req.source_id)
|
||||
.bind(req.target_id)
|
||||
.execute(&state.db)
|
||||
.await
|
||||
{
|
||||
tracing::error!("propagate_belongs_to_access feilet: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger rendering ved belongs_to
|
||||
if req.edge_type == "belongs_to" {
|
||||
if let Ok(Some(config)) = crate::publishing::find_publishing_collection_by_id(&state.db, req.target_id).await {
|
||||
|
|
@ -1946,6 +1968,16 @@ pub async fn create_communication(
|
|||
context_id = %context_id,
|
||||
"belongs_to-edge opprettet til kontekstnode"
|
||||
);
|
||||
|
||||
// Propager tilgang fra kontekstnoden
|
||||
if let Err(e) = sqlx::query("SELECT propagate_belongs_to_access($1, $2)")
|
||||
.bind(node_id)
|
||||
.bind(context_id)
|
||||
.execute(&state.db)
|
||||
.await
|
||||
{
|
||||
tracing::error!("propagate_belongs_to_access feilet: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
|
|
|
|||
51
migrations/020_belongs_to_access_propagation.sql
Normal file
51
migrations/020_belongs_to_access_propagation.sql
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
-- 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;
|
||||
$$;
|
||||
3
tasks.md
3
tasks.md
|
|
@ -296,8 +296,7 @@ fiks direkte hvis det er småting, eller opprett nye work_items (tasks)
|
|||
med spesifikasjon for det som trenger en dedikert sesjon.
|
||||
|
||||
- [x] 23.1 Valider fase 1–2 (infra + maskinrommet): PG-skjema, indekser, auth-middleware, intensjoner, STDB-klient (nå erstattet av WS). Verifiser at skjema matcher docs, at auth fungerer, at skrivestien er konsistent.
|
||||
- [~] 23.2 Valider fase 3–4 (frontend + tilgang): SvelteKit-oppsett, OIDC-flow, sanntid, mottaksflate, TipTap-editor, node_access-matrise, team-transitivitet, visibility-filtrering.
|
||||
> Påbegynt: 2026-03-18T14:30
|
||||
- [x] 23.2 Valider fase 3–4 (frontend + tilgang): SvelteKit-oppsett, OIDC-flow, sanntid, mottaksflate, TipTap-editor, node_access-matrise, team-transitivitet, visibility-filtrering.
|
||||
- [ ] 23.3 Valider fase 5–8 (kommunikasjon + CAS + lyd + aliaser): chat-loop, kontekst-arv, CAS-hashing/deduplisering, Whisper-pipeline, segmenttabell, SRT-eksport, alias-identitet.
|
||||
- [ ] 23.4 Valider fase 9–10 (visninger + AI): kanban drag-and-drop, kalender, dagbok, kunnskapsgraf, LiteLLM-ruting, AI-foreslåtte edges, oppsummering, TTS.
|
||||
- [ ] 23.5 Valider fase 11 (produksjon): LiveKit-oppsett, sanntidslyd, pruning-logikk, podcast-RSS.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue