A watch party that works everywhere, with nixamp as the room and the identity - #223
Merged
Merged
Conversation
…identity The page did not do what its name said: the host could not pick a file (the modal's open state was thrown away), Sync All had no handler, the chat was a picture of one, the member list never refreshed, and the link nixamp hands its members (/watch-party?code=ABC123) landed on an empty form. The nixamp bridge was bolted onto a party that did not sync. Now: - The host's player is the clock. Play, pause and seek go to a new PATCH /api/watch-party/playback; every other member polls the party every 3 s and follows within 2 s, with a "tap to join playback" overlay when the browser will not autoplay. The host is proven by the session, and the guest id is accepted only for a guest-hosted party, so a member cannot present the host id they saw in the member list. - ?code= joins on its own once there is a name, and the name defaults to the nixamp handle (or the account) so a member sent from nixamp is in with no typing. The party's URL is put in the address bar for sharing. - Chat is the nixamp room's chat: read through the bridge by anybody with the code, posted as the member's own nixamp self, so the same lines appear in the nixamp app, a terminal, the desktop app and on a TV. Without nixamp connected the box says so and links to connecting, landing back here. - A host with nixamp connected has the party bridged as soon as they open it; play/pause/seek sync nixamp immediately instead of at the next 15 s. - Sign in with nixamp (OAuth 2.1, PKCE, now with the email scope) on /login and /signup: the start route runs signed out, the callback finds or makes the account with that email and mints a real Supabase session server-side (admin magic link generated and spent in the same request), then lands on ?redirect=, which is the party for somebody who arrived from nixamp. The OAuth routes are public in proxy.ts for that reason. - Buttons are Focusable for the Fire TV WebView. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ThreatCrush Security Scan99 finding(s) HIGH/CRITICAL: 11 | MEDIUM: 29 | LOW: 59
…and 49 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
/watch-partydid not do what its name said. The host could not pick a file (the modal's open state was thrown away), Sync All had no handler, the chat was a picture of one, the member list never refreshed, and there was no sync between browsers at all. The link nixamp hands its members,/watch-party?code=ABC123, landed on an empty form. So the OAuth 2.1 bridge from PR #217 was bolted onto a party that did not work, and a nixamp user arriving from the app, a terminal or a TV hit the members-only login with no way in.What
The party itself
PATCH /api/watch-party/playback; every other member polls the party every 3 s and follows within 2 s, with a "tap to join playback" overlay when the browser refuses to autoplay.PATCHhad that hole).?code=fills the form and joins on its own once there is a name. The name defaults to the nixamp handle, or the account, so a member sent from nixamp is in with no typing.nixamp, on every surface
live_event_chat), read through the bridge by anybody with the code and posted as the member's own nixamp self. The same lines appear on nixamp.com's room page (A party's room is a page: nixamp.com/live/<slug>, open to read, with the chat nixamp#218), innixamp party, the desktop app, MCP and on a TV.emailscope) on/loginand/signup. The start route runs signed out; the callback finds or creates the account with that email and mints a real Supabase session server-side (admin magic link generated and spent in the same request, token never leaves the process), then lands on?redirect=, which is the party for somebody who came from nixamp./api/v1/nixamp/oauthis public inproxy.tsfor that reason;redirectis restricted to a path on this site.Focusablefor the Fire TV WebView.Tests
playback/route.test.ts: host moves playback, pause is a paused party, a member with the host's id is refused, a guest host is accepted, bad positions refused, gone parties 404/410.nixamp/route.test.ts: chat read is open, any member posts as themselves, no nixamp → 409 with a connect link back to this party.signin.test.ts: account made confirmed with the handle as its name, existing account signed in, no email refused, other failures surfaced,safeRedirectrefuses//and/\, the cookie shape matches a password login.pnpm typecheckclean; lint has no errors.After merge
email; they keep working for parties. Only Sign in with nixamp needs it, and that is a fresh consent._store.ts), as before; only the bridge row is durable.🤖 Generated with Claude Code