8 Commits
Author SHA1 Message Date
agw 6f21c07d91 feat(admin): log Claude ind igen fra telefonen
Claude Codes login på værten holder 28 dage, og et langtidstoken kan ikke
bruges til Remote Control, så der skal logges ind igen hver 4. uge. Hidtil
krævede det en terminal for at kopiere en adresse ud og en kode ind igen.

/admin/claude-login viser hvornår login udløber og har en "Start login"-knap.
Værten (claude-login-agent, som spørger portalen, ikke omvendt) starter
`claude auth login`, og siden viser login-adressen; koden fra Claudes side
indsættes på samme side og hentes af værten et par sekunder senere. Portalen
gemmer kun den korte kode, indtil den er hentet; den virker kun sammen med
login-processen på værten (PKCE).

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
2026-10-03 08:32:29 +02:00
agw 50612a643a Fjern interne referencer fra kildekoden
Kommentarer og docstrings nævnte containernumre, værtsplatformen og
edge-hostens adresse og sti. Eksempel-env'en bruger nu en pladsholder.
Ingen adfærd er ændret.

Claude-Session: https://claude.ai/code/session_01GGe7kUhooMFuzY6GaDb2w9
2026-10-01 17:30:00 +02:00
agw fd50bed5fd feat(admin): hemmeligheds-drop til Claude
/admin/secrets tager imod et token eller kodeord og krypterer det med det
samme med PVE-værtens offentlige X25519-nøgle (sealed box: HKDF-SHA256 +
ChaCha20-Poly1305, navnet som associated data). Kun ciphertext gemmes;
portalen kan ikke læse det igen. På værten henter secret-drop get <navn>
det én gang og sletter kopien her.

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
2026-09-30 21:59:59 +02:00
agw 52b1a2bb6c feat(admin): invitationslinks med gruppe og udløbstid
Udrullet direkte til prod 2026-09-29; importeret her så repo == prod.
Bruger Authentik-flowet weircon-invitation (grupper og engangs via
fixed_data og politikker i flowet).

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
2026-09-29 17:13:43 +02:00
agw 9675a5b76b feat(mcp): eksponér YouTube-offline i portalens MCP + importér MCP-laget i repoet
Fem nye værktøjer i portal-navnerummet: yt_status, yt_download, yt_watch,
yt_unwatch, yt_check_subs. Gatewayen monterer mcp_server under namespace
"portal", så de arver portal_-præfikset og de scopes nøglerne allerede har —
ingen ekstra registrering.

Download og abonnement-tjek returnerer med det samme og arbejder videre i
baggrunden, så et MCP-kald ikke blokerer i minutter på en lang video.

Importerer samtidig mcp_server.py, mcp_gateway.py, mcpkeys.py og
templates/admin_mcp_keys.html, som kun har eksisteret i prod (CT151) og aldrig
i repoet.

ÅRSAG TIL IMPORTEN: den manglende viden i repoet kostede nedetid. Da jeg
udrullede repoets main.py og config.py til prod i går, overskrev jeg
MCP-monteringen (mcp_app.lifespan + route/middleware-overførsel), hele
/admin/mcp-keys-modulet og konstanterne MCP_REGISTRY/MCP_SELF_URL.
weircon.dk/mcp svarede 404 i ~13 timer. Rettet ved at genopbygge begge filer
fra prod-backuppen plus YouTube-ændringerne, ikke omvendt.

Repo og prod er nu identiske bortset fra static/portal.css og
templates/admin.html, hvor repoet er FORAN (wt-*-temaklasser, aldrig udrullet).

Claude-Session: https://claude.ai/code/session_011WxG8pbLj61jYU1MMaD7VC
2026-09-20 09:20:35 +02:00
agw fdf015946e feat(yt): YouTube offline — hent til Emby, slet igen når videoen er set
Nyt admin-modul /admin/yt: indsæt en YouTube-URL, og videoen hentes med yt-dlp
til Emby-biblioteket "YouTube" (/media/yt-offline) — klar til offline-brug.

Oprydningen er bevidst modsat mediaclean.py: dér tæller selv delvis afspilning
som "set" for at frede alt der er rørt, her slettes kun videoer der er eksplicit
markeret som set (Emby UserData.Played). Halvt sete videoer bliver liggende.
Favoritter slettes aldrig, og en favoritering i karensperioden freder igen.

Sikkerhedsnet: oprydningen rører kun filer portalen selv har hentet (registreret
med fuld sti i yt_state.json). Det eksisterende YT-bibliotek er urørligt, og
download-træet er lagt uden for det, så Emby ikke indekserer dobbelt.

Standardvalg:
- H.264/AAC foretrækkes frem for AV1. Pascal-GPU'en i CT100 kan ikke afkode AV1,
  og mange afspillere kan det slet ikke offline. Koster ~1,8x diskplads.
- SponsorBlock klipper sponsorater ud og beholder resten som kapitler.
- Undertekster hentes hvis de findes, men er aldrig et krav: YouTube rate-limiter
  undertekst-endpointet uafhængigt af videoen, så en 429 dér ville ellers vælte
  hele hentningen. Fald-tilbage henter videoen uden undertekster.
- Metadata, miniature og kapitler indlejres, så Emby har noget at vise.

Alt kan redigeres i UI'et. Natlig timer (yt-offline.timer) tømmer køen og rydder op.

Claude-Session: https://claude.ai/code/session_011WxG8pbLj61jYU1MMaD7VC
2026-09-19 19:47:48 +02:00
agw d9d5a12df1 reconcile: import current prod state from CT151 (media-cleanup, access admin, ops versioning, newer dashboard) 2026-06-15 12:27:24 +02:00
agwandClaude Opus 4.8 742d08c9fb refactor: split main.py i moduler (config/cache/store/services/authentik) + async dashboard (TTFB ~6ms, indhold via /dashboard-content) + TTL-cache på Authentik-læsninger
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 21:50:00 +02:00