mesh: a grant is spent only by its issuer, at the steward it names, and its spend survives a restart #301

Merged
dcharlot merged 1 commit from feat/mesh-caller-auth-durable-spend into main 2026-10-18 00:42:18 -04:00

2026-10-17

Transaction Science
mesh: a grant is spent only by its issuer, at the steward it names, and its spend survives a restart
All checks were successful
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 4s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 4s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Has been skipped
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Has been skipped
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 4s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 4s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Has been skipped
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been skipped
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been skipped
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been skipped
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Has been skipped
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been skipped
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been skipped
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 4s
wai-web wasm32 / does this change touch it (pull_request) Successful in 4s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been skipped
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been skipped
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 1m34s
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 56s
After #294, mesh decided a grant with JCP's runtime but honoured it as a
bearer token. Whoever presented a grant was taken to be its subject, and
the steward's spend lived in memory. Three consequences:
- Anyone who obtained a grant could spend it and receive the output.
- The same grant spent its full budget again at every steward it was
  shown to.
- A restart gave every grant its budget back.

**Caller authentication (SPEC §2.1).** A grant is now presented as a
`Presentation`: the delegation chain, root first, plus a caller, a nonce
and an Ed25519 signature over the request id, the leaf's id, the caller
and the nonce.
- The steward refuses a presentation whose caller is not the leaf's
  issuer, or whose signature is not for this request.
- The steward refuses a presentation it has already spent, keyed by leaf
  and nonce, so a captured one cannot be replayed.

**Steward-held grants (SPEC §2.1).** The steward decides the chain as its
holder, under its sealing key's identity, so the leaf's subject must be
this steward. A grant shown to another steward is refused
`NotThisSteward`. One budget over several stewards is sharded with
`jcp_grant::shard` (JCP §4.5): one shard held by each steward, summing to
no more than the parent. Chains are decided with jcp-runtime's new
`authorize_chained` / `charge_chained` (#300), which check every link and
debit every link.

**Durable spend (SPEC §2.2, JCP §4.11).** The decision journal:
- **Before the engine runs,** each decision is recorded as an
  `Authorised` entry. A decision that cannot be recorded is refused.
- **After the debit,** a `Debited` entry is recorded.
- **On restart,** `Mesh::with_journal` replays the journal through the
  gate. Each authorisation is verified and decided again at its recorded
  time, and each debit is applied to its serve.
- **Inconsistent journals** fail with `JournalInconsistent`: a replay the
  gate refuses, a debit with no authorisation, or a presentation spent
  twice.
- **In-flight serves** (authorised, never debited) stay debited at their
  ceiling. They are listed in `unresolved()` with the caller and backend,
  and never retried.
- **The reference `FileJournal`** is append-only JSON lines, synced per
  append. A torn final line is dropped and cut from the file.

`Mesh::serve` and mesh-openai's `complete_chat` / `complete_responses`
take `Option<&Presentation>`. The demo and the falcon binary present
their grants. The HTTP server presents none, as before. SPEC §2, §2.1,
§2.2, §7 and §8 and the README describe all of it.
joulehook-rs locks mesh-core through a path dependency, so its Cargo.lock
is updated too.

Checked on the build host:
- mesh-rs: 73 tests pass, eight of them new. They cover a grant held
  elsewhere, a wrong or misdirected caller, replay, shards across two
  stewards, restart resumption, an in-flight serve, a forged journal and a
  torn file line.
- Every `mesh/1` vector is byte-identical, and the lockfile is current.
- The gguf and openai server features build, the demo runs, and clippy is
  clean on mesh-core and mesh-openai.
- Mutations each fail tests: no caller check, no replay check, bearer
  subject, replay dropping debits, in-flight not debited, and replay
  trusting the journal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 17:13:42 -04:00