Thirteen routes, one switch
Router.route is a switch over the method and the path, and there are thirteen pairs in it. I list them in the order a caller meets them:
| Route | Token | What it answers |
|---|---|---|
GET /hello | no | who answers here: app, version, build, paired, and the wire's part versions |
POST /pair | no | sets the token once; 409 after that |
GET /status | yes | the body now: device, battery, grants, what it is doing |
POST /photo, POST /clip | yes | a JPEG, or 1 to 15 s of HEVC video, with facts in a header |
GET /where | yes | one fresh GPS fix |
POST /say, POST /hush | yes | plays a line and says how long it played; stops the line now |
POST /face | yes | Oriel's push of what the face should show |
GET /ears, POST /ears, GET /ears/next, POST /listen | yes | the ears, their switches, Oriel's long poll, the listening grant |
A known path asked with the wrong method gets 405 with the sentence "GET is not how /photo is asked". A path the switch does not know gets 404, "no route /nowhere". Both are in wrongMethodAndUnknownPath.
Two routes before the token
The first block is the top of route. /hello and /pair are matched before anything checks a token, because a fresh install has none. /hello says what Oriel needs to decide whether to talk at all: paired, and the version of each part of the wire, wire 1, ears 1, onair 2, solo 1. The numbers let Oriel tell an older build from a newer one without guessing: the comment beside earsVersion says a body whose /hello lacks it has no ears.
/pair has three answers. The first valid token, 64 hex characters, is saved and answered 200. A token of any other shape is 400, "a token is 64 hex characters". A second pair, whatever its token, is 409: "this body is already paired; reinstall Cordelia to pair it again". Re-pairing is a reinstall on purpose, and the next track explains why.
Then come two guards in a row, both 401 and with different words. An unpaired body answers every other route with "this body is not paired yet; Oriel pairs it first". A paired body answers a missing or wrong token with "the token does not match this body's pairing". Because these guards stand before the route lookup, a stranger without the token gets 401 even for a path that does not exist. The door tells it nothing about which routes are behind it.
The body refuses, the router only carries it
The router decides only the refusals it can see in the request: a camera that is not back or front, a clip outside 1 to 15 s, a /say whose body is not audio or is empty, an /ears change that names nothing. Everything about the device's state is decided by the device, which throws a Refusal carrying a status and a sentence. The bottom of route (second block) turns any Refusal into exactly that status and sentence, any WireError into 400, and anything else into 500 with "the body failed:" and the error's description. The test theBodysRefusalKeepsItsStatusAndReason loads a fake with .notActive("camera") and checks that 409 and the words "not in front" both arrive.
| Status | What it names on this wire |
|---|---|
| 401 | no pairing yet, or a token that does not match |
| 403 | the camera or the location grant is missing; a person allows it once in Settings |
| 409 | the app is not in front, so iOS has the camera off; already paired; a line is already playing |
| 413 | a head over 16 KB or a body over 32 MB (from the door, before routing) |
| 423 | the camera is busy with another capture |
| 503 | no such camera on this device, a camera that would not open, the body shutting down |
| 504 | a named deadline ran out (the last lesson of this track) |
The order of the guards is part of the meaning. A photo checks the front first (409), then the grant (403), then whether the camera is free (423). So a 423 also tells Oriel that the app is in front and allowed: only the camera's own state is in the way. A fix checks the grant before the front, because a missing grant is the problem a person has to solve first.
409 means three things, and the sentence says which
409 shows up for an app in the background, a second pair, and a second line while one plays. A status code is a category, never a diagnosis. Each of the three carries its own sentence, and that sentence is what Oriel logs and what a brain reads back. The number lets code branch; the words let a person act.
What Oriel does with a refusal
Oriel's side reads the wire the same way. ensure_paired (third block) calls /hello first and refuses a body that speaks another wire version. A body that says it is paired while Oriel holds no token for it was paired by someone else, and Oriel stops with "reinstall Cordelia there to pair it again". Only an unpaired body gets a fresh token. When a body answers an error, Oriel's _json keeps the body's sentence ("refused a front photo: …") and folds the number for its own callers: anything under 500 becomes 409, anything from 500 up becomes 503. The device's fine distinctions survive in the words, and Oriel's callers branch on two numbers.