Repository navigation
fix(website): render Fig 1's hotspots as Astro markup and escape its JSON blocks - #26
Merged
Merged
Conversation
|
Hebilicious
added this pull request to stack #37
October 13, 2026 20:10
Hebilicious
force-pushed
the
audit/figure-escaping
branch
from
October 14, 2026 06:04
c3d505c to
b685261
Compare
Hebilicious
removed this pull request from stack #37
October 14, 2026 06:05
Hebilicious
added this pull request to stack #42
October 14, 2026 06:05
Hebilicious
force-pushed
the
audit/figure-escaping
branch
from
October 14, 2026 06:10
b685261 to
9fca7d8
Compare
Hebilicious
force-pushed
the
audit/figure-escaping
branch
from
October 14, 2026 07:09
9fca7d8 to
ed7b76c
Compare
…JSON blocks The hotspot layer was an HTML string with unescaped attribute values, and the two data blocks were raw JSON.stringify output written through set:html. The SVG element and its hotspots are now Astro markup, which escapes every attribute, and the data blocks escape <, >, &, U+2028 and U+2029 through website/src/json-script.ts. The built page is unchanged apart from <path></path> in place of <path/>. Refs #20
Hebilicious
force-pushed
the
audit/figure-escaping
branch
from
October 14, 2026 08:50
ed7b76c to
3df9646
Compare
1 of 2 tasks
Hebilicious
added a commit
that referenced
this pull request
Oct 14, 2026
… changes them (#50) Closes #49 ## What changed - **`.github/workflows/check.yml`:** adds a `deploy` job. It runs after `check` passes, on a push to `main` or a manual run. It asks moon which tasks the push affects (`moon query affected` from `github.event.before` to the pushed commit), then deploys: - the **demo** when `infra:demo-deploy` is affected; - the **docs** when `website:build` or `infra:docs-deploy` is affected, building the site first; - nothing when neither is affected. A manual run, or a push with no usable base, deploys both. The job uses the `cloudflare` environment and runs one deploy at a time without cancelling one in progress. It fails with a clear error if a credential is missing. - **`infra/moon.yml`:** `infra:demo-deploy` declares the runtime code the demo's Workers are built from as its `inputs`, and `infra:docs-deploy` declares its stack files. These lists are the only path rules: the workflow keeps none of its own. - **`AGENTS.md`, `docs/deploy.md`:** say that CI redeploys the maintainer's stages, and which token permissions it needs. Two traps the workflow avoids, both checked locally: - With `CI=true`, moon silently skips a `runInCI: "skip"` task, so the deploy steps run the same `alchemy deploy … --stage demo|docs --yes` commands directly. The tasks keep `runInCI: "skip"`, so a stray `moon ci` never deploys. - Without a terminal, `moon query affected` waits to read changed files from stdin and hangs, so the workflow closes stdin (`< /dev/null`). ## How it was reproduced Not a bug. To check the path rules, I replayed the job's decision with this branch's moon inputs over the last 16 merges to `main`: ``` demo docs 31f1281 fix(market-worker): limit the Pearl Abyss rate per region, not for the whole deployment (#48 - - 8988949 docs(agris): name an issue in every pull request, reproduce before fixing, and free the demo - docs 76c2457 docs: correct the search, limit and namespace claims, and Fig 1's search pigeonhole (#36) demo docs f76218d fix(gateway-worker): serve GraphiQL under a strict CSP, and send nosniff and no referrer eve demo docs aaabc17 feat(infra)!: limit each client of a self-hosted gateway to 60 requests a minute by default demo docs af0118d fix(gateway-worker): admit each client's market reads exactly, and every request through the demo docs 92720e0 fix(market-worker): hold one Pearl Abyss rate allowance for the whole deployment (#32) demo docs 98d50ea fix(market-worker): bound the Pearl Abyss coordinator's queue and let one caller's abort end demo docs 5672fee fix(market-subgraph)!: hold Market.items to the 100-item batch cap and require Market.catalo demo docs 3677cbb fix(market-worker): report Pearl Abyss throttling as 429 and budget refusals as QUERY_BUDGET demo docs 3dd2aee fix: mask market and catalog errors to a closed set, and keep originals out of the gateway's demo docs 139323a chore: add a security policy, a minimum release age and a pinned, checksummed proto installe - docs 28b17a8 fix(website): render Fig 1's hotspots as Astro markup and escape its JSON blocks (#26) - docs 526a3b9 feat(website): send security headers from the docs site (#25) demo docs aa2f4a5 fix(pearl-abyss): cap the Huffman decoder's declared output at 8 MiB (#41) - - ab3e94f docs(agris): fast-forward the main checkout to origin/main after every merge (#46) ``` Website-only merges (#25, #26, #36) deploy only the docs. Process-only merges (#43, #46) deploy nothing. Runtime merges deploy both, because the site renders runtime facts (cache windows, limits) through `@group(agris-sources)`. This PR changes neither stage's inputs, so merging it deploys nothing. The deploy itself is first exercised by a manual run once `CLOUDFLARE_API_TOKEN` is set (see below). ## Credentials - **Done:** the `cloudflare` environment exists, only `main` may deploy to it, and it holds `CLOUDFLARE_ACCOUNT_ID`. - **Missing:** `CLOUDFLARE_API_TOKEN`. The local OAuth sign-ins (Alchemy and Wrangler) are refused by Cloudflare's token endpoints (`9109 Unauthorized`), and Alchemy's own token command needs the account's Global API Key. The token has to be created in the dashboard with Workers Scripts edit, Account Settings read and Secrets Store edit. ## Checks - [x] `moon run agris:check` passes on this branch - [ ] In a stack, this pull request holds one concern and its own layer passes `agris:check` (not a stack)
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.
Closes #20
What changed
website/src/components/Exchange.astro: the hotspot layer used to be an HTML string with unescapedd,data-hotandaria-labelvalues. The<svg>element and its hotspot paths are now Astro markup, which escapes every attribute. Only the kit's art, which is generated from build-time constants, still goes throughset:html.website/src/json-script.ts(new):jsonForScriptescapes<,>,&, U+2028 and U+2029, and bothapplication/jsondata blocks now use it.<path/>becomes<path></path>.audit/docs-claims.How it was reproduced
Not reproduced. This was found by reading the code, and it cannot be reached:
So no scenario fails on the parent layer (
audit/docs-site-headers). The change is defence in depth, andwebsite:build,website:figure-audit,website:headers-checkandwebsite:links-checkpass on this layer.Refs #21 (security audit tracking issue). Part of stack #42; review bottom-up, each layer shows only its own diff.