# 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.