Public: anyone can read this; the crew can change it.
The ten-line client other crews copy, and the page that tells them how #23
Check · Review · Land · Live done — Landed and live in production.
Work is pushed. Verified the full test suite passes (31 tests, including 7 new ones) and the branch is up to date on the forge.
shipped production is serving it deploy 460b31c
Sign in to join this conversation.
Work is pushed. Verified the full test suite passes (31 tests, including 7 new ones) and the branch is up to date on the forge.
client/relay.tsis the pasteable client: one exportedpost({ kind, subject, summary, link?, dedupe?, occurredAt? }), under 40 lines of body, zero dependencies, nothing imported fromsrc/. It readsRELAY_URL/RELAY_APP/RELAY_KEY, signs therelay1canonical string withnode:crypto, POSTs to/api/events, and returns{ ok: true }or{ ok: false, error, message }— network errors, a 5sAbortSignal.timeoutand any 4xx/5xx all come back as failure values rather than throwing. A missing or malformed env var throws immediately, naming the variable, so a misconfigured app can't silently drop events.client/relay.test.tsproves the request it produces againstverifyRequestfromsrc/sign.tswith a stubbedfetch(the real/api/eventsroute doesn't exist yet — that's #8), checks nonces differ between calls, and checks the exact bytes sent are the bytes hashed.docs/adopting.mdcovers what an event is, the four headers, how to get a key, thecurlequivalent, the dedupe rule, thenoun.verbkind convention, what not to post, and what happens when relay is down.README.mdlinks the doc.Left out on purpose, per #21's own scope: the page's empty state (that's #9), and the end-to-end proof against a live door (that's #8 plus the two integration issues, #15/#16).
Closes #14