feat(site): host the repository's docs, rendered at build time (phase 3) - #22
Merged
Merged
Conversation
…he deployed commit Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
TMHSDigital
force-pushed
the
site/phase-3-docs
branch
from
September 22, 2026 23:29
624e3cf to
c10e716
Compare
…tags CodeQL flagged the strip-then-inspect pattern as incomplete multi-character sanitization. The output was never the stripped string, so nothing leaked, but the rule is now stated directly: every '<' must open an allowed tag. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
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.
Phase 3 of the Pages site: the repository's docs, hosted on the same origin and rendered from the commit being deployed. Nothing deploys yet (Phase 4).
What is hosted. README, METHODOLOGY, docs/PLAN.md, docs/example-report.md, CONTRIBUTING, SECURITY, CHANGELOG, and datasets/public/README.md. Each becomes
docs/<slug>.html, with a verbatim copy atdocs/<slug>.md, plus adocs/index page. Nothing is fetched at runtime, from raw.githubusercontent.com or anywhere else.Renderer: markdown-it 15.0.2, vendored in
site/vendor/markdown-it/.LICENSEholds its MIT license, andTHIRD-PARTY-LICENSESholds the licenses of the five packages its browser build inlines (entities is BSD-2-Clause, so its notice has to ship). Why this one:javascript:,vbscript:,file:and non-imagedata:link targets.I checked the tarball against the registry's sha512. The file's sha256 is pinned in
render_docs.mjs, which refuses to run if the file changes, and.gitattributesmarks it-textso a Windows checkout cannot rewrite its line endings and break the hash.One deviation from the brief, on purpose: the docs render at build time, not in the browser.
scripts/render_docs.mjsruns the vendored file under the runner's own Node (no install), andbuild_site.pywraps the result in the page template. The pages carry no script at all, so they work with JS off, and there is no renderer that can fail to load. That is stronger than the "raw markdown if the renderer fails" fallback, which I'd otherwise have built. The vendored file is excluded from the build output because nothing on the site loads it.Script injection.
html: trueis on only so raw HTML can be checked against an allowlist of exact tag strings:<details>,<details open>,<summary>,<b>, and their closers, which README's install sections use. Anything else fails the build; nothing is quietly cleaned up.Links.
#fragmentmust match a heading there. Heading IDs follow GitHub's rules, so the same anchors work on both.github.com/.../blob/<built sha>/...(ortree/for a directory).file:line.Provenance. Each doc page opens with "Rendered from
<path>at commit<sha>, built<UTC time>", linking the file at that SHA and the commit. A local build with uncommitted changes to a doc says so on that page.SOURCE_DATE_EPOCHis honoured if set.Navigation. Every doc page links back to the explainer and to every other doc, with the current page marked by
aria-current. There is a skip link. The explainer's nav and footer now link todocs/, and its example-report link goes to the site page instead of GitHub.Shared styles. The explainer's tokens and base typography moved to
site/base.css, which both page types load.docs.cssstyles the rendered prose. The explainer looks unchanged.Also fixed: the explainer's footer said "MIT licensed". plumbline is Apache-2.0; only the vendored JevBench fixture is MIT.
CI.
site.ymlrunsnode scripts/render_docs.mjs --self-test(14 cases: each refusal, a tampered vendored file, the link rewrites, the allowlist) before building. The build now renders the docs in the same job as the parity check, so the Phase 4 deploy job only needs that job to pass. The job's name is unchanged, so required checks are not affected.Checked locally:
mypy --strict, the self-test, and the build all pass.floor.jsstill agrees with the Python and reproduces the example report's line.<script>: the build refused all three in one message.<details>blocks work, and every request was same-origin.This branch was cut from main before #21 (em dash cleanup) merged. The two may conflict trivially in CHANGELOG.md.
🤖 Generated with Claude Code