Players open a no-login link and see live cursors and dragged gear
pieces synced in real time, backed by a small Workerman WebSocket
relay (src/Command/PuzzleRelayCommand.php) run alongside symfony
serve - no Docker/Mercure hub needed. The board renders the wall
artwork with a spare-gears tray, and a "Reset puzzle" button (visible
only to logged-in users, verified server-side via a signed token) lets
the DM wipe the shared state for everyone.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DB_PORT was doing double duty - the container-internal port baked into
DATABASE_URL (must be 3306) and the host-published port in
docker-compose.yml. Setting it to 3306 for the URL made compose try to
publish host :3306, which collides with another stack's MySQL.
DATABASE_URL now hardcodes database:3306 (always correct inside the
compose network); the host publish uses ${DB_HOST_PORT:-3310}.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>