Skip to content
Oznog

Tools

What each tool in the repository is for.

The tools live in github.com/oznog-holdings/node0-public under tools/, and every command below runs from the repository root. sanitize-check.py also needs two private files that each site writes for itself and never commits. The names list holds the literals that must never appear, one per line: host, people, place and account names. The rules file holds the site’s own patterns, one name: regex per line, such as its address ranges and identifier shapes.

toolwhat it is forstatus
sanitize-check.pythe mechanical half of the publication checklist: addresses, credential shapes, credential-store names, image metadatain use on this repository, locally and in CI
diagrams/gen.pydraws every diagram on these pages from a data filein use on this repository
seed-rungs.pygenerates the Seed’s rung pages from the rung READMEs in the node0-seed repositoryin use on this repository
site-check.pyreads a built copy of the site and reports broken links and anchors, pages nothing links to, repeated links, images without alt text and stray dashesin use before each publication

sanitize-check.py #

Needs Python 3.11 or later and nothing else. Scans what git would publish (every tracked and untracked-not-ignored file, or the paths given), file names included, and prints one line per hit with the rule, the file, the line and the length of the match, never the match itself. Exit 0 is clean, 1 is at least one hit, 2 is a configuration error: a missing path, an unreadable private file, a bad regex, a malformed exception. Text is scanned as text; JPEG, PNG and WebP files are walked segment by segment to the end and every segment must be one that carries pixels; anything else that cannot be decoded, a symlink or a special file is a hit. Exceptions live in .sanitize-allow at the repository root, each scoped to one rule and carrying a reason, and there are none for images.

The tool carries only generic patterns. What is specific to a site, its names and its regexes, goes in two files that never enter the repository, passed as --names and --rules; without them the summary line says the pattern half ran alone. Run it before every push:

python3 -B tools/sanitize-check.py --names ../private/sanitize-names.txt --rules ../private/sanitize-rules.txt

A green run is necessary, never sufficient. It cannot read a label in a photograph, decode a secret someone encoded, or know that an unlisted word is a name, and it scans a tree, not a history.

diagrams/gen.py #

Needs Python 3.11 or later and PyYAML. Reads data/diagrams/*.yaml and writes one SVG per drawing into static/images/node0/diagrams/, plus one strip per layer for the stack. Text comes from the data files, sizes from the drawing code; the output is deterministic, so a regenerated tree that differs is a change to look at. Run it from the repository root after editing a data file:

python3 tools/diagrams/gen.py

The site pages inline the SVGs, so a regenerated drawing is live on the next build. The generator does no sanitizing; its inputs and outputs go through the gate like every other file.

seed-rungs.py #

Needs Python 3 and git, and a checkout of node0-seed beside this repository, or its path given with --src. It reads each rungs/<n>-<name>/README.md there, writes content/node0/seed/rung-<n>.md, and copies the photos the rungs use into static/images/node0/seed/. The README’s H1 becomes the page title, and its “In plain terms” paragraph becomes the description and is removed from the body. Links into the repository become links to it on GitHub, and links between rungs become links between the rung pages. It stops with an error on a link or a photo that is not in the repository.

python3 tools/seed-rungs.py
python3 tools/seed-rungs.py --check

--check writes nothing and exits 1 if any page or photo would change, so the gate can refuse a stale page. Edit the README in node0-seed, never the generated page, because the next run overwrites it.

Every tool here is MIT licensed, so it can be copied into your own repository, changed, and shipped, with the notice kept. The pages and data around them are CC BY 4.0.

site-check.py #

Needs Python 3 and a built copy of the site. Build it with hugo -d <dir>, then run python3 tools/site-check.py <dir> --base <the baseURL it was built with>. It reads every index.html and reports, per page: broken internal links and anchors; pages that no content links to (the section nav and the breadcrumb do not count); pages more than three clicks from the home page; the same internal target linked more than once in one page, and the same external link repeated; images without alt text; en or em dashes in page text; and headings under /node0 that look Title Case. It exits 1 on a broken link, a missing alt text or a dash. The rest is for reading: a page that links the same evidence twice to prove two different claims is fine.

Sanitized: checklist v0.1, 20260928. Part of oznog.com/node0.