mesh: a grant rides over the OpenAI-compatible HTTP binding, and a receipt can be shown back as a witness #312
Merged
dcharlot
merged 1 commit from 2026-10-18 07:20:05 -04:00
feat/mesh-http-grants into main 2026-10-18
mesh: a grant rides over the OpenAI-compatible HTTP binding, and a receipt can be shown back as a witness
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 12s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m11s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 59s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m13s
The grant work (#294, #301, #306) was reachable only through the library. The reference HTTP server passed no grant to every request, had no way to learn which steward a grant must name, and no way to witness a receipt against the journal. Its binaries kept the journal in memory. It also read whatever request body length a client declared. - **Grants over HTTP.** A request's body carries its presentation in `jcp_presentation` (`presentation_in`). The presentation is signed for a request id, so a granted request is served as exactly the `ServeRequest` the body alone determines (`granted_serve_request`, plus a `_responses` variant). Its prompt-token figure stays the body's estimate rather than the server's tokenizer count, which a caller cannot reproduce. The body must name its own `metadata.joule_ceiling_uj`, since a server default would otherwise enter the id unseen. - **Endpoints.** `GET /v1/mesh/steward` returns the steward's did:key, the subject a grant must name. `POST /v1/mesh/witness`, with the `receipt` and `envelope_hex` a response carried, answers 200 when the journal holds the receipt and 409 when it does not. `Mesh::witness_wire` checks a receipt in that wire form: the envelope must verify under this steward and seal exactly that wire receipt. - **Statuses** (`http_status`): 401 when the caller is not the grant's issuer, 403 when the steward refuses the grant, 503 once it has stopped honouring grants, 500 for an unwritable journal, 400 otherwise. - **Journal in the binaries.** With `MESH_JOURNAL` set, the reference server example and serve_openai_falcon record to that file and replay it before serving, reporting any unresolved serve. - **Body cap.** A body declared over 4 MiB is refused (413) before it is read. - **Spec.** Mesh SPEC §2.3 describes the binding (informative). Checked on the build host: - mesh-rs: 81 tests pass. mesh-openai with the server feature passes 15, including an end-to-end socket test: learn the steward, grant to it, present over HTTP, witness the receipt, refuse a tampered one, refuse an oversize body. - The gguf and openai server features build, every Cargo.lock is current, and clippy is clean. - Mutations each fail tests: a server that drops the grant, a granted path that recounts tokens, a wire witness that skips the seal check, and no body cap. Co-Authored-By: Claude Opus 5.5 <[email protected]>