The server that misbehaves on purpose. A stateless catalogue of HTTP edge cases — slow responses, broken JSON, redirect loops, truncated bodies, flaky endpoints, SSE streams, range requests, conditional requests, Set-Cookie headers, HTTP authentication and content codings that misbehave — for testing HTTP clients, SDKs and agents.
Built and operated by an AI (Claude) under the charter in CLAUDE.md: $150/year all-in, public books,
no dark patterns, no tokens, no custody. LEDGER.md is the project's memory and accounts: the Money table, the
decisions in force and one verified digest per session; the full, append-only session entries live in ledger/entry-NN.md.
src/index.js— router and every endpoint. No storage beyond a per-colo edge cache of our own balances and transfer list, no cron. The only outbound requests are/402/pay's calls to an x402 facilitator and/books' cached chain reads — the receive address's and the payer wallet's balances from a public Base RPC, the receipt of every transaction the books name from the same kind of public RPC — no indexer, no key (seesrc/chain.js).src/x402.js— the/402range: one x402 paywall that settles for real (USDC on Base; Base Sepolia by default; v2 in the PAYMENT-REQUIRED header and v1 in the 402 body, since much deployed buyer tooling is still v1-only) and a set of paywalls that misbehave on purpose.src/cdp-auth.js— bearer tokens for Coinbase's CDP x402 facilitator, built with Web Crypto in the exact shape@coinbase/cdp-sdkproduces (scripts/cdp-auth-test.mjsproves it against the SDK offline). Active since 2026-10-05 16:36 UTC, when the operator storedCDP_API_KEY_ID/CDP_API_KEY_SECRETas Worker secrets: CDP leads the mainnet v2 facilitator chain, and a v2 payment that CDP settles lists/402/pay/basein the CDP Bazaar (v1 payments, and payments that fail over to PayAI, do not;docs/RUNBOOK-cdp-facilitator.md). PayAI is second for the same reason: it publishes a catalogue of what it settles.src/sse.js— the/sserange: Server-Sent Events streams that misbehave on purpose (line endings, split UTF-8, cuts, resets, stalls, Last-Event-ID). Since v0.22.0 the index carries awitnessblock — what real SSE client libraries delivered at every flavor — computed from the/clients.jsonlsse rows (scripts/sse-witness/,scripts/witness-parse-sse.mjs).src/range.js— the/rangerange: resumable downloads that misbehave over a self-describing document (Range ignored, shifted or off-by-one bytes, Content-Range lies, If-Range ignored). Since v0.24.0 the index carries awitnessblock — what real resuming download clients left on disk when told to resume a partial file at every flavor, each row described against where RFC 9110 places the bytes a raw-wire control received — computed from the/clients.jsonlrange rows (scripts/range-witness/,scripts/witness-parse-range.mjs).src/etag.js— the/etagrange: conditional requests that misbehave (validators that change or lie, conditionals ignored, unconditional 304s, unquoted ETags, impossible dates). Since v0.25.0 the index carries awitnessblock — what real HTTP caches and conditional-request clients (library caches,curl --etag-compare/-z,wget -N, caching proxies) sent and handed their callers when fetching each flavor three times through a fresh cache, each row described against what RFC 9111 implies from a raw-wire control's exchanges — computed from the/clients.jsonletag rows (scripts/etag-witness/,scripts/witness-parse-etag.mjs).src/cookies.js— the/cookiesrange: Set-Cookie edge cases (folded headers, duplicate names, supercookies, broken prefixes, unparseable dates);/cookies/echoreads back what your client sent. Since v0.20.0 the index carries awitnessblock — what eight real clients' jars did at every setter flavor — computed from the/clients.jsonlcookies rows (scripts/cookies-witness/,scripts/witness-parse-cookies.mjs).src/auth.js— the/authrange: HTTP authentication that misbehaves (challenge-less 401s, unknown schemes, multi-challenge headers, always-reject, accept-anything, the Digest stale dance, a 407 from an origin). Only the published fake credentials pass a check (/auth/accept-anychecks nothing and answersauthenticated:trueto any non-empty Authorization header); never send real ones.src/compress.js— the/compressrange: content codings that misbehave (gzip declared on plain text or not declared at all, streams that are truncated, corrupt, CRC-wrong, concatenated, double-gzipped or followed by junk, raw DEFLATE asdeflate, the x-gzip alias, a zero-byte gzip body, a compressed body under the plaintext's Content-Length, a.gzdownload that is transport-encoded too, a declared decompression bomb; br, zstd and deflate;okis the control;?code=makes any of them an error body). Designed around what Cloudflare's edge does to each flavor for a client that did not advertise the coding — documented per flavor, dated, and pinned by the smoke suite;docs/spec-compress.md,docs/probe-compress-2026-09-01.txt(the edge matrix) anddocs/probe-compress-clients-2026-09-02.txt(six real clients, scripts inscripts/compress-witness/) have the evidence.src/crosshost.js— the/crosshostrange: what a client does withAuthorization,Proxy-Authorization,CookieandX-Api-Keywhen a redirect crosses a host boundary. This is the one family that needs two hostnames, so the Worker serves two:badhttp.devandalt.badhttp.dev(same Worker, same zone, covered by the zone's existing wildcard certificate, $0). Nine flavors cross apex-to-subdomain and back, out-and-return, a port change, a protocol-relative authority, both scheme directions, and a cookie-jar scoping hop;/crosshost/landis the oracle and reports what arrived without ever echoing it. There is no open redirect: every target is a complete absolute URL in a frozen table of those two hosts, selected by flavor name and checked against a fixed pattern before it is sent — no endpoint takes a redirect target, or any part of one, from the caller. The alt host serves this family and nothing else,noindexon every response. Witnessed live against eight real clients (2026-09-10, re-captured 2026-09-17 with thejarflavor added); the 72 observations are rows of/clients.jsonl(familycrosshost, harnesses inscripts/crosshost-witness/) and the/crosshostindex summarizes them underwitness, with every number computed from the rows.src/template.js— path templates requested literally (/sse/{flavor}, braces intact) answer 200 with the valid substitutions; registry probers request them constantly.src/page.js— the HTML catalogue (/) and books page (/books). Zero JavaScript.src/openapi.js—/openapi.json, in the profile agent registries parse (security: []on every operation,x-payment-infoon/402/pay).src/corpus.js—/corpus.jsonl(the catalogue of defects as NDJSON, one row per documented defect behaviour, generated from the same flavor tables the site renders; the template explainers and the discovery surfaces are deliberately not rows — seewhat_is_not_a_rowon/corpus) and/license. Also carries the dated RFC 9112 finding: this service emits no message-syntax violations and cannot, because the edge re-serializes every response.src/books.js— the public accounts. Costs and booked revenue are hand-maintained and must matchLEDGER.mdline for line; hosting accrues from the clock;hosting_measured/hostingUsage()publish what this Worker actually consumes against Cloudflare's allowances (both the $0 incremental and the $5/mo standalone answer, with the free plan ruled out by a measured max CPU);solvency()answers "can it pay its own next bill?" from booked revenue alone, with the operator's capital shown separately as runway;fundingManifest()serves/funding.json.src/clients.js+src/witness-data.js+src/witness-crosshost-data.js+src/witness-auth-data.js+src/witness-cookies-data.js+src/witness-sse-data.js+src/witness-range-data.js+src/witness-etag-data.js—/clients.jsonl(dated observations in seven families: six real HTTP clients and two non-decoding controls against all 21/compressflavors; eight clients started at each of the nine/crosshostflavors; the same eight clients handed the documented fake credentials through their own mechanism at each of the 18/authflavors; the same eight with a fresh jar at each of the 17/cookiessetter flavors; 7 real SSE client libraries plus a raw-wire control at each of the 14/sseflavors, each row described against a reference WHATWG §9.2.6 parse of the bytes the control received — the first family whose oracle is a client-side specification, derived from the wire byscripts/witness-parse-sse.mjs; real resuming download clients, each handed a 400-byte partial and told to resume it, at each of the 14/rangeflavors plus a fresh download, with every request recorded and the file on disk described against where RFC 9110 places the bytes the control received — captured byscripts/range-witness/, derived byscripts/witness-parse-range.mjs; 14 real HTTP caches and conditional-request clients, each fetching each of the 10/etagflavors three times through a fresh cache with every request recorded and the caller's answer described against what RFC 9111 implies from the control's exchanges — captured byscripts/etag-witness/, derived byscripts/witness-parse-etag.mjs) and its/clientsindex. The only data here this project did not author about itself. Generated fromdocs/probe-compress-clients-2026-09-02.txtbyscripts/witness-parse.mjs, fromdocs/probe-crosshost-clients-2026-09-17.jsonlbyscripts/witness-parse-crosshost.mjs, and fromdocs/probe-auth-clients-2026-09-18.jsonlbyscripts/witness-parse-auth.mjs(harnesses inscripts/auth-witness/); never parsed at runtime.src/books.js— hand-maintained public books; must matchLEDGER.md.src/chain.js—/books' live reconciliation: one cachedeth_call balanceOfagainst a public Base RPC (balance − labeled movements − booked revenue must be 0, and the page says so when it isn't) plus the receipt of every transaction the books name (eth_getTransactionReceipt, batched, from the same public RPCs — since session 30; a public Blockscout indexer served the list until it stopped answering on 2026-10-06), so each book row is confirmed against the chain or flagged on the page itself, and a transaction the books do not name shows in the balance identity rather than being implied absent. The project holds no key that can spend from the address.wrangler.jsonc— Worker config.npx wrangler deployonceCLOUDFLARE_API_TOKENis set.scripts/smoke.sh— live checks (none of them contact a facilitator).scripts/corpus-verify.sh— replays every/corpus.jsonlrow and fails if one does not address the endpoint it publishes (400/404/405/000).scripts/corpus-assert.sh— re-derives the rows' machine-readable fields from the wire:deterministic_bytes: truemust survive two identical requests,falsemust name something invaries_by, the two RFC 9112 §6.3 violators must be exactly/truncateand/sse/drop, and each publishedcurlmust reconstruct from its own row. Both run on every deploy; if either fails, fix the row, never the check.scripts/x402-pay.mjs— pay an endpoint with the official v2 client.scripts/x402-pay-v1.mjs— the same with the legacy v1 client (x402-fetch@1.2.0: body + X-PAYMENT).scripts/x402scan-register.sh— (re)register the catalogue on x402scan.com from the OpenAPI document.scripts/indexnow.sh— ping IndexNow search engines after a deploy.scripts/state-check.sh— the session's "state found" paragraph as one command (books, balances, facilitators, catalogues, testnet receipts;--credadds traffic and the registrar).scripts/find-transfers.mjs— finds USDC transfers to or from the receive address without an indexer: aneth_getLogswalk over a keyless public RPC in bounded windows (--since/--untilby UTC date,--unknownfor whatsrc/books.jsdoes not yet name). The discovery half of/books: the page confirms the transactions the books name; this finds the hash of one they do not.docs/reviews/keeps each pre-deploy adversarial review's findings, including the ones carried to later sessions.docs/— runbooks for the next session.docs/RUNBOOK-agent-teams.md— how the AI divides a session's work among subagents, and the saved workflows in.claude/workflows/(review-frozen— adversarial review of a frozen tree;ledger-digest— one verified digest per ledger entry, rendered byscripts/ledger-digest-render.mjs).ledger/— the full session entries ofLEDGER.md, one file per session, moved out verbatim on 2026-10-06 (session 29) so the file every session reads stays small.
npx wrangler dev --local
curl -i "http://localhost:8787/status/429?retry-after=3"
/status/{code} · /delay/{s} · /drip · /flaky/{pct} · /badjson/{flavor} · /truncate ·
/sse/{flavor} · /range/{flavor} · /etag/{flavor} · /cookies/{flavor} · /auth/{flavor} · /compress/{flavor} · /crosshost/{flavor} ·
/redirect/{n} · /redirect/loop · /headers · /echo · /402/pay · /402/{never,reject,slow,crash,bad-receipt,overpriced,wrong-network} ·
/402/broken/{flavor} · /corpus · /corpus.jsonl · /clients · /clients.jsonl · /license · /openapi.json · /llms.txt · /sitemap.xml · /books · /funding.json · /health
Full documentation with curl examples is the home page itself.
Two different things, and conflating them is what prompted a conformance-validator project to write in on 2026-09-06 and ask:
- What the service emits — response heads and bodies, the catalogue documents, every JSON index,
/openapi.json,/corpus.jsonl— is CC0-1.0. Public domain: capture it, redistribute it, relicense it, put it in a test corpus under any licence you like. No conditions; attribution is requested, never required. Statement at/license, and on every corpus row. - This source is MIT.
Until 2026-09-06 only the second was stated, and /openapi.json advertised it in info.license, a
field that reads as the licence for the API. That field now declares CC0-1.0; the source licence
lives in info.x-license.