From efaa2373dc0b36a26dfaf53625734a25de0d0722 Mon Sep 17 00:00:00 2001 From: pleb Date: Mon, 9 Nov 2026 14:17:08 -0800 Subject: [PATCH] Update plan after confirming replays work --- docs/plan.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/docs/plan.md b/docs/plan.md index 7aaf703..c0d17eb 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -803,7 +803,8 @@ the BL score, and confirm the improvement display and the ArcViewer replay. ### Phase 6: Ongoing sync -**Built 2026-11-09, not deployed yet.** `node scripts/archive/cli.ts sync +**Built 2026-11-09; deployed on incineroar the same day (daily timer at +17:00, first run clean; see phase 7).** `node scripts/archive/cli.ts sync [--ratings] [--no-ss-replays]` (this repo `d182fd8`), packaged as the flake's `plebleader-archive`. Tested against the local archive: the token refresh rotated the chain (now valid until about 2026-11-23), and with the @@ -871,7 +872,34 @@ the local zip. ### Phase 7: NixOS deployment on incineroar -**Built 2026-11-09, not switched yet.** Phase 6 added a second commit on the +**Done 2026-11-09: merged into nix-pleb `main` (fast-forward to `3b3eb47`), +switched on incineroar, first sync clean, and BL `.bsor` replays play in +ArcViewer.** Issues hit after the switch: + +- **Missing `/run/secrets/plebleader.env`.** The file was encrypted only to + litten's age key (the repo `.sops.yaml` rule lists only litten), so + incineroar's host key couldn't decrypt it. Fixed by adding incineroar's host + key and `age1kuxd…` with `sops rotate --add-age`. Any new incineroar sops + file needs the same three recipients as `sops.yaml`. +- **First sync (13:48):** the token refreshed, with the chain valid to + 2026-11-23 (each daily refresh moves that forward), 0 new scores, and the + importer loaded 3565 scores and 2552 songs in 11 s. The token now lives only + in `/var/lib/plebleader/auth/`. +- **Website "TypeError: Cannot read properties of undefined (reading + 'id')".** `utils/format.js` takes the first host label as the leaderboard + context when the host has more than 2 labels, so the context became + `incineroar` and the navbar's context lookup found nothing. The phase 4 dev + check missed it because a numeric last label (`127.0.0.1`) raises that limit + to 4. Website fix `e5f6279a`: non-BeatLeader hosts always use `general`. +- **ArcViewer "Download failed! HTTP/1.1 403 Forbidden"** for + `/cdn/replays/…bsor`, and `/cdn/maps/…` redirected to BeatSaver even for + archived zips. Caddy had been running since 2026-11-07. The switch added it + to group `plebleader` but only reloaded it, so the process still had just + `caddy` (`grep Groups /proc//status`). Fixed with + `doas systemctl restart caddy`. Any later change to Caddy's groups needs a + restart too. + +Phase 6 added a second commit on the branch: the `plebleader.env` sops secret, `plebleader-sync` (sync, then the importer) and its timer, and lock bumps for `plebsaber-stream` (`d182fd8`) and `plebleader-server` (`dd94772`). The `plebsaber-stream` bump also @@ -944,6 +972,42 @@ To deploy (the user does this): `nix build .#nixosConfigurations.incineroar.config.system.build.toplevel --no-link`. The user does the switch. +### Phase 8: Self-hosted BeatLeader web replay viewer + +Upstream, the score row's replay icon opens BeatLeader's web viewer +(`BL_REPLAYS_URL`, replay.beatleader.com), and turning on ArcViewer in the +score settings adds a separate `altReplay` icon (`Song/Icons.svelte`, +`webPlayerLink(…, 'arcviewer', …)`). Phase 4 pointed `BL_REPLAYS_URL` at +`/watch/`, so both icons open ArcViewer now. The user wants the upstream +behaviour back: the replay icon opens the BeatLeader viewer, and ArcViewer +stays a separate icon. + +Source: `~/src/BeatLeader/BeatSaber-Web-Replays` (webpack 5, npm). Steps: + +1. Fork it to gitea `pleb/BeatSaber-Web-Replays` with a `pleb/main` branch, + and change as little as possible. +2. Resolve `getApiUrl()` (`src/utils.js`, `src/open-replay-decoder.js`) to + `/cors/blapi` on non-BeatLeader hosts, the same rule as the website's + `IS_MIRROR`. Check how it fetches the replay file and the score (`link=`, + `scoreId=`) against the mirror's `/cdn/replays/` and `/cors/blapi/score/{id}`. +3. Maps: `zip-loader.js` tries `cdn.songs.beatleader.xyz`, then + `/cors/beat-saver2/api/maps/…` (a Netlify proxy), then `r2cdn`/`cdn.beatsaver.com`. + Try `/cdn/maps/.zip` first, which already falls back to r2cdn in Caddy. + Either proxy `/cors/beat-saver2/` to `api.beatsaver.com` in Caddy or skip it. +4. Drop or stub analytics (googletagmanager), and check its other runtime + fetches (fonts, `cdn.jsdelivr.net`). Discord and Patreon are plain links. +5. Add a flake with `buildNpmPackage` that outputs the built static files + (`index.html`, `assets`, `build`, `vendor`, as in its `predeploy` script), + and add it as a nix-pleb input. +6. Caddy: serve it at `/replay/` on the plebleader vhost. +7. Website: in mirror mode set `BL_REPLAYS_URL` to `/replay/` instead of + `/watch/`. Leave the explicit ArcViewer links (`altReplay`, `ReplayButton` + with `webPlayer == 'arcviewer'`) on `/watch/`. + +**Check:** on `/u/pleb` the replay icon plays a score in the BeatLeader +viewer from local files, and with ArcViewer turned on in settings, the second +icon plays it in ArcViewer. + ## Risks and fallbacks - **The server doesn't build or run on Linux, or EF/SQLite can't translate