- Omorganiser docs/: konsepter, features, infra og proposals i egne mapper - Ny docs/erfaringer/ med lærdommer fra chat-implementering (Svelte 5, SpacetimeDB, adapter-mønster) - Oppdater ARCHITECTURE.md: Lag 1 status, ny §10 Erfaringslogg, SpacetimeDB i lokal dev - Oppdater synkronisering.md med implementeringsstatus og designvalg - Oppdater lokal.md med SpacetimeDB og AI Gateway - Utvid PG-skjema med channels, messages, media_files, message_revisions - Legg til seed_dev.sql, migration_safety.md, .env.example - Nye feature-specs: chat, kanban, whiteboard, live_ai, lydmeldinger m.fl. - Nye konsept-specs: studioet, møterommet, redaksjonen, den asynkrone gjesten m.fl. - SpacetimeDB og AI Gateway i docker-compose.dev.yml - collect-docs.sh inkluderer erfaringer/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.9 KiB
2.9 KiB
Feature Spec: Podcast-Statistikk
Filsti: docs/features/podcast_statistikk.md
1. Konsept
IAB-kompatibel lytterstatistikk bygget fra bunnen av. Vi fanger all rådata via Caddy, og bruker asynkron batch-prosessering for å bygge grafer og tall uten å belaste webserveren eller databasen med sanntids-skriving.
2. Arkitektur & Dataflyt
- Rådata (Caddy): Caddy konfigureres til å skrive access-logs for stien
/media/podcast/*.mp3til en formatert JSON-fil (f.eks./srv/sidelinja/logs/caddy/podcast_access.log). - Logrotate: Standard Linux logrotate arkiverer loggene nattlig.
- Rust Batch Processor (Jobbkø): Statistikkparseren kjøres som en
stats_parse-jobb i den felles jobbkøen (sedocs/infra/jobbkø.md), medscheduled_forsatt 1 time frem for periodisk kjøring. Workeren re-enqueuer seg selv ved fullføring.- Steg A (Filtrering): Leser JSON-loggen. Fjerner treff fra kjente bots ved å krysjekke
User-Agentmot OPAWG (Open Podcast Analytics Working Group) sine åpne bot-lister. - Steg B (Deduplisering): Slår sammen byte-range forespørsler. Hvis samme IP og User-Agent har lastet ned deler av samme fil innenfor et 24-timers vindu, telles det som KUN én (1) nedlasting.
- Steg C (Geografi/Klient): Mapper User-Agent til Podcast-klient (Spotify, Apple) basert på OPAWG-regler.
- Steg A (Filtrering): Leser JSON-loggen. Fjerner treff fra kjente bots ved å krysjekke
- Lagring (PostgreSQL): Rust-programmet skriver det aggregerte resultatet inn i PostgreSQL (
episode_statstabell med felter forworkspace_id,date,episode_id,client_name,unique_downloads). Workspace-tilhørighet utledes fra filstien i loggen (/media/{workspace_slug}/...).
3. Personvern og GDPR
Caddy access-logger inneholder IP-adresser og User-Agent — dette er personopplysninger under GDPR.
Tiltak:
- IP-anonymisering: Rust-workeren hasher IP-adresser (SHA-256 med daglig roterende salt) før de lagres i
episode_stats. Rå IP-er lagres aldri i PostgreSQL. - Loggretensjon: Caddy-logger roteres og slettes etter 90 dager (kategori 4, flyktig). Etter at statistikk-workeren har prosessert en loggfil, inneholder PG kun aggregerte tall — ingen identifiserbar data.
- Ingen sporing på tvers: Vi bruker ikke cookies, fingerprinting eller tredjepartstracking. Deduplisering basert på IP + User-Agent i 24-timers vindu er IAB-standard og minimumsdata.
- Dokumentasjon: Podcastens RSS-feed bør lenke til en personvernerklæring som forklarer at anonymisert nedlastingsstatistikk samles inn.
4. Instruks for Claude Code
- Bruk Rust-biblioteket
serde_jsonfor rask parsing av Caddy-loggene. - Dette programmet må skrives robust med tanke på at filer kan være låst av Caddy. Det bør tåle å avbrytes, og må holde styr på hvilken linje i loggfilen det prosesserte sist (f.eks. via en liten cursor-fil).
- Rålogger skal ALDRI lagres i PostgreSQL.
- Statistikk er workspace-scopet.
episode_statsmerkes medworkspace_id. Admin-visningen filtrerer per workspace.