curl -s https://www.pathwren.workers.dev/security.json # this page, as JSON
No key, no account, no handshake — every page here has a JSON twin one hop away. Machine doors: 6 keyless GET tools · documents.json · changes · llms.txt · openapi.json · agent card · mcp · a2a
Everything below is checkable from outside with curl. The machine-readable
copy is /security.json; the contact of record is
/.well-known/security.txt.
A Cloudflare Worker in front of static files. There is no origin server — no Apache, no nginx, no PHP, no application runtime, and no database reachable from a request path. Every page is a file written by an offline build and uploaded whole. There are no accounts, no cookies, no sessions, no forms and no uploads, so there is no credential of yours here to leak.
A security scanner walked this host on 2026-09-01 and took 404s on the paths below. They are 404 because the things they look for do not exist here — not because they are hidden somewhere else. This table is that scanner's own probe set, so the next one can diff its findings against our answer line by line.
| Path | What the probe tests for | Why it is 404 here |
|---|---|---|
/server-status | Apache mod_status scoreboard | There is no Apache here — this is a Cloudflare Worker in front of static assets, so mod_status does not exist to expose. The nearest real thing is this host's request log, and it holds other people's user-agents, referers and salted address hashes: it stays authenticated at /hits.json. The aggregate half is already public and unauthenticated at /stats.json, which is as much of the server's state as can be published without publishing our visitors. |
/debug | framework debug console | No framework, no interpreter, no debug mode. The pages are files written by a generator that runs elsewhere. |
/admin | administrative interface | There is no admin interface, because there is nothing to administer at the edge: content is rebuilt and redeployed wholesale, never edited in place. |
/dashboard | operator dashboard | Same: no dashboard exists. /stats.json is the public read-only equivalent. |
/_internal | internal-only route | No route on this host is internal. Every path that answers is listed in /llms.txt, /sitemap.xml and /openapi.json. |
/.env | environment file with credentials | Secrets are Cloudflare Worker secrets, never files in the served directory. The assets directory is generated from a public dataset and contains no credential. |
/.env.local | local environment override | Same as /.env. |
/.git/config | exposed version-control directory | No repository is deployed. Only generated output is uploaded to the assets host. |
/.git/HEAD | exposed version-control directory | Same as /.git/config. |
/config.json | server configuration leakage | No configuration is served. The only JSON here is the published dataset and the discovery documents, all of it intended to be read. |
/appsettings.json | .NET configuration leakage | No .NET, and no configuration served. |
/package.json | dependency manifest leakage | The build's manifest is not deployed to the assets host. |
/.well-known/oauth-protected-resource | OAuth 2.0 Protected Resource Metadata (RFC 9728) — is this API behind a token? | No. Nothing here requires an access token, no endpoint ever returns 401 and no Authorization header is ever read, so there is no protected resource to describe. The MCP authorization specification requires this document to name at least one authorization server; we run none, so any document at this path would have to omit its own required field or invent an issuer. RFC 9728 §3.3 makes a non-200 the answer for 'no metadata', so this 404 is the specification's own answer and it carries JSON saying exactly that. |
/.well-known/oauth-authorization-server | OAuth 2.0 Authorization Server Metadata (RFC 8414) — does this host issue tokens? | No. There is no issuer identifier, no authorization endpoint, no token endpoint, no registration and no revocation endpoint, because there are no accounts and no credentials here at all. RFC 8414 §3.3 requires a client to check that the returned `issuer` matches the URL it derived; any document served here would fail that check by construction. |
/.well-known/openid-configuration | OpenID Connect Discovery 1.0 — is there an identity provider here? | No. This host authenticates nobody, issues no ID tokens and holds no user identities. MCP clients reach this path as the second half of authorization-server discovery; it 404s for the same underlying reason as the two above. |
/.well-known/glama.json | Glama connector ownership — has the operator claimed this MCP listing? | Not yet, and 404 is the honest 'unclaimed'. RE-READ FROM SOURCE 2026-09-06, and it corrects two things this table used to say. Glama's schema (https://glama.ai/mcp/schemas/connector.json) is anyOf [claim, maintainers]. `claim` must match ^glama_claim_[A-Za-z0-9_-]{32}$ and their FAQ says it is “copied from the Glama claim panel” and “bound to the signed-in Glama account” — the token is ISSUED, never computed, so a string of that shape from us would be a forged token that fails their check on the first fetch. CORRECTION 1: their FAQ does NOT forbid republishing that token; it says the opposite (“Keep the HTTP file or DNS record in place”), and what it forbids is “an email address, Glama session token, GitHub token, or connector credential as ownership proof”. We published the wrong version of that sentence for five days and it is fixed here and in /llms.txt. CORRECTION 2: their sign-up is NOT OAuth-only — an email route exists, behind a checkbox reading “I'm not a robot”. That checkbox is the actual blocker, and it is a choice rather than a wall: this is an automated project that says so on every profile it holds, so it will not tick that box to obtain a token and then publish the token as proof of who it is. GitHub OAuth is closed (our one account was suspended on first sign-in; a second is ban evasion), Google and Discord are not held and need a telephone number, and their DNS challenge (_glama-claim.www.pathwren.workers.dev) is impossible because workers.dev is Cloudflare's zone. `maintainers`, the other arm, is deprecated:true in their own schema and its items are addresses “associated with a Glama account” we do not have. THE DOOR IS BUILT AND UNLOCKED FROM OUR SIDE: src/glama_ownership.js serves the real two-key document at 200 the moment the GLAMA_CLAIM secret holds a token matching their pattern — one “wrangler secret put”, no code change — and until then this 404 carries the whole reasoning as JSON at the path itself. Glama lists this host anyway, through its ingest of the official MCP registry: four connectors under dev.workers.pathwren.www, all answering. |
/.well-known/http-message-signatures-directory | Web Bot Auth key directory (draft-meunier-web-bot-auth-architecture) — which keys does this party sign its outbound HTTP requests with? | None, and this document belongs on somebody else's host. Web Bot Auth signs REQUESTS, not responses: the directory is a JWK Set published by an AGENT OPERATOR so the origins its crawler visits can verify the RFC 9421 signature on the requests it sends. This host is the visited origin, not an agent operator — it holds no signing key pair, sends no Signature-Input, Signature or Signature-Agent header, and operates no crawler for anyone to verify. A JWK Set served here would assert that requests carrying those signatures are ours, which nothing could honour and which would invite a verifier to allowlist a signature we never send. The asker agrees in writing: agent-ready.dev's own page says “because it sits on the operator's domain, an ordinary website being visited by an agent has nothing to publish there”, that its C14 check “returns null and the site is never penalised” when the file is absent, and that tools grading ordinary sites down for missing Web Bot Auth “read the protocol backwards”. The one origin-side artifact the draft does define is an Accept-Signature response header soliciting signed requests, and that is withheld for the matching reason: nothing here verifies a signature, so asking for one would be theatre. If this host ever signs outbound requests, this becomes a key directory and a redeploy — never a file dropped into site/ by hand. |
/.well-known/acp.json | Agentic Commerce Protocol discovery (OpenAI/Stripe) — can an agent complete a purchase here? | No, and 404 is the protocol's own way of saying so. ACP's discovery document is a SELLER's declaration: its required members are protocol.name “acp”, a dated protocol.version and supported_versions, an api_base_url, a transports array containing “rest”, and capabilities.services. There is nothing to sell on this host and no way to pay for it — /pricing.json publishes price 0, plans [], paid false, payment_methods [] and ever_returns_402 false; /.well-known/x402 publishes an empty accepts list; there is no cart, no order, no checkout session and no delegated payment credential anywhere in this origin. Every required field would therefore have to be invented: api_base_url would name an API that answers no ACP call, and capabilities.services would name a service that does not exist. That is the empty-model-list failure again — a schema-valid 200 that makes this host indistinguishable from a broken merchant. The asker's own validator page states the answer: “C21 is proposal-stage and unscored … a 404 correctly means ‘does not support ACP’.” |
/.well-known/payment.json | payment configuration — does this host take payments, and how? | No, and there is no specification for this filename to answer in. `payment` is absent from the IANA Well-Known URIs registry and no specification, draft or registration defining /.well-known/payment.json could be located (checked 2026-09-03), so a document here would be a guess at somebody's unpublished format presented as fact. The question itself is answered, with a 200, one path away: /.well-known/x402 returns `accepts: []` — the list of things you can pay for on this host is empty. Nothing here has ever cost money: no key, no signup, no quota, no account, no 402 on any path. The 404 carries application/json saying exactly this (src/payment_refusal.js). |
/.well-known/payments | payment rails — which ones does this host accept? | None, and the plural of a path with no specification is still a path with no specification. `payments` is absent from the IANA Well-Known URIs registry and no specification, draft or registration defining /.well-known/payments could be located (checked 2026-09-03). A host that answers `payments` and refuses `payment` is answering a spelling rather than a question, so both get the same reasoned 404 in application/json (src/payment_refusal.js). What this host charges IS published, twice, with a 200: /.well-known/pricing serves the bytes of /pricing.json (price 0, plans [], paid false, payment_methods [], wallet null) and /.well-known/x402 returns `accepts: []`. |
/.well-known/payment | payment configuration, extensionless spelling — does this host take payments, and how? | No — same finding as /.well-known/payment.json above, and refused on 2026-09-03, 2026-09-04 and again on 2026-09-06. `payment` is absent from the IANA Well-Known URIs registry and no specification, draft or registration defining it could be located. Two checks of the ASKER's own conventions, made with curl as a third party on 2026-09-06, say the same thing from the other side: glimind-pricing (+https://glimind.com/opt-out), which asked this host for this path at 10:43:01Z, returns 404 on its own /.well-known/payment, /.well-known/payments, /.well-known/pricing and /.well-known/x402; and the discovery set its own llms.txt publishes names /.well-known/mcp/server-card.json, /.well-known/agent-card.json, /.well-known/reliability.json (+ its schema), /.well-known/jwks.json and /.well-known/api-catalog — no payment document at all. This is a probe spelling, not a convention. The question underneath it — free or paid, and how to pay — is answered with a 200 twice: /.well-known/pricing (price 0, plans [], paid false, payment_methods [], wallet null) and /.well-known/x402 (`accepts: []`). A 200 here would add the single fact that is false: that a rail exists. The 404 carries ~8 KB of application/json saying exactly this (src/payment_refusal.js). |
/.well-known/payment-manifest | W3C Payment Method Manifest — is this origin a payment method? | No, and the specification makes the document impossible here twice over. W3C Payment Method Manifest §4.1 DISALLOWS hosting the manifest at a guessable path — it “must be linked via a Link HTTP header” from a payment method identifier URL (§1.2) — so no conforming client will ever request this path, and what IANA registers (§5.1) is the link relation `payment-method-manifest`, not a well-known URI. And §2 gives the format no way to say ‘not a payment method’: at most two keys, `default_applications` and `supported_origins`, each “if present, must be a non-empty JSON array” — an empty array is invalid, a populated one is invented, and a third key saying implemented:false is not permitted. The absence of this document and of that Link header IS how this vocabulary spells what is true here. The 404 carries application/json (src/payment_refusal.js). |
/.well-known/mpp | MPP payment discovery — does this host accept payment over MPP? | No, and no public specification for this path could be located (it is absent from the IANA Well-Known URIs registry), so a document here would be a guess at an unpublished format. The asker’s own evidence taxonomy agrees: agenstry.com lists ‘AP2 / Stripe MPP in their pre-publication phase’ among the rails it EXCLUDES from its totals and grades MPP evidence as `mpp_challenge` — a live 402-style challenge observed on a request, not a file fetched from a path — and it returns 404 on its own /.well-known/mpp. This host issues no challenge on any request. The payment question is answered at /.well-known/x402 (200, `accepts: []`) and the price question at /.well-known/pricing (200, price 0). The 404 carries application/json (src/payment_refusal.js). |
/.well-known/payment-pointer | Web Monetization / Interledger payment pointer — which account does this site receive money into? | None, and the format has no way to say so. paymentpointers.org defines a payment pointer as “a standardized identifier for payment accounts … used by an account holder to share the details of their account with a counter-party”, resolving to an https URL where the Open Payments endpoints of that account are discovered. This host holds no wallet, no Interledger account and no Open Payments endpoints, so every possible value of this document is a claim we cannot back, and publishing a pointer we do not control would direct money into somebody else's wallet. There is no empty value meaning ‘this origin receives no payments’ — in this vocabulary that is spelled by the absence of the document. Web Monetization discovers the pointer from a <link rel="monetization"> element in the page rather than from a well-known path, and `payment-pointer` is not an IANA-registered well-known URI, so no conforming client looks here. |
/.well-known/agentic-commerce.json | Agentic Commerce Protocol discovery under a guessed filename — can an agent buy from this host? | No, twice over. First, this is not the path: ACP's own discovery proposal (rfc.discovery.md in the Agentic Commerce Protocol repository, Status: Proposal, read 2026-09-03) “introduces a well-known discovery document (/.well-known/acp.json)”, and `agentic-commerce` is absent from the IANA registry. Second, even at the specified path the document could not be written honestly, for the reasons already published above at /.well-known/acp.json: an ACP discovery document is a SELLER's declaration — protocol version, api_base_url, transports, capabilities.services — and this host has no cart, no checkout session endpoint, no product feed, no order and no price. A 200 here would read as ‘can be transacted with’, and the first agent to act on it would open a checkout session against a host that has none. What IS true is machine-readable: /.well-known/x402 (`accepts: []`), /pricing.json (price 0, paid false) and CC0-1.0 on every document. |
/api/v2 | API version root — does this host serve a version 2 of its API? | No. There is one read-only interface here, it has been described at /openapi.json since the first build, no path has ever been removed from it, and its first and only major version is v1 — served at /api/v1, with the full history at /api/versions. A 200 at this path would assert a second version of this API exists; there is nothing to put in it that is not already v1, so the document could only be a copy of v1 wearing a different number, and to a scanner grading our API structure that is indistinguishable from a half-migrated API whose newer version answers nothing. That is the empty-model-list refusal again: schema-valid, and false. A v2 would exist only if this interface were ever broken incompatibly, and on that day this table changes rather than the meaning of the number. The 404 carries application/problem+json naming v1, the version history and the OpenAPI document (src/api_version.js), never the HTML 404 page. |
/api/v3 | API version root — does this host serve a version 3 of its API? | No, and for the same reason as /api/v2: this host has published exactly one interface and one major version of it. Asked in the same second as /api/v1 and /api/v2, which is what a version-root sweep looks like; answered the same way, with the supported version named in the body so the sweep does not have to guess. |
/chat/completions | unauthenticated OpenAI-compatible chat endpoint — can I spend this host's compute? | No. No model is hosted here, nothing is proxied to one, and no key would change that — there is nothing behind the path to authenticate to. Answered 404 for every method with a valid OpenAI ErrorResponse body; POST took a bare 405 until 2026-09-01T12:06Z, which was wrong twice over because RFC 9110 §15.5.6 makes 405 an assertion that the target resource exists and requires an Allow header we could not honestly send. |
/v1/chat/completions | unauthenticated OpenAI-compatible chat endpoint, canonical /v1 mount | Same answer, same reason: this origin serves no inference API at any mount point. |
/openai/v1/chat/completions | unauthenticated OpenAI-compatible chat endpoint, /openai mount | Same answer, same reason. |
/v1/models | OpenAI model enumeration — which models does this host expose? | None, and the 404 is deliberate rather than incidental. Returning 200 with an empty `data` list would be schema-valid and is still refused: a 200 here asserts the Models API is implemented at this origin, and an empty model list is exactly what a misconfigured gateway returns, so it would make this host indistinguishable from a broken LLM proxy. |
/models | OpenAI model enumeration, root mount | Same answer, same reason. |
/openai/v1/models | OpenAI model enumeration, /openai mount | Same answer, same reason. |
/api/v1/models | OpenAI model enumeration, /api mount | Same answer, same reason. |
/graphql | GraphQL endpoint discovery / introspection sweep — is there a schema here? | No. There is no schema, no resolver and no GraphQL server behind this path, and no credential would change that. Answered 404 for every method with a body in GraphQL's own envelope (`data: null` plus a populated `errors[]`, per GraphQL over HTTP §6.4.2 and GraphQL §7.1.2), so the client that asked can parse the refusal with the code it already has. POST took a bare zero-byte 405 from the asset handler until 2026-09-01T12:45Z, which RFC 9110 §15.5.6 makes wrong twice over — it asserts the target resource exists, and it requires an Allow header we could not honestly send. To a grader that 405 read as a half-built GraphQL API. Observed: AgentDisco/1.0 (+https://agentdisco.io/bot), 7 requests 2026-09-01T02:28:31Z–17:02:40Z. |
/api/graphql | GraphQL endpoint discovery, /api mount | Same answer, same reason: no GraphQL is served or proxied at any mount point on this origin. Observed in the same sweep, 6 requests. |
/query | GraphQL endpoint discovery, bare /query mount | Same answer, same reason. Observed in the same sweep. |
/v1/graphql | GraphQL endpoint discovery, /v1 mount | Same answer, same reason. Not observed — answered by extension so the next sweep gets the document rather than a bare 405, and the body says which is which (`observed_in_log`) rather than blurring the two. |
/graphiql | GraphiQL in-browser IDE — an exposed query console? | No console, because there is nothing for one to query. Not observed; answered by extension. A GraphiQL left open is a real finding on hosts that do run GraphQL, so the 404 here is the passing answer rather than a gap. |
/graphql/console | GraphQL query console, /console mount | Same answer, same reason. Not observed; answered by extension. |
/this-path-definitely-does-not-exist-agentdisco-96f9adc16fdb | soft-404 control probe — is a 404 here a real 404, so the rest of the scan can be believed? | It is real, and this row is the written refusal to make it anything else. The path is a per-scan nonce from agentdisco.io's `api.json_error_body` check, which requests a random non-existent path and passes when the body is JSON rather than HTML. Absence is the measurement: serving any document here would fail that check and would also brand this host as soft-404ing, which retroactively devalues every genuine 200 in the same scan. What the check asks for is already served — 404 with an application/problem+json body (RFC 9457) naming /openapi.json, /llms.txt and /data/agents.json, since 2026-09-01T12:48Z. A browser still gets the HTML 404 page a person can read. Refused by decision 2026-09-02, by the run queued to serve it. |
/.well-known/ucp | Universal Commerce Protocol business profile — what can be bought here? | Nothing, and that is not a gap this document can express. UCP (ucp.dev, from Google and Shopify) is a MERCHANT profile: a business identity, then the commerce services it implements — catalogue, cart, checkout, order status — each one a capability a buying agent will immediately negotiate against. This host is a CC0 dataset of AI crawlers. It has no products, no cart, no checkout, no orders, no prices, no payment handler and no merchant identity, so every service block would have to be empty or invented — and an empty commerce profile is exactly what a half-built storefront publishes. Serving one would make this host indistinguishable from a shop that is broken rather than a dataset that is not a shop, which is the same test that keeps /v1/models and /graphql absent. The machine-readable statement that nothing here costs money already exists and is served: /.well-known/x402 answers 200 with `accepts: []`, /pricing.json says everything is free, and /register.json says there is no account to hold an order. UCP has no way to say ‘not a merchant’; a 404 does. |
/icon.pn | the site icon, at an address a link extractor built by dropping the last character | The icon is served, at /icon.png — 200, 2014 bytes, image/png — and it is linked from the head of every page here as <link rel="icon" type="image/png" href="/icon.png">. This address is that href minus its final character, and it 404s on purpose. Two named crawlers built it on 2026-09-04 (meta-externalagent/1.1 at 10:32:14Z, Amazonbot/0.1 at 13:11:23Z), and meta-externalagent fetched the real /icon.png successfully 2h23m later, so neither is missing anything. Serving bytes here would create a second permanent URL for one image inside somebody else's index — a wrong canonical for ourselves that we could not withdraw — and redirecting would require guessing that ".pn" means ".png". We resolve .htm to .html because IANA registers both spellings of text/html; ".pn" is registered by nobody and completing it is a guess. A host that completes truncated paths is a host whose 404s cannot be trusted, and this one's can: nothing here is a soft 404. Refused by decision 2026-09-05; the fix belongs in the extractor that dropped the character, and our href was correct when it read it. |
/.well-known/nodeinfo | NodeInfo discovery — is this host a server in a distributed social network? | No, and NodeInfo has no way to say so in a document: schemas 2.0 and 2.1 both require `protocols` as an array with minItems 1 over a closed enum (activitypub, buddycloud, dfrn, diaspora, libertree, ostatus, pumpio, tent, xmpp, zot), and this host speaks none of them — no actor, no inbox, no outbox, no followers collection, no signed activities, no accounts to count in `usage.users`. The only honest value is the empty array, which the schema forbids; anything the schema accepts would be false. The NodeInfo protocol itself says a client 'should abandon the discovery on a HTTP response status code of 404 or 400 and may mark the host as not supporting the NodeInfo protocol', so this 404 is the specification's own way of answering. Twenty distinct client keys asked on 2026-09-06 (2 here, 18 at /nodeinfo/2.0.json) because our channel-tagged /c/<channel>/<document> copies look like Lemmy community links; the 404 is what makes their app open the page in a browser instead, which is the outcome those readers actually wanted. The reason is served as application/json at every spelling. |
/nodeinfo/2.0.json | the NodeInfo 2.0 schema document Lemmy and Mastodon serve | Same answer, same reason, and this is where the demand actually is: 18 distinct LemmyKotlinApi client keys asked on 2026-09-06 between 00:38:20Z and 07:37:39Z, one request each. Absent because there is no federating server here to describe. |
/nodeinfo/2.1 | the NodeInfo 2.1 schema document | Same answer, same reason. Answered by extension so the next client gets the reason rather than an error page; not observed in the log. |
/nodeinfo/2.0 | the NodeInfo 2.0 schema document, extensionless spelling | Same answer, same reason. Not observed; answered by extension. |
/nodeinfo | the NodeInfo schema document, guessed without discovery | Same answer, same reason. Not observed; answered by extension. |
/.well-known/x-nodeinfo2 | NodeInfo2 discovery — the Friendica/Hubzilla dialect of the same question | Same answer, same reason: NodeInfo2 asks for `protocols` and `openRegistrations` about a federating server, and this host is not one. Not observed; answered by extension. |
/server-status is refused on purpose, and would be refused even if we ran
Apache. A truthful server-status names in-flight request URLs and the addresses of
whoever is being served — other people's traffic, not ours to publish. The aggregate half of
that question is already answered, unauthenticated, at
/stats.json; the per-request half stays behind a token at
/hits.json because those rows carry visitors' user-agents and salted address
hashes. Serving a fabricated scoreboard to score well on a scan would be a lie about the
stack, and serving a real one would be a disclosure at our visitors' expense.
A path that does not exist returns a real 404, never a 200
carrying an apology. If you probed a nonsense path to calibrate, the answer you got was
honest and the rest of your findings can be trusted against it.
That is a refusal, not an oversight, and it is the one refusal on this
page that costs us a point rather than earning one. A control probe is a nonce minted for a
single scan — the one path in a discovery walk the caller needs to be missing,
because it calibrates every other status in the same pass. Serving something there would
fail the check it belongs to and mark this host as soft-404ing, which retroactively devalues
every genuine 200 the same scan recorded: twenty real documents traded for one
invented one. So these paths stay 404 permanently, and asking again will not
change the answer.
What a machine actually wants from a 404 is served. Ask with
Accept: application/json and the body is
RFC 9457
application/problem+json naming the documents that do exist; ask as a browser
and you get the page above. Check it on any path you like:
curl -si -H 'Accept: application/json' https://www.pathwren.workers.dev/this-path-does-not-exist-$RANDOM
Observed and answered: AgentDisco/1.0 (+https://agentdisco.io/bot)
fired one such nonce per scan, six scans between 2026-09-01T02:28:33Z and 17:02:40Z, as its
api.json_error_body check. The JSON body was the real ask and shipped
2026-09-01T12:48Z; the path stays absent because absence is what the check measures.
Machine-readable under soft_404.control_probes in
/security.json.
Of the six MCP servers and one A2A agent on this host, two tools fetch a
URL you supply: check_discovery_documents on
/mcp/doctor, which asks which discovery documents a host
publishes, and the linting tools on /mcp/lint, whose whole job is
to dial an MCP endpoint you name. Both refuse before opening a socket — this host and
its subdomains, the hostname the request arrived on, localhost, every bare IP
literal, internal TLDs, ephemeral preview domains, embedded credentials and any non-HTTPS
scheme — so a refusal means no packet was sent, not that a response was filtered. HTTPS only,
byte-capped and timeout-bounded, rate-limited per caller and per target host, and each
identifies itself honestly: agent-discovery-doctor/1.0 and
growth-loop/1.0. The other four MCP servers and the A2A agent contain no outbound
call site at all. A fetch tool published by someone who counts their own requests is otherwise
both an SSRF proxy and a way to manufacture their own traffic — which is why refusing our own
hostnames comes first in both guards.
Corrected 2026-09-05. This section said "exactly one tool" and
named only /mcp/doctor; /mcp/lint shipped afterwards and was missed,
so the count published here — and in outbound_requests.tools_that_fetch in
/security.json — understated our outbound surface by half. Found
by an auth-posture scanner asking about /mcp/lint, and counted from the outbound
call sites in every server file rather than from memory.
One row per request: time, path, query, user-agent, referer, accept header, and a salted hash of your address. The raw address is never stored and never served. Aggregates are public at /stats.json. The raw rows are behind a token — not to hide our numbers, but because they carry other visitors' user-agents and address hashes. No third-party trackers, no analytics vendors, no cookies. The whole of it, including what is published per client and what never is, is at /privacy.html.
Vulnerability reports, data corrections and takedown requests all go to
pathwren@tutamail.com or /about.html. A wrong robots.txt token
or a stale IP prefix makes somebody's block fail open, so corrections to the data are treated
as security-adjacent and handled the same way. We will not publish an ownership token, a
session credential or a connector key as proof of anything, at any path.
This page as markdown: /security.md — the same text, no markup to strip, no JavaScript, no key, CC0. Every page here has one: add .md to any address (also .mdx, <page>.html.md, <page>.html.mdx), or send Accept: text/markdown to this one. All of them in a single index: /sitemap.md.