synops/tasks.md
2026-03-18 19:45:28 +00:00

43 KiB
Raw Blame History

Synops — Implementeringsoppgaver

Sekvensiell liste. Hver oppgave gjøres i én Claude Code-sesjon. Runner-scriptet plukker første ugjorte oppgave som ikke er blokkert.

Statuser

  • - [ ] — Klar til å gjøres
  • - [~] — Pågår. En agent jobber på denne. Andre agenter hopper over.
  • - [x] — Ferdig
  • - [?] — Åpent spørsmål, trenger avklaring fra Vegard.
  • - [!] — Blokkert av teknisk problem.

[~], [?] og [!] blokkerer alle oppgaver som avhenger av denne. Detaljer skrives som innrykket tekst med > prefix under oppgaven. Runner-scriptet legger automatisk til > Påbegynt: <timestamp> for [~].

Hvis en [~]-oppgave har stått i >60 min uten commit, anta at sesjonen krasjet. Kjør run-next-task.sh --unstale for å frigjøre.

Avhengigheter

Oppgaver innen en fase er sekvensielle (1.1 før 1.2, osv). Faser avhenger av hverandre slik:

Fase 1 (infra) → Fase 2 (maskinrommet) → Fase 3 (frontend)
                                        ↘ Fase 4 (tilgang)
Fase 3 + 4 → Fase 5 (kommunikasjon)
Fase 2 → Fase 6 (CAS) → Fase 7 (lyd)
Fase 5 → Fase 8 (aliaser)
Fase 3 → Fase 9 (visninger)
Fase 2 → Fase 10 (AI)
Fase 5 + 6 + 7 → Fase 11 (produksjon)
Fase 3 + 4 → Fase 13 (traits)
Fase 6 + 13 → Fase 14 (publisering)
Fase 3 + 10 → Fase 15 (adminpanel)
Fase 11 + 13 → Fase 16 (lydmixer)
Fase 17 (lydstudio-utbedring) — ingen avhengigheter, kan kjøres parallelt
Fase 10 + 13 → Fase 18 (AI-verktøy)
Fase 3 + 13 → Fase 19 (arbeidsflaten — spatial canvas)
Fase 19 → Fase 20 (universell overføring + panelrework)
Fase 2 → Fase 21 (CLI-verktøy — unix-filosofi)
Alt → Fase 12 (herding)
Fase 12 → Fase 22 (SpacetimeDB-migrering — fullført)
Fase 22 → Fase 23 (validering — alle faser)
Fase 23 → Fase 24 (orkestrering)
Fase 24 → Fase 25 (web clipper)
Fase 25 → Fase 26 (epost)
Fase 25 → Fase 27 (tankekart) — uavhengig av epost
Fase 25 → Fase 28 (manglende CLI + AI-ruting) — uavhengig av epost
Fase 25 → Fase 29 (universell input) — uavhengig av epost
Fase 25 → Fase 30 (podcast-hosting) — uavhengig av epost

Hvis en oppgave er [?] eller [!], hoppes den over — og alle oppgaver som avhenger av den (innen fasen + avhengige faser). Uavhengige faser kan fortsatt plukkes.


Fase 1: Infrastruktur-fundament

  • 1.1 PostgreSQL schema: opprett database synops, enums (visibility, access_level), tabeller (nodes, edges, node_access, auth_identities) med indekser. Kjør på server via SSH. Ref: docs/primitiver/nodes.md, docs/primitiver/edges.md, docs/retninger/bruker_ikke_workspace.md.
  • 1.2 Seed-data: opprett Vegards brukernode (node_kind='person', title='Vegard') og auth_identities-rad. Opprett Sidelinja samlings-node og owner-edge fra Vegard.
  • 1.3 SpacetimeDB modul: opprett Rust-modul med nodes og edges-tabeller som speiler PG-skjema. Grunnleggende reducers for CRUD. Deploy til server. Ref: docs/retninger/datalaget.md, docs/erfaringer/spacetimedb_integrasjon.md.
  • 1.4 Caddy-config: reverse proxy for maskinrommet (api.sidelinja.org), SpacetimeDB, og SvelteKit. Auto-TLS. Ref: docs/setup/produksjon.md.
  • 1.5 Authentik: opprett OIDC-provider og applikasjon for Synops. Konfigurer redirect URIs. Ref: docs/erfaringer/authentik_oppsett.md.

Fase 2: Maskinrommet — skjelett

  • 2.1 Rust-prosjekt: opprett maskinrommet/ med axum, tokio, sqlx (PG), serde. Dockerfile. Kompilerer og starter. Ref: docs/retninger/maskinrommet.md.
  • 2.2 Auth-middleware: valider Authentik JWT-tokens, slå opp auth_identities → node_id. Returner 401 for ugyldige tokens.
  • 2.3 SpacetimeDB-klient i maskinrommet: koble til STDB, skriv noder og edges via reducers.
  • 2.4 Skrivestien: POST /intentions/create_node — valider, skriv STDB (instant), spawn async PG-skriving. Returner node_id umiddelbart.
  • 2.5 Flere intensjoner: create_edge, update_node, delete_node. Validering av tilgang (created_by eller owner/admin-edge).
  • 2.6 Docker Compose: legg maskinrommet inn i server-stacken. Intern nettverkstilgang til PG og STDB.

Fase 3: Frontend — skjelett

  • 3.1 SvelteKit-prosjekt: opprett frontend/ med TypeScript, TailwindCSS. PWA-manifest. Lokal dev med HMR.
  • 3.2 Authentik login: OIDC-flow (authorization code + PKCE). Session-håndtering. Redirect til login ved 401.
  • 3.3 STDB WebSocket-klient: abonner på noder og edges. Reaktiv Svelte-store som oppdateres ved endringer.
  • 3.4 Mottaksflaten v0: vis noder med edge til innlogget bruker, sortert på created_at. Enkel liste med tittel og utdrag.
  • 3.5 TipTap-editor: enkel preset (tekst, markdown, lenker). Send create_node-intensjon til maskinrommet ved submit.
  • 3.6 Sanntidstest: åpne to faner, skriv i én, se noden dukke opp i den andre via STDB.

Fase 4: Tilgangskontroll

  • 4.1 recompute_access i maskinrommet: ved edge-endring, oppdater node_access-matrisen. Håndter direkte edges (owner, admin, member, reader).
  • 4.2 Team-transitivitet: member_of-edge til team → arv tilgang fra teamets edges.
  • 4.3 Visibility-filtrering: STDB-spørringer respekterer visibility-enum. Frontend ser bare noder brukeren har tilgang til.
  • 4.4 RLS-policies på PG: node_access-basert filtrering for tunge spørringer.

Fase 5: Kommunikasjonsnoder

  • 5.1 Opprett kommunikasjonsnode: intensjon create_communication → node med node_kind='communication', deltaker-edges, metadata (started_at).
  • 5.2 Kontekst-arv: input i kommunikasjonsnode → automatisk belongs_to-edge.
  • 5.3 Chat-visning i frontend: noder med belongs_to-edge til kommunikasjonsnode, sortert på tid, sanntid via STDB.
  • 5.4 Én-til-én chat: opprett kommunikasjonsnode med to deltakere. Full loop: skriv melding → vis i sanntid hos begge.

Fase 6: CAS og mediefiler

  • 6.1 CAS-lagring: filsystem med content-addressable hashing (SHA-256). Katalogstruktur med hash-prefix. Deduplisering.
  • 6.2 Upload-endepunkt: POST /intentions/upload_media → hash fil, lagre i CAS, opprett media-node med has_media-edge.
  • 6.3 Serving: GET /cas/{hash} → stream fil fra disk. Caddy kan serve direkte for ytelse.
  • 6.4 Bilder i TipTap: drag-and-drop/paste → upload → CAS-node → inline i metadata.document via node_id.

Fase 7: Lyd-pipeline

  • 7.1 faster-whisper oppsett: Docker-container, GPU hvis tilgjengelig, norsk modell. Ref: docs/erfaringer/.
  • 7.2 Transkripsjons-pipeline: lydfil i CAS → maskinrommet trigger Whisper → resultat i content-feltet.
  • 7.3 Voice memo i frontend: opptak-knapp i input-komponenten → upload → CAS → transkripsjon.
  • 7.4 Lyd-avspilling: spiller av original lyd fra CAS-node. Waveform-visning.
  • 7.5 Segmenttabell-migrasjon: opprett transcription_segments-tabell i PG. Oppdater transcribe.rs til SRT-format → parse → skriv segmenter. Miljøvariabler: WHISPER_MODEL (default "medium"), WHISPER_INITIAL_PROMPT. Ref: docs/concepts/podcastfabrikken.md § 3.
  • 7.6 Transkripsjonsvisning i frontend: segmenter med tidsstempler, avspillingsknapp per segment (hopper til riktig sted i lydfilen), redigerbare tekstfelt (setter edited = true). Universell komponent for podcast, møter, voice memos.
  • 7.7 Re-transkripsjonsflyt: ved ny transkripsjon, vis side-om-side med forrige versjon. Highlight manuelt redigerte segmenter fra forrige versjon. Bruker velger per segment.
  • 7.8 SRT-eksport: generer nedlastbar SRT-fil fra transcription_segments-tabellen.

Fase 8: Aliaser

  • 8.1 Alias-noder: opprett alias-node med alias-edge (system=true) fra hovednoden. Usynlig for traversering.
  • 8.2 Kontekstbasert identitet: maskinrommet setter created_by til alias-node når brukeren opererer i kontekst der aliaset er vert/deltaker.

Fase 9: Flere visninger

  • 9.1 Kanban-visning: noder med board-edge, gruppert på status-edge. Drag-and-drop for statusendring.
  • 9.2 Kalender-visning: noder med scheduled-edge, på tidslinje.
  • 9.3 Dagbok-visning: private noder (ingen delte edges), sortert på tid.
  • 9.4 Kunnskapsgraf: topic-noder, mentions-edges. Visuell graf-visning.

Fase 10: AI og beriking

  • 10.1 LiteLLM oppsett: Docker-container, API-nøkler, modell-routing. Ref: docs/infra/ai_gateway.md.
  • 10.2 AI-foreslåtte edges: maskinrommet sender innhold til LLM → foreslår mentions, topics.
  • 10.3 Oppsummering: kommunikasjonsnode → AI-generert sammendrag som ny node.
  • 10.4 TTS: tekst → lyd via ElevenLabs. Mottaker-preferanse i metadata.

Fase 11: Produksjons-pipeline

  • 11.1 LiveKit oppsett: Docker-container for WebRTC. Ref: docs/setup/produksjon.md.
  • 11.2 Sanntidslyd: kommunikasjonsnode med live-status → LiveKit-rom for deltakere.
  • 11.3 Pruning-logikk: TTL per modalitet, signaler som forlenger levetid, disk-nødventil.
  • 11.4 Podcast-RSS: samlings-node med publiserings-edges → generert RSS-feed.

Fase 13: Trait-system

  • 13.1 Trait-metadata på samlingsnoder: maskinrommet validerer metadata.traits-objektet ved create_node og update_node for samlingsnoder. Avvis ukjente trait-navn. Ref: docs/primitiver/traits.md.
  • 13.2 Trait-aware frontend: samlingssider leser traits fra metadata og rendrer kun aktive komponenter. Dynamisk komponent-lasting basert på trait-liste.
  • 13.3 Pakkevelger: UI for å opprette ny samling med forhåndsdefinert pakke (nettmagasin, podcaststudio, redaksjon osv.) eller manuelt valg av traits.
  • 13.4 Trait-administrasjon: admin-UI for å legge til/fjerne traits på eksisterende samlinger med konfigurasjon per trait.

Fase 14: Publisering

  • 14.1 Tera-templates: innebygde temaer (avis, magasin, blogg, tidsskrift) med Tera i Rust. Artikkelmal + forside-mal per tema. CSS-variabler for theme_config-overstyring. Ref: docs/concepts/publisering.md § "Temaer".
  • 14.2 HTML-rendering av enkeltartikler: maskinrommet rendrer metadata.document til HTML via Tera, lagrer i CAS. Noden får metadata.rendered.html_hash + renderer_version. SEO-metadata (OG-tags, canonical, JSON-LD).
  • 14.3 Forside-rendering: maskinrommet spør PG for hero/featured/strøm (tre indekserte spørringer), appliserer tema-template, rendrer til CAS (statisk modus) eller serverer med in-memory cache (dynamisk modus). index_mode og index_cache_ttl i trait-konfig.
  • 14.4 Caddy-ruting for synops.no/pub: Caddy reverse-proxyer til maskinrommet som gjør slug→hash-oppslag og streamer CAS-fil. Cache-Control: immutable for artikler. Kategori/arkiv/søk serveres dynamisk av maskinrommet med kortere cache-TTL.
  • 14.5 Slot-håndtering i maskinrommet: slot og slot_order i belongs_to-edge metadata. Ved ny hero → gammel hero flyttes til strøm. Ved featured over featured_max → FIFO tilbake til strøm. pinned-flagg forhindrer automatisk fjerning.
  • 14.6 Forside-admin i frontend: visuell editor for hero/featured/strøm. Drag-and-drop mellom plasser. Pin-knapp. Forhåndsvisning. Oppdaterer edge-metadata via maskinrommet.
  • 14.7 Publiseringsflyt i frontend (personlig): publiseringsknapp på noder i samlinger med publishing-trait der require_approval: false. Forhåndsvisning, slug-editor, bekreftelse. Avpublisering ved fjerning av edge.
  • 14.8 RSS/Atom-feed: samling med rss-trait genererer feed automatisk ved publisering/avpublisering. synops.no/pub/{slug}/feed.xml. Maks rss_max_items (default 50).
  • 14.9 Custom domains: bruker registrerer domene i publishing-trait. Maskinrommet validerer DNS, Caddy on-demand TLS med validerings-callback. Re-rendring med riktig canonical URL.
  • 14.10 Redaksjonell innsending: submitted_to-edge med status-metadata (pending, in_review, revision_requested, rejected, approved). Maskinrommet validerer at kun roller i submission_roles kan opprette submitted_to, og kun owner/admin kan endre status eller opprette belongs_to. Ref: docs/concepts/publisering.md § "Innsending".
  • 14.11 Redaktørens arbeidsflate: frontend-visning av noder med submitted_to-edge til samling, gruppert på status. Kanban-stil drag-and-drop for statusendring. Siste kolonne ("Planlagt") setter publish_at i edge-metadata.
  • 14.12 Planlagt publisering: maskinrommet sjekker periodisk (cron/intervall) for belongs_to-edges med publish_at i fortiden som ikke er rendret. Ved treff: render HTML → CAS → oppdater RSS.
  • 14.13 Redaksjonell samtale: ved innsending kan redaktør opprette kommunikasjonsnode knyttet til artikkel + forfatter for diskusjon/feedback utover kort notat i edge-metadata.
  • 14.14 Bulk re-rendering: batch-jobb via jobbkø ved temaendring. Paginert (100 artikler om gangen), oppdaterer renderer_version. Artikler serveres med gammelt tema til re-rendret.
  • 14.15 Dynamiske sider: kategori-sider (filtrert på tag-edges), arkiv (kronologisk med månedsgruppering), søk (PG fulltekst). Alle paginerte, cachet i maskinrommet. Om-side som statisk CAS-node.
  • 14.16 Presentasjonselementer som noder: publisert tittel, ingress, OG-bilde, undertittel er egne noder med title/summary/og_image-edges til artikkelen. Frontend for å opprette/redigere varianter. Ref: docs/concepts/publisering.md § "Presentasjonselementer".
  • 14.17 A/B-testing: maskinrommet roterer varianter ved forside-rendering, logger impressions/klikk per variant, normaliserer CTR mot tidspunkt-baseline. Etter statistisk signifikans markeres vinner. Redaktør kan overstyre. Edge-metadata: ab_status, impressions, clicks, ctr.

Fase 15: Adminpanel

  • 15.1 Systemvarsler: varslingsnode (node_kind='system_announcement') med type (info/warning/critical), nedtelling og utløp. Frontend viser banner/toast for alle aktive klienter via STDB. Ref: docs/concepts/adminpanelet.md.
  • 15.2 Graceful shutdown: admin setter vedlikeholdstidspunkt → nedtelling i frontend → nye LiveKit-rom blokkeres → jobbkø stopper → vent på aktive jobber → restart. Vis aktive sesjoner før bekreftelse.
  • 15.3 Jobbkø-oversikt: admin-UI for aktive, ventende og feilede jobber. Filtrer på type/samling/status. Manuell retry og avbryt.
  • 15.4 AI Gateway-konfigurasjon: admin-UI for modelloversikt, API-nøkler (kryptert), ruting-regler per jobbtype, fallback-kjeder, forbruksoversikt per samling. Ref: docs/infra/ai_gateway.md.
  • 15.5 Ressursstyring: prioritetsregler mellom jobbtyper, ressursgrenser per worker, ressurs-governor for automatisk nedprioritering under aktive LiveKit-sesjoner, disk-status med varsling.
  • 15.6 Serverhelse-dashboard: tjeneste-status (PG, STDB, Caddy, Authentik, LiteLLM, Whisper, LiveKit), metrikker (CPU, minne, disk), backup-status, logg-tilgang.
  • 15.7 Ressursforbruk-logging: resource_usage_log-tabell i PG. Maskinrommet logger AI-tokens (inn/ut, modellnivå), Whisper-tid (sek), TTS-tegn, CAS-lagring (bytes), LiveKit-tid (deltaker-min). Båndbredde via Caddy-logg-parsing. Ref: docs/features/ressursforbruk.md.
  • 15.8 Forbruksoversikt i admin: aggregert visning per samling, per ressurstype, per tidsperiode. Drill-down til jobbtype og modellnivå.
  • 15.9 Brukersynlig forbruk: hver bruker ser eget forbruk i profil/innstillinger. Per-node forbruk synlig i node-detaljer for eiere.

Fase 16: Lydmixer

Ref: docs/features/lydmixer.md

  • 16.1 LiveKit-klient i frontend: installer livekit-client, koble til rom, vis deltakerliste. Deaktiver LiveKit sin auto-attach av <audio>-elementer — lyd rutes gjennom Web Audio API i stedet.
  • 16.2 Web Audio mixer-graf: opprett AudioContext, MediaStreamSourceNode per remote track → per-kanal GainNode → master GainNodedestination. AnalyserNode per kanal for VU-meter.
  • 16.3 Mixer-UI (MixerTrait-komponent): kanalstripe per deltaker med volumslider (0150%), nød-mute-knapp (stor, rød), VU-meter (canvas/CSS), navnelabel. Master-fader og master-mute. Responsivt design (mobil: kompakt fader-modus).
  • 16.4 Delt mixer-kontroll via SpacetimeDB: MixerChannel-tabell + reducers (set_gain, set_mute, toggle_effect). Frontend abonnerer og oppdaterer Web Audio-graf ved endring fra andre deltakere. Visuell feedback (sliders beveger seg i sanntid). Tilgangskontroll: eier/admin kan sette deltaker til viewer-modus.
  • 16.5 Sound pads: pad-grid UI (4×2), forhåndslast lydfiler fra CAS til AudioBuffer. Avspilling ved trykk (AudioBufferSourceNode). Pad-konfig i metadata.mixer.pads (label, farge, cas_hash). Synkronisert avspilling via LiveKit Data Message.
  • 16.6 EQ-effektkjede: fat bottom (BiquadFilterNode lowshelf ~200Hz), sparkle (BiquadFilterNode highshelf ~10kHz), exciter (WaveShaperNode + highshelf). Per-kanal toggles, synkronisert via STDB. Presets (podcast-stemme, radio-stemme).
  • 16.7 Stemmeeffekter: robotstemme (ring-modulasjon: OscillatorNodeGainNode.gain), monsterstemme (egenutviklet AudioWorkletProcessor med phase vocoder for pitch shift). Effektvelger-UI per kanal. Parameterjustering (pitch-faktor, oscillator-frekvens).

Fase 17: Lydstudio-utbedring

Ref: Kodegjennomgang av b4c4bb8 (Lydstudio: lydredigering via FFmpeg).

  • 17.1 Responsivt studio-layout: /studio/[id] sidebar stacker under waveform på mobil. Verktøypanel som modal/sheet på små skjermer. Ref: feedback om at alt UI skal være responsivt uten unntak.
  • 17.2 FFmpeg-parametervalidering: valider at alle numeriske verdier (threshold, gain, ratio, frekvenser) er innenfor sikre grenser i audio.rs før de interpoleres i filterstrenger. Avvis ugyldige verdier med feilmelding.
  • 17.3 Fade/silence-logikk: fiks negativ fade-out start (clamp til 0), og adaptiv silence-margin (margin skal ikke overstige halve regionens varighet). Gi feilmelding ved ugyldige fade-varigheter.
  • 17.4 Frontend input-begrensninger: legg til min/max på alle tallfelter i OperationPanel (silenceThreshold, fadeMs, normTarget, compRatio). Hindre ugyldig input.
  • 17.5 Job-polling opprydding: rydd opp interval/timeout ved navigering bort fra studio-siden. Vis feilmelding etter N mislykkede polling-forsøk. Wrap metadata JSON.parse i try/catch.
  • 17.6 Temp-fil opprydding: legg til periodisk jobb i maskinrommet som sletter gamle temp-filer i CAS tmp-katalog. Bruk /tmp eller sett TTL.
  • 17.7 FFmpeg feilmeldinger til bruker: propager stderr fra FFmpeg-feil til frontend via strukturert feilrespons. Vis i RenderDialog.

Fase 18: AI-verktøy (arbeidsflate)

Ref: docs/features/ai_verktoy.md, docs/retninger/arbeidsflaten.md

  • 18.1 AI-preset node-type: node_kind: 'ai_preset' med metadata (prompt, model_profile, category, icon, color). Maskinrommet validerer ved opprettelse. Seed standardprompter (rens tekst, korrektør, oppsummering, oversett, skriv om, trekk ut fakta, forenkle, endre tone).
  • 18.2 AI-prosessering endepunkt: POST /intentions/ai_process med source_node_id, ai_preset_id, direction (node_to_tool / tool_to_node). Maskinrommet henter kilde-content og preset-prompt, mapper modellprofil → LiteLLM-alias, sender til AI Gateway. Logg forbruk i ai_usage_log.
  • 18.3 Direction-logikk: tool_to_node → lagre original som revisjon, oppdater node content. node_to_tool → opprett ny node med AI-output, opprett derived_from-edge til kilde + processed_by-edge til AI-preset.
  • 18.4 AI-verktøy panel (frontend): Svelte-komponent for arbeidsflaten. Prompt-velger med standardprompter, fritekst-felt for egendefinert prompt, modell-indikator (readonly). Drag-and-drop mottak for tekstnoder.
  • 18.5 Drag-and-drop integrasjon: node → verktøy (ny node), verktøy → node (in-place revisjon). Drop-sone feedback med verktøyets farge. Inkompatibilitet for lyd/bilde-noder med forklaring.
  • 18.6 Egendefinerte presets: brukere kan opprette egne AI-preset-noder med custom prompt. Dele via edges til samling/team. Modellprofil satt av admin.

Fase 19: Arbeidsflaten — Spatial Canvas

Ref: docs/retninger/arbeidsflaten.md, docs/features/canvas_primitiv.md

  • 19.1 Canvas-primitiv Svelte-komponent: pan/zoom kamera med CSS transforms, viewport culling, pointer events (mus + touch), snap-to-grid (valgfritt), fullskjermsmodus. Ref: docs/features/canvas_primitiv.md.
  • 19.2 BlockShell wrapper-komponent: header med tittel + fullskjerm/resize/lukk-knapper, drag-handles for repositionering, resize-handles, drop-sone rendering (highlight ved drag-over). Responsivt (min-size, max-size).
  • 19.3 Arbeidsflaten layout: skriv om /collection/[id] fra vertikal stack til Canvas + BlockShell. Last brukerens lagrede arrangement eller bruk defaults fra samlingens traits. Persist arrangement i bruker-edge metadata. Desktop: spatial canvas, mobil: stacked/tabs. Ref: docs/retninger/arbeidsflaten.md § "Tre lag".
  • 19.4 Kontekst-header: header tilhører flaten, viser gjeldende node som nedtrekksmeny/kontekst-velger. Mest brukte noder øverst (frekvens/recency), søkbart. Verktøymeny for å instansiere nye paneler. Ref: docs/retninger/arbeidsflaten.md § "Kontekst-header".
  • 19.5 Snarveier: paneler kan minimeres til kompakt ikon/fane. Dobbeltklikk → minimer/gjenopprett. Bevarer posisjon og størrelse. Ref: docs/retninger/arbeidsflaten.md § "Snarveier".
  • 19.6 Personlig flate: brukerens standard arbeidsflate (node_kind: 'workspace'). Vises når ikke koblet til en annen node. Persistent layout.

Fase 20: Universell overføring + panelrework

Ref: docs/features/universell_overfoering.md, docs/retninger/arbeidsflaten.md § "Kompatibilitetsmatrise"

  • 20.1 message_placements tabell: PG-migrasjon + SpacetimeDB-modul med place_message, remove_placement, move_on_canvas reducers. Synk STDB→PG. Ref: docs/features/universell_overfoering.md § 2.
  • 20.2 source_material edge-type: legg til i edge-skjema + maskinrommet-validering. Støtt kontekst-metadata (quoted, summarized, referenced) og excerpt-felt. Ref: docs/retninger/arbeidsflaten.md § "source_material-edge".
  • 20.3 BlockReceiver interface: implementer canReceive(), receive(), renderDropZone() i alle trait-komponenter (Chat, Kanban, Kalender, Editor, Studio). Kompatibilitetsmatrise bestemmer godkjente drops. Ref: docs/features/universell_overfoering.md § 45.
  • 20.4 Transfer service: innholdstransfer-modus (ny node + source_material edge) og lettvekts-triage (eksisterende node + ny edge/placement). Bestem modus fra verktøy-par. Shift-modifier for override. Ref: docs/features/universell_overfoering.md § 1, 3.
  • 20.5 Panelrework — Chat: gjør ChatTrait til fullverdig BlockShell-panel med BlockReceiver, fullskjerm-toggle, og responsivt design innenfor begrenset container.
  • 20.6 Panelrework — Kanban: gjør KanbanTrait til BlockShell-panel med drag-and-drop aksept fra andre paneler, fullskjerm, responsivt.
  • 20.7 Panelrework — Kalender: gjør CalendarTrait til BlockShell-panel med drop-aksept for scheduling, fullskjerm, responsivt.
  • 20.8 Panelrework — Editor/Artikkelverktøy: gjør artikkelverktøy til BlockShell-panel med source_material mottak fra andre paneler. Ref: docs/features/artikkelverktoy.md.
  • 20.9 Panelrework — Studio: gjør StudioTrait til BlockShell-panel med drop-aksept for lydfiler, fullskjerm, responsivt.

Fase 21: CLI-verktøy — Unix-filosofi

Ref: docs/retninger/unix_filosofi.md. Bryt ut prosessering fra maskinrommet til standalone CLI-verktøy i tools/. Maskinrommet kaller dem fra jobbkøen, Claude kaller dem direkte. Samme verktøy, to brukere.

Prosessering (erstatter jobbkø-handlere)

  • 21.1 synops-transcribe: Whisper-transkribering. Input: --cas-hash <hash> --model <model> [--initial-prompt <tekst>]. Output: JSON med segmenter. Skriver segmenter til PG, oppdaterer node metadata. Erstatter transcribe.rs.
  • 21.2 synops-audio: FFmpeg-prosessering. Input: --cas-hash <hash> --edl <json>. Output: ny CAS-hash. Erstatter audio.rs. Inkluder parametervalidering (fase 17.217.3).
  • 21.3 synops-render: Tera HTML-rendering. Input: --node-id <uuid> --theme <tema>. Output: CAS-hash for rendret HTML. Erstatter publishing.rs.
  • 21.4 synops-rss: RSS/Atom-generering. Input: --collection-id <uuid>. Output: XML til stdout. Erstatter rss.rs.
  • 21.5 synops-tts: Tekst-til-tale. Input: --text <tekst> --voice <stemme>. Output: CAS-hash for lydfil. Erstatter tts.rs.
  • 21.6 synops-summarize: AI-oppsummering. Input: --communication-id <uuid>. Output: sammendrag som tekst. Erstatter summarize.rs.
  • 21.7 synops-suggest-edges: AI-foreslåtte edges. Input: --node-id <uuid>. Output: JSON med forslag (target, edge_type, confidence). Erstatter ai_edges.rs.
  • 21.8 synops-respond: Claude chat-svar. Input: --communication-id <uuid> --message-id <uuid>. Output: svartekst. Erstatter agent.rs sin prosessering (auth/ratelimit forblir i maskinrommet).
  • 21.9 synops-prune: Opprydding av gamle noder. Input: --dry-run for forhåndsvisning. Erstatter pruning.rs.

Oppslag (Claude-verktøy)

  • 21.10 synops-context: Hent kontekst for en samtale. Input: --communication-id <uuid>. Output: markdown med spec, deltakere, historikk, relaterte noder.
  • 21.11 synops-search: Fulltekstsøk i grafen. Input: <query> [--kind <node_kind>] [--limit N]. Output: matchende noder med utdrag.
  • 21.12 synops-tasks: Parse tasks.md og vis status. Input: [--phase N] [--status todo|done|blocked]. Output: formatert oppgaveliste.
  • 21.13 synops-feature-status: Sjekk feature-status. Input: <feature_key>. Output: spec-sammendrag, oppgavestatus, nylige commits, ubesvart feedback.
  • 21.14 synops-node: Hent/vis en node med edges. Input: <uuid> [--depth N] [--format json|md]. Output: node-data med edges.

Infrastruktur

  • 21.15 Jobbkø-dispatcher: endre maskinrommets jobbkø-handlere til å spawne CLI-verktøy (Command::new("synops-X")) i stedet for inline-kode. Stdout → jobbresultat, stderr → feillogg, exitkode → status.
  • 21.16 Felles lib: synops-common crate med PG-tilkobling, CAS-helpers, og node/edge-typer. Deles mellom alle CLI-verktøy for å unngå duplisering.

Fase 12: Herding

  • 12.1 Observerbarhet: strukturert logging, metrikker (request latency, queue depth, AI cost).
  • 12.2 Backup: PG-dump rutine.
  • 12.3 Feilhåndtering: retry med backoff i skrivestien, dead letter queue for feilede PG-skrivinger.
  • 12.4 Ytelse: profiler PG-spørringer, optimaliser node_access-oppdatering.

Fase 22: SpacetimeDB-migrering — PG LISTEN/NOTIFY

Ref: docs/retninger/datalaget.md (revidert mars 2026). Faser ut SpacetimeDB til fordel for PG LISTEN/NOTIFY + WebSocket i portvokteren. Én datakilde, ingen synk-kompleksitet.

  • 22.1 WebSocket-lag i portvokteren: implementer PG LISTEN/NOTIFY-lytter og WebSocket-endepunkt. Legg til PG-triggers (notify_node_change, notify_edge_change) for nodes og edges. Frontend kobler til begge (STDB + nytt WS) i parallell for verifisering.
  • 22.2 Frontend-migrering: erstatt SpacetimeDB-klient med vanlig WebSocket til portvokteren. Erstatt STDB-stores med reaktive stores som lytter på WebSocket. Verifiser all sanntidsfunksjonalitet (chat, kanban, kalender, mixer, canvas).
  • 22.3 Fjern STDB-skrivestien: portvokteren slutter å skrive til SpacetimeDB. All skriving går kun til PG. NOTIFY-triggere er eneste push-mekanisme. Verifiser at ingenting avhenger av STDB-data.
  • 22.4 Fjern SpacetimeDB: stopp Docker-container, fjern STDB-modul, fjern STDB-klient fra portvokteren og frontend, fjern synkroniseringskode, oppdater docs og CLAUDE.md.
  • 22.5 Opprydding: arkiver STDB-relaterte erfaringsdocs, oppdater alle docs-referanser, fjern Docker-konfig for SpacetimeDB, fjern SpacetimeDB-loven fra feedback-memories.

Fase 23: Validering — test og kvalitetssikring per fase

Hver oppgave spinner opp en ny sesjon med frisk kontekst som gjennomgår implementeringen fra den angitte fasen. Sesjonen tester, leser kode, verifiserer mot spec, og sjekker at ting faktisk fungerer. Ved funn: fiks direkte hvis det er småting, eller opprett nye work_items (tasks) med spesifikasjon for det som trenger en dedikert sesjon.

  • 23.1 Valider fase 12 (infra + maskinrommet): PG-skjema, indekser, auth-middleware, intensjoner, STDB-klient (nå erstattet av WS). Verifiser at skjema matcher docs, at auth fungerer, at skrivestien er konsistent.
  • 23.2 Valider fase 34 (frontend + tilgang): SvelteKit-oppsett, OIDC-flow, sanntid, mottaksflate, TipTap-editor, node_access-matrise, team-transitivitet, visibility-filtrering.
  • 23.3 Valider fase 58 (kommunikasjon + CAS + lyd + aliaser): chat-loop, kontekst-arv, CAS-hashing/deduplisering, Whisper-pipeline, segmenttabell, SRT-eksport, alias-identitet.
  • 23.4 Valider fase 910 (visninger + AI): kanban drag-and-drop, kalender, dagbok, kunnskapsgraf, LiteLLM-ruting, AI-foreslåtte edges, oppsummering, TTS.
  • 23.5 Valider fase 11 (produksjon): LiveKit-oppsett, sanntidslyd, pruning-logikk, podcast-RSS.
  • 23.6 Valider fase 1314 (traits + publisering): trait-validering, pakkevelger, Tera-templates, HTML-rendering, forside, slot-håndtering, redaksjonell flyt, planlagt publisering, A/B-testing.
  • 23.7 Valider fase 1516 (admin + lydmixer): systemvarsler, graceful shutdown, jobbkø-oversikt, ressursstyring, serverhelse, Web Audio mixer, delt kontroll, sound pads, EQ, stemmeeffekter.
  • 23.8 Valider fase 1718 (lydstudio-utbedring + AI-verktøy): responsivt layout, FFmpeg-validering, fade/silence, AI-presets, direction-logikk, drag-and-drop integrasjon.
  • 23.9 Valider fase 1920 (arbeidsflaten + universell overføring): canvas pan/zoom, BlockShell, layout-persistering, snarveier, transfer service, alle panelreworks (chat, kanban, kalender, editor, studio).
  • 23.10 Valider fase 21 (CLI-verktøy): kjør hvert synops-*-verktøy, verifiser --help, --payload-json, output-format, feilhåndtering, synops-common integrasjon.
  • 23.11 Valider fase 22 (STDB-migrering): WebSocket-sanntid fungerer, PG LISTEN/NOTIFY-triggere, ingen STDB-rester i aktiv kode/konfig.

Fase 24: Orkestrering — trigger-drevne automatiseringer

Ref: docs/concepts/orkestrering.md. Orkestreringsnoder (node_kind: 'orchestration') med fritekst-instruksjoner som boten utfører via function calling. Strukturerte triggere, automatisk eskalering av intelligens ved feil, kompilering av velprøvde mønstre.

  • 24.1 Orchestration node-type: legg til orchestration i maskinrommets node-validering. Metadata-skjema: trigger (event + conditions), executor, intelligence, effort, compiled, pipeline. Valider trigger-events mot kjent liste.
  • 24.2 Trigger-evaluering i portvokteren: ved node/edge-events, sjekk om noen orchestration-noder matcher triggeren. Effektiv lookup (indeksert på metadata.trigger.event). Ingen LLM-kall for trigger-matching.
  • 24.3 Script-kompilator: parser menneskelig scriptspråk ("transkriber lydfilen (stor modell)") og kompilerer til tekniske CLI-kall. Matcher verb mot cli_tool-noders aliases, argumenter mot args_hints, variabler fra trigger-kontekst. Rust-stil kompileringsfeil med forslag.
  • 24.4 cli_tool alias-metadata: utvid alle cli_tool-noder med aliases (norske verb) og args_hints (menneskelige argumenter → CLI-flagg). Seed for alle eksisterende verktøy.
  • 24.5 Script-executor: vaktmesteren parser kompilert script og eksekverer steg sekvensielt via generisk dispatch. VED_FEIL-håndtering. Logger i orchestration_log.
  • 24.6 Orchestration UI: editor med tre visninger (Enkel/Teknisk/Kompilert) som tabber. Sanntids kompileringsfeil. Trigger-velger, "Test kjøring"-knapp, kjørehistorikk. Ref: docs/concepts/orkestrering.md.
  • 24.7 AI-assistert oppretting: synops-ai med auto-generert systemprompt (fra cli_tool-noder) foreslår script fra fritekst-beskrivelse. Vaktmesteren validerer. Eventually-modus: lagre som work_item for Claude Code.
  • 24.8 Kaskade: triggers-edge mellom orkestreringer. Output fra én trigger neste. Syklusdeteksjon for å unngå uendelige loops.
  • 24.9 Seed-orkestreringer: opprett standard-orkestreringer for podcast-pipeline, publiseringsflyt, og AI-beriking basert på eksisterende hardkodet logikk i vaktmesteren. Skrives i menneskelig scriptspråk.

Fase 25: Web Clipper — synops-clip

Ref: docs/proposals/web_clipper.md. CLI-verktøy som henter URL, parser med Readability, og oppretter innholdsnode med AI-beriking. Brukes av @bot i chat ("les denne artikkelen"), orkestreringer, og fremtidig browser-extension.

  • 25.1 synops-clip CLI: hent URL, parse med Readability (mozilla/readability via JS eller Rust-port), returner ren tekst + metadata (tittel, forfatter, dato, ingress). Fallback til headless browser (Playwright) for JS-rendrede sider. Detekter betalingsmur (kort/avkuttet innhold, "logg inn for å lese", kjente paywall-mønstre) — returner "paywall": true og tilgjengelig innhold (ingress/utdrag). Output: JSON med title, author, date, content, url, paywall.
  • 25.2 Node-opprettelse: synops-clip --write oppretter content-node med artikkelinnhold, metadata.source_url, og tagged-edge "clipped". AI-oppsummering via LiteLLM. mentions-edges til gjenkjente entiteter i kunnskapsgrafen.
  • 25.3 @bot-integrasjon: bruker limer inn URL i chat → boten gjenkjenner URL, kaller synops-clip, presenterer oppsummering i chatten, oppretter node i bakgrunnen. Ved paywall: "Denne artikkelen er bak betalingsmur. Jeg fikk med tittel og ingress — lim inn innholdet om du vil dele resten."
  • 25.4 Orkestrering-støtte: synops-clip tilgjengelig som verktøy i orkestreringer. F.eks. "Clip alle URL-er som deles i #Redaksjonen og oppsummer dem".

Fase 26: Epost — send og motta via synops.no

Vaktmesteren kan sende epost (msmtp) og motta epost (Postfix → synops-mail). Brukernavn@domene ruter til brukerens innboks. Alle domener (synops.no, sidelinja.org, vegard.info) ruter til samme bruker basert på username.

  • 26.1 Username i auth_identities: legg til username-kolonne, populer fra Authentik preferred_username ved login. Unik constraint. Oppdater auth-callback i SvelteKit til å lagre username.
  • [?] 26.2 msmtp oppsett: konfigurer utgående epost via SMTP-relay. Avsender: vaktmester@synops.no. Tilgjengelig som synops-mail --send --to <epost> --subject <emne> CLI-verktøy.

    Spørsmål: Trenger SMTP-relay credentials. Hetzner-relay (mail.your-server.de:587) krever autentisering, og port 25 er blokkert utgående. Verktøyet (synops-mail) og msmtp-config er ferdig — mangler kun brukernavn/passord i /srv/synops/config/msmtp/msmtprc. Alternativer: (1) Hetzner Robot-konto credentials, (2) ekstern SMTP-relay (Brevo, Mailgun, etc.), (3) annen tilnærming? Kontekst: Alt er implementert og testet (CLI kompilerer, msmtp kobler til relay, auth feiler pga placeholder-credentials). Trenger bare ekte SMTP-bruker/passord.

  • 26.3 MX-records: sett opp MX for synops.no, sidelinja.org, vegard.info som peker til serveren.
  • 26.4 Postfix minimal: installer Postfix som lokal MTA kun for mottak. Ingen relay, ingen kø for utgående. Pipe innkommende epost til synops-mail --receive.
  • 26.5 synops-mail --receive: Rust CLI som leser raw epost fra stdin. Sjekk 1: avsender-epost matcher auth_identities.email? Sjekk 2: innhold starter med "Kjære vaktmester" (eller konfigurerbar frase)? Begge må matche. Opprett content-node i brukerens innboks med epostinnholdet. Alt annet → /dev/null, ingen bounce.
  • 26.6 Domene-alias: vegard@synops.no, vegard@sidelinja.org, vegard@vegard.info ruter alle til samme bruker via username-oppslag i PG. Domenet er irrelevant.
  • 26.7 Utgående varsler: vaktmesteren kan sende epost-varsler til brukere (ny oppgave tildelt, innsendt artikkel godkjent, etc.) via synops-mail --send. Konfigurerbart per bruker i metadata.preferences.

Fase 27: Tankekart — radial grafvisning

Ref: docs/features/tankekart.md. Tankekart-panel som viser noder og edges i radial layout med en rotnode i sentrum. Ingen ny backend — ren frontend- visning av eksisterende grafdata.

  • 27.1 MindMap Svelte-komponent: radial/tree-layout av noder rundt en rotnode. Hent relaterte noder (1-2 hopp) via WebSocket. d3-hierarchy eller trigonometri for layout. Pan/zoom via canvas-primitiv. Klikk node = ny rot, dobbeltklikk = åpne i editor.
  • 27.2 BlockShell-panel: MindMap som BlockShell-panel i arbeidsflaten med fullskjerm, resize, drag-handle. Rotnode fra kontekst-header. Responsivt.
  • 27.3 MindMap-trait: mindmap-trait for samlingsnoder. Vises i trait-velger ved opprettelse. Konfigurasjon: default dybde (1-3 hopp), layout-stil (radial/tree).

Fase 28: Manglende CLI-verktøy + AI-rutingskontroll

Verktøy som mangler i verktøykassen, pluss admin-styring av hvilken modell som brukes til hva.

synops-ai: lettvekts LLM-kall

  • [~] 28.1 synops-ai CLI: direkte LLM-kall via LiteLLM. Input: --prompt <tekst> [--model <alias>] [--system <systemprompt>]. Output: tekst til stdout. Ingen fillesing, ingen verktøy, bare prompt inn/ut. Bruker ai_job_routing-tabellen for å bestemme modell hvis --model ikke er satt. Logger i ai_usage_log.

    Påbegynt: 2026-03-18T19:45

  • 28.2 AI-rutingskontroll i admin: utvid admin-UI (fase 15.4) med konfigurasjon av hvilken modell som brukes per kontekst. Tabellen ai_job_routing mapper (job_type, context)model_alias. Kontekster: orchestration_script, orchestration_dream, bot_chat, bot_triage, summarize, suggest_edges, classify. Admin kan endre uten redeploy.
  • 28.3 Kostnadstak per bruker/samling: ai_budget-felt i metadata for brukere og samlinger. synops-ai sjekker budsjett mot ai_usage_log aggregat før kall. Ved overskridelse: returner feilmelding, opprett work_item.

Øvrige manglende verktøy

  • 28.4 synops-notify: send varsel via epost (synops-mail), WebSocket-push, eller begge. Input: --to <node_id> --message <tekst> [--channel email|ws|both]. Brukes av orkestreringer og vaktmesteren.
  • 28.5 synops-validate: sjekk at en node matcher forventet skjema for sin node_kind. Input: --node-id <uuid>. Output: liste av avvik. Brukes av valideringsfasen og som pre-commit sjekk.
  • 28.6 synops-backup: PG-dump + CAS-filiste + metadata-snapshot. Input: [--full | --incremental]. Output: backup-sti. Erstatter cron-scriptet fra 12.2.
  • 28.7 synops-health: sjekk status for alle tjenester (PG, Caddy, vaktmesteren, LiteLLM, Whisper, LiveKit). Output: JSON med status per tjeneste. Brukes av admin-dashboard og overvåking.

Fase 29: Universell input — alle modaliteter blir noder

Ref: docs/features/universell_input.md. Utvid input-primitiven til å dekke alle relevante modaliteter. Alt ender som noder. Modaliteten er transport, noden er det som lever videre.

Skjermklipp

  • 29.1 Skjermklipp-input: paste screenshot fra clipboard i chat/editor → upload til CAS → media-node. Frontend detekterer bilde-paste (ClipboardEvent). Valgfri AI-beskrivelse via synops-ai ("beskriv dette bildet"). Metadata: { "source": "screenshot", "description": "..." }.

RSS/Feed-abonnement

  • 29.2 synops-feed CLI: abonner på RSS/Atom-feed. Input: --url <feed-url> --collection-id <uuid> [--interval 30m]. Poller feed, oppretter content-node for nye entries med metadata.source_url og tagged-edge "feed". AI-oppsummering valgfritt. Paywall-deteksjon gjenbrukt fra synops-clip.
  • 29.3 Feed-orkestrering: standard-orkestrering "Overvåk RSS-feed" som bruker synops-feed. Konfigurerbar per samling. Nye artikler havner i innboks eller direkte i en kanal.

Webhook (universell ekstern input)

  • 29.4 Webhook-endepunkt i vaktmesteren: POST /api/webhook/<token> → opprett node fra JSON-body. Hvert webhook har et unikt token (UUID) knyttet til en webhook-node med belongs_to-edge til målsamling. Validerer token, oppretter content-node med payload i metadata.
  • 29.5 Webhook-admin: UI for å opprette/administrere webhooks. Vis token, mål-samling, siste hendelser, aktivitet-logg. Regenerer token. Deaktiver/slett.
  • 29.6 Webhook-templates: forhåndsdefinerte mappinger for kjente tjenester (GitHub → commits/issues, Slack → meldinger, CI/CD → build-status). Template mapper JSON-felt til node title/content/metadata.

Video

  • 29.7 Video-opptak i frontend: webcam/skjermopptak via MediaRecorder API → upload til CAS → media-node. Start/stopp-knapp i input-komponenten. Maks varighet konfigurerbar.
  • 29.8 Video-prosessering: synops-video CLI for transcode (H.264), thumbnail-generering, og varighet-uttrekk. Input: --cas-hash <hash>. Output: ny CAS-hash (trancodet) + thumbnail CAS-hash.

Geolokasjon

  • 29.9 Lokasjon-input: "Del posisjon"-knapp i input-komponenten → Geolocation API → node med metadata.location: { "lat": 59.91, "lon": 10.75 }. Kart-visning i node-detaljer (Leaflet/OpenStreetMap). Valgfritt: reverse geocoding via Nominatim for adresse.

Håndskrift/tegning

  • 29.10 Tegne-input: enkel canvas-basert tegneflate i input-komponenten. Eksporter som PNG → CAS → media-node. Ikke whiteboard (det er et eget verktøy) — dette er "rask skisse som input", som en post-it.

Kalender-import

  • 29.11 ICS-import: synops-calendar CLI som parser ICS-fil og oppretter noder med scheduled-edges. Input: --file <ics> --collection-id <uuid>. Duplikatdeteksjon via UID. Oppdatering ved re-import.
  • 29.12 CalDAV-abonnement: abonner på ekstern CalDAV-kalender (Google, Outlook). Poller periodisk, synkroniserer endringer. Som RSS-feed men for kalenderhendelser.

Fase 30: Podcast-hosting — komplett, uten ekstern avhengighet

Ref: docs/features/podcast_hosting.md. Bygg komplett podcast-hosting i Synops. Ingen castopod, ingen ekstern tjeneste. Import fra eksisterende podcast med prøveimport-flyt.

RSS og metadata

  • 30.1 iTunes/Podcasting 2.0 RSS-tags: utvid synops-rss med <itunes:*> og <podcast:*> namespace. Tags fra samlingens podcast-trait metadata (author, category, explicit, language). Podcast:transcript og podcast:chapters fra eksisterende edges.
  • 30.2 Podcast-trait metadata: utvid podcast-trait med iTunes-felt (itunes_category, itunes_author, explicit, language, redirect_feed). Admin-UI for å redigere.

Statistikk

  • 30.3 synops-stats CLI: parse Caddy access-logger for /media/*-requests. Aggreger nedlastinger per episode per dag. IAB-regler: filtrer bots (user-agent), unik IP per 24t. Output: JSON med episode_id, date, downloads, unique_listeners. --write lagrer i PG.
  • 30.4 Statistikk-dashboard: vis nedlastinger per episode, trend over tid, topp-episoder, klienter (Apple/Spotify/andre), geografi. Integrert i admin-panelet.

Embed-spiller

  • 30.5 Podcast-spiller komponent: Svelte-komponent med artwork, tittel, play/pause, progress, waveform, kapittelmerkering. Responsiv. Serveres som iframe-embed: synops.no/pub/<slug>/<episode>/player.

Import

  • 30.6 synops-import-podcast CLI: importer eksisterende podcast fra RSS-feed. Parse metadata, last ned lydfiler/artwork/transkripsjoner til CAS, opprett noder med edges. Duplikatdeteksjon via <guid>. --dry-run for forhåndsvisning. Idempotent: kjør flere ganger, bare nye episoder importeres.
  • 30.7 Prøveimport-flyt i frontend: "Importer podcast"-wizard i admin. Steg 1: lim inn RSS-URL, vis forhåndsvisning av episoder. Steg 2: importer (kan ta tid for mange episoder). Steg 3: sjekk resultat, sammenlign feeds. Steg 4: re-importer nye episoder når klar. Steg 5: aktiver 301-redirect på gammel host.

Eksport og redirect

  • 30.8 Feed-redirect: redirect_feed-felt i podcast-trait. Når satt: Caddy returnerer 301 for feed-URL. Brukeren kan alltid flytte bort. Admin-UI med én-klikks aktivering og advarsel.