carlos / platform Public

refs-design

Design, no code. It covers the original ask behind the Errors and Availability work: a customer sees a unique reference on an error page, reads it to support, and support finds exactly what went wrong.

docs/superpowers/specs/2026-09-24-request-reference-design.md:

  • Format: R-0K7M-3QXA-9F2C. That is 30 bits of seconds plus 30 random bits in Crockford base32 (32/28 in the first draft; changed in review), which is safe to read aloud and case-insensitive. The time is inside it, so lookup reads one narrow window with no index.
  • Minted once, at the first CARLOS edge a request reaches. - Kept across verified backhaul hops, and across the fleet tunnel, which today marks nothing; the tunnel client gains a context flag. - A client-supplied X-Request-Id is dropped. - Carried to the app as X-Request-Id, which Rails already reads. - Returned on the response. - Never stored in the edge cache, since writeCached replays stored headers.
  • Shown on every error page the edge writes: the proxy 502s, the wake 503s, fleet-dark, static, and the pending retry page.
  • Stored: up to 20 refs per coalesced error record (additive refs field). Past the cap, lookup falls back to the reference's second.
  • Looked up with carlos errors --app X --ref R-… and a Reference box on both tabs. The answer is the exact occurrence, or "near" failures when the ref wasn't stored individually, plus log lines carrying the ref, or a plain "nothing carries this reference".
  • Rollout: mint and carry, then store and look up, then titogo prints the header on its 500 page.

Review and rulings

Bill's rulings on §8, now recorded in the spec (status: approved):

  1. The reference is returned on every response.
  2. A client-supplied X-Request-Id is ignored.
  3. MaxRefs = 20.
  4. The R- prefix and 4-4-4 grouping stand.

Ready to merge. Implementation plans follow, one per rollout step (§7).

Fable design review: approve-with-amendments. All amendments are taken in the latest commit, and spec §10 records them. The ones that change the design:

  • Where the response header is set. Setting it at the mint site would have lost it on every gzip response and after a 103, and duplicated it when the app echoes its own. It is now set in countingWriter.WriteHeader, the bottom wrapper, with no new wrapper. Upgrades and the early-return paths are named explicitly.
  • Mixed-version trust. On a verified hop or over the tunnel, the inbound value is kept only if it parses as a reference. Otherwise an old front box would pass a client's own X-Request-Id through to a new box that trusts it.
  • Bit split 32/28 → 30/30, which lasts to 2060, with the birthday bound stated honestly. This stays within the prefix and grouping ruling. Lookup shows collisions rather than guessing.
  • Lookup window. Errors ship every 10 s, not every 5 min, so the old reasoning was wrong. What delays a record is request duration: a 13 s redial, or an abandoned wait lasting minutes. The window is now [t − 1 m, t + 30 m], and "near" covers [t, t + 60 s].
  • A ref names the group, not the page. Path and status are the group's first sample, and lookup labels them as such.
  • Smaller changes: - the overflow row clears refs; - a "not shipped yet" answer comes before "nothing"; - log lookup needs an any-field substring match; - the cache drop happens in maybeStore; - the pending page becomes per-request.

Also fixes the errors spec's stale five-minute flush claim.

First opened as github.com/carlosframework/platform/pull/420; moved to amadan when amadan became the source of truth (2026-09-24).

Commits 0
Discussions 0 0 open
Tasks 0/0 done

Discussions

  • No discussions on this branch yet.

Tasks

  • No tasks yet.

Activity

  • No activity yet.