# Curbi v28 — developer layer and hardened footer

Every example on the API and MCP pages is produced by running the real checker, Check API handler and public MCP handler at build time, and every snippet is executed against the exported Worker in the test suite. New: a live JSON-RPC console on /mcp/, MCP Chaos, Six promises, this changelog and a rebuilt connectors page. One data-driven footer is on every page, and the build fails on any broken link.

## What changed
- **/api/**: quickstart tabs (curl, JavaScript, Python stdlib, MCP JSON-RPC, Vercel AI SDK); live tester; five recipes showing the checker's actual responses; response reference generated from the OpenAPI contract; the handler's real error statuses and messages; endpoint table.
- **/mcp/**: a live console (initialize → tools/list → tools/call against /api/mcp, every message shown); connect tabs (official TypeScript SDK, raw curl, mcpServers config); a tool reference generated from tools/list; a recorded session transcript; client compatibility (tested vs not verified); boundaries.
- **/chaos/**: the 6-entry failure catalog × 3 integrations matrix from revenue-engine/mcp-chaos, plus a deterministic source zip (no node_modules).
- **/promises/**: rendered from docs/claims/promises.json, with the security and disclosure section.
- **/changelog/**: rendered from RELEASE files.
- **/connectors/**: Vercel AI SDK, LangChain, LiveKit Agents and stream interceptor snippets, with pinned versions read from the connectors package.json. The stream snippet now flushes the final sentence with `end()`.
- **Footer**: v28/footer.json (8 columns, status, honesty line) is rendered identically on all 41 pages and published to agents as /site-index.json.
- **CSS**: v28 rules are appended to each page's own stylesheet, so each page still loads exactly one content-addressed stylesheet (the review delivery-v17 invariant). Tables scroll inside their own container on phones.

## Build
`python3 v17/build.py && node v28/build.mjs`

v28 post-processes public/ and is a fixed point: a second run changes no byte. It exits 1 if the link audit finds any missing page, file or anchor.

## Evidence
- **`node --test v28/site.test.mjs`**: 14 tests. They need `npm ci --prefix v27` (MCP SDK) and `npm ci --prefix ../connectors` (ai, @langchain/core, @livekit/agents).
  - Footer: one identical footer on every page.
  - Stylesheets: one stylesheet per page, with fingerprints that match.
  - Links: zero missing.
  - Snippets: curl, JavaScript, Python and MCP snippets run against the exported Worker on a real socket; the TypeScript SDK snippet runs end to end; the AI SDK, LangChain, LiveKit and stream snippets run on their pinned packages.
  - Recorded data: documented recipes, errors and the MCP transcript equal the Worker's output.
  - Safety: console samples succeed and no tool can write; CSP routes are strict with no inline script; the claims gate scan is clean.
  - Registries and discovery: the registries render as recorded and discovery resolves.
  - Build: the build is a fixed point.
- **Mutation check**: 12 of 12 seeded page mutations were caught. Among them:
  - removing the stream flush;
  - deleting a footer link;
  - altering a documented response;
  - injecting an inline script;
  - changing transcript, console or promise status data.
- **`node v28/browser-check.mjs <dir>`** (Chromium, production _headers CSP applied): 11 pages at 1440px and 390px.
  - Zero console errors or CSP violations, and zero horizontal overflow.
  - Every tab switches.
  - The MCP console negotiates 2025-06-18, lists the tools and calls policy_check (pass=false) and search.
  - The API live tester returns pass=false.
- **Regression check**: the full site suite shows no change against the v27 baseline.

## Not changed
No new endpoints, no auth changes, no write tools, no hosted-client claims and no npm publishing. Hosted MCP clients (Claude, ChatGPT, Cursor) remain "not yet verified".

