# Reference patch — 03-short-circuit-audit

The answer key for how the reference absorbs this change, and the thing that makes
`budget.json` reproducible. **Never shipped to the candidate.**

1. **No contract change.** `use(Middleware)` already exists and already means exactly what the
   requirement asks for.
2. **No new file.** `edits.json` is empty; `reference/src` is byte-identical before and after.
3. The gate and the access log in the curveball's own tests are ordinary `Middleware` lambdas,
   written in the test, calling `router.use(...)` twice in the right order. Nothing in
   `RouterFactory`, `Router` or `MiddlewareChain` needed to change to make that legal.

Measured: `reference_diff = 0`, so `diff_budget = max(3, 0 + ceil(0/2)) = 3` — the floor. Both the
curveball suite (3 tests) and the base suite (23 tests) are green with no patch applied at all.

## Why it costs nothing

Three decisions, already made for the base problem, are what pay for this:

- **`use(Middleware)` composes in registration order with no special case for "the last one."**
  The requirement's whole shape — gate first, log second, log never sees what the gate rejected —
  is exactly what registering the gate before the log already means. There is no ordering rule to
  add; there was only ever one ordering rule, stated once in the contract, and this requirement is
  an instance of it, not an exception to it.
- **A middleware's decision to short-circuit is a plain `return` with no call to `chain.next`.**
  There is no `SKIP` sentinel, no boolean flag on `Request`, nothing a candidate has to remember
  to check. `MiddlewareChain.wrapping` does not know or care whether the middleware it just
  invoked called `next` — it only sees whatever `Response` came back. So "the log middleware is
  never invoked at all" for a rejected request is not a special behaviour bolted on for this
  curveball; it is what "did not call next" has meant since the base problem.
- **Middleware is expressed against `Request` and `Chain`, both plain contract types**, so an
  interviewer's brand-new requirement — an auth gate, here, but it could as easily have been rate
  limiting or a feature flag — is implementable entirely inside `use()`'s existing contract,
  by a caller, without the router's own source being open at all.

**This is the curveball that is supposed to cost nothing.** It exists to show that the base
design was not merely lucky on the two tests that happened to be written for it (short-circuit
and ordering, both already asserted in the base suite) — it generalises to a genuine, differently
-shaped requirement about the same seam, with zero additional code.

## What a candidate is most likely to get wrong here

Building a bespoke two-step pipeline specifically for "auth then logging" — a dedicated
`SecureHandler` wrapping a plain one, say — rather than reaching for `use()` twice. That would
still pass this curveball's tests, but it duplicates a mechanism the design already has, and the
next requirement shaped like this one would not be free.
