fix(website): download gate never enables when the GitHub API lookup fails - #805
Open
felipesalinasr wants to merge 1 commit into
Open
fix(website): download gate never enables when the GitHub API lookup fails#805felipesalinasr wants to merge 1 commit into
felipesalinasr wants to merge 1 commit into
Conversation
…fails Users reported entering the invite code correctly and the download button staying dead. Root cause: the button required BOTH a code match AND a runtime fetch of api.github.com to have succeeded. Unauthenticated GitHub API calls are limited to 60/hour per IP, so visitors behind shared IPs (offices, VPNs, mobile carrier NAT) never got an installer URL; the fetch also had no .catch, and validation only ran on keystrokes so a URL arriving after the code was pasted never unlocked the button. The failure was invisible in analytics because download_unlocked only fired on the happy path. Fixes: - New build-time data file (src/_data/release.js) resolves the latest installer URLs on every deploy and bakes them into the pages as guaranteed direct-download fallbacks. Fails closed in CI so a deploy can never ship with empty fallbacks; helper logic lives in lib/release-assets because Eleventy treats named exports in data files as data keys. - Gate unlocks on the code alone; href prefers the live lookup, falls back to the baked link. Validation re-runs when the lookup lands (fixes the paste-before-fetch race). Same treatment for the Windows modal and the early-access page (whose fallback previously sent users to the homepage). - Runtime lookup now has a .catch (warn + baked fallback per beta policy). - Code comparison is case-insensitive and both inputs disable mobile autocapitalize/autocorrect (iOS typed "Getsh*tdone" and never validated). - download_unlocked fires on code match regardless of URL state, and download events carry link_source (live|baked) so this failure mode is measurable in the funnel. - website-deploy.yml passes the workflow token to the build so the build-time lookup is not rate-limited on shared Actions runners. Verified: Eleventy build bakes real URLs; Playwright run against the built site with the API deadened (wrong code stays locked; correct code, mixed case and padded, enables Mac + both Windows buttons with direct installer hrefs); race test (code typed before fetch resolves) unlocks immediately and stays unlocked; CI fail-closed path throws on API 401; Biome clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Before merging / deploying
github.tokento the build (no new repo secret).The bug (user-reported)
Invited users paste the correct code and the download button never enables; clicks do nothing.
The button required both a code match and a successful runtime fetch of
api.github.com/.../releases/latestfrom the visitor's browser:.catch; blocked/failed lookups fail silently and permanently.inputevents, so a code pasted before the fetch resolved stayed locked even after the URL arrived.pointer-events: none.download_unlockedonly fired on the happy path, so affected users were indistinguishable from visitors without a code.The fix
Plan A (live, upgraded): the runtime lookup stays, now with
.catch+ re-validation when it lands (fixes the paste-before-fetch race).Plan B (baked fallback): new
src/_data/release.jsresolves the latest installer URLs at build time and bakes them into the page. If the live lookup fails, the baked link downloads the app directly. Worst case: the release current at deploy time, and the app self-updates on first launch. Nothing hand-written, nothing version-pinned in source.Gate rule change: a correct code alone unlocks the button; the href is live-or-baked. Same for the Windows modal and the early-access page (whose fallback previously dumped users on the homepage).
Hardening: case-insensitive code check;
autocapitalize="none" autocorrect="off"on both inputs (iOS typedGetsh*tdoneand never validated);download_unlockedfires on code match unconditionally; download events carrylink_source: live|bakedso the fallback path is measurable.lib/release-assets.jsholds the pure asset-picking logic outside_data— Eleventy treats named exports in data files as data keys and silently drops the default export (verified the broken build output before moving it).Verification
pickInstallerUrlsunit-checked via node against the real v0.4.27 asset list + empty/undefined inputs./,/early-access/(en/es/pt).CI=1+ failing lookup throws (tested with a 401).🤖 Generated with Claude Code