Skip to content

fix(site): read digests as the API ships them, add a favicon, un-box the UI - #11

Merged
DevCop95 merged 1 commit into
mainfrom
fix/site-cors-favicon
Oct 18, 2026
Merged

DevCop95 merged 1 commit into
mainfrom
fix/site-cors-favicon

Conversation

@DevCop95

Copy link
Copy Markdown
Owner

Why

The live download table shipped broken for every real visitor. The page fetches
checksums.txt from github.com/DevCop95/pullgoscript/releases/download/...
to fill its SHA-256 column, and that origin cannot be read from a browser:
the endpoint answers with a 302 to release-assets.githubusercontent.com, and
neither the redirect nor the final CDN response carries
Access-Control-Allow-Origin. Chrome (and every other browser) refuses the
response, logs blocked by CORS policy, and the table renders hashless.

Verified with raw requests: neither hop sends ACAO. Following the redirect from
the API asset endpoint (Accept: application/octet-stream) does not help
either — the final response is the one the browser checks, and it also has
none. No amount of redirect-chasing fixes a CDN that does not opt in.

Meanwhile the page already had a CORS-clean source for every hash it needed:
the digest field each asset carries in the /releases/latest response
(api.github.com sends Access-Control-Allow-Origin: *), which matches
checksums.txt byte for byte — verified against the published v2.0.2 file for
all four hashed assets.

What changed

1. site.js — one request, one CORS-safe origin.
parseSums and the second fetch are gone. The SHA-256 column is now filled
from a.digest. hashOf() accepts only exactly sha256: + 64 hex characters;
anything else (absent, truncated, a different algorithm) renders as an em dash,
never as a plausible-looking wrong hash. The status line distinguishes the
all-digests case from a partial one and states the counts.

2. site.test.js — the regression test for this bug. The failure was
invisible to DOM stubs because stubs do not implement CORS: a stub happily
"returns" a cross-origin body a real browser would refuse. So the test asserts
the request budget instead — exactly one fetch, to
https://api.github.com/..., and any other origin is both flagged as a
violation and made to fail the way a browser fails (opaque rejection). Also
rewritten: fixtures carry real digest values, the old sumsText/sumsBroken
scenarios are replaced by a digests-malformed scenario (absent / truncated /
non-sha256 → em dash), and the pinned-fallback check now compares against the
fixture's digests. 35 assertions pass, zero dependencies, zero network.

3. Favicon — favicon.svg + favicon.ico, linked from all five pages.
The 404 reported was the browser's default /favicon.ico probe, which only
fires when no icon is declared; a <link rel="icon"> stops it. SVG drawn by
hand (console prompt: red chevron, amber cursor), ICO generated at real
16/32/48/64 sizes. Both served locally at 200 before this PR.

4. site.css — un-box the design. The palette drew a saturated 1px
#262c37 stroke around cards, pills, callouts, code and tables on a near-black
background, so every surface read as a dirty wireframe box. Surfaces are now
separated by gradients, 6%-white hairlines and shadows; cards lift on hover;
callouts keep their accent bar and gain a tinted fill; pills are tinted chips
instead of caged text; h2 rules are softened to a 5% break. No HTML or class
names changed — CSS only.

Verification

  • node docs/site.test.js: 35/35 (fixtures), plain node, no installs
  • HTML/link checker over all five pages: OK
  • local python -m http.server smoke: /, /favicon.svg, /favicon.ico,
    /site.css all 200
  • future releases that ship digests render hashes with no page change; the
    v2.0.2 pinned fallback in index.html was regenerated only in the sense that
    the release genuinely carries these digests (no numbers were edited by hand)

…the UI

The SHA-256 column used to fetch checksums.txt from
github.com/.../releases/download/... That origin 302s to a CDN whose
response carries no Access-Control-Allow-Origin, so every real browser
blocked the request and rendered the table hashless. (The API asset
endpoint fails the same way - the final response is the one the browser
checks, and it has no ACAO header either.)

The browser-side fix is to stop re-downloading the file at all: every
release asset already carries a digest field in the /releases/latest
response, which matches checksums.txt exactly and arrives over
api.github.com, the one origin that sends CORS headers. The page is now
exactly one request to one CORS-safe origin, and a regression test
asserts that request budget offline.

Also un-box the visual design: hard #262c37 borders read as dirt on the
dark palette and made cards, pills and callouts look flat. Surfaces are
now separated by gradient, hairline and shadow, and hover states arrive
as tints. The favicon is a hand-drawn SVG plus a four-size ICO, linked
from all five pages.
@DevCop95
DevCop95 merged commit 0c1d1c7 into main Oct 18, 2026
6 checks passed
@DevCop95
DevCop95 deleted the fix/site-cors-favicon branch October 18, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant