# Forslag: Sosial publisering fra chat ## Idé Post til X (og senere Bluesky/Mastodon) direkte fra Redaksjonens chat. Noen sier noe morsomt eller skarpt — én kommando, og det er ute i verden. Flere teammedlemmer deler én konto uten å dele passord. ## Hvorfor er det interessant? - **Senker terskelen.** En podcast-konto på X dør ofte fordi kun én person har tilgang og gidder. Med chat-integrasjon kan hvem som helst foreslå en post, og flyten er én handling — ikke "åpne X, logg inn på riktig konto, skriv, post". - **Spontanitet.** De beste sosiale medie-postene er de som kommer i øyeblikket. Å fange dem rett fra chatten der samtalen skjer bevarer energien. - **Kontroll uten friksjon.** Konfigurerbar godkjenningsflyt per workspace — fra "alle poster fritt" til "admin godkjenner alt". - **Bygger på det som finnes.** Chat, jobbkø, workspace-settings — ingen ny infrastruktur. ## Hva bygger den på? - **Chat** — `/x`-kommando som trigger publisering - **Jobbkø** — `social_post`-jobbtype med retry ved rate limit - **Workspace settings** — API-nøkler og godkjenningsflyt per workspace - **Admin-panel** — Workspace-innstillinger for plattformer og tilgangsstyring ## Flyt ### Uten godkjenning (workspace-innstilling: `approval: none`) ``` Vegard i chat: "Fantastisk intervju med @støre i dag, han innrømmet at han liker brunost på vaffel" Marte svarer: /x ┌──────────────────────────────────────┐ │ Post til X: │ │ │ │ Fantastisk intervju med @støre i │ │ dag, han innrømmet at han liker │ │ brunost på vaffel 🧇 │ │ │ │ 156/280 tegn │ │ │ │ [Rediger] [Avbryt] [Post nå] │ └──────────────────────────────────────┘ → Jobb opprettes → Rust-worker poster til X → Systemmelding i chat: "Marte postet til X: https://x.com/sidelinja/status/..." ``` ### Med godkjenning (workspace-innstilling: `approval: required`) ``` Marte: /x → Jobb opprettes med status 'pending_approval' → Systemmelding: "Marte foreslår X-post: «...» — reager med ✅ for å godkjenne" → Admin reagerer med ✅ → Jobb endres til 'pending', worker poster → Systemmelding oppdateres: "Postet av Marte, godkjent av Lars: https://x.com/..." ``` ### Med godkjenning fra hvem som helst med riktig rolle (workspace-innstilling: `approval: role`) Samme flyt, men `approval_role` i settings styrer hvem som kan godkjenne (default: `admin`+`owner`). ## Workspace-innstillinger Lagres i `workspaces.settings` under nøkkelen `social`: ```json { "social": { "platforms": { "x": { "enabled": true, "api_key": "...", "api_secret": "...", "access_token": "...", "access_token_secret": "..." } }, "approval": "none", "approval_role": "admin", "default_hashtags": ["#sidelinja"], "max_daily_posts": 20 } } ``` **`approval`-verdier:** | Verdi | Oppførsel | |---|---| | `none` | Alle workspace-medlemmer kan poste direkte | | `required` | Alle poster krever godkjenning | | `role` | Poster fra brukere med lavere rolle enn `approval_role` krever godkjenning | ## Datamodell Ingen ny tabell — bruker jobbkøen med `job_type = 'social_post'`: ```json { "job_type": "social_post", "payload": { "platform": "x", "text": "Fantastisk intervju med @støre...", "source_message_id": "uuid", "suggested_by": "authentik_id", "approved_by": null, "thread_ids": [] } } ``` For godkjenningsflyt brukes en ekstra jobbstatus. Jobber med `approval: required` opprettes med `status = 'pending_approval'` (ny enum-verdi) og endres til `pending` ved godkjenning. ## Admin-panel (workspace-innstillinger) Denne featuren forutsetter et minimalt admin-panel i SvelteKit (`/workspace/settings`). Første iterasjon trenger kun: - **Sosiale kontoer:** Koble til X (OAuth-flyt), se tilkoblet konto, fjern - **Godkjenningsflyt:** Velg mellom `none` / `required` / `role` - **Historikk:** Liste over poster sendt fra dette workspacet (fra jobbkø-data) Admin-panelet vil vokse med andre workspace-innstillinger over tid (Whisper-config, AI-prompts, channel-defaults, etc.), men sosial publisering er et godt første bruksområde. ## Plattform-abstraksjon Chat-kommandoen og jobbkøen vet ikke om X spesifikt. Arkitekturen er: ``` Chat (/x, /bsky, /social) │ ▼ Jobbkø: social_post { platform: "x", text: "..." } │ ▼ Rust worker: matcher platform → riktig API-klient ├── X (OAuth 1.0a, v2 API) ├── Bluesky (AT Protocol) [fremtidig] └── Mastodon (OAuth 2.0, REST) [fremtidig] ``` Å legge til en ny plattform er å implementere én ny handler i Rust-workeren + legge til credentials i workspace-settings. Ingen endring i chat-koden. ## X API: Tekniske detaljer - **API:** X API v2, `POST /2/tweets` - **Auth:** OAuth 1.0a (User Context) — krever app + bruker-tokens - **Rate limit:** 200 poster/15 min per bruker (mer enn nok) - **Tråd-støtte:** `reply.in_reply_to_tweet_id` for tråder - **Pris:** Free tier tillater 1500 poster/mnd. Basic ($100/mnd) gir 3000 poster + lesing. Free er nok for start. ## Innsats **Lav–Middels** — X API-integrasjonen er enkel. Chat-kommandoen er en ny handler. Det meste av arbeidet er UI for preview/redigering-popupen og admin-panelet for innstillinger. ## Wow-faktor **Høy** — Gjør podcast-kontoen levende uten at noen må "huske å poste". Demokratiserer kontoen uten å dele passord. ## Åpne spørsmål - Skal `/x` kunne brukes på en hel tråd (flere meldinger → X-tråd)? - Bilder/media i poster — fra chat-vedlegg eller kun tekst i v1? - Skal poster inkludere en automatisk lenke tilbake til episoden/temaet fra grafen? - Bør det finnes en `/draft`-kommando som legger posten i en kø uten å sende (planlagt posting)? - Varsling i chat når en foreslått post venter på godkjenning for lenge?