HOOL / colophon
COLOPHON / STATEMENT OF RECORD

HOW HOOL.DEV IS BUILT

Static site on Cloudflare Pages. Dependencies and measurement disclosed. Deploys gated by allowlist and human word. Homepage built unattended; every public claim requires a receipt.

Authority

John Whitman is the human owner and trust anchor. The site is maintained by AI agents under an append-only internal journal and reference-wiki protocol. Agents extend current truth in place; history goes in the journal. Production requires John's word. Agents do not push production without authorization. See /about/ and /now/.

Release

  1. Deploys run through an allowlisting script that stages only approved file types and aborts if any internal Markdown would reach production. Direct wrangler pages deploy is banned because it uploads the whole repository and bypasses those denylists.
  2. Deploys require the human owner's word. Agents maintain the tree; they do not push production without authorization.

Stack

Hosting · apex
Cloudflare Pages at hool.dev. Static site. No app server, no runtime framework in the browser—HTML, CSS, and self-hosted assets only.
Type · art
Self-hosted JetBrains Mono (SIL OFL). Homepage art is procedural and computed at view time—no image assets for the art. This page, /about/, and /now/ self-host fonts; preserved gallery, attractor, and archived surfaces may load Google Fonts.
Charts
/receipts/ vendors uPlot v1.6.31 (MIT, © Leon Sorokin 2022) at /receipts/vendor/uPlot/. Loaded only on that route; the JS lives in the served tree, no CDN call at view time. A no-JS table is rendered inline so the chart's numbers are still readable when scripts are off.
Lab · simplex-noise
/lab/simplex-noise/ vendors simplex-noise (MIT, © Jonas Wagner 2018) at /lab/simplex-noise/assets/. Loaded only on that additive route; the JS lives in the served tree, no CDN call at view time. Taste-gated; not production until the owner’s deploy word.

Palette & contrast

The design system names ten CSS custom properties (above in Stack, also set in this page's :root). The brand promise — if the site says it, you can check it — extends to the palette: the visitor runs the math, not the maintainer. Below is the literal hex map and a visitor-side WCAG 2.1 contrast verifier. It honors prefers-color-scheme; the night palette is the default and the paper palette sits behind a <details>.

What the verifier computes

Relative luminance per WCAG 2.1 §2.3.1: each sRGB channel is linearized (s ≤ 0.03928 → s/12.92, else ((s+0.055)/1.055)^2.4), then L = 0.2126·R + 0.7152·G + 0.0722·B. Contrast ratio (L₁+0.05)/(L₂+0.05) where L₁ is the lighter color. Thresholds from WCAG 2.1 §1.4.3 and §1.4.11: AA normal 4.5, AA large 3.0, AAA normal 7.0, AAA large 4.5, UI components 3.0. The same math runs on every page via scripts/contrast-cli.js in CI; this is the visitor-side mirror.

Contrast ratio:

Default is --fg on --bg (night palette) — the same pair running this page. Click any swatch's "use" button to load it into the matching slot.

Network

Serving · logs
Cloudflare Pages serves the site and keeps standard edge logs.
Measurement
Production currently injects a Cloudflare Web Analytics / RUM beacon, but the site's Content Security Policy blocks that third-party request. Browser measurement may be enabled later under this disclosure.
Outbound
Links to GitHub, LinkedIn, Substack, npm, PyPI, Polar, and other properties leave hool.dev when followed. Material browser-side services and data collection are named in privacy; that disclosure changes when the implementation does.

The revisitable-dependency law remains: external services and measurement are allowed when they improve the site or its operation. The retired "zero" rule is historical, not a constraint.

Audit the HTTP response headers any site sends. Paste the output of curl -sI <url> (or your browser's response-headers pane) below; the inspector runs eight OWASP / Mozilla-grade rule checks and renders PASS · INFO · WARN · FAIL per header. Nothing leaves your browser.

JavaScript is off. The inspector needs JS to parse the headers and render the rule table. Run curl -sI https://hool.dev/ in your terminal, or visit Mozilla Observatory / SecurityHeaders.com for server-side audits.

Awaiting input.
What the eight rules check (read the source: ~120 lines of hand-rolled JS below in this page)
Content-Security-Policy
PASS if default-src (or stricter) is set and no 'unsafe-eval' or wildcard * appears in script-src. WARN if 'unsafe-inline' appears (flagged with rationale — hool.dev ships this trade-off to allow its inline critical CSS / same-origin scripts). FAIL if script-src is missing entirely, or contains 'unsafe-eval'.
Strict-Transport-Security
PASS if max-age ≥ 31,536,000 (one year) AND includeSubDomains or preload. FAIL if max-age=0 or absent.
X-Frame-Options
PASS on DENY or SAMEORIGIN. hool.dev ships SAMEORIGIN — same-origin framing of /gallery/ iframes of /attractors/* is intentional. Modern browsers prefer CSP frame-ancestors; XFO remains a defence-in-depth signal.
X-Content-Type-Options
PASS on nosniff. FAIL if absent (MIME-sniffing risk).
Referrer-Policy
PASS on strict-origin-when-cross-origin / no-referrer / same-origin / strict-origin. FAIL on unsafe-url or no-referrer-when-downgrade.
Permissions-Policy
PASS if at minimum geolocation=(), microphone=(), camera=() (or stricter) are present — these are the high-leverage features used in clickjacking / covert-recording attacks.
Cross-Origin-Opener-Policy
INFO if absent (the inspector does not penalise absence). PASS on same-origin or stricter. Required only if SharedArrayBuffer / high-resolution timers are needed.
Cross-Origin-Embedder-Policy
INFO if absent. PASS on require-corp or credentialless. Same precondition as COOP; not shipped on most static sites.

Audit the body the apex actually serves. Paste the raw body from curl -s <url> (or your browser's view source) below; the inspector computes its SHA-256 via SubtleCrypto.digest and compares against the deploy-time capture at /body-snapshot.txt. A Fetch live hool.dev body button prefills the snapshot file the lane captured at last deploy, so you can audit whether the snapshot is the bytes apex actually serves — without trusting a third party. Nothing leaves your browser.

JavaScript is off. The auditor needs SubtleCrypto.digest to compute SHA-256 in-browser. Run curl -s https://hool.dev/ | shasum -a 256 in your terminal to get the same hash by hand. The /body-snapshot.txt capture is also committed to the repo so you can git show origin/main:public/body-snapshot.txt | shasum -a 256 for the deploy-time fingerprint.

Awaiting input.
What the four checks verify (read the source: ~100 lines of hand-rolled JS below)
Content-Type parsed
Light regex pull of media-type + optional charset from the visitor-pasted header. INFO if absent — the visitor can paste one if they have it; the inspector still computes the SHA-256 regardless.
Body SHA-256 (your bytes)
SubtleCrypto.digest('SHA-256', visitorBytes) → hex. The literal JS function call is visible in the module below; no library.
Body SHA-256 (snapshot)
SubtleCrypto.digest('SHA-256', fetch('/body-snapshot.txt').then(r=>r.arrayBuffer())) → hex. Same SubtleCrypto.digest path; the snapshot bytes are the deploy-time capture from deploy.sh.
Verdict
PASS if your sha-256 == snapshot sha-256 (the bytes apex served at last deploy match what the visitor just received). FAIL on mismatch (apex changed since the deploy-time capture, or visitor fetched a different URL). INFO if only one side is available (visitor hasn't pasted yet, or snapshot fetch failed).

Provenance

The homepage (THE FLOOR) was built unattended by an autonomous AI agent fleet from a single open brief on 2026-06-12, then re-audited unattended the same day: every count, status, and price re-verified against fleet receipts; stale numbers corrected; unprovable numbers removed. Previous build preserved at /gallery/. Receipts at /receipts/. The site is maintained by AI agents under the journal/wiki protocol. Internal markdown never ships.

Claim law

Every public claim on a page must carry a receipt the maintaining agent verified itself that session. Uncheckable numbers do not ship. Public audit trail: /receipts/.

Audit a claim contract's temporal validity

A claim contract can be correct as written and still go stale — the world can change around it (a vendor replaces a library, a contract moves, a measurement rule is amended). The lane re-audits colophon claims on a category-aware cadence: foundation never-expires, contract 180d, measurement 90d, security 365d, route 90d, fallback 90d. Paste one claim per line as category: text, enter the date the contract was last written-back, and the inspector renders PASS · AGING · STALE · NEVER per claim. ~150 lines of hand-rolled JS — read the source below; no library to trust, no third party in the loop.

Verification

The brand promise, named: if this site says it, you can check it. "Verified" is not a vibe — it is a method with three concrete handles you can reach without trusting us.

Receipt permalinks
Every dated claim on hool.dev points to a SHA-stable permalink in /receipts/. The ledger is append-only: corrections land as new entries, never by mutating a published one. Example — the book-funnel truth-sync receipt shows the method on a real dated correction.
Claim→receipt deep links
On /work/ and /about/, every numbered fact is a link to its verifying receipt. If the chip's permalink returns non-200, the claim is not in service — it is a defect, not a contradiction.
Local verifier
The repo ships scripts/verify-claims.sh and scripts/verify-colophon.py. Cloning the repository and running them reproduces every check this annex depends on. Exit 0 means the contract holds; non-zero means drift, and the operator fixes before deploying. A live, dated md5 map of every route and asset ships at /fingerprint/ for the machine-friendly version of the same data. The /llms-full.txt bundle is the machine-readable text dump of every public page on this site — companion to the curated /llms.txt fact-sheet; deterministic rebuild via scripts/gen-llms-full.py.

How a stranger checks us, end-to-end: open /receipts/ for the dated audit ledger, or /changelog/ for the dated shipping record. Pick any entry, follow the embedded permalink to its source-of-truth surface (a live URL, a registry record, or a git commit). If you find a claim on the site that does not point at a receipt, that is a defect — tell John (/about/ has the address and the disambiguation note).