Implementerer Row Level Security for tunge PostgreSQL-spørringer.
Maskinrommet skriver som superuser (sidelinja), men leser med
SET LOCAL ROLE synops_reader som er underlagt RLS-policies.
Endringer:
- Migration 004: synops_reader rolle, current_node_id() funksjon,
RLS-policies på nodes (created_by/node_access/visibility),
edges (endepunkt-tilgang + system-edge-skjuling),
og node_access (kun egne rader)
- queries.rs: RLS-kontekst-helper (set_rls_context) og
GET /query/nodes endepunkt med søk, filtrering og paginering
- migration_safety.md: omskrevet fra v1 workspace-RLS til
node_access-basert RLS med oppdaterte leak hunter-tester
Verifisert på server: hidden noder filtrert for ukjente brukere,
synlige for eiere. Edges filtrert tilsvarende.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Visibility-filtrering (oppgave 4.3, del 1/2):
- Ny node_access-tabell i STDB-modulen som speiler PG
- Reducers: upsert_node_access, delete_node_access, delete_node_access_for_subject
- STDB-klient i maskinrommet: metoder for node_access
- Warmup synker node_access fra PG til STDB ved oppstart
- Tilgangsgivende edges synker node_access til STDB etter PG-commit
- clear_all tømmer også node_access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Når en tilgangsgivende edge (owner, admin, member_of, reader)
opprettes, kalles nå recompute_access() i samme PG-transaksjon
som edge-insertet. Dette sikrer at node_access-matrisen alltid
er oppdatert — ingen vindu med stale tilgang.
Implementasjon:
- edge_type_to_access_level() mapper edge-typer til access_level enum
- insert_edge_with_access() wrapper edge-insert + recompute_access i tx
- Vanlige edges (belongs_to, mentions, etc.) skrives som før (fire-and-forget)
Verifisert med SQL-tester: direkte tilgang + transitiv tilgang via
belongs_to-edges fungerer korrekt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementerer tre nye skrivestier i maskinrommet med tilgangskontroll:
- POST /intentions/create_edge — opprett retningsbestemt edge mellom
to noder. Validerer at begge noder eksisterer og edge_type er satt.
- POST /intentions/update_node — partial update av eksisterende node.
Kun oppgitte felter endres, resten beholdes fra PG.
- POST /intentions/delete_node — slett node med cascade av edges.
Tilgangskontroll for update/delete: brukeren må enten være created_by
på noden, eller ha en owner/admin-edge til den. Sjekkes mot PG som
autoritativ kilde.
Alle endepunkter følger samme mønster som create_node:
STDB-skriving (instant) → async PG-persistering → umiddelbar respons.
Verifisert på server med 10 testcaser:
1. /me med gyldig token → 200
2. create_node → 200 med node_id
3. create_edge (gyldig) → 200 med edge_id
4. create_edge (ugyldig source) → 400
5. create_edge (tom edge_type) → 400
6. update_node (partial, eier) → 200
7. update_node (ingen tilgang) → 403
8. delete_node (eier) → 200
9. delete_node (ingen tilgang) → 403
10. update via owner-edge (Sidelinja) → 200
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementerer den første intensjonen i maskinrommet — skrivestien
som gjør at frontend kan opprette noder via maskinrommet.
Flyten:
1. Valider input (node_kind, visibility, metadata)
2. Generer UUIDv7 (tidssortert)
3. Skriv til SpacetimeDB (instant — frontend ser noden umiddelbart)
4. Spawn async tokio-task for PG-persistering
5. Returner node_id uten å vente på PG
Verifisert på server med fire testcaser:
1. Uten auth → 401
2. Ugyldig visibility → 400 med feilmelding
3. Minimal request (tomt body) → 200, node opprettet med defaults
4. Full request → 200, node verifisert i både STDB og PG
Også: Dockerfile oppdatert til Rust 1.88 (avhengigheter krevde >1.86),
og api_grensesnitt.md oppdatert med endepunktdokumentasjon.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fiks NULL-håndtering i warmup (COALESCE for title/content/created_by)
- Renere health check (delete nonexistent node i stedet for create+delete)
- Dokumenter HTTP API-format og warmup-flyt i erfaringer
- Lagre STDB-token i server .env
- Republiser STDB-modul etter containerrestart
Verifisert: warmup laster 2 noder + 1 edge, /health viser stdb=connected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legger til HTTP-klient som kaller STDB-reducere via JSON API.
Warmup-modul laster hele grafen fra PG til STDB ved oppstart.
- stdb.rs: HTTP-klient med create/update/delete for noder og edges
- warmup.rs: PG → STDB sync (clear_all → noder → edges)
- main.rs: Integrerer STDB i AppState, kjører warmup ved oppstart
API-format: POST /v1/database/{db}/call/{reducer} med navngitte params.
STDB-token kan settes via SPACETIMEDB_TOKEN eller opprettes automatisk.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fikser audience-validering (AUTHENTIK_CLIENT_ID som forventet aud)
- Oppdaterer seed-data med reell Authentik sub for Vegard
- Fikser DATABASE_URL i .env: peker nå til synops-database (ikke sidelinja)
- Dokumenterer maskinrommet-miljøvariabler i produksjon.md
- Markerer oppgave 2.2 som ferdig i tasks.md
Verifisert på server med fem testcaser:
1. /health (public) → 200
2. /me uten token → 401 "Mangler Authorization-header"
3. /me med ugyldig token → 401 "Ugyldig token"
4. /me med gyldig JWT, ukjent sub → 401 "Ukjent brukeridentitet"
5. /me med gyldig JWT, kjent sub → 200 med node_id
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Legger til Authentik JWT-validering i maskinrommet:
- Henter JWKS fra Authentik ved oppstart
- Validerer RS256-signatur, issuer og utløpstid
- Slår opp sub-claim i auth_identities → node_id
- AuthUser axum-extractor for beskyttede endepunkter
- /me test-endepunkt som krever gyldig token
- /health forblir offentlig
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Axum-server med health-endepunkt, PostgreSQL-tilkobling via sqlx,
strukturert logging med tracing. Flertrinns Dockerfile for produksjon.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>