Files
zeekay 0910c3cc68 agents: a start page for AI agents, and the site describes itself to them
/agents is where an agent lands: get a key (device flow or HTTP sign-up),
the free tier as /v1/billing/plans states it, a first call, the MCP server
for Claude Code, Codex, Cursor and Zed, Kai and its harness, a campaign
draft, and how an owner pays and bounds spend. The Agents SDK page moves
to /agents/sdk.

The prompt an agent pastes is lib/agents.ts, drawn on /agents and written
into llms.txt, which now keeps every hand-written section. robots.txt names
the AI crawlers; JSON-LD carries the positioning, 2014, the founders as
/about names them, and drops a SearchAction /search never answered;
/.well-known/api-catalog points at the OpenAPI document. /about gains a
track-record band, each line beside its source.

Claude-Session: https://claude.ai/code/session_017vrVus6PPBgP5YRzKV1iqW
2026-10-26 11:45:15 -07:00

75 lines
2.9 KiB
JavaScript

/**
* Put /.well-known into the export, and refuse to finish the build without it.
*
* `public/.well-known/security.txt` is committed, the deploy was current, and
* the URL still answered with the app shell — because this site is
* `output: 'export'` and a static export plus a SPA fallback answers EVERY path
* with index.html. So a missing file does not 404. It returns 200, with HTML,
* and looks fine to anything that checks a status code.
*
* That is the whole reason this script exists rather than a copy step: the
* failure it guards against is invisible from the outside. RFC 9116 fixes the
* address at /.well-known/security.txt, so if the file is not there the file
* does not exist, no matter what the server returns.
*
* Loud, never partial, like noindex.mjs beside it: it copies, then reads back
* what it wrote, and exits non-zero if the bytes are not there. A build that
* quietly ships without a disclosure address is worse than a build that stops.
*/
import { readdirSync, mkdirSync, copyFileSync, readFileSync, existsSync } from "node:fs";
import { join } from "node:path";
const SRC = "public/.well-known";
const DST = "out/.well-known";
if (!existsSync(SRC)) {
console.error(`[well-known] ${SRC} does not exist — nothing to publish.`);
process.exit(1);
}
mkdirSync(DST, { recursive: true });
const names = readdirSync(SRC).filter((n) => !n.startsWith("."));
if (names.length === 0) {
console.error(`[well-known] ${SRC} is empty.`);
process.exit(1);
}
for (const name of names) copyFileSync(join(SRC, name), join(DST, name));
// Read back rather than trust the copy. The point is to prove the bytes are at
// the address, which is the one thing nobody could confirm from outside.
let bad = 0;
for (const name of names) {
const out = join(DST, name);
if (!existsSync(out)) {
console.error(`[well-known] ${out} missing after copy`);
bad++;
continue;
}
const body = readFileSync(out, "utf8");
if (name === "security.txt" && !/^\s*(#|Contact:)/m.test(body)) {
console.error(`[well-known] ${out} does not look like RFC 9116 — no Contact: field`);
bad++;
}
// RFC 9727's API catalog is a linkset document; anything else is not one.
if (name === "api-catalog") {
let linkset = null;
try {
linkset = JSON.parse(body).linkset;
} catch {}
if (!Array.isArray(linkset) || !linkset.length) {
console.error(`[well-known] ${out} is not an RFC 9727 linkset ({"linkset": [...]})`);
bad++;
}
}
// Apple Pay's domain proof is hex, and Square checks it byte for byte: anything else is not it.
if (name === "apple-developer-merchantid-domain-association" && !/^[0-9A-Fa-f]+\s*$/.test(body)) {
console.error(`[well-known] ${out} is not the hex domain association Apple Pay asks for`);
bad++;
}
}
if (bad) process.exit(1);
console.log(`[well-known] published ${names.length} file(s): ${names.join(", ")}`);