server/docs/proposals/social_posting.md
vegard a5985ef3f8 Dokumentasjon, erfaringslogg, migrasjoner og infra-oppdateringer
- 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>
2026-03-15 01:40:14 +01:00

150 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
**LavMiddels** — 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?