Innarbeid ekstern review: RLS-siloer, AGE-pragmatisme, compute-separasjon
- bruker_ikke_workspace: RLS-advarsel tatt på alvor — samlings-noder er harde sikkerhetsiloer under panseret, edge-basert tilgang er UX-lag innenfor siloene - datalaget: AGE moderert fra "beslutning" til "planlagt utvidelse" — start med CTEs, legg til AGE når det faktisk trengs - maskinrommet: compute-separasjon dokumentert — tunge workers kan flyttes til egen node, maskinrommet ruter transparent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ec430141b
commit
c5de6086ca
3 changed files with 63 additions and 8 deletions
|
|
@ -102,20 +102,47 @@ Ingen "slett bruker fra workspace." Fjern deltaker-edges. Brukerens
|
||||||
private noder som hadde edge til samlings-noden beholder den edgen
|
private noder som hadde edge til samlings-noden beholder den edgen
|
||||||
(det er brukerens innhold), men de mister tilgang til andres noder.
|
(det er brukerens innhold), men de mister tilgang til andres noder.
|
||||||
|
|
||||||
|
## RLS og sikkerhet: samlings-noder som harde siloer
|
||||||
|
|
||||||
|
Viktig arkitekturbeslutning: **"bruker, ikke workspace" er en
|
||||||
|
UX-modell, ikke en sikkerhetsmodell.**
|
||||||
|
|
||||||
|
Ren edge-basert tilgangskontroll — der hver lesing traverserer grafen
|
||||||
|
for å sjekke om brukeren har en sti til noden — ville kvelt
|
||||||
|
databasen når grafen vokser. I dag har PG bunnsolid RLS med
|
||||||
|
`workspace_id = current_setting(...)` — instant og vanntett.
|
||||||
|
|
||||||
|
Løsningen er å skille UX fra sikkerhet:
|
||||||
|
- **UX-laget:** Brukeren ser sine edges. Ingen "velg workspace."
|
||||||
|
Filtrering etter samlings-node er frivillig.
|
||||||
|
- **Sikkerhetslaget:** Under panseret har hver node fortsatt en
|
||||||
|
`workspace_id` (eller samlings-node-id) som RLS sjekker. Det er
|
||||||
|
den harde sikkerhetsgensen — billig, velprøvd, instant.
|
||||||
|
- **Finere tilgang innenfor siloen:** Edge-basert tilgang (eier,
|
||||||
|
admin, deltaker, leser) sjekkes *innenfor* en silo, ikke som
|
||||||
|
erstatning for den.
|
||||||
|
|
||||||
|
Samlings-noder er altså ikke bare frivillig organisering — de er
|
||||||
|
sikkerhetsiloer i databasen. Brukeren merker det ikke, men PG
|
||||||
|
trenger det.
|
||||||
|
|
||||||
## Spenninger og åpne spørsmål
|
## Spenninger og åpne spørsmål
|
||||||
|
|
||||||
- **Overblikk.** Uten workspaces som organisatorisk enhet — hvordan
|
- **Overblikk.** Uten workspaces som organisatorisk enhet — hvordan
|
||||||
unngår du at alt flyter sammen? Samlings-noder er svaret, men de
|
unngår du at alt flyter sammen? Samlings-noder er svaret, men de
|
||||||
må være intuitive å opprette og bruke uten å bli "workspaces med
|
må være intuitive å opprette og bruke uten å bli "workspaces med
|
||||||
ny navn."
|
ny navn."
|
||||||
- **Tilgangskontroll i praksis.** Edge-basert tilgang er fleksibelt,
|
- **Kryssgående noder og siloer.** Hvis noder har `workspace_id` for
|
||||||
men kan det bli uoversiktlig? "Hvem har tilgang til hva" må være
|
RLS, kan en node da tilhøre to samlings-noder? Kanskje via en
|
||||||
lett å besvare. Kanskje samlings-noden gir en naturlig audit-visning.
|
"primær silo" for RLS + sekundære edges for visning. Trenger
|
||||||
|
gjennomtenkt design.
|
||||||
- **Arv og konflikter.** En node med edge til to samlings-noder med
|
- **Arv og konflikter.** En node med edge til to samlings-noder med
|
||||||
ulike pruning-profiler — hva vinner? Trenger klare regler som er
|
ulike pruning-profiler — hva vinner? Trenger klare regler som er
|
||||||
intuitive for brukeren.
|
intuitive for brukeren.
|
||||||
- **Migrering.** Eksisterende workspace-modell har innhold. Kan
|
- **Migrering.** Eksisterende workspace-modell har innhold. Kan
|
||||||
workspaces bli samlings-noder gradvis?
|
workspaces bli samlings-noder gradvis? RLS-modellen gjør dette
|
||||||
|
enklere — workspace_id kan bli samlings-node-id uten endring i
|
||||||
|
sikkerhetslogikk.
|
||||||
|
|
||||||
## Forhold til andre retninger
|
## Forhold til andre retninger
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ og edges lagres i PG-tabeller, men spørres med Cypher-semantikk.
|
||||||
|
|
||||||
## Beslutning
|
## Beslutning
|
||||||
|
|
||||||
**PostgreSQL + Apache AGE** som enhetlig datalager for noder og edges.
|
**PostgreSQL** som enhetlig datalager for noder og edges.
|
||||||
|
**Apache AGE** som planlagt utvidelse — ikke forpliktet fra dag én.
|
||||||
|
|
||||||
De fleste spørringer i dette systemet er grunne:
|
De fleste spørringer i dette systemet er grunne:
|
||||||
- "Vis noder med edge til denne brukeren" — 1 hopp
|
- "Vis noder med edge til denne brukeren" — 1 hopp
|
||||||
|
|
@ -60,9 +61,15 @@ De fleste spørringer i dette systemet er grunne:
|
||||||
- "Finn alle kommunikasjonsnoder brukeren har tilgang til" — 2-3 hopp
|
- "Finn alle kommunikasjonsnoder brukeren har tilgang til" — 2-3 hopp
|
||||||
- "Traverser kunnskapsgrafen mellom to emner" — 3-5 hopp
|
- "Traverser kunnskapsgrafen mellom to emner" — 3-5 hopp
|
||||||
|
|
||||||
AGE håndterer dette. Skulle det vise seg at dypere traverseringer
|
PG med rekursive CTEs håndterer 1-3 hopp utmerket. AGE legges til
|
||||||
blir en flaskehals *i praksis*, kan Neo4j evalueres da — men med
|
når graftraversering faktisk blir en målbar flaskehals — ikke før.
|
||||||
én VPS og realistiske datamengder er det usannsynlig.
|
AGE er en extension, ikke en migrering, så den kan boltes på uten
|
||||||
|
å endre eksisterende kode.
|
||||||
|
|
||||||
|
Pragmatisk rekkefølge:
|
||||||
|
1. **Nå:** PG med nodes/edges-tabeller og CTEs
|
||||||
|
2. **Når CTEs blir smertefulle:** Legg til AGE for Cypher-spørringer
|
||||||
|
3. **Usannsynlig:** Evaluer Neo4j hvis AGE ikke holder
|
||||||
|
|
||||||
## Lagmodell
|
## Lagmodell
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,6 +255,27 @@ Rekkefølge: definer traits → migrer eksisterende worker-jobber inn →
|
||||||
legg til nye tjenester etter hvert. Fast punkt fra dag én, full
|
legg til nye tjenester etter hvert. Fast punkt fra dag én, full
|
||||||
dekning over tid.
|
dekning over tid.
|
||||||
|
|
||||||
|
## Compute-separasjon
|
||||||
|
|
||||||
|
Maskinrommet orkestrerer — men tunge jobber trenger ikke kjøre på
|
||||||
|
samme maskin. Hetzner CPX42 (8 vCPU, 16 GB RAM) skal håndtere state
|
||||||
|
(PG, SpacetimeDB) og sanntid (Caddy, LiveKit, SvelteKit). Whisper
|
||||||
|
(CPU-intensiv, spesielt large-v3) og lokal LLM (kildevern-modus)
|
||||||
|
vil konkurrere om ressurser under live innspilling.
|
||||||
|
|
||||||
|
Maskinrommets abstraksjon gjør dette løsbart:
|
||||||
|
- **Nå:** Alt på én VPS. Jobbkøen prioriterer sanntid over batch.
|
||||||
|
Whisper kjøres med lavere concurrency under live-sesjoner.
|
||||||
|
- **Senere:** Trekk ut tunge workers til en separat node (billig
|
||||||
|
ARM/Ampere-instans) som poller jobbkøen over internt nettverk.
|
||||||
|
Maskinrommet ruter transparent — primitivene merker ingenting.
|
||||||
|
- **Kildevern-modus:** Lokal LLM (Llama/Gemma) krever GPU eller
|
||||||
|
dedikert compute. Urealistisk på delt VPS. Egen node for dette.
|
||||||
|
|
||||||
|
Poenget: maskinrommet er designet for å rute arbeid, ikke for å
|
||||||
|
*utføre* alt selv. Compute-separasjon er en konfigurasjon, ikke en
|
||||||
|
arkitekturendring.
|
||||||
|
|
||||||
## Spenninger og åpne spørsmål
|
## Spenninger og åpne spørsmål
|
||||||
|
|
||||||
- **Synkron vs asynkron.** "Fang" og "lever" kan være instant, men
|
- **Synkron vs asynkron.** "Fang" og "lever" kan være instant, men
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue