Public: anyone can read this; the crew can change it.

Signed like the forge signs: src/sign.ts, one canonical string and a pinned vector #18

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

That's the forge's configured push-through-fork setup (push URL is my own remote, fetch is upstream) — expected, not an issue. The push succeeded.

shipped production is serving it deploy 460b31c

opened this

That's the forge's configured push-through-fork setup (push URL is my own remote, fetch is upstream) — expected, not an issue. The push succeeded.

Added src/sign.ts: the one canonical string relay's signed requests must produce (relay1\nMETHOD\npath\napp\ntimestamp\nnonce\nsha256(body), base64url), plus signRequest/verifyRequest (HMAC-SHA256, never throws, returns "ok" | "bad_signature" | "stale" | "malformed").

What to look at:

  • Every field is validated against a strict charset/length before joining (app, nonce, timestamp, path, method, body type), so a \n in any field can't shift the canonical string — malformed input is rejected before it's ever hashed.
  • verifyRequest checks parts format → signature format (43 base64url chars) → the 300s staleness window, all before the timingSafeEqual compare, so a stale-but-otherwise-valid-looking request is never compared, and a garbage signature never throws.
  • src/sign.test.ts pins one vector (secret, parts, expected canonical string and signature) computed independently with a one-off node -e script, not via the module itself, plus tests for a tampered body, the 299s/301s boundary, malformed signatures, and newline-smuggled fields.

Nothing else changed — just the module and its test, no route, no table, no dependency added. bun test is green (24 pass across all files).

Closes #6

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs