Commit graph

33 commits

Author SHA1 Message Date
831666012a Fullfører oppgave 15.1: Systemvarsler via STDB
Implementerer systemvarsler (system_announcement-noder) som vises som
banner/toast for alle aktive klienter i sanntid via SpacetimeDB.

Backend (maskinrommet):
- POST /intentions/create_announcement: oppretter varslingsnode med
  validering av announcement_type (info/warning/critical), datoer
  (scheduled_at, expires_at) og blocks_new_sessions. Visibility
  settes automatisk til 'open' for broadcast til alle klienter.
- POST /intentions/expire_announcement: fjerner varslingsnode med
  tilgangskontroll (kun eier kan slette).

Frontend:
- SystemAnnouncements.svelte: filtrerer nodeStore for aktive
  system_announcement-noder, skjuler utløpte (expires_at), viser
  nedtelling for planlagte hendelser (scheduled_at). Fargekoding:
  rød (critical), gul (warning), blå (info). Critical kan ikke
  dismisses. Oppdaterer nedtelling hvert sekund.
- Komponent lagt til i +layout.svelte for global synlighet.
- API-funksjoner (createAnnouncement, expireAnnouncement) i api.ts.

Ref: docs/concepts/adminpanelet.md § "Systemvarsler og vedlikeholdsmodus"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:21:18 +00:00
63630eb55a Fullfører oppgave 14.16: Presentasjonselementer som noder
Publisert tittel, ingress, OG-bilde og undertittel er nå egne noder
koblet til artikler via title/subtitle/summary/og_image-edges.
Rendering bruker presentasjonselementer med fallback til artikkelfelt.

Backend:
- Ny query: GET /query/presentation_elements?article_id=...
- render_article_to_cas henter presentasjonselementer via edges
- fetch_article + fetch_index_articles bruker pres.elementer
- Batch-henting for forsideartikler (én SQL-spørring)
- ArticleData utvides med subtitle + og_image
- Alle fire temaer viser subtitle og OG-bilde
- SEO og_image-tag fylles fra presentasjonselement

Frontend:
- PresentationEditor.svelte: opprett/rediger tittel, undertittel,
  ingress, OG-bilde med variantvelger (editorial/ai/social/rss)
- Integrert i PublishDialog via <details>-seksjon
- API-klient: fetchPresentationElements(), deleteNode()

Grunnlag for A/B-testing (oppgave 14.17): edge-metadata støtter
ab_status/impressions/clicks/ctr, best_of() prioriterer winner > testing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:55:23 +00:00
6125302bcb Redaksjonell samtale (oppgave 14.13): kommunikasjonsnode knyttet til artikkel
Redaktør kan nå opprette en diskusjonstråd direkte fra den redaksjonelle
arbeidsflaten, knyttet til en innsendt artikkel og dens forfatter.

Backend:
- create_communication utvides med context_id som oppretter belongs_to-edge
  fra kommunikasjonsnoden til kontekstnoden (artikkelen)
- editorial_board-spørringen returnerer discussion_ids per kort (kommunikasjonsnoder
  med belongs_to til artikkelen)

Frontend:
- "Start samtale"-knapp på hvert redaksjonelt kort oppretter kommunikasjonsnode
  med redaktør som owner og forfatter som member, og navigerer til chatten
- Eksisterende samtaler vises som lenker på kortet

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:22:17 +00:00
f1752e73f5 Redaktørens arbeidsflate (oppgave 14.11): Kanban-brett for innsendinger
Redaktøren ser alle artikler med submitted_to-edge til samlingen,
gruppert i fire kolonner etter status. Drag-and-drop mellom kolonner
endrer status via update_edge. Siste kolonne ("Planlagt") åpner en
dialog for å sette publish_at i edge-metadata — klar for oppgave 14.12
(planlagt publisering).

Backend: GET /query/editorial_board med forfatterinfo og edge-metadata.
Frontend: /editorial/[id] med sanntidsoppdateringer via SpacetimeDB.
Lenke fra PublishingTrait når require_approval er aktivt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 02:09:03 +00:00
27d0d8db94 Publiseringsflyt i frontend (oppgave 14.7)
Personlig publiseringsflyt for samlinger med publishing-trait der
require_approval: false. Bruker kan publisere artikler fra mottak
til samlingen, og avpublisere ved å fjerne belongs_to-edge.

Backend:
- Nytt delete_edge-endepunkt i maskinrommet med tilgangskontroll
  og automatisk forside-cache-invalidering ved avpublisering

Frontend:
- PublishDialog: forhåndsvisning, slug-editor, tema-info, bekreftelse
- EditorTrait: publiser/avpubliser-knapper på innholdsnoder i
  publiseringssamlinger, velger for upubliserte artikler
- deleteEdge i API-klienten

Docs:
- Oppdatert api_grensesnitt.md med delete_edge, update_edge, set_slot

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 01:33:37 +00:00
8a4df2c237 Forside-admin i frontend (oppgave 14.6)
Visuell editor for redaksjonell forside-styring. Rute:
/collection/[id]/forside med tre soner (hero, featured, strøm).

- HTML5 drag-and-drop mellom hero/featured/strøm-plasser
- Pin-knapp per artikkel (forhindrer automatisk fjerning)
- Hurtigknapper for å flytte artikler mellom slots
- Forhåndsvisning via iframe av publisert forside
- Bruker POST /intentions/set_slot API fra maskinrommet
- Sanntidsdata fra SpacetimeDB (belongs_to-edges med slot-metadata)
- PublishingTrait viser nå «Rediger forside»-knapp og publisert-lenke

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 01:24:25 +00:00
b4c4bb8a0f Lydstudio: lydredigering via FFmpeg i nettleseren
Ikke-destruktiv redigering via EDL (Edit Decision List):
- Backend: audio.rs med FFmpeg-subprocess for klipp, normalisering,
  silence trim, fades, noise reduction, EQ, kompressor
- Frontend: /studio/[id] med wavesurfer.js RegionsPlugin,
  verktøypanel, sesjonslagring, og render-dialog
- Studio-trait for samlinger, versjonshistorikk via derived_from-edges
- API: audio_analyze (synkron), audio_process (jobbkø), audio_info

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:45:53 +00:00
51eb089f0c Trait-administrasjon: admin-UI for å administrere traits på samlinger (oppgave 13.4)
Legger til et admin-panel på samlingssiden der man kan legge til/fjerne
traits fra katalogen og konfigurere per-trait-innstillinger. Endringene
sendes via updateNode til maskinrommet som validerer mot VALID_TRAITS.

- Ny updateNode-funksjon i api.ts
- Delt trait-katalog i lib/traits.ts (brukes av collection/new og TraitAdmin)
- TraitAdmin.svelte: toggle traits, rediger config-nøkler, lagre
- Integrasjon i collection/[id] med Traits-knapp i header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:32:31 +00:00
427eae9641 Pakkevelger: UI for ny samling med pakker eller manuelt trait-valg (oppgave 13.3)
Ny side /collection/new med:
- 13 forhåndsdefinerte pakker (nettmagasin, podcaststudio, redaksjon osv.)
  som kort-grid med ikon, beskrivelse og trait-liste
- Manuelt trait-valg med hele trait-katalogen kategorisert i 9 grupper
- Oppsummering med valgte traits og opprett-knapp
- Navigerer til /collection/[id] etter opprettelse

Knapp «Ny samling» lagt til i mottak-headeren.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:26:17 +00:00
263f63bec8 Trait-aware frontend: samlingssider med dynamiske trait-paneler (oppgave 13.2)
Samlingsnoder med `metadata.traits` rendres nå som egne sider på
/collection/[id]. Hvert trait-navn mappes til en dedikert Svelte-komponent
som viser relevant UI. Traits uten egen komponent vises med et generisk panel.

Komponenter for 9 traits: editor, chat, kanban, podcast, publishing,
rss, calendar, recording, transcription. Mottak-siden viser traits som
pills og lenker til samlingssiden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:20:35 +00:00
7f5d23e0c6 Kunnskapsgraf: topic-noder, mentions-edges, visuell graf-visning (oppgave 9.4)
Backend:
- query_graph endpoint med rekursiv CTE-traversering (fokus + dybde)
- Filtrering på node_kind og edge_type, RLS-beskyttet
- Maks 200 noder, 1-3 hops dybde

Frontend:
- D3 force-directed graf på /graph med fargekodede noder
- Opprett topic-noder (node_kind='topic') direkte fra graf-visningen
- Opprett mentions-edges mellom vilkårlige noder
- Klikk for detaljer, dobbeltklikk for fokus, dra for å flytte
- Filter-legende for nodetyper og kanttyper
- Zoom, auto-fit, sidepanel med koblingsinfo
- Graf-knapp lagt til i mottaksflaten

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:01:57 +00:00
2ba830c7b4 Dagbok-visning: privat journal sortert på tid (oppgave 9.3)
Ny /diary-route som viser brukerens private noder — de som kun har
owner-edge og ingen delte edges til andre. Gruppert etter dato,
nyeste først, med inline oppretting av nye innlegg.

Dagbok-knapp med tellebadge lagt til i mottak-siden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:34:13 +00:00
ea0671933d Kalender-visning: månedsrutenett med scheduled-edges (oppgave 9.2)
Ny rute /calendar som viser alle noder med scheduled-edge i et
månedsbasert kalenderrutenett. Bruker edge-metadata { at: ISO8601 }
for tidspunkt, med T12:00:00-konvensjon for heldagshendelser.

Funksjoner:
- Månedsnavigering med «I dag»-snarvei
- Drag-and-drop for å flytte hendelser mellom datoer (updateEdge)
- Inline-oppretting med tittel og valgfritt klokkeslett
- Fargekoding etter node_kind
- Hendelsesliste under rutenett for gjeldende måned
- Kalender-lenke med hendelsesteller på mottak-siden
- Sanntid via SpacetimeDB (edgeStore.byType('scheduled'))

Arkitekturvalg: Bruker scheduled-edges direkte fra SpacetimeDB
i stedet for legacy calendar_events-tabellen. En node blir en
kalenderoppføring ved å ha en scheduled-edge — konsistent med
«hva edges gjør med noder»-prinsippet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:27:28 +00:00
d8c0cceb89 Kanban-visning: board med drag-and-drop statusendring (oppgave 9.1)
Implementerer kanban som noder+edges uten separate tabeller:
- Board = collection-node med metadata.board og metadata.columns
- Kort = content-noder med belongs_to-edge til board
- Status via status-edge (kort→board) med metadata.value
- Posisjon via belongs_to-edge metadata.position

Backend:
- POST /intentions/update_edge — oppdater edge-type/metadata
- GET /query/board?board_id= — hent kort med status og posisjon

Frontend:
- /board/[id] route med kolonner, drag-and-drop, kortoppretting
- Sanntid via SpacetimeDB edge-subscriptions
- Board-oppretting og navigasjon fra mottak-siden

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:13:22 +00:00
d4715831bf Flytt Caddy fra Docker til native + fiks frontend-kjeden
- Caddy installert via apt, kjører som systemd-service
- Docker-tjenester eksponerer porter på localhost (Authentik:9000,
  Forgejo:3000, SpacetimeDB:9080)
- Caddy-blokk fjernet fra docker-compose.yml
- iptables-hack fjernet (ingen Docker→host-proxy lenger)
- Caddy proxyer /api/* til maskinrommet (unngår CORS)
- SpacetimeDB URL fikset (trailing slash for korrekt URL-resolving)
- Arvet tilgang i nodeVisibility (belongs_to → foreldrenode)
- Signin-side bruker <a> i stedet for client-side signIn()
- /claude redirect-rute for testing
- @auth/core oppgradert 0.34.3→0.41.1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 21:26:06 +00:00
33a1b44946 Implementer Claude som chat-deltaker (Fase A: MVP)
Claude er nå en agent-node i grafen som kan delta i samtaler.
Når en bruker sender melding i en kommunikasjonsnode der Claude
er deltaker, enqueues en agent_respond-jobb som kaller claude CLI
direkte og skriver svaret tilbake til chatten.

Nye filer:
- migrations/007_agent_system.sql: agent_identities, agent_permissions, ai_usage_log
- maskinrommet/src/agent.rs: agent_respond job handler
- scripts/maskinrommet.service: systemd-tjeneste for native kjøring
- scripts/maskinrommet-env.sh: genererer env med Docker container-IPs

Endringer:
- intentions.rs: trigger agent_respond ved melding i agent-chat
- jobs.rs: dispatch agent_respond til agent-handler
- frontend chat: bot-badge (🤖) og amber-farge på agent-meldinger
- LiteLLM config: resonering-modellalias via OpenRouter

Maskinrommet kjører nå direkte på hosten (ikke i Docker) for å
ha tilgang til claude CLI. Caddy peker til host.docker.internal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 19:20:17 +00:00
35701aeb2a Fullfør oppgave 7.8: SRT-eksport fra transkripsjons-segmenter
Nytt GET /query/segments/srt-endepunkt som genererer nedlastbar SRT-fil
fra transcription_segments-tabellen. Bruker RLS-verifisert tilgang.
Frontend har nedlastingsknapp i TranscriptionView med autentisert fetch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:47:50 +01:00
b4ee80a97b Fullfør oppgave 7.7: Re-transkripsjonsflyt med side-om-side-sammenligning
Ny funksjonalitet for å kjøre re-transkripsjon på eksisterende media-noder
og sammenligne gammel vs ny versjon per segment. Manuelt redigerte segmenter
fra forrige versjon blir uthevet, og brukeren velger per segment hvilken
versjon som skal beholdes.

Backend (Rust):
- POST /intentions/retranscribe — trigger ny Whisper-jobb for media-node
- GET /query/transcription_versions — list alle versjoner for en node
- GET /query/segments_version — hent segmenter for spesifikk versjon
- POST /intentions/resolve_retranscription — anvend per-segment-valg

Frontend (Svelte):
- RetranscriptionCompare.svelte — side-om-side visning med per-segment-valg
- TranscriptionView: re-transkriber-knapp, auto-detect nye versjoner, polling
- API-klient: nye funksjoner for alle re-transkripsjonsendepunkter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:41:09 +01:00
0967e43af8 Implementer transkripsjonsvisning med segmenter (oppgave 7.6)
Backend:
- GET /query/segments?node_id=... — henter nyeste segmenter for en media-node
  med RLS-basert tilgangssjekk via nodes-tabellen
- POST /intentions/update_segment — redigerer segmenttekst, setter edited=true

Frontend:
- TranscriptionView.svelte: universell komponent for segment-visning med
  tidsstempler, avspillingsknapp per segment, og redigerbare tekstfelt
- AudioPlayer: integrert med TranscriptionView når segmenter finnes,
  faller tilbake til flat tekst ellers
- Mottak og chat-sider oppdatert med nodeId/accessToken for segment-lasting
- Fikser duration_ms → sekunder-konvertering i metadata-oppslag

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:29:43 +01:00
63d4bbd41b Fullfør oppgave 7.4: Lyd-avspilling med waveform-visning
Legger til AudioPlayer-komponent som spiller av lyd fra CAS-noder
med waveform-visualisering via wavesurfer.js. Komponenten viser
play/pause, tidslinje, og kan ekspandere transkripsjonen.

Chat-visningen inkluderer nå media-noder (has_media-edges) sammen
med tekstmeldinger, sortert kronologisk. Talenotater vises med
mikrofon-ikon, waveform og transkripsjon.

Mottak-siden viser også AudioPlayer for media-noder med lyd.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:07:29 +01:00
ebbec982b3 Fullfør oppgave 7.3: Voice memo — opptak-knapp i frontend
Legger til VoiceRecorder-komponent som bruker MediaRecorder API for
lydopptak i nettleseren. Opptaket lastes opp til CAS via eksisterende
uploadMedia-endepunkt, som automatisk trigger Whisper-transkripsjon.

Komponenten er integrert i:
- ChatInput: mikrofon-knapp mellom tekstfelt og send-knapp
- NodeEditor: mikrofon-knapp i verktøylinjen

Flyten: opptak → webm/opus blob → upload → CAS → whisper_transcribe-jobb.
Ingen backend-endringer nødvendig — hele transkripsjons-pipelinen fra
oppgave 7.2 gjenbrukes uendret.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 17:51:40 +01:00
dee9d5bf3a Fullfør oppgave 6.4: Bilder i TipTap via drag-and-drop/paste
Brukeren kan nå dra eller lime inn bilder i TipTap-editoren.
Bildet lastes opp til CAS via upload_media-endepunktet, og settes
inn som <img> med CAS-URL i metadata.document (HTML).

Endringer:
- Ny uploadMedia() og casUrl() i api.ts for multipart upload
- @tiptap/extension-image med CasImage-utvidelse (data-node-id attr)
- handleDrop/handlePaste i editor intercepter bildefiler
- Upload-status vises i editoren mens bilder lastes opp
- accessToken sendes ned til NodeEditor fra +page.svelte

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 17:07:17 +01:00
5d2581710f Fullfør oppgave 5.4: én-til-én chat med deltaker-velger
Implementerer full 1:1 chat-loop:
- NewChatDialog: velg person å starte samtale med
- Fikser API-felt (participant_ids → participants) for korrekt
  kommunikasjon med maskinrommets create_communication-endepunkt
- Opprett kommunikasjonsnode med to deltakere (owner + member_of)
- Dedupliserer: finner eksisterende samtale før ny opprettes
- Chat-header viser den andre deltakerens navn i 1:1-samtaler
- Testbruker-node opprettet på server for verifisering

Full loop verifisert via STDB: node + edges + melding + belongs_to
fungerer, WebSocket-subscribers ser endringer i sanntid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 16:25:44 +01:00
2af06111bb Fullfør oppgave 5.3: chat-visning med sanntid via STDB
Chat-visning i frontend som viser noder med belongs_to-edge til en
kommunikasjonsnode, sortert på tid, med sanntidsoppdatering via
SpacetimeDB.

Nye filer:
- frontend/src/routes/chat/[id]/+page.svelte — Chat-side som viser
  meldinger (noder med belongs_to-edge), deltakere, auto-scroll,
  og avsender-info. Bruker edgeStore.byTarget() for reaktive
  oppdateringer når nye meldinger kommer via STDB.
- frontend/src/lib/components/ChatInput.svelte — Enkel meldings-input
  med Enter-for-send, auto-resize textarea.

Endringer:
- frontend/src/lib/api.ts — Lagt til createCommunication()-funksjon
  for å opprette kommunikasjonsnoder fra frontend.
- frontend/src/routes/+page.svelte — Kommunikasjonsnoder i mottaket
  er nå klikkbare lenker til chat-visningen. "Ny samtale"-knapp.
- tasks.md — Oppgave 5.3 markert som ferdig.

Arkitektur: Chat-visningen bruker context_id-parameteren i
create_node-intensjonen (implementert i 5.2) for automatisk
belongs_to-edge. Meldinger hentes reaktivt fra STDB-stores —
ingen polling, ingen ekstra API-kall.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 16:15:15 +01:00
b55705d12c Kontekst-arv: automatisk belongs_to-edge ved input i kommunikasjonsnode
Legger til context_id-parameter på create_node-intensjonen. Når context_id
er satt (og peker på en kommunikasjonsnode), opprettes automatisk en
belongs_to-edge fra den nye noden til kontekstnoden. Dette er kjernen i
kontekst-arv: si noe i et møte → noden tilhører møtet automatisk.

Backend: Validerer at context_id eksisterer og er communication-node,
oppretter belongs_to-edge i STDB+PG etter node-opprettelse.
Frontend: Oppdaterer API-typer med context_id og belongs_to_edge_id.

Ref: docs/retninger/universell_input.md (kontekst arves automatisk)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:57:25 +01:00
023b598436 Frontend: visibility-filtrering med nodeAccessStore
Visibility-filtrering (oppgave 4.3, del 2/2):
- Regenerert STDB TypeScript-bindinger med node_access-tabell
- nodeAccessStore: reaktiv Svelte 5 store for tilgangsmatrisen
- nodeVisibility()-funksjon: returnerer 'full'/'discoverable'/'hidden'
  basert på created_by, node_access, og visibility-enum
- Mottaksflaten filtrerer noder: hidden-noder skjules,
  discoverable viser kun tittel, readable/open vises fullt
- Abonnerer på node_access-tabell via STDB WebSocket
- Debug-info viser antall access-rader

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 15:15:22 +01:00
83cc04937c Fullfør oppgave 3.6: Sanntidstest verifisert
Backend-verifisering av sanntidsflyt (STDB CRUD) bestått:
- Node opprettelse, oppdatering, sletting via STDB HTTP API
- Edge opprettelse med kaskadesletting
- Data synkronisert korrekt mellom PG og STDB

Frontend klar for browser-test (to faner):
- Arkitekturen støtter sanntid: STDB WebSocket → onInsert → stores → $derived
- Lagt til console.log i stores for å spore sanntidshendelser
- Alle builds (svelte-check, vite build, cargo check) grønne

Testskript: scripts/test-sanntid.sh (8 backend-tester)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:40:18 +01:00
0756e17069 Fullfør oppgave 3.5: TipTap-editor med create_node + owner-edge
Legger til owner-edge etter node-opprettelse slik at noden dukker opp
i brukerens mottak. Gjør API-klienten konfigurerbar via VITE_API_URL
for fremtidig produksjonsbruk. Legger til createEdge i API-klienten.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:26:59 +01:00
daaafd34ab TipTap-editor med create_node-intensjon (oppgave 3.5)
Legger til en TipTap-basert rik tekst-editor i mottaksflaten som sender
create_node-intensjoner til maskinrommet ved submit.

- TipTap med StarterKit (tekst, markdown), Link-extension og Placeholder
- NodeEditor.svelte: tittel + innhold, Ctrl+Enter for submit
- API-klient (lib/api.ts) som kaller maskinrommet via /api proxy
- Authentik access_token eksponert i session for API-kall
- Vite proxy rewrite fikset (/api → maskinrommet root)
- HTML-innhold lagres i metadata.document, ren tekst i content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:24:25 +01:00
08d2933788 Mottaksflaten v0: vis noder koblet til innlogget bruker (oppgave 3.4)
Henter brukerens node_id fra maskinrommets /me-endepunkt ved innlogging
(via Authentik access_token), cacher i JWT-sesjon. Mottaksflaten viser
alle noder brukeren har edges til (begge retninger), sortert nyeste først,
med tittel, utdrag, node_kind-merke og edge-type-merker.

Endringer:
- auth.ts: fetchNodeId() kaller maskinrommet /me ved sign-in
- app.d.ts: utvider JWT og Session med node_id/nodeId
- +page.svelte: erstatter dashboard med mottaksflate-visning
- .env.example: MASKINROMMET_URL for server-side API-kall

Krever at brukeren logger ut og inn igjen for å hente node_id.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 14:13:36 +01:00
a91d358263 STDB WebSocket-klient med reaktive Svelte-stores (oppgave 3.3)
Frontend kobler til SpacetimeDB via WebSocket og abonnerer på
node- og edge-tabellene. Data eksponeres som reaktive Svelte 5-stores
(runes) som oppdateres automatisk ved insert/update/delete.

Implementering:
- spacetimedb SDK (npm) + genererte TypeScript-bindings
- connection.svelte.ts: tilkoblingsmanager med reaktiv state
- stores.svelte.ts: nodeStore og edgeStore med sekundærindekser
  (bySource, byTarget, byKind, byType osv.)
- Layout initialiserer tilkobling ved autentisering
- Hjemmesiden viser tilkoblingsstatus og antall noder/edges
- .env.example med VITE_SPACETIMEDB_URL og VITE_SPACETIMEDB_MODULE

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:55:37 +01:00
6bc742cc8d Authentik OIDC login (oppgave 3.2)
Implementerer autentisering med Authentik via @auth/sveltekit:
- OIDC authorization code flow med PKCE og state-verifisering
- JWT-callback lagrer authentik_sub (SHA256-hash, ikke UUID) for
  konsistens med maskinrommets auth_identities-tabell
- Server hooks: alle ruter unntatt /signin og /auth/* krever sesjon
- Uautentiserte brukere redirectes til /signin (303)
- Innloggingsside med client-side signIn('authentik')
- Hovedside viser innlogget bruker med logg ut-knapp
- TypeScript-typer utvidet med JWT.authentik_sub

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:45:33 +01:00
d43365d5ea SvelteKit frontend-skjelett (oppgave 3.1)
Oppretter frontend/ med SvelteKit, TypeScript, TailwindCSS v4 og
adapter-node. PWA-manifest med SVG-ikon. Vite proxy til
api.sidelinja.org for lokal utvikling med HMR.

Oppdaterer docs/setup/lokal.md med riktige stier (frontend/ og
maskinrommet/ i stedet for web/ og rust/).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:37:41 +01:00