Commit Graph
35 Commits
Author SHA1 Message Date
edde746 89d54d8f1d feat(watch-together): let the host hand the room to another participant
close #2183

Reusing a room means whoever enters first becomes the host, and moving the
session to someone else's library meant everyone leaving and re-entering in
the right order. The host can now promote any connected guest from the
participant list (Watch Together screen and the in-player session sheet),
with playback, control mode, and reconnect identities carried across.

The relay owns the swap: a new `transferHost` message validates the sender
is the live host and the target a connected modern-protocol guest, then
swaps `HostPeerID` and the reconnect verifiers (each peer keeps its own
token), persists the room, and broadcasts `hostChanged` to every peer.

Clients flip roles in place: the controller swaps its role engine while
keeping the session, message queue, and player attachment. A promoted guest
seeds the coordinator with the room's last known intent (a paused room
stays paused) and the known-peer roster so the fresh epoch re-gates
instead of solo-starting; a demoted host falls back to a reconciler with a
fresh clock sync and asks the new authority for state. Guests re-pin the
host identity, reset their sequence, and re-converge their clocks.

A rejected transfer (`not_host` / `peer_not_found`) surfaces as a toast
instead of tearing the session down. Pre-transfer app builds in the room
ignore `hostChanged` and stop following the room at the next transfer;
targets on an old sync protocol are not offered the action.
2026-08-31 08:55:45 +02:00
edde746 6ab46ced54 fix(relay): claim OAuth callbacks before the code exchange and bound poster and poll traffic per IP
Two callbacks with the same state could both exchange the authorization code upstream (concurrently or by replay); the session is now atomically claimed under the proxy lock before the exchange.

GET /posters/ and the /auth/result long-poll had no per-IP limiting or concurrency bound, and every poster lookup serialized through an exclusive store lock; both endpoints now use the established limiter and non-expired hits take a read lock. The limiter also tracks active transfers per IP with caps below the global limits (4 for fetches, 2 for uploads), because one unauthenticated client could otherwise take all 16 global poster-fetch slots and hold them through slow ServeContent reads, starving everyone else with 429s; concurrency checks precede bucket charges so a capped denial consumes no admission tokens.

/auth/result gets its own per-IP budget instead of sharing /auth/start's burst-3 bucket, where two concurrent NAT'd sign-ins 429'd on the fourth request. It is charged only after the poll secret validates (bogus requests keep the generic 410 and cost nothing), denials carry an honest Retry-After, and the Dart poller - which treated 429 as terminal and abandoned a valid session - retries them until the session's 10-minute lifetime expires.
2026-08-21 19:23:43 +02:00
edde746 a9cbb72c63 chore(server): bump bugs image to sha-c996cf3
Deployed 2026-08-20. Adds dartsymbolmap chunk-upload support and
crashpad minidump ingestion; fixes the method-scoped SPA fallback
that 405'd every non-GET API request.

Old: sha-319e0eb@sha256:1e5a2d8ab80e703de4a8a8b15d858ce931609e2226bf1e6d04979c0ca52a3005
New: sha-c996cf3@sha256:540d985c51f953704c8b97c6c568d0ffc107b91223dd5279136cce1c5522598b
Index verified on two hosts; linux/amd64 + linux/arm64 present.
Migration 18 (event_attachments) rehearsed on a cloned DB copy.
Rollback: prior digest + /root/bugs-db-backup-20260820-082218 on the host.
2026-08-20 10:31:06 +02:00
edde746 f622ba8efe chore(scripts): group scripts into checks, codegen, maestro and release subdirectories
scripts/ had ~80 flat files. Entry points (ci_*.sh, codegen.sh, run_tests.sh, format_native.sh, setup_hooks.sh, upload-symbols.*) and the shared pubspec_version.py stay at the root; checkers, generators, maestro tooling and release tooling move into subdirectories with their tests. Updated every reference: workflow steps, guard-test glob, Docker COPY paths and .dockerignore whitelist, website audit path, dart test imports, and regenerated the five outputs whose headers embed generator paths.
2026-08-17 01:40:54 +02:00
Aldo BarrerasandGitHub 8383c7b73b chore: bump go server version, run formatter & regenerate podfile lock file checksum (#1944)
* Bump go server and run formatter.

* Regenerate Podfile lock file checksum.
2026-08-15 13:44:56 +02:00
edde746 69fadc220d chore: clean up code comments 2026-08-10 20:28:41 +02:00
edde746 1be982f43d fix(watch-together): re-host an abandoned room code instead of joining it
A room whose peers have all left is a code nobody is using, but the relay
kept it bound to the creator's reconnect capability and rejected every
other create with room_exists. The app compounded it: enterRoom only
promoted to host on room_not_found, so tapping a recent code landed the
user in the retained room as a guest of a host that was never coming
back, until the cleanup sweep finally dropped the room.

Create now replaces a room with no connected peers, and enterRoom hosts
the code when its probe join finds an empty room. An occupied room still
rejects create, including from its previous owner, and a host that is
merely disconnected still reclaims its peer ID through join with the
matching token.
2026-07-28 03:30:32 +02:00
edde746 314fec5383 fix(relay): mint five-character log ids again
A 25-character upload capability is unreadable over the phone or in a
support thread, which is the only way these ids are ever exchanged.
Lookups stay bounded by the per-source failed-lookup limiter and the
three-day expiry, and ids minted at the longer shape are retired on the
next startup because they no longer match the store's filename shape.
2026-07-28 03:30:32 +02:00
edde746 a56b9a3dfb Merge the deduplication and dead-code removal pass
Consolidates duplicated logic behind shared implementations — paginated
grid tabs, focus chrome, cached remote stores, sheet selection columns,
the server artifact store and a test fixture layer — and removes code
that had become unreachable. Net reduction of about 5,500 lines with no
behaviour change.

Where a fix had landed separately in code that moved into a shared
helper, the fix was re-applied inside the helper rather than left behind
in the copy that went away.
2026-07-26 19:41:23 +02:00
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00
edde746 516bd69c19 fix(server): bypass debounce for terminal mutations 2026-07-25 17:38:09 +02:00
edde746 0717009ade fix(server): make room persistence transactional 2026-07-25 16:16:48 +02:00
edde746 40833e65ec fix(ci): align toolchains and isolate platform tests 2026-07-24 10:06:50 +02:00
edde746 09656fa4d3 fix(supply-chain): verify CI and production inputs
Pin external actions, images, toolchains, native archives, and tvOS engine artifacts; enforce fail-closed CI checks and keep website privacy disclosures aligned with shipped behavior.
2026-07-24 03:56:40 +02:00
edde746 43a8fe020d fix(relay): secure reconnect and room ownership 2026-07-24 03:46:50 +02:00
edde746 1d1c301f61 test: stabilize deterministic integration coverage 2026-07-24 03:40:06 +02:00
edde746 e6e7d8cdfd test: remove redundant coverage and shorten timers 2026-07-13 02:15:03 +02:00
edde746 a9493f4f0e fix(relay): harden lifecycle and protocol handling 2026-07-12 17:31:15 +02:00
edde746 05e70ab56d chore: remove caddy 2026-07-04 23:09:41 +02:00
edde746 bdbd667584 feat(discord): self-host rich presence posters 2026-05-11 04:19:41 +02:00
edde746 a13cfedbce fix(tvos): app store builds 2026-04-24 17:35:22 +02:00
edde746 e8729a4e27 feat: oauth proxy for mal/anilist auth 2026-04-24 09:46:45 +02:00
edde746 05aeee1124 test(server): relay integration coverage 2026-04-22 15:24:34 +02:00
edde746 74c6af2980 feat(server): persist rooms across restarts 2026-04-22 14:57:41 +02:00
edde746 0883fe2e36 chore(server): tune bugs memory limits 2026-04-22 14:29:36 +02:00
edde746 34815f22ee fix: watch together server races, reconnect readiness, session end 2026-04-16 15:24:44 +02:00
edde746 1d3ae3e1c5 fix: watch together bugs and server write serialization 2026-04-16 14:00:24 +02:00
edde746 3cf1ebc09b fix: watch together room re-join and participant discovery
close #875
2026-04-16 13:17:24 +02:00
edde746 6dfdb62df8 feat: relay connection limits and container memory caps 2026-04-13 07:55:28 +02:00
edde746 a948d82c24 switch from glitchtip 2026-04-12 09:11:42 +02:00
edde746 02e175e4d3 feat: replace rustrak with glitchtip 2026-03-03 14:27:11 +01:00
edde746 cd36e3acb0 feat: switch crash reporting from BugSink to Rustrak 2026-03-03 09:19:25 +01:00
edde746 229d6b24e1 feat: crash log reporting 2026-03-02 07:29:21 +01:00
edde746 747fee0889 feat: log uploading 2026-02-07 20:09:30 +01:00
edde746 f67ca187a8 feat: replace webrtc with ws relay 2026-02-04 07:49:35 +01:00