Repository navigation
fix(frontend): live-panel correctness — wrong series, oldest-12 slice, dead preflight, double-escaped hrefs - #64
Merged
Conversation
…, dead preflight, double-escaped hrefs Four functional bugs found auditing the JS before the demo: - runtime.js: defaultSeries was "CPI", a series db-init never seeds — the live fetch 404s and the panel can never show live data even with the API worker wired. Set to FXCADUSD (the seeded series). This re-lands the fix from 35de446, which was stranded on fix/rename-config-js-waf when PR #46 was squash-merged before that commit was pushed (the liveData gate from the same commit is deliberately NOT re-landed: once the api- route/DNS is permanent, a parked backend yields a caught 502 + snapshot fallback, which is the demo's resilience story — no console noise, no gate needed). - app.js: observations arrive newest-first from BOTH sources (read lambda ORDER BY observed_on DESC; snapshot sorted reverse=True), so .slice(-12) rendered the 12 OLDEST of 90 observations. Take the first 12. - api-worker.js: the OPTIONS branch answered preflights with 204 and no Access-Control-Allow-Origin — any preflighted request would fail CORS. Forward OPTIONS (plus Access-Control-Request-*) to API Gateway, which owns the CORS allowlist and auto-answers preflights. Verified with a node harness (17 checks: rewrite/secret/ACAO passthrough, preflight forwarding, 405/404/ 414/400/421/502 rejections). - md-renderer.js: inline() escapes the whole line before link parsing, then safeHref escaped the href AGAIN, so ?a=1&b=2 rendered as a=1&b=2 (literal "amp;b" param). Unescape entities before the single escape; javascript: blocking and attribute-injection escaping verified unchanged. 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.
Summary
Audit of every first-party JS file (both Cloudflare workers + the four frontend assets) ahead of the demo. Four functional bugs, all demo-relevant:
runtime.js—defaultSeries: "CPI"can never work. db-init only seedsFXCADUSD(runbook), so the live fetch 404s and falls back regardless of the API worker being wired. This re-lands stranded commit35de446(its branch missed the fix(frontend): parked-state fixes — WAF-safe runtime.js rename + opt-in live panel #46 squash). TheliveDatagate from that commit is deliberately dropped: with the api- route/DNS permanent (issue 011), a parked backend produces a caught 502 → snapshot fallback, which is the resilience story.app.js— panel showed the 12 oldest observations. Both the read lambda (ORDER BY observed_on DESC) and the snapshot (sorted(..., reverse=True)) are newest-first;.slice(-12)took the tail. Now.slice(0, 12).cloudflare/api-worker.js— preflight handler was functionally dead. OPTIONS returned 204 with noAccess-Control-Allow-Origin, failing any preflighted request. Now forwards OPTIONS (+Access-Control-Request-*) to API Gateway, which owns the CORS allowlist (feat(frontend): Cloudflare API worker — browser live-API path never worked #63) and auto-answers preflights. Today's panel fetch is a simple GET (no preflight), so this is latent — but it becomes live the moment any header/param is added.md-renderer.js— link hrefs double-escaped.inline()escapes the line before link parsing, thensafeHrefescaped again:?a=1&b=2rendered as a literalamp;bparam. Entities are now unescaped before the single escape;javascript:blocking and attribute-injection escaping verified unchanged.Verification
javascript:scheme still blocked; attribute injection still escaped; plain relative links unchanged.node --checkclean on all six JS files.cloudflare/api-worker.jsinto the Cloudflare dashboard worker (it is deployed by copy-paste) and redeploy the frontend (just deploy-frontend+ purge Cloudflare cache).🤖 Generated with Claude Code