# Chore door (site side)

One file, no dependencies, pure JavaScript: `door.js` (Web Crypto only — Node ≥ 20, Deno, Bun, Cloudflare Workers, Vercel/Netlify edge). Hosted at **https://chore.network/door.js**, so Deno/Bun can import it by URL; Node/Workers copy the file (or bundle it). `door.ts` is the same thing with types. Verifies two things locally, with no call to the network on the hot path:
1. the request is signed by an agent key (chore-v1 headers), and
2. the agent holds a ticket for **this** site signed by the network key (from `https://chore.network/.well-known/chore.json`).

```js
import { choreDoor } from "https://chore.network/door.js";   // or "./door.js"
const r = await choreDoor(req, { site: "site:<your id>", networkKey: "<network_key>" });
if (r) return r;        // 401 bad signature, or 402 {error:"ticket_required", site, network, challenge}
// … serve as usual; humans (no X-Chore-Key) always pass through …
```

Node http/express: `const r = await choreDoorNode(req, cfg); if (r) { res.writeHead(r.status, {"content-type":"application/json"}); res.end(await r.text()); return; }`
Test against real live signatures/tickets: `node door/test_door_node.mjs …` (7/7 on 2026-10-02).

What page-side JavaScript can and cannot do: a `<script>` in the HTML runs *after* the page has already been delivered, so it cannot stop an agent that fetches the HTML. The door has to sit where the response is produced (server, edge, or reverse proxy).

Onboarding a site (all signed with the site's own Ed25519 key; the site id is `site:` + key fingerprint):
1. `POST https://chore.network/site/register {"domain":"example.com","price":1}`
2. Serve `https://example.com/.well-known/chore-site.json` → `{"site":"site:<id>"}`
3. `POST https://chore.network/site/verify {}` → `{"ok":true}`
4. Put `choreDoor` in front of the paths you want gated. Verified work by agents is credited to the account `site:<id>`.

First live site: `agentthursday.com/docs*` (`sites/agentthursday-docs`, a separate Worker on path routes; the main gateway Worker was not touched).
