synops/docs/infra/api_grensesnitt.md
vegard b5aa5bb243 Fjern SpacetimeDB komplett (oppgave 22.4)
SpacetimeDB er nå helt fjernet fra Synops. Sanntid håndteres av
PG LISTEN/NOTIFY + WebSocket i portvokteren (maskinrommet).

Kode fjernet:
- spacetimedb/ Rust-modul og spacetime.json
- maskinrommet/src/stdb.rs (HTTP-klient for STDB-reducers)
- frontend module_bindings/ (23 auto-genererte filer)
- spacetimedb npm-avhengighet fra package.json
- scripts/test-sanntid.sh (testet STDB-flyt)

Infrastruktur:
- Docker-container stoppet og fjernet fra docker-compose.yml
- Caddy: fjernet /spacetime/* reverse proxy
- maskinrommet-env.sh: fjernet STDB_IP og SPACETIMEDB_*-variabler
- .env.example: fjernet SpacetimeDB-seksjoner

Dokumentasjon oppdatert:
- CLAUDE.md: stack, lagmodell, kjerneprinsipper, driftsmodell
- docs/arkitektur.md: skrivestien, lesestien, datalag, teknologivalg
- docs/retninger/datalaget.md: migrasjonshistorikk, status "fjernet"
- 37 andre docs oppdatert (features, concepts, infra, ops, retninger)
- Alle kode-kommentarer med STDB-referanser oppdatert

Verifisert: maskinrommet bygger og starter OK, frontend bygger OK,
helsesjekk returnerer 200. Caddy reloadet.
2026-03-18 13:39:09 +00:00

150 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Infrastruktur: API-grensesnitt og Tjenesteansvar
## 1. Konsept
Frontend sender **intensjoner** til maskinrommet (Rust/axum HTTP API).
Maskinrommet eier alle skrivinger: det validerer, skriver til PG,
og orkestrerer konsekvenser.
Sanntid: PG LISTEN/NOTIFY → maskinrommet → WebSocket `/ws` → frontend.
Frontend bruker portvokterens WebSocket for sanntid.
Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → PG.
## 2. Kommunikasjonskart
```
┌─────────────────────────────────────────────────────────────┐
│ Brukerens nettleser (SvelteKit klient) │
└──────────┬──────────────────────┬───────────────────────────┘
│ │
│ HTTP (intensjoner) │ WebSocket (sanntid)
▼ ▼
┌──────────────────────────────────────┐
│ Maskinrommet / Portvokteren (Rust) │
│ axum HTTP API + WebSocket │
│ │
│ Ansvar: │
│ - Validere intensjoner │
│ - Skrive til PG │
│ - Orkestrere bakgrunnsjobber │
│ - Tunge spørringer │
│ - Sanntid via PG LISTEN → WS │
└──┬─────────────┬─────────────────────┘
│ │
▼ ▼
┌─────┐ ┌─────────────┐
│ PG │ │ Whisper, │
│ │ │ LiteLLM, │
│ │ │ LiveKit ... │
└─────┘ └─────────────┘
```
## 3. Ansvarsfordeling
| Komponent | Rolle | Snakker med |
|---|---|---|
| **SvelteKit (klient)** | UI, brukerinteraksjon | Maskinrommet (HTTP + WS) |
| **Maskinrommet (Rust)** | Intensjons-API, orkestrering, sanntid, tunge spørringer | PG, CAS, Whisper, LiteLLM |
| **PostgreSQL** | Eneste datakilde, sanntid via LISTEN/NOTIFY | Maskinrommet (SQL) |
## 4. Viktige avklaringer
- **Maskinrommet er HTTP API + WebSocket-server** (axum). Frontend sender intensjoner via HTTP, mottar sanntid via WebSocket.
- **Maskinrommet eier alle skrivinger.** Frontend skriver aldri direkte til PG.
- **SvelteKit er et rent frontend-prosjekt.** Ingen server-side PG-tilgang.
- **Bakgrunnsjobber** (Whisper, LLM, TTS) orkestreres av maskinrommet, aldri direkte fra frontend.
## 5. Implementerte endepunkter
### Offentlige
- `GET /health` — Helsesjekk. Verifiserer PG-tilkobling.
### WebSocket (sanntid, oppgave 22.122.2)
- `GET /ws?token=<JWT>` — WebSocket-oppgradering for sanntidsstrøm.
Token sendes som query-parameter (nettlesere støtter ikke custom headers ved WS upgrade).
- Ved tilkobling: sender `initial_sync` med alle noder, edges, access og mixer_channels
brukeren kan se.
- Deretter: strømmer berikede events (`node_changed`, `edge_changed`, `access_changed`,
`mixer_channel_changed`), filtrert på brukerens tilgangsmatrise (node_access).
- Berikede events: INSERT/UPDATE-events inneholder full raddata fra PG (ikke bare ID),
slik at frontend kan oppdatere stores direkte uten ekstra API-kall.
- Kilder: PG LISTEN/NOTIFY-triggere på nodes, edges, node_access og mixer_channels.
- Ved lag (klient sakker etter): sender full resync (ny initial_sync).
### Autentiserte (krever `Authorization: Bearer <JWT>`)
- `GET /me` — Returnerer autentisert brukers `node_id` og `authentik_sub`.
- `POST /intentions/create_node` — Opprett node. Skriv til PG,
returner `node_id` umiddelbart.
- Body (JSON): `{ node_kind?, title?, content?, visibility?, metadata? }`
- Defaults: `node_kind="content"`, `visibility="hidden"`, andre felter tomme
- Respons: `{ node_id: "<uuid>" }`
- `POST /intentions/create_edge` — Opprett edge mellom to noder.
Validerer at begge nodene eksisterer og at edge_type ikke er tom.
- Body (JSON): `{ source_id, target_id, edge_type, metadata?, system? }`
- Defaults: `metadata={}`, `system=false`
- Respons: `{ edge_id: "<uuid>" }`
- `POST /intentions/update_node` — Oppdater eksisterende node (partial update).
Krever tilgang: created_by eller owner/admin-edge.
- Body (JSON): `{ node_id, node_kind?, title?, content?, visibility?, metadata? }`
- Kun oppgitte felter endres, resten beholdes
- Respons: `{ node_id: "<uuid>" }`
- `POST /intentions/delete_node` — Slett node og tilhørende edges.
Krever tilgang: created_by eller owner/admin-edge.
- Body (JSON): `{ node_id }`
- Respons: `{ deleted: true }`
- `POST /intentions/update_edge` — Oppdater eksisterende edge (partial update).
Krever tilgang: created_by eller owner/admin-edge til source-noden.
- Body (JSON): `{ edge_id, edge_type?, metadata? }`
- Kun oppgitte felter endres, resten beholdes
- Respons: `{ edge_id: "<uuid>" }`
- `POST /intentions/delete_edge` — Slett en edge. Brukes bl.a. for avpublisering.
Krever tilgang: created_by eller owner/admin-edge til source-noden.
Ved fjerning av belongs_to-edge til publiseringssamling invalideres forside-cache.
- Body (JSON): `{ edge_id }`
- Respons: `{ deleted: true }`
- `POST /intentions/set_slot` — Sett slot-metadata (hero/featured/strøm) på
belongs_to-edge i publiseringssamling. Håndterer hero-erstatning og featured-overflow.
- Body (JSON): `{ edge_id, slot, slot_order?, pinned? }`
- Respons: `{ edge_id, displaced[] }`
### LiveKit / Sanntidslyd (oppgave 11.2)
- `POST /intentions/join_communication` — Koble til sanntidslyd i en kommunikasjonsnode.
Validerer deltaker-tilgang (owner/member_of/host_of-edge eller via alias).
Genererer LiveKit access token (JWT), oppdaterer node-metadata.
- Body (JSON): `{ communication_id, role? }` (role: "publisher" | "subscriber", default "publisher")
- Respons: `{ livekit_room_name, livekit_token, livekit_url, identity, participants[] }`
- Frontend bruker `livekit_token` + `livekit_url` til å koble livekit-client SDK.
- `POST /intentions/leave_communication` — Forlat sanntidsrom.
Fjerner deltaker fra live-rom.
- Body (JSON): `{ communication_id }`
- Respons: `{ status: "left" }`
- `POST /intentions/close_communication` — Steng sanntidsrom (krever owner/admin).
Fjerner alle deltakere, setter `live_status=ended` i metadata.
- Body (JSON): `{ communication_id }`
- Respons: `{ status: "closed" }`
### Mixer-kanaler (oppgave 22.2)
Delt mixer-tilstand i LiveKit-rom.
Skriver til PG `mixer_channels`-tabell; NOTIFY-trigger propagerer til WS.
- `POST /intentions/create_mixer_channel` — Opprett mixer-kanal for deltaker i rom.
- Body: `{ room_id, target_user_id }`
- `POST /intentions/set_gain` — Sett gain (0.01.5) for en kanal.
- Body: `{ room_id, target_user_id, gain }`
- `POST /intentions/set_mute` — Mute/unmute en kanal.
- Body: `{ room_id, target_user_id, is_muted }`
- `POST /intentions/toggle_effect` — Toggle en lydeffekt.
- Body: `{ room_id, target_user_id, effect_name }`
- `POST /intentions/set_mixer_role` — Sett rolle (editor/viewer) for deltaker.
- Body: `{ room_id, target_user_id, role }`
## 6. Instruks for Claude Code
- Maskinrommet (`maskinrommet/`) er Rust-prosjektet med axum, tokio, sqlx.
- Intensjoner fra frontend → `POST /intentions/*` endepunkter i maskinrommet.
- Tunge spørringer fra frontend → `GET /query/*` endepunkter i maskinrommet.
- Frontend (SvelteKit) har ingen direkte databasetilgang.
- Bakgrunnsjobber trigges av maskinrommet, ikke via en separat jobbkø-tabell.
> **Historisk merknad:** Tidligere beskrev dette dokumentet en arkitektur
> der SvelteKit var web-API og Rust kun var workers. Denne ble erstattet
> av maskinrommet-arkitekturen (se `docs/retninger/maskinrommet.md`).