synops/docs/arkitektur.md
vegard 0a467066ba Synops v2: arkitektur, retninger og dokumentasjon
Nystart basert på arkitektonisk innsikt fra Sidelinja v1.
Koden er ny, visjon og primitiver er validert gjennom tidligere arbeid.

Inneholder:
- Komplett arkitekturdokumentasjon (docs/arkitektur.md)
- 6 vedtatte retninger (docs/retninger/)
- Alle concepts, features, proposals og erfaringer fra v1
- Server-oppsett og drift (docs/setup/)
- LiteLLM-konfigurasjon (API-nøkler via env)
- Editor.svelte referanse fra v1

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

158 lines
6 KiB
Markdown

# Arkitektur — Sidelinja v2
## Visjon
Sidelinja er en plattform for redaksjonelt arbeid og podcast-produksjon.
Ikke en webapp med features — en plattform med primitiver som kan bli
hva som helst.
Alt er noder og edges i en graf. Input fanger, mottak presenterer,
kommunikasjonsnoder samler folk. Maskinrommet orkestrerer tekniske
tjenester under. Frontend er et tynt lag som viser grafen.
## Lagmodell
```
┌─────────────────────────────────────┐
│ GUI (SvelteKit) │
│ Visninger: spørringer mot grafen │
└────────┬──────────────────┬─────────┘
│ skriv │ les (sanntid)
│ │ direkte WebSocket
┌────────▼────────┐ ┌─────▼─────────┐
│ Maskinrommet │ │ SpacetimeDB │
│ (Rust) │ │ Aktive noder │
│ Orkestrering │ └───────────────┘
└──┬─────┬─────┬──┘
│ │ │
▼ ▼ ▼
┌─────┐┌─────┐┌─────┐┌─────────────┐
│ PG ││STDB ││ CAS ││ Whisper, │
│ ││(skr)││ ││ LiteLLM, │
│ ││ ││ ││ LiveKit ... │
└─────┘└─────┘└─────┘└─────────────┘
```
### Skrivestien
GUI → Maskinrommet (Rust) → tjenester
All orkestrering, edge-logikk, validering og ressursallokering
går gjennom Rust. Maskinrommet leser edges og bestemmer hvilke
tjenester som trigges.
### Lesestien (sanntid)
SpacetimeDB → GUI (direkte WebSocket)
STDB klient-SDK gir ~10μs-oppdateringer med lokal cache.
En bevisst optimering — ikke et hull i lagmodellen.
### Lesestien (tradisjonell)
GUI → Maskinrommet (Rust) → PG
Søk, historikk, statistikk, arkiv. Cypher via AGE for
graftraversering når CTEs ikke holder.
## Datamodell
### Noder
Én tabell. Alt innhold er noder: meldinger, oppgaver, notater,
faktoider, mediefiler, kommunikasjonsrom, samlings-noder, brukere.
Felles skjema: id, innhold, created_at, author, content_hash (→ CAS).
Modalitetsspesifikk metadata i JSONB.
### Edges
Én tabell. Alle relasjoner er edges: tilhørighet, tilgang, type,
synlighet, rolle, status.
Hva en node "er" bestemmes utelukkende av edges:
- Node + edge til kanal = chatmelding
- Node + edge til board + status-edge = kanban-kort
- Node + edge til dato = kalenderoppføring
- Node + edge til kun bruker = privat notat
- Node + edge til topic = faktoid
- Node uten edges = løs tanke
### Visninger
Visninger er spørringer mot grafen med ulike filtre:
- Chat = noder med kanal-edge, sortert på tid
- Kanban = noder med board-edge, gruppert på status
- Kalender = noder med dato-edge, på tidslinje
- Mottaksflate = noder med edge til deg, vektet på relevans
## Tre primitiver
### 1. Input
Én multimodal overflate som fanger alt: tekst, lyd, bilde, AI,
URL. To versjoner — sanntid (STDB-lag) og flat (PG-lag).
Output er alltid en node.
### 2. Mottak
Én personlig flate som presenterer alt tilpasset deg. Format
bestemmes av mottaker (tekst/lyd). Filtrering via dine edges.
Sanntid (stream) eller asynkront (digest).
### 3. Kommunikasjon
En node som samler folk med tilgangsregler. Samme type fra
én-til-én-samtale til livesending. Forskjellen er edges:
eier, input-tilgang, mottak-tilgang, rolle.
## Maskinrommet
Rust-tjeneste med tre operasjoner: **fang**, **prosesser**, **lever**.
Edge-drevet ressursorkestrering: maskinrommet leser edges og
bestemmer hvilke tjenester som spinnes opp. Dagboknotat = bare
transkriber. Livesending = transkriber + LiveKit + AI + mediaprosessering.
Forvalter også CAS (binærlagring) med intelligent pruning basert
på modalitet, edges og aksessmønstre.
## Sikkerhet
### RLS-siloer
Samlings-noder (det som var workspaces) er harde sikkerhetsgenser
i PG med RLS. `workspace_id = current_setting(...)` — instant,
vanntett. Edge-basert tilgang er UX *innenfor* siloen.
### Privat er default
Input uten mottaker-edge er automatisk privat. Ingen ser det.
Deling er å legge til edges.
## Datalag
### PostgreSQL
Arkiv og graf. Alle noder og edges. Fulltekstsøk, pgvector
(semantisk søk), JSONB. Apache AGE for Cypher når CTEs ikke holder.
### SpacetimeDB
Sanntidslag. Aktive noder og edges speilet fra PG. Frontend
abonnerer via WebSocket. Ingen eierskapskonflikt — STDB er en
live-visning av en delmengde av PG-grafen.
### CAS (Content-Addressable Store)
Binærdata (lyd, bilde, video) lagret med hash. TTL basert på
modalitet, edges og aksesslog. Tekst lever evig, lyd 30 dager,
video 14 dager — forlenges ved aksess. Generert innhold (TTS,
thumbnails) er en cache som regenereres on-demand.
## Teknologivalg
| Rolle | Teknologi | Begrunnelse |
|-------|-----------|-------------|
| Orkestrator | Rust | Ytelse, typesikkerhet, allerede i stacken |
| Frontend | SvelteKit | PWA, SSR, allerede i stacken |
| Database | PostgreSQL | Økosystem (pgvector, fulltekstsøk, AGE), stabilitet |
| Sanntid | SpacetimeDB | In-memory, WebSocket-subscriptions, ~10μs |
| Binærlagring | CAS (filsystem) | Enkel, deduplisering, ingen ekstern avhengighet |
| AI Gateway | LiteLLM | Multi-provider, BYOK, OpenRouter fallback |
| STT | faster-whisper | Lokal, god norsk kvalitet |
| TTS | ElevenLabs (→ lokal) | Kommersiell start, lokal når kvaliteten holder |
| Auth | Authentik | SSO, OIDC, self-hosted |
| Reverse proxy | Caddy | Auto-TLS, enkel config |
| Lyd/video | LiveKit | WebRTC, self-hosted |
## Retninger
Arkitekturen er basert på vedtatte retninger dokumentert i
`docs/retninger/`. Se `docs/retninger/README.md` for oversikt.