Skip to content

Build1 publisher3 min readPublished

A hash-checked JSON file decides which status codes an agent's mapper may return

A dev.to case study freezes four error codes, with their HTTP status, retry flag, message key and log level, into one JSON file, hash-checks it in CI, and then lets the generator rewrite the mapper as often as it likes.

The Engineer · Build desk

Illustration accompanying A hash-checked JSON file decides which status codes an agent's mapper may return

What happened

  • The service in the case study sits behind a queue worker and answers three clients: a web app, a mobile app, and a partner integration.
  • Whether a failure was retryable, and what the user should be shown, had never been written down; those answers lived in the heads of the people who wrote the original catch blocks.
  • Asked to generate the mapper from that state, the agent picked 422 for one validation failure and 400 for its sibling.
  • The same generated mapper forwarded err.message into the response body, where the partner client could read a stack trace.
  • The fix commits four codes to contract/error-cases.json, each with an HTTP status, a retry flag, a message key and a log level, stamped version 1 and frozen_at 2026-09-15.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint With the mapper reduced to a pure function of a file it cannot edit, discarding and regenerating it stops being a review event, and the diff a human has to read shrinks to the JSON.
  • exposure The digest lives in the same directory as the contract, so an agent with commit rights to contract/ can refreeze the taxonomy and still get a green build. The guard is branch protection.
  • decision Splitting a second validation status out of the single 422 entry becomes a change to the contract, which all three clients read at once, instead of a branch someone edits inside the mapper.
  • cost Adoption costs one JSON file, one digest file and one dependency-free test on Node 20, so nobody has to fund a schema registry to get a stable retry flag.

Run the suite and it does three things in order. It hashes `contract/error-cases.json` and compares the hex digest against the string stored in `contract/error-cases.sha256` [19]. It walks the four entries in the file, calls `toProblem` with each code, and asserts the returned `type`, `status`, `retryable` and `message_key` match the file exactly [20]. Then it calls `toProblem` with `ECONNRESET` and a message carrying a database host and port, and asserts the result is type `INTERNAL`, status 500, with `detail` undefined [21]. One assertion for the hash, four fields across four cases, three for the unknown code: twenty in all [23].

Twenty assertions is also the coverage. The loop runs in one direction, from the file into the mapper [20]. A mapper that grows an extra branch for a code the file does not list, with an invented status and retry flag, passes everything unless the code it invents is `ECONNRESET` [26]. The freeze removes the generator's room to invent policy for the codes you enumerated [13].

The digest guard is a change detector. `sha256sum` writes the hash into a file sitting beside the one it covers, in the same working tree [17]. Any process that can write `contract/` can write both and get a green build, so the case study's control is procedural: regenerate the digest only through a reviewed pull request [17][27].

The drift being fixed started with an agent picking 422 for one validation failure and 400 for its sibling [7]. It also marked a rate-limit response non-retryable because the word "limit" read like a permanent condition [8], which is a fair inference about English and a wrong one about HTTP. The frozen file holds one validation entry, `VALIDATION_FAILED` at 422, non-retryable, log level info [16]. Both siblings now return 422 until someone adds a second entry in review [16][17]. The case study blames the brief: "The problem is that you handed it a task with no acceptance criteria, so it optimized for readability instead of contract stability" [10].

`log_level` is in the contract too, so pager noise is a reviewed decision [11][13]. Two of the four cases are retryable [24]. The two non-retryable ones log at info, `RATE_LIMITED` logs at warn, and `UPSTREAM_TIMEOUT` logs at error [16][25].

Before that number transfers to your service, a few conditions have to hold. Your clients have to branch on a retryable flag, the way the web app, mobile app and partner integration in the example each decide retries for themselves [5]. The failure modes have to be enumerable before generation, and this project starts from four known ones [3]. And your runner has to read the contract with no dependency, which the listing does with `node:test`, `node:assert`, `node:fs` and `node:crypto` on Node 20 or newer [18][15].

The post gives no numbers. Six slightly different 4xx answers for one failure is asserted as the outcome of ungoverned generation, and nobody counted it across runs [1]. It also tells you to treat the listings as a reference implementation and run them in your own repository before adopting any of it [22].

What to watch

  • Whether the follow-up publishes the mapper listing these twenty assertions constrain.
  • Whether the digest check is replaced by something an agent cannot regenerate, such as a hash pinned in CI configuration outside the repository tree.
  • Whether the suite grows a reverse check that enumerates the mapper's branches and fails on any code absent from the contract.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories