Skip to content

fix(cdn): fingerprint joule.css + sap-fundamental.css (dual-emit) [#1605] - #1611

Merged
jung-thomas merged 10 commits into
mainfrom
worktree-issue-1605-fingerprint-css
Aug 10, 2026
Merged

fix(cdn): fingerprint joule.css + sap-fundamental.css (dual-emit) [#1605]#1611
jung-thomas merged 10 commits into
mainfrom
worktree-issue-1605-fingerprint-css

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

Why

Follow-up to #1601 / #1603 (CSS fingerprinting) and the 2026-08-10 giant-logo incident. Two stylesheets were still referenced by hardcoded bare path and so were NOT fingerprinted — leaving them exposed to the same CDN stale-edge bug (fresh HTML pairing with an edge-cached stale stylesheet under a stable /css/<name>.css URL):

  • joule.cssbaseof.html
  • sap-fundamental.csshead.html + scanner-vue/list.html

Closes #1605.

Two corrections to the issue's premises (found during recon)

  1. The assets/ copy of sap-fundamental.css was NOT a usable equivalent. hugo/assets/css/sap-fundamental.css (76 KB) was the uncompiled @import source; the shipped hugo/static/css/sap-fundamental.css (807 KB) was the compiled output of npm run build:css. Fingerprinting the source as-is would ship a browser-broken (@import 'fundamental-styles/dist/...') stylesheet. This PR fingerprints the compiled bytes.
  2. Normal CAP pages already inherit the Hugo <head>. Catalog/mission/group/concept pages render through Hugo's published __shell__ (the _shell layout wraps baseof.htmlhead.html), so fingerprinting head.html automatically flows the hashed URL into CAP-served pages. The hardcoded /css/sap-fundamental.css in content-store.js / concept-list-page.js is only the rare degraded fallback — left bare intentionally.

What — single-source dual-emit

Each stylesheet lives once in hugo/assets/css/. The layout links a | fingerprint (hashed) URL and calls Hugo's Resource.Publish to also emit the bare /css/<name>.css. So:

  • Anonymous pages + the CAP __shell__ link the edge-safe hashed URL.
  • The bare copy stays live for consumers that can't take a build-time hash: the static admin-shell page (app/admin-shell/webapp/index.html), the scanner layout, the CAP degraded-fallback renderers, and the joule smoke tests.

sap-fundamental.css's @import source is renamed sap-fundamental.src.css; build:css now compiles it into hugo/assets/css/sap-fundamental.css (committed compiled bytes — npm run dev runs hugo server with no CSS build step and depends on the committed file, exactly as before).

Changed

  • package.jsonbuild:css retargeted to …src.css → hugo/assets/css/sap-fundamental.css
  • hugo/assets/css/sap-fundamental.src.css — renamed @import source (+ drift-guard header)
  • hugo/assets/css/sap-fundamental.css — regenerated committed compiled bytes
  • hugo/static/css/sap-fundamental.css — deleted
  • hugo/static/css/joule.csshugo/assets/css/joule.css — moved
  • hugo/layouts/_default/baseof.html, partials/head.html, scanner-vue/list.html — dual-emit
  • test/hugo-css-fingerprint.test.js — new guard test
  • docs/developers/architecture/{cdn-caching,build}.md — doc updates

Deliberately untouched

srv/lib/content-store.js, srv/lib/concept-list-page.js, app/admin-shell/webapp/index.html, and both joule smoke tests keep their bare /css/* paths — .Publish guarantees those files still exist.

Verification

  • Full npm run build:css && hugo --minify build confirms dual-emit in hugo/public: both <name>.css and <name>.<hash>.css emit; rendered pages link only the hashed URLs (zero bare <link>s); the published bare sap-fundamental.css is the compiled form.
  • New guard test + existing hugo-step-badges.test.js: 24/24 pass.
  • Whole-branch review (Opus): APPROVED, no Critical/Important findings.

Note

This is the durable fix; JS islands (/js/*) remain un-fingerprinted (tracked separately as the gate for raising the static-asset TTL to immutable). See #1604 + the CDN cache-policy umbrella item.

@jung-thomas
jung-thomas merged commit e5e4feb into main Aug 10, 2026
5 of 6 checks passed
@jung-thomas
jung-thomas deleted the worktree-issue-1605-fingerprint-css branch August 10, 2026 21:43
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.

Make joule.css + sap-fundamental.css fingerprintable (bare-path CSS, stale-edge risk)

1 participant