Backend: - ws.rs: Fikset WS auth via query-param (browser kan ikke sende headers ved WS upgrade) - auth.rs: Gjort decoding_key pub for gjenbruk i ws-modulen Frontend: - pg-ws.svelte.ts: Ny PG WebSocket-klient med auto-reconnect og event-logging - index.ts: Eksporterer pgWsConnect/pgWsDisconnect/pgWsState - +layout.svelte: Kobler til PG WS i parallell med STDB for verifisering Docs: - api_grensesnitt.md: Dokumentert /ws endepunkt og sanntidsarkitektur - tasks.md: Merket 22.1 som ferdig Deploy: Krever restart av maskinrommet + rebuild av frontend.
7.7 KiB
7.7 KiB
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.
SpacetimeDB er under utfasing — frontend kobler til begge i parallell
under verifiseringsfasen (Fase M1).
Tunge spørringer (søk, statistikk, graftraversering) går via maskinrommet → PG.
2. Kommunikasjonskart
┌─────────────────────────────────────────────────────────────┐
│ Brukerens nettleser (SvelteKit klient) │
└──────────┬──────────────────────┬───────────────────────────┘
│ │
│ HTTP (intensjoner) │ WebSocket (sanntid)
▼ ▼
┌──────────────────────┐ ┌──────────────────┐
│ Maskinrommet (Rust) │ │ SpacetimeDB │
│ axum HTTP API │ │ │
│ │ │ - Hele grafen │
│ Ansvar: │ │ - Push til │
│ - Validere │ │ klienter │
│ - Skrive STDB+PG │ │ │
│ - Orkestrere │ └──────────────────┘
│ - Tunge spørringer │
│ - Bakgrunnsjobber │
└──┬─────┬─────┬───────┘
│ │ │
▼ ▼ ▼
┌─────┐┌─────┐┌─────────────┐
│ PG ││STDB ││ Whisper, │
│ ││ ││ LiteLLM, │
│ ││ ││ LiveKit ... │
└─────┘└─────┘└─────────────┘
3. Ansvarsfordeling
| Komponent | Rolle | Snakker med |
|---|---|---|
| SvelteKit (klient) | UI, brukerinteraksjon | Maskinrommet (HTTP), SpacetimeDB (WS) |
| Maskinrommet (Rust) | Intensjons-API, orkestrering, tunge spørringer | PG, SpacetimeDB, CAS, Whisper, LiteLLM |
| SpacetimeDB | Sanntids state, push til klienter | Klienter (WS), maskinrommet (skriver) |
| PostgreSQL | Persistent arkiv, søk, statistikk | Maskinrommet (SQL) |
4. Viktige avklaringer
- Maskinrommet er en HTTP API-server (axum). Frontend sender intensjoner hit.
- Maskinrommet eier alle skrivinger. Frontend skriver aldri direkte til PG eller STDB.
- SpacetimeDB nås direkte fra klienten via WebSocket for lesing (sanntid).
- 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- og STDB-tilkobling.
WebSocket (sanntid, oppgave 22.1)
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_syncmed alle noder, edges og access brukeren kan se. - Deretter: strømmer
node_changed,edge_changedogaccess_changedevents, filtrert på brukerens tilgangsmatrise (node_access). - Kilder: PG LISTEN/NOTIFY-triggere på nodes, edges og node_access-tabellene.
- Events er JSON med
{ "type": "node_changed"|"edge_changed"|"access_changed", ... }.
- Ved tilkobling: sender
Autentiserte (krever Authorization: Bearer <JWT>)
GET /me— Returnerer autentisert brukersnode_idogauthentik_sub.POST /intentions/create_node— Opprett node. Skriv til STDB (instant), spawn async PG-skriving, returnernode_idumiddelbart.- Body (JSON):
{ node_kind?, title?, content?, visibility?, metadata? } - Defaults:
node_kind="content",visibility="hidden", andre felter tomme - Respons:
{ node_id: "<uuid>" }
- Body (JSON):
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>" }
- Body (JSON):
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>" }
- Body (JSON):
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 }
- Body (JSON):
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>" }
- Body (JSON):
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 }
- Body (JSON):
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[] }
- Body (JSON):
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), oppretter rom i STDB, 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_urltil å koble livekit-client SDK.
- Body (JSON):
POST /intentions/leave_communication— Forlat sanntidsrom. Fjerner deltaker fra STDB live-rom.- Body (JSON):
{ communication_id } - Respons:
{ status: "left" }
- Body (JSON):
POST /intentions/close_communication— Steng sanntidsrom (krever owner/admin). Fjerner alle deltakere, setterlive_status=endedi metadata.- Body (JSON):
{ communication_id } - Respons:
{ status: "closed" }
- Body (JSON):
SpacetimeDB sanntidstabeller (LiveKit)
live_room— Aktive rom. Felt:room_id,communication_id,is_active,started_at,participant_count.room_participant— Deltakere i rom. Felt:id,room_id,user_id,display_name,role,joined_at. Frontend abonnerer på disse via SpacetimeDB WebSocket for sanntids deltakerliste.
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).