feat(beta): phase 5 — the app page and the closed-beta signup #8
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/phase-5-beta"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 5 of
PLAN.md§13:/app/,/beta/, the signup handler, the SQLite store, rate limiting and the export CLI of §8 — plus this repository's first test suite.Built against the decisions taken 2026-08-24, recorded in §8 under "How phase 5 built the app and the beta" as D26–D29.
What the repositories said when §8 and §10 were checked
Three things this plan had assumed turned out not to hold, and each changed what got built:
docs/android/screenshots/is a trusted-device and recovery-code smoke test from 2026-07-22 — captured against a development instance with no seeded content, before the theming work changed how every screen looks, and five of them are two-factor prompts. The home shot is an almost empty page.ConnectScreen.ktonAndroid-appmain: nothing in the app runs until a valid Runic Gateway site has been entered and validated. §8 never said what a tester would point it at./app/can offer a download today. EveryAndroid-apprelease attaches a signed APK and aSHA256SUMS. §8 and §10 were both written as though Play were the only delivery path.The four decisions
Screenshots.astroexists now rendering nothing, so filling it is a data change./betahandles its own POST; there is no/api/beta-signup. An endpoint answers with JSON (form works only with JavaScript) or a redirect (a mistyped address returns to a blank form with no explanation). §6's diagram is amended.platform.json'sandroidApk.serviceableisfalsebecause the publishedv0.5.0build does not work, so the panel states that plainly instead of linking it. The panel is not removed: a page that omitted sideloading would read, to somebody who knows the APK exists, as a page hiding it.serviceableis the one value inplatform.jsonwith no authority behind it, deliberately — no fetch can tell whether an APK runs. Flipping it totrueis the single edit that turns the link back on.Three mechanisms the plan did not anticipate
liveBrand()— §7's boot rewrite patches files indist/client, and an on-demand route's HTML never was a file, so/betareadingbrandwould show stock values forever. It reads the mountedbrand.jsonitself behind an mtime guard. Strictly better where it applies: pasting the Play opt-in URL into the mount takes effect on the next request, no restart.checkLinks.mjslearned what an on-demand route is./betais the first on-demand page and rule 1 resolves against the build, where it has no file. APLANNED_ROUTESentry would have been wrong in the exact way that list's own comment warns about — its reverse check fires when a route has been built, and an on-demand route never produces a file, so the entry could never rot out. Routes are derived fromprerender = falsein the source instead; deletebeta.astroand the links fail again.One design conflict the tests caught
removeSignuperases the address rather than flagging it, so it cannot also recognise that address later — the two properties are incompatible and erasure is the one §9 actually promises. Keeping a hash so the form could say "you were removed" would mean retaining a derived identifier for the one person who asked not to be retained. A re-signup after removal is an ordinary new row, and a test now guards against somebody "fixing" that.Verified end to end
Against the built server, not the dev server:
checkOriginrefuses cross-origin POSTs (403) — a free CSRF layer §8 did not anticipate.betaOptInUrlreached the running server with no restart, replacing the waiting state with the real link..txtpaste list, idempotent re-export, case-insensitive removal.checkFactsgains the APK assets andminSdk, and learns that RFC 2606 reserved domains are not contact addresses — it had flaggedplaceholder="you@example.com". The D13 rule is otherwise unchanged, and it is still the check that would catch a real address.npm run verifyis green: tokens, brand,astro check, 25 tests, production build, 159 links, 19 facts.🤖 This pull request was written with Claude Code.
Co-Authored-By: Claude noreply@anthropic.com