server/docs/retninger/datalaget.md
vegard 8ca9832248 Legg til ops/ (vedlikeholdsjobber) og docs/retninger/ (arkitektoniske teser)
Ny mappe ops/ med repeterbare vedlikeholdsjobber:
- ryddejobb.md — full prosjektrevisjon
- doc-audit.md — docs vs kode
- drift-sjekk.md — prod vs lokal vs docs

Ny mappe docs/retninger/ med arkitektoniske teser:
- status_quo.md — hva Sidelinja er i dag
- rom_ikke_forum.md — opplevelse-først, to-lags-modell, administrativ opplevelse
- universell_input.md — tre primitiver (input, mottak, kommunikasjon), noder+edges
- maskinrommet.md — Rust-orkestrator, edge-drevet ressursorkestrering, CAS+pruning
- bruker_ikke_workspace.md — brukeren er sentrum, workspaces er samlings-noder
- datalaget.md — PG+Apache AGE, SpacetimeDB som sanntidslag, lagmodell

Oppdatert CLAUDE.md og proposals/README.md med referanser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 04:54:17 +01:00

175 lines
8 KiB
Markdown

# Datalaget — PG + AGE som enhetlig graf og arkiv
> PostgreSQL er den eneste databasen. Apache AGE gir Cypher-semantikk
> for graftraverseringer. SpacetimeDB er sanntidslaget over samme data.
> Én database, to tilgangsmønstre, ingen eierskapskonflikt.
## Observasjoner
Hele retningsarbeidet har bygget seg mot "alt er noder og edges."
Tilgang er edges, visninger er spørringer, administrasjon er
traversering. Spørsmålet er: hvilken teknologi støtter dette best?
### Neo4j ble vurdert og forkastet
Neo4j er best-in-class for dype graftraverseringer, men for dette
prosjektet gir den mer problemer enn den løser:
- **Tredje database.** PG + SpacetimeDB + Neo4j = tre systemer å
drifte, sikkerhetskopiere og overvåke. På én Hetzner VPS.
- **Mister PG-økosystemet.** pgvector (semantisk søk), fulltekstsøk,
JSONB, pg_cron, statistikk-aggregeringer — alt dette trenger vi
uansett, og det lever i PG. Med Neo4j trenger vi PG *i tillegg*.
- **Minnehungrig.** Neo4j anbefaler 8-16GB heap. På en delt VPS med
PG, SpacetimeDB, Whisper og LiteLLM er det for mye.
- **Lisens.** Community er AGPLv3. Enterprise-features (clustering,
avansert sikkerhet) krever betalt lisens.
### Apache AGE — Cypher i PG
Apache AGE er en PG-extension som legger til openCypher-støtte. Noder
og edges lagres i PG-tabeller, men spørres med Cypher-semantikk.
**Oppsider:**
- **Én database.** Ingen ny infrastruktur. Samme backup, connection
pooling, tooling, monitoring.
- **SQL + Cypher i samme spørring.** "Finn alle noder brukeren har
tilgang til via team-traversering, JOINet med fulltekstsøk og
pgvector." Det kan du ikke gjøre med en separat grafdatabase.
- **Null migrasjonskostnad.** Eksisterende nodes/edges-tabeller kan
eksponeres som graf. Legg til extension, ikke bytt database.
- **Økosystemet bevares.** pgvector, fulltekstsøk, JSONB, pg_cron —
alt fungerer side om side med Cypher-spørringer.
- **Produksjonsbruk.** Azure og EDB tilbyr AGE som managed extension.
**Nedsider:**
- **Ikke native graf.** Under panseret er det PG-tabeller. For svært
dype traverseringer (10+ hopp over millioner av noder) er Neo4j
raskere. Men de fleste spørringene våre er 1-5 hopp.
- **Yngre prosjekt.** Mindre community, tynnere dokumentasjon enn Neo4j.
- **Quirks.** Spørringer må være enten read-only eller write-only
(WITH-clause for overgang). Noen pg_upgrade-begrensninger.
## Beslutning
**PostgreSQL + Apache AGE** som enhetlig datalager for noder og edges.
De fleste spørringer i dette systemet er grunne:
- "Vis noder med edge til denne brukeren" — 1 hopp
- "Sjekk tilgang via team" — 2 hopp
- "Finn alle kommunikasjonsnoder brukeren har tilgang til" — 2-3 hopp
- "Traverser kunnskapsgrafen mellom to emner" — 3-5 hopp
AGE håndterer dette. Skulle det vise seg at dypere traverseringer
blir en flaskehals *i praksis*, kan Neo4j evalueres da — men med
én VPS og realistiske datamengder er det usannsynlig.
## Lagmodell
```
┌─────────────────────────────────────┐
│ GUI (SvelteKit) │
│ Primitiver, visninger │
└────────┬──────────────────┬─────────┘
│ skriv │ les (sanntid)
│ │ direkte WebSocket
┌────────▼────────┐ ┌─────▼─────────┐
│ Maskinrommet │ │ SpacetimeDB │──┐
│ (Rust) │ │ (STDB) │ │
│ Orkestrering │ └───────────────┘ │
└──┬─────┬─────┬──┘ │
│ │ │ sync ↕ │
▼ ▼ ▼ │
┌─────┐┌─────┐┌─────┐┌─────────────┐ │
│ PG ││STDB ││ CAS ││ Whisper, │ │
│+AGE ││(skr)││ ││ LiteLLM, │ │
│ ││ ││ ││ LiveKit ... │ │
└─────┘└─────┘└─────┘└─────────────┘ │
```
### Skriv vs les — to stier med god grunn
**Skriv:** GUI → Maskinrommet (Rust) → tjenester (PG, STDB, CAS, ...)
All orkestrering, edge-logikk, ressursallokering og validering går
gjennom Rust. Maskinrommet bestemmer hva som skjer: hva som skrives
til PG, hva som speiles til SpacetimeDB, hva som lagres i CAS,
hvilke tjenester som trigges.
**Les (sanntid):** SpacetimeDB → GUI (direkte WebSocket)
SpacetimeDB sitt klient-SDK kobler seg direkte via WebSocket,
definerer SQL-subscriptions, og synkroniserer automatisk med lokal
cache — uten network round-trips for lesing (~10μs per transaksjon).
Å proxy dette gjennom Rust ville lagt til et hopp, serialisering og
kontekstbytte — en dårligere reimplementering av noe STDB gjør
optimalt. Den direkte lese-stien er en bevisst arkitekturbeslutning,
ikke et hull i lagmodellen.
**Les (tradisjonelt):** GUI → Maskinrommet (Rust) → PG
Søk, historikk, statistikk, arkiv — alt som ikke er sanntid går
gjennom Rust og PG. AGE-spørringer for graftraversering, pgvector
for semantisk søk, SQL for aggregeringer.
### PG er arkivet og grafen
Alle noder og edges lever i PG. AGE gir Cypher-spørringer for
traversering. Standard SQL for alt annet (aggregeringer, fulltekstsøk,
JOINs mot pgvector). Én database, to spørrespråk som utfyller
hverandre.
### SpacetimeDB er sanntidslaget
Aktive noder og edges speilet til SpacetimeDB for live-oppdateringer.
Ting som er "nå" lever i SpacetimeDB. Ting som er "ferdig" lever kun
i PG. Ingen eierskapskonflikt — SpacetimeDB er en live-visning av
en delmengde av PG-grafen.
### CAS er binærlageret
Lyd, bilde, video lagres content-addressable utenfor PG. Noder i
PG peker på CAS-hasher. Pruning-regler basert på edges, aksesslog
og modalitet (se maskinrommet).
## Migreringsstrategi
### Fase 1: AGE på eksisterende PG
Installer Apache AGE extension. Eksponer eksisterende nodes/edges-
tabeller som graf. Ingen endring for resten av systemet — bare en
ny måte å spørre på.
### Fase 2: Konsolider til node+edge-modellen
Migrer meldingsboks, kanban, kalender etc. til den universelle
node+edge-modellen gradvis. Gamle tabeller kan leve som views
over grafen i overgangsperioden.
### Fase 3: Parallell prototype
Det gamle systemet kjører uforstyrret. En ny frontend-prototype
bygges ved siden av som bruker AGE-grafen direkte. Live sync fra
gammelt til nytt via enveis oppdateringer. Testbrukere leker i
det nye, produksjon er trygt i det gamle.
### Fase 4: Cutover
Når det nye er godt nok, flyttes trafikk over. Det gamle systemet
kan kjøre som read-only fallback en periode.
## Spenninger og åpne spørsmål
- **AGE-modenhet.** Prosjektet er aktivt og støttet av Azure/EDB,
men community er mindre enn Neo4j. Risikoen er håndterbar fordi
dataene alltid er PG-tabeller — AGE er bare et spørrelag.
- **SpacetimeDB-synk.** Hvordan synkes noder/edges mellom PG (AGE)
og SpacetimeDB effektivt? Trenger en sync-mekanisme som forstår
"aktiv delmengde."
- **Skjemadesign.** Én node-tabell med alle typer innhold — hva er
felles kolonner vs edge-metadata vs JSONB-payload? Trenger
gjennomtenkt skjema som balanserer fleksibilitet og spørrbarhet.
## Forhold til andre retninger
- [Universell input og mottak](universell_input.md) — noder og edges
er den underliggende datamodellen for alle tre primitiver
- [Maskinrommet](maskinrommet.md) — CAS og pruning lever her, AGE
brukes for edge-drevet ressursorkestrering
- [Bruker, ikke workspace](bruker_ikke_workspace.md) — tilgang via
graf-traversering (AGE) i stedet for workspace-membership-tabeller
- [Rom, ikke forum](rom_ikke_forum.md) — to-lags-modellen:
SpacetimeDB for nåtid, PG+AGE for arkiv og graf