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>
6 KiB
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.