feat(api): fold four route tables into one, and split the union that fed them
§5 Dimension 5.1. The Zig daemon keeps four total switches over one `Route` union in four files — `route_table.zig` (middleware chain), `route_scopes.zig` (capabilities), `route_admission.zig` (shed class), `route_template.zig` (span template). Adding an endpoint meant editing four, and the compiler caught only three: `route_admission.zig` had traded its exhaustive match for `else => .api` and rebuilt the check as a runtime walk over two hand-maintained name lists. `Route::meta` states all four at once. Both name lists are gone. Not a transcription. Three things are shaped differently on purpose: Identity carries no payload. The Zig union puts path parameters in the route (`poll_auth_session: []const u8`), so every metadata switch is payload-shaped and its own exhaustiveness test fabricates values with `@unionInit(..., undefined)` that it must never read. Here a route is an identity and parameters are the extractor's job — nothing to fabricate, so nothing to get wrong. The enum nests. Eighty-one variants in one flat list is a thing nobody reads and therefore nobody reviews; ten families keep each file to a surface a person can hold, and rustc stays exhaustive at both levels. Two families are splits Zig did not draw, and both follow a seam already there: workspace/fleet divides on whether a route is addressed by a fleet id, runner/runner_ops divides on the GUARD — a runner speaking for itself versus an operator looking at runners. HEAD is refused rather than resolved. agentsfleetd has never served it; the matchers switch on GET, POST and DELETE, and httpz keeps a separate `_head` table the daemon registers nothing into. The Zig scope table would nonetheless answer HEAD with the WRITE rung, because HEAD is unnamed and falls to `else` — dormant only because the request never arrives. axum's `get()` answers HEAD by default, which would have made that trap live, so the table has no HEAD rung and the router will refuse the method outright. Indy's call. All 81 routes carried over, 100% coverage, 8 tests. No reconciliation ledger by decision — review is the net, which is what the family split is for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
K
Kishore Kumar committed
bbae80d7b4aa6ad067ce5d115968bba5e0c5052a
Parent: ff5fb30