fromclaudetoprod.dev
menu

Living Checklist

This page was the site's homework, shown rather than described. The job was meant to visit the deployed site — not the source, not a local build — and record what it found. The tables below are that record, rendered. Nothing on this page is typed by hand. The job was never armed: every run on record was triggered by hand (2026-09-06 and 2026-10-06), and nothing runs now. If the job has never run, the page says so rather than showing you a green bar.

The rows marked na are the most useful thing here. They are checks the job deliberately did not run, each shown with the reason it did not. A tool that reports "passed" for a check it never performed is worse than one that reports nothing at all, so this one refused to.

Part of the origin story: how this site started →
nightly-verification · pipeline · run 2026-10-06T14:45:39.670Z-37481586926PASSED
  1. 1content / output validationmarkup, leaked secrets, dead links, foreign scriptsok
  2. 2dependency & secrets scanlockfile vulns, committed env filesok
  3. 3automated pen test passZAP baseline, exposed routes, headers, TLSok
  4. 4decisionerrored > failed > passed
  5. 5rollbackrestore tree to last known-good, prove it, then alert

The latest run, in full

latest run · 2026-10-06 14:45 UTC · commit 6152885PASSED
stagecheckresultdetail
contentroute-statuspassed8 declared routes returned 200
contenthtml-validpassedevery declared route parses as valid HTML5
contentdead-linkspassed8 internal links resolve
contentforeign-scriptspassedevery script is same-origin
contentinjected-scriptsnano content path takes input
contentcontent-secretspassedno secrets in commits since 2d35482
dependenciesnpm-auditpassedproduction: 0 critical, 0 high, 0 moderate, 0 low; dev-only: 5 high/critical, not gating@next/eslint-plugin-next (high, dev-only), braces (high, dev-only), eslint-config-next (high, dev-only), fast-glob (high, dev-only), micromatch (high, dev-only)
dependenciestracked-envpassedno env files tracked
dependenciesnew-dependenciespassedno new dependencies
pentestzap-baselinepassed0 high, 2 mediumMEDIUM Content Security Policy (CSP) Header Not Set (10038-1) at https://fromclaudetoprod.dev, MEDIUM Cross-Domain Misconfiguration (10098) at https://fromclaudetoprod.dev
pentestundeclared-routespassed8 reachable paths, all declared
pentestprobe-404passed9 probe paths all non-200
pentestsecurity-headerspassedevery declared route sends the required headers
pentesttls-certpassedcertificate valid, expires in 59 days
pentestauth-bypassnano protected routes
pentestinjectionnano forms or query handling
pentestidornano resources addressed by id
pentestrate-limitnano endpoints to limit

Stage 1 — content and output

What it checked. Every declared route had to return 200. Every page had to parse as valid HTML5. Every internal link had to resolve to a route that exists. Every script had to be same-origin — a third-party script failed this outright, because the contract forbade them. And a scanner read the repository's commit history for anything shaped like a committed key.

What it could not check. Whether the words are true. A page can return 200, validate cleanly, link correctly, and still say something false. That check is a person reading, and it is the one thing this site never claimed to automate.

Stage 2 — dependencies and secrets

What it checked. The lockfile against the published advisory database, where anything rated high or critical in code that ships failed the run. Findings in development-only tools were recorded on the run, not hidden, but they did not fail it: that code never reaches a visitor, and rolling back cannot fix an advisory nobody has patched. That no environment file was tracked in git. And which dependencies were added since the last good run — recorded rather than judged, so a new package could not arrive unnoticed even when it is harmless.

What it could not check. Whether a dependency carrying no reported advisory is safe. "No known vulnerabilities" describes what has been published, not what exists. It is the weakest claim on this page, and it is stated weakly on purpose.

Stage 3 — automated pen test

What it checked. A baseline scanner crawled the running site: high-severity findings failed the run, medium findings were recorded for a person to judge, low and informational ones were ignored. Nothing reachable that the route table did not declare. Probe paths for common admin and config files could not return 200. Four security headers on every route, plus protection against being framed. A TLS certificate with more than fourteen days left.

What it could not check, and why rows say na. Four of its checks — auth bypass, injection, IDOR, rate limiting — needed something to attack: a login, a form, an endpoint that takes input. This site had none, so each was recorded as not applicable with its own reason. A fifth, injected scripts, sat in stage 1 for the same reason. Reporting them as passed would have been a lie. Hiding them would have been a worse one.

The tripwire. If a form or input element had ever appeared on this site, those checks would have stopped reading na and started reading input surface detected; check not implemented — and every run would have failed until someone wrote them. The not-applicable state was meant to last exactly as long as the reason for it was true.

Run history

Two words in this table mean different things. A failed run finished its checks and something was wrong. If a last-known-good commit existed and a person's commit came after it, the job was designed to restore the tree to that commit, prove the restored tree matched before it committed anything, and push.

An errored run could not finish its checks — a tool crashed, the network went out — and it never rolled back. A run that does not know what is wrong has not earned the right to revert production.

The oldest run listed here is an errored one, kept deliberately. The scanner could not write to its own working directory, so the job recorded the crash instead of guessing, and reverted nothing.

runwhenresultwhat happened
374815869262026-10-06 14:45 UTCpassed—
374107679092026-10-06 03:49 UTCfailedfailed: npm-auditrolled back to 2d35482
340668149042026-09-06 23:25 UTCpassed—
340567664612026-09-06 20:03 UTCpassed—
340252345902026-09-06 09:39 UTCpassed—
340248390772026-09-06 09:30 UTCerrorederror: zap-baseline crashed: zap produced no report (exit 0): complete 372beebcd1ba: Pull complete ef80d0c5902f: Pull complete 1a1e22703782: Pull complete 832a68ab77b4: Pull complete 8c78b421bef3: Pull complete a59279b59ae8: Pull complete 5c554884f9ef: Pull complete bda18bc6327a: Pull complete Digest: sha256:781a2bdaea47324e7bab583e2263f21d257b0aee61ed51521a5be45f5f5081ef Status: Downloaded newer image for ghcr.io/zaproxy/zaproxy:stable 2026-09-06 09:31:49,855 Unable to copy yaml file to /zap/wrk/zap.yaml [Errno 13] Permission denied: '/zap/wrk/zap.yaml'

Beyond this site

Everything above is the small case. One static site, no database, no login, nothing to attack — checked by a job that was meant to run nightly and was only ever run by hand. It was a real check and it proves very little, because there was very little here to get wrong. The five not-applicable rows say so out loud.

The question worth answering is the one you actually have if you build this way: how do you know the things you run are still safe? Not the brochure site. The app with a login, a database, and other people's money in it.

One place that watches all of them. Not a tool per app, not a dashboard you remember to open on a Tuesday. A single process that checks every system you operate, on a schedule, and tells you only when something changed. That is the design; this site never armed it. The value is not any individual check — it is that the checking happens whether or not you are thinking about it, which is the entire difference between a practice and an intention.

Check the boundary, not the uptime. Almost every monitor asks whether a page returned 200. For a page that requires a login, 200 is not health — it is the failure. The check that matters is the one nobody runs: request every protected route with no cookie, no token, nothing at all, and confirm it refuses. Generated code fails this more than any other way, because authorization is the thing an AI adds when you ask and omits when you don't. It is column two of the checklist, and it is worth more than everything else on this page combined.

Read-only, enforced in code. These are live systems with real users and real email flows. A scanner that submits forms will create records and send mail to actual people. So the monitor may issue GET and HEAD requests and nothing else — a thrown error in the request layer with a test asserting it, not a line in a comment. Anything stricter is theatre; anything looser eventually gets used.

Decommissioning is not deletion. The first thing this caught on my own systems was a scheduled job's endpoint answering anonymous requests with a database client that bypassed every access rule I had. It belonged to a feature I shut down months earlier. I had turned off its schedule and taken down its interface, and its routes stayed deployed and reachable the entire time, holding the credentials they always had — and I had stopped watching them precisely because I believed they were gone. If you have ever sunset a feature and left the code deployed, that surface is still answering. Go and look.

Merged is not deployed. I deleted the whole dead surface, opened a pull request, and merged it — and the endpoint kept answering. The merge had landed on a development branch, and that application's production serves a different one. The check stayed in the monitor until a live request came back with a 404, because that is the only evidence that means anything. A green build, an approved review, and a merged pull request can all be true at once while the hole is still open.

None of this makes a system secure, and a monitor that says otherwise is lying to you. A monitor like this tells you what changed since last night. That is a smaller claim than the tools in this space usually make, and it is the one that survives being checked.