Quality/CI tooling: local gate, hash-integrity check, workflow-security CI#6
Merged
Conversation
The latin and latin-extended woff2 files of Anthesis Legible Sans roman carried each other's content hash in their filenames: each file's actual sha256 matched the token on the other file. Glyph coverage confirms the semantic names are correct (latin holds basic Latin, latin-extended holds U+0100-024F), so only the hash tokens were crossed at hashing time. Rename both files to their true content hashes, update the @font-face URLs in the stylesheet, and rehash the stylesheet accordingly in _header.html and errdocs/err.html.
POSIX sh script enforcing three invariants that were previously manual: filename hash tokens match file contents, every hashed asset referenced by _header.html, errdocs/err.html, and site.webmanifest exists on disk, and the two HTML files agree on the hash tokens they reference. Wired as a local pre-commit hook. This check is what surfaced the swapped font hash tokens fixed in the previous commit.
Report-only: --force-exclude retained from upstream defaults so excludes apply to explicitly passed filenames, --write-changes dropped. First-run false positives (heading-anchor slugs, British 'uncatalogued') handled in config; no real typos found in content.
Convention rules that conflict with published articles (MD014 prompts, MD029/MD030 list styles, MD036 captions, MD040 bare fences) are disabled in config rather than mass-editing 25 articles. MD041 stays on: every article starts with an H1.
domain-sift.md mixed indented and fenced code blocks; convert its three indented blocks to fenced so the article is internally consistent. firefox-keyword-search.md pointed at www.wiktionary.org as bare text; make it a real link.
Blank-line conventions and keyword lowercasing (currentcolor, optimizelegibility) from stylelint --fix; behavior-identical since CSS keywords are case-insensitive. Both stylesheets renamed to their new content hashes with references updated in _header.html and errdocs/err.html.
extends stylelint-config-standard with targeted overrides instead of nulls where possible: page-break-* aliases are deliberate print compat, -webkit-/-moz-text-size-adjust has no unprefixed support. The hashed styles.*.css files are source and stay linted; only stagit/ is ignored. no-duplicate-selectors and no-descending-specificity are off: the stylesheet is organized in thematic sections that legitimately repeat selectors. The hook entry computes --config-basedir from the stylelint binary so extends resolves inside pre-commit's isolated node env.
Local hook (the official one hardcodes --staged) running a full-history scan at push time. Allowlists cover content that is public by design: pubkeys/, migration/, stagit/, the GPG transition statement, PGP public key blocks, and the Monero donation address. Validated against full history: no findings.
Two jobs on pull_request and pushes to master: the full pre-commit suite (both stages; gitleaks needs full history, hence fetch-depth 0) with the pre-commit cache keyed on the config hash, and zizmor workflow-security auditing with GH_TOKEN set so the online audits actually run. Top-level permissions are empty, jobs get contents: read, actions are SHA-pinned, and checkout never persists credentials. actionlint joins the pre-commit suite in this same commit; both it and zizmor are clean on this workflow.
Weekly updates for github-actions and pre-commit ecosystems. enable-beta-ecosystems covers dependabot-core paths that still gate the pre-commit ecosystem despite its GA. Caveat: additional_dependencies pins inside .pre-commit-config.yaml (stylelint, stylelint-config-standard, gitleaks) are invisible to both Dependabot and pre-commit autoupdate; bump them manually quarterly.
zizmor's dependabot-cooldown audit (online-only, so it surfaced in CI rather than the local pre-push run) requires a cooldown so new releases age before being adopted. Seven days for both ecosystems.
This was referenced Jun 12, 2026
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
Adds the staged-rollout layer 1 of quality tooling: a fast local pre-commit gate (hygiene, typos, markdownlint, stylelint), a machine-enforced asset hash-integrity check, gitleaks full-history scanning at push time, and a hardened CI workflow with zizmor workflow-security auditing plus weekly Dependabot.
Changes
.github/, so ssg never copies them into the rendered site (verified by a clean render-diff againstanthesis_rendered).check-hashes.shenforces the previously manual invariant that content-hashed filenames match file contents and that_header.html/errdocs/err.htmlagree. Its first run caught a real bug: the sans roman latin and latin-extended woff2 files carried each other's hash token (fixed infix(fonts), with the stylesheet rehash ceremony).fix(content)andstyle(css)commits; convention-vs-style conflicts went to config instead of mass-editing published articles.persist-credentials: false, zizmor running withGH_TOKENso its online audits execute.Testing
pre-commit run --all-filesand--hook-stage pre-push(full-history gitleaks) both green locally.uvx zizmor==1.25.2 .and actionlint: no findings.Notes for reviewers
additional_dependenciespins (stylelint, gitleaks) are invisible to Dependabot — quarterly manual bump noted in the dependabot commit body.chore(styles)), which was local-only on master at branch time.