TASKS.md is now the index (status table, open items, research pointer). 33 files: 32 task files + 1 research facts file. The full take-saga narrative and all design decisions are preserved verbatim; the catalog makes the queue readable without opening every task body. Schema and AGENTS.md updated to reflect the new layout.
4.1 KiB
TASK 2 — YouTube OAuth2 Authentication
Catalog:
TASKS.md— status and requirements live here.
Goal: Fully working Google OAuth2 flow — user clicks "YouTube", browser opens, authorization callback lands, channel info is stored.
Status: ✅ Done
- ✅ Two-state Start/End Stream button, go-live dialog (account + title/description/visibility), red top bar, pulsing LIVE badge + elapsed timer, preview glow, taskbar red dot
- ✅ Real OAuth2 wiring — baked-in Google credentials (desktop client; loopback callback) +
YouTubeAuthServicecomplete: browser launch,HttpListenercallback, token exchange, refresh, channel fetch - ✅ Token persistence via Windows DPAPI (
Helpers/TokenStore.cs→%APPDATA%\ytLlive\ytLlive.auth), best-effort reload + proactive refresh at startup, saved after every exchange/refresh - ✅ Account sign-in/change surfaced in the GoLive dialog (saved account shown with "Change Account"; "Sign in to YouTube" when none; Start disabled until signed in)
- ✅
End Livestream signs outSUPERSEDED by TASK 18 (2026-08-29): explicit sign-out only —StopStream()no longer clears the session (sign out via Logout / Change Account,SignOutYouTubeAsync); stopping a stream or recording leaves the creator signed in. Originally shipped as: a graceful end completes the session:StopStream()callsYouTubeAuthService.ClearSession()+TokenStore.Clear()+IsConnected = false, so the next Start Stream dialog requires a fresh sign-in. A crash never runs End, so the DPAPI token survives and the creator stays signed in. Resume/reconnect after a midstream crash is deliberately deferred to TASK 3: the socket can't be resumed (it dies with the process), so "resume" = fast reconnect with a saved broadcast ID/stream key within YouTube's disconnect-grace window; too slow andenableAutoStopends the broadcast. Orphan closed 2026-09-01: this mechanism is owned by TASK 32 (Stream resilience) — in-session blip retry inside the grace window; cross-process "resume" of a dead broadcast is officially out-of-product (the API makes it impossible — creator ruling). - ✅ Tests in
ytLive.Tests(xUnit, net8.0-windows): TokenStore DPAPI roundtrip/corrupt/missing/clear + mocked exchange channel-parse + refresh expiry bump +ClearSession— 7 passing
Design constraint: Sign-in must NEVER block core exploration. Users can build scenes, add sources, and audition the software without authenticating. But going live requires authentication — the "Start Stream" dialog is where the account sign-in lives, alongside all stream metadata.
Two-state flow: There is no separate "Connect" button. The top bar shows a single button — Start Stream when idle, End Stream when live. Clicking Start Stream opens one dialog that supplies everything: account (previously-saved account shown as default, with a Change Account action) + title/description/visibility.
Live indicators (unmissable): Top bar + window title bar flip red, a pulsing ● LIVE badge with elapsed timer appears in the top bar, the preview area gets a red glow, and the taskbar icon shows a red overlay dot. Window title bar shows the stream title once validated.
Requirements:
- Google Cloud OAuth credentials — client ID + secret, baked into
Helpers/OAuthCredentials.cs(desktop "Desktop app" OAuth client; loopback callback — no console redirect URI registration needed; creators never configure) - Local HTTP listener —
HttpListeneronhttp://localhost:PORT/oauth2/callbackto catch the redirect - Browser launch — open the authorization URL in the default browser
- Token persistence — store access/refresh tokens securely (Windows DPAPI), reload on startup
- UI state — account shown in the Start Stream dialog; "Change Account" action triggers re-auth
- Go Live gated on auth — Start Stream dialog requires sign-in to enable the Start button; scene building works without it
Tests:
- Mock token exchange response, verify channel info parsed
- Verify token refresh triggers when near expiry
- Verify credential load/save roundtrip