Take the console online: OIDC sign-in, outbox, play reporting #41

Merged
forgejo-admin merged 1 commit from feature/console-go-online into main 2026-09-28 06:39:33 +00:00

Problem

The app server and guest site exist, but the console can't open a session or report what it plays.

Solution

Engine

  • createEngine takes an optional hooks argument with onPlay and onSetEnd.
  • onPlay fires after each play is recorded. onSetEnd fires when the last song ends, and on newSet with the old set's id.
  • Hooks run synchronously; anything they throw is logged and swallowed, so they can never delay or break playback.

Link (src/live/link.ts)

  • The console only calls out to the app server; nothing calls in.
  • Sign-in: a browser PKCE login, using the issuer and client id from the app server's config. The redirect goes to the console's /auth/callback, and the token is stored in settings.
  • Going online: goOnline(passcode) calls openSession directly, so a reused passcode shows its message inline. It then sends the set's plays so far through the outbox.
  • Outbox: plays and session closes are stored locally first and sent oldest first.
    • Each play's id is setId:playId, so a resend never duplicates it.
    • A network failure waits and retries (1s, doubling to a 30s cap).
    • An auth rejection (401 or 403) signs the console out.
    • Any other rejection is logged and dropped, so one bad message can't wedge the queue.
  • Closing: the session closes when the set ends, when a new set starts, or on "Go offline".
  • App server URL: LIVE_URL, else the stored live.url setting, else https://dj.incarnadine.org/live.

Console UI

  • A Go online control in the live set panel. It renders nothing without a link, so the offline layout is unchanged.
  • Online, it shows "Online · guests follow at dj.incarnadine.org/live · N waiting to send", plus Go offline and Sign in again when needed.

This is Slice 5 of projects/2026-09-27-dj-online-companion/plan.md.

Testing

  • bun run test: 193 pass. The link tests run against a real in-process app server:
    • going online delivers each play exactly once
    • with the server stopped, the next track still fires on schedule, and its play arrives once the server is back
    • the set ending closes the session
    • a reused passcode shows its message
  • PKCE is tested with a fake discovery document and token endpoint.
  • bun run check: clean.
  • Not tried: a real Authentik login and the real console, which drives Spotify through AppleScript. The redirect URIs are http://localhost:3000 and http://127.0.0.1:3579, so open the console on one of those.

🤖 Generated with Claude Code

## Problem The app server and guest site exist, but the console can't open a session or report what it plays. ## Solution **Engine** - `createEngine` takes an optional hooks argument with `onPlay` and `onSetEnd`. - `onPlay` fires after each play is recorded. `onSetEnd` fires when the last song ends, and on `newSet` with the old set's id. - Hooks run synchronously; anything they throw is logged and swallowed, so they can never delay or break playback. **Link (`src/live/link.ts`)** - The console only calls out to the app server; nothing calls in. - **Sign-in:** a browser PKCE login, using the issuer and client id from the app server's `config`. The redirect goes to the console's `/auth/callback`, and the token is stored in settings. - **Going online:** `goOnline(passcode)` calls `openSession` directly, so a reused passcode shows its message inline. It then sends the set's plays so far through the outbox. - **Outbox:** plays and session closes are stored locally first and sent oldest first. - Each play's id is `setId:playId`, so a resend never duplicates it. - A network failure waits and retries (1s, doubling to a 30s cap). - An auth rejection (401 or 403) signs the console out. - Any other rejection is logged and dropped, so one bad message can't wedge the queue. - **Closing:** the session closes when the set ends, when a new set starts, or on "Go offline". - **App server URL:** `LIVE_URL`, else the stored `live.url` setting, else `https://dj.incarnadine.org/live`. **Console UI** - A Go online control in the live set panel. It renders nothing without a link, so the offline layout is unchanged. - Online, it shows "Online · guests follow at dj.incarnadine.org/live · N waiting to send", plus Go offline and Sign in again when needed. This is Slice 5 of `projects/2026-09-27-dj-online-companion/plan.md`. ## Testing - `bun run test`: 193 pass. The link tests run against a **real in-process app server**: - going online delivers each play exactly once - with the server stopped, the next track still fires on schedule, and its play arrives once the server is back - the set ending closes the session - a reused passcode shows its message - PKCE is tested with a fake discovery document and token endpoint. - `bun run check`: clean. - **Not tried:** a real Authentik login and the real console, which drives Spotify through AppleScript. The redirect URIs are `http://localhost:3000` and `http://127.0.0.1:3579`, so open the console on one of those. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The console signs in with PKCE against the IdP the app server names, opens
an online session for the set with a passcode, and reports each play
through a stored outbox that retries until the app server is back. The
session closes when the set ends, on a new set, or on Go offline. Playback
never waits on any of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
forgejo-admin force-pushed feature/console-go-online from 65a1d6616f to 6743ab52bb 2026-09-28 06:39:11 +00:00 Compare
forgejo-admin deleted branch feature/console-go-online 2026-09-28 06:39:34 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
celilo/tango-dj!41
No description provided.