smart-byte: unbreak the build, and add CI for the three standards workspaces #58

Closed
dcharlot wants to merge 14 commits from ci-standards-workspaces into main
87 changed files with 7289 additions and 5755 deletions

View file

@ -27,13 +27,13 @@ jobs:
# Bootstrap rustup: the docker runner image ships no Rust, and
# dtolnay/rust-toolchain cannot help — it calls `rustup`, which is absent.
- name: Install Rust 1.97.1
- name: Install Rust 1.98.0
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Cache cargo

View file

@ -39,13 +39,13 @@ jobs:
# Bootstrap rustup: the docker runner image ships no Rust, and
# dtolnay/rust-toolchain cannot help — it calls `rustup`, which is absent.
- name: Install Rust 1.97.1
- name: Install Rust 1.98.0
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Cache cargo registry + target

126
.github/workflows/standards-build.yml vendored Normal file
View file

@ -0,0 +1,126 @@
name: standards workspaces build + test
# Build gate for every Rust workspace in the repo.
#
# It started as three. Then a toolchain bump compiled the rest for the first
# time and found FIVE more that did not build — smart-byte (47k LOC), openpay
# (six separate breakages across five crates), eoc, mesh and joule-ui — all
# broken by the same handful of upstream migrations (hmac -> KeyInit, reqwest
# feature-gating, cipher 0.4 -> 0.5, a struct gaining fields), and all invisible
# because nothing ever compiled them. Partial coverage is how that happens, so
# the matrix now covers everything.
#
# The original case, still the clearest: smart-byte-rs had never been compiled by
# anything, and it did not build. A single wrong `rand` pin — 0.10 against code
# written for 0.8, whose crypto stack requires rand_core 0.6 — silently disabled
# the entire identity pillar, BBS+ included. `cargo check` would have caught it
# on day one. An unbuilt standard is not a standard, so this workflow is the
# floor under every claim the specs make.
#
# One workflow with a matrix rather than sixteen files: the bootstrap step is
# identical everywhere, and a shared dependency change should rebuild all of
# them anyway. `fail-fast: false` so one red workspace does not mask the others.
on:
push:
branches: [main]
pull_request:
# Deliberately NO `paths:` filter.
#
# The first attempt used `**/*.rs` and `**/Cargo.toml`, and the workflow then
# silently did not fire — pushes touching exactly those files triggered other
# workflows but not this one, so `**`-prefixed globs evidently do not match here
# the way they do on GitHub. A build gate that quietly fails to run is worse than
# no gate at all: it reports nothing and everyone assumes green.
#
# This is the repo-wide floor, so it runs on every push and every PR. The cost is
# CI minutes on doc-only changes. The alternative cost is what this branch spent
# a day fixing — five workspaces silently broken because nothing compiled them.
jobs:
build:
name: ${{ matrix.name }}
# Spread across the fleet's runners rather than pinning every job to `linux`.
# These are pure-Rust builds with no platform-specific behaviour, so the
# runner is a capacity choice, not a correctness one — and 16 jobs on a
# single runner queue behind whatever else is using it.
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { name: jcp-rs, dir: jcp/jcp-rs, runner: linux }
- { name: sandbox-rs, dir: sandbox/sandbox-rs, runner: linux }
- { name: smart-byte-rs, dir: smart-byte/smart-byte-rs, runner: linux }
- { name: openpay, dir: openpay, runner: linux-arm64 }
- { name: joule-code-rs, dir: joule-code/joule-code-rs, runner: linux-arm64 }
- { name: map-rs, dir: map/map-rs, runner: linux-arm64 }
- { name: aac-rs, dir: aac/aac-rs, runner: linux-arm64 }
- { name: joulecontract-rs, dir: joulecontract/joulecontract-rs, runner: linux-arm64, z3: true }
- { name: jouledesk-rs, dir: jouledesk/jouledesk-rs, runner: macos }
- { name: arl-rs, dir: arl/arl-rs, runner: macos }
- { name: sense-rs, dir: sense/sense-rs, runner: macos }
- { name: proof-rs, dir: proof/proof-rs, runner: linux, z3: true }
- { name: joulehook-rs, dir: joulehook/joulehook-rs, runner: macos }
- { name: eoc-rs, dir: eoc/eoc-rs, runner: linux }
- { name: mesh-rs, dir: mesh/mesh-rs, runner: linux-arm64 }
- { name: joule-ui-rs, dir: joule-ui/joule-ui-rs, runner: macos }
steps:
- uses: actions/checkout@v5
# Two workspaces shell out to `z3`, and the runner image has no solver.
# Without one, `joulecontract-proof`'s z3 test takes its solver-absent
# branch — which asserts the ladder returns Unproved, "never a fake pass",
# and fails, because the ladder actually escalates past its two real rungs
# to a model STAND-IN that reports Proved. That is a genuine defect in the
# proof standard and is NOT fixed here: the stand-ins are load-bearing in
# proof-cascade and proof-conformance, which has a published vector pack,
# so changing whether a stand-in may close a goal is a deliberate decision
# for that standard's owner. Installing the solver lets CI exercise the
# intended path; it does not make the fallback correct.
# Both z3 jobs are pinned to Linux runners deliberately: the macOS runner is
# a host executor with no apt. `sudo` may or may not exist depending on
# whether the container runs as root, so fall back to a bare invocation.
- name: Install z3
if: matrix.z3
shell: bash
run: |
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq z3
z3 --version
# The docker runner image ships no Rust at all, so rustup is bootstrapped
# here. dtolnay/rust-toolchain cannot be used: it shells out to `rustup`,
# which the image lacks. Harmless where cargo already exists.
- name: Install Rust (workspace pin)
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Cache cargo registry + target
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
${{ matrix.dir }}/target
key: standards-${{ matrix.name }}-${{ hashFiles(format('{0}/Cargo.lock', matrix.dir), 'rust-toolchain.toml') }}
restore-keys: |
standards-${{ matrix.name }}-
# --all-targets is load-bearing: a plain `cargo check` does not build test
# targets, and smart-byte's dev-dependencies drifted independently of its
# normal ones (rand_chacha 0.10 against rand 0.8). The library compiled
# while the tests did not.
- name: Check (all targets)
working-directory: ${{ matrix.dir }}
run: cargo check --workspace --all-targets
- name: Test
working-directory: ${{ matrix.dir }}
run: cargo test --workspace

View file

@ -52,22 +52,22 @@ jobs:
# unix: bootstrap rustup (docker image ships no Rust; macOS host has it but
# launchd's PATH omits ~/.cargo/bin). Windows is a host executor with rustup
# already present, and must use pwsh — its `bash` is the WSL stub.
- name: Install Rust 1.97.1 (unix)
- name: Install Rust 1.98.0 (unix)
if: matrix.os != 'windows'
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Rust 1.97.1 (Windows)
- name: Install Rust 1.98.0 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
- name: Decode fixtures, assert golden bytes
working-directory: wai/byte-exact-conformance

View file

@ -51,25 +51,25 @@ jobs:
# is bootstrapped; the macOS `host` runner has it but launchd's PATH omits
# ~/.cargo/bin. dtolnay/rust-toolchain is unusable — it calls a `rustup`
# the docker image lacks.
- name: Install Rust 1.97.1 (unix)
- name: Install Rust 1.98.0 (unix)
if: matrix.os != 'windows'
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
# Windows: a host executor with rustup already installed. Only ensure the
# pinned toolchain is present + default. pwsh, never bash (that is WSL here).
- name: Install Rust 1.97.1 (Windows)
- name: Install Rust 1.98.0 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
- name: Build the cargo classes (pure Rust, no C codec chain)
working-directory: wai/wai-rs
@ -141,22 +141,22 @@ jobs:
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.97.1 (unix)
- name: Install Rust 1.98.0 (unix)
if: matrix.os != 'windows'
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Rust 1.97.1 (Windows)
- name: Install Rust 1.98.0 (Windows)
if: matrix.os == 'windows'
shell: pwsh
run: |
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
- name: Integer rANS + int_synth + JPEG-AI mANS goldens (one machine → every machine)
working-directory: wai/byte-exact-conformance

View file

@ -48,13 +48,13 @@ jobs:
working-directory: wai
run: python tools/wai_validate_synthetic.py --size 256
# Bootstrap rustup: the docker runner image ships no Rust.
- name: Install Rust 1.97.1
- name: Install Rust 1.98.0
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.97.1
rustup toolchain install 1.97.1 --profile minimal
rustup default 1.97.1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Each Rust decoder reproduces its reference end-to-end
working-directory: wai/wai-rs

683
aac/aac-rs/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ version = "0.1.0"
edition = "2024"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
authors = ["Transaction Science <[email protected]>"]
[workspace.dependencies]

75
arl/arl-rs/Cargo.lock generated
View file

@ -117,7 +117,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -199,15 +199,15 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "once_cell"
@ -227,18 +227,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -263,9 +263,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.22"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]]
name = "semver"
@ -275,9 +275,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -285,29 +285,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -354,9 +354,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -365,22 +376,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -439,7 +450,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
"wasm-bindgen-shared",
]
@ -454,12 +465,12 @@ dependencies = [
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -10,7 +10,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["ARL Contributors"]

View file

@ -10,7 +10,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["EOC Benchmark Contributors"]

980
eoc/eoc-rs/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["EOC Contributors"]

View file

@ -20,7 +20,7 @@ jsonschema = { version = "0.46", default-features = false }
tokio = { workspace = true, features = ["macros", "rt", "sync", "fs", "process", "io-util", "time"] }
async-trait.workspace = true
futures = "0.3"
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json"] }
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json", "query"] }
thiserror.workspace = true
tracing = "0.1"

View file

@ -1,4 +1,4 @@
[toolchain]
channel = "1.97.1"
channel = "1.98.0"
components = ["rustc", "cargo", "rust-std", "rustfmt", "clippy"]
profile = "default"

View file

@ -0,0 +1,379 @@
{
"vectors": [
{
"core_hex": "b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590422b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e7458401ea0820e7bd612d95b106aed237731422872f7f8fb6f5ea6304c9001bfd1bfcb12d78b3744cad517085786986965a556f5b74fa951322cf41c57e2994f02bf0b",
"expect": "verify",
"id_hex": "c5b0e62aecf6bab69a0434216fa989a9d1935a299a50dd48855743071f7eb580",
"name": "reversible-local",
"note": "Read-modify-write resolved on-device. Nothing left the machine, so egress is `none` with zero bytes.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533566656666656374a265636c617373646e6f6e656674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a059038bb1647469657262533566656666656374a265636c617373646e6f6e656674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e7458405acb134e4267a5e8e0909dd36cc41194f5c0b796e36039f8d39108e7f9e9619dc5acdeb45368ee620d9f3c15f7f3f919e10bb656e4793e1d1a03abd23825320b",
"expect": "verify",
"id_hex": "318270be152d0a33ed88c8de6ae622ba12d019703c56554f8e347f32fc2f4da8",
"name": "read-only",
"note": "A query that changed nothing. Safe to replay; no before/after state to record.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"class": "none",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533566656666656374a565616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736b636f6d70656e7361626c65666265666f7265784062626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262667461726765747840643733376233653539376632353233346234616563373134393366313133653435363061336135633937306431366237393130363961363233643331343233626b636f6d70656e7361746f7278406561626436306166366361303332336436396161633538666639346262313538616133643862356337616133363633303231373138663264396439396338636166656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590471b1647469657262533566656666656374a565616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736b636f6d70656e7361626c65666265666f7265784062626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262667461726765747840643733376233653539376632353233346234616563373134393366313133653435363061336135633937306431366237393130363961363233643331343233626b636f6d70656e7361746f7278406561626436306166366361303332336436396161633538666639346262313538616133643862356337616133363633303231373138663264396439396338636166656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e745840808826b8524ace60d9f2cbb24abc8b284ab8d1181429c65b952f88a37424da5b31e6c4e3dc16bd079a200806b92ecfd26dc86b2e8c3abcfbbb31b19132889b06",
"expect": "verify",
"id_hex": "8843e43c0f4591985d9d96c5ad319d63fca7c4baaca3af7bcd606f2cc6835b9b",
"name": "compensable-with-compensator",
"note": "Cannot be undone, but the grant that could compensate is named at the time of acting — not discovered afterwards.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "compensable",
"compensator": "eabd60af6ca0323d69aac58ff94bb158aa3d8b5c7aa3663021718f2d9d99c8ca",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533566656666656374a565616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736c697272657665727369626c65666265666f7265784062626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262667461726765747840643733376233653539376632353233346234616563373134393366313133653435363061336135633937306431366237393130363961363233643331343233626c706c616e5f7265636569707478406466383635316564316434653064356264393936623963363337323531316432373136396265333363336237386237393334336636376531346665636462393166656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590473b1647469657262533566656666656374a565616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736c697272657665727369626c65666265666f7265784062626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262667461726765747840643733376233653539376632353233346234616563373134393366313133653435363061336135633937306431366237393130363961363233643331343233626c706c616e5f7265636569707478406466383635316564316434653064356264393936623963363337323531316432373136396265333363336237386237393334336636376531346665636462393166656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e7458409fc1a7362b97f0ce75f2e2afb695e4ac78567bc3ef4af4c3e935ea9c64a77912959bdc1870c5f052ba992aced3eff720a232344130b025de11c094e5af443f04",
"expect": "verify",
"id_hex": "f84610524e627953f2023e4af155958c61861e530f3e4dcdcfe030d515c836be",
"name": "irreversible-with-plan",
"note": "An irreversible commit carrying the plan receipt that preceded it. This is the only shape in which `irreversible` is well-formed.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "irreversible",
"plan_receipt": "df8651ed1d4e0d5bd996b9c6372511d27169be33c3b78b79343f67e14fecdb91",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a3647065657278403135643161323961656661653564646337323437633438356437613539306538376635616633343034626130333163653031386630386230386236316633306365627974657319100065636c6173737061747465737465645f656e636c617665677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590477b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a3647065657278403135643161323961656661653564646337323437633438356437613539306538376635616633343034626130333163653031386630386230386236316633306365627974657319100065636c6173737061747465737465645f656e636c617665677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e7458403695157a344c7aa68dc768507a195225d1a6fa4d843a5e6a4969fb421d600c94718da5ae12a09780cb4093b0e676c1fe7425e1a523da33cfa64b91459bbc7805",
"expect": "verify",
"id_hex": "aee95ef630da5356efb75c8cd40b029eefd5023a8014e257f218b5ed1e87cdd2",
"name": "egress-attested-enclave",
"note": "Work left the device to somewhere that proved what it was running. The peer attestation is bound in the receipt.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 4096,
"class": "attested_enclave",
"peer": "15d1a29aefae5ddc7247c485d7a590e87f5af3404ba031ce018f08b08b61f30c"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533066656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a265627974657319200065636c6173736b74686972645f7061727479677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e6768736f667477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a059042bb1647469657262533066656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a265627974657319200065636c6173736b74686972645f7061727479677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e6768736f667477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e74584048e3a978439989c20d7ad5122f1d35fb4e50afae506c7b19a65c9d6b03781888de9e7bf2d1fbda44c1816cec11dc3d6a8ca6fa980cb0c141428777f6b0bce006",
"expect": "verify",
"id_hex": "cb9cb90ed902a8ede09ee56e57f76ab10e3f50f88915c11ea8868150aae24b33",
"name": "egress-third-party-honest",
"note": "An unattested destination, honestly recorded rather than upgraded. Trust is not an egress class.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 8192,
"class": "third_party"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "software",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S0",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"core_hex": "b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a00124f806a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e636569457374696d61746f72",
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590424b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a00124f806a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e636569457374696d61746f725840e3b4480fdddf8664bc505b94d1597fda6e391234be07435ae9e11ffefa646c7013d57d75f1f05613a897c9f55f8f0e28824ca4d7b6dde814dcc45a8295963d06",
"expect": "verify",
"id_hex": "37ad6db4defd7ec0e248cc5cdacc61a16f962aa5adba9bdee0dd0f8989356c1f",
"name": "estimated-energy",
"note": "Energy from an estimator, not a hardware counter. `HwShunt` and `Estimator` are different claims and must never collapse into one number.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "Estimator",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 1200000,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590424b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736c697272657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a26562797465730065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e7458406c575b828bc2baea9c27d8e4cf60fbd17a6961bb75f8927ee19d0b4e3b1a5e6b43731523c13f819023bf8af5bc29afa405b57cf379f737f75ccc2582a84ad90a",
"expect": "reject:irreversible-without-plan",
"name": "irreversible-without-plan",
"note": "Correctly signed, structurally invalid: an irreversible effect with no plan receipt. A verifier that only checks signatures accepts this.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "irreversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 0,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590424b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a265627974657319100065636c617373646e6f6e65677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e745840d2c9adfe8cd2c27cf19d717f2fc1357cbfa949bda511e76cd2e407d0aa326e159931c9142cb0d1510f70f715f6f99fb6f755ca02c63ab3f2d62cb4cd6f3e330c",
"expect": "reject:egress-none-with-bytes",
"name": "egress-none-with-bytes",
"note": "Claims nothing left the device while counting 4096 bytes that did. The claim is falsified by its own byte count.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 4096,
"class": "none"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
},
{
"envelope_hex": "d284581ea201270458186469643a6578616d706c653a61722d7265666572656e6365a0590430b1647469657262533566656666656374a465616674657278406363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636365636c6173736a72657665727369626c65666265666f72657840626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626674617267657478406437333762336535393766323532333462346165633731343933663131336534353630613361356339373064313662373931303639613632336433313432336266656772657373a265627974657319100065636c6173737061747465737465645f656e636c617665677374657761726478186469643a6578616d706c653a61722d7265666572656e6365677665726469637465616c6c6f77686772616e745f696478403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376169636861696e5f6964738278403638356362636634396464346232316530616264383766376563353233346664373765373937306434653762386235643464356237383961616461616538376178403938663862363936613365383733306163343236393431383538663134333066386135633466616631343861636439613635346639626430653565353835393969636c6f7365645f617474323032362d30382d32355431323a30303a30305a6967726f756e64696e67686861726477617265696a6f756c65735f756a1a012a21686a61725f726563656970746a61722f312d64726166746a696e7075745f686173687840616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616c776f726b5f726563656970747840663234393233393436356434386237366265313538636532366630383237636563353739666334396265383330303237353064353538376636306164353634666d70726f6f665f63656c6c5f69647840396637356165393638333165653062653663316238653930633863613535633664343564653361633838333237353831663361623865393030666332626132666e6174746573746174696f6e5f696478403439656632363965623033343833636334666465396239336666333134363530623331333765396333373331616161653366306265363636653663643937623971617574686f726974795f7265636569707478406134366235393539353665313963613132623039363962396666616331383165383861636533323764363164323761643334366466383661663063613133636371656e657267795f70726f76656e616e63656748775368756e745840c81d8fe4462d5834f802bd0a0d7c11a547f488dd237a941df6cbf0bae37d58ec6d225ff22b1517e03a48b9495eb46192c4787652e3e3219fb18bcf0c9cdc8009",
"expect": "reject:attested-egress-without-peer",
"name": "attested-egress-without-peer",
"note": "Claims an attested destination with no peer attestation to bind. The router may not claim a stronger class than its evidence supports.",
"wire": {
"ar_receipt": "ar/1-draft",
"attestation_id": "49ef269eb03483cc4fde9b93ff314650b3137e9c3731aaae3f0be666e6cd97b9",
"authority_receipt": "a46b595956e19ca12b0969b9ffac181e88ace327d61d27ad346df86af0ca13cc",
"chain_ids": [
"685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"98f8b696a3e8730ac426941858f1430f8a5c4faf148acd9a654f9bd0e5e58599"
],
"closed_at": "2026-08-25T12:00:00Z",
"effect": {
"after": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"before": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"class": "reversible",
"target": "d737b3e597f25234b4aec71493f113e4560a3a5c970d16b791069a623d31423b"
},
"egress": {
"bytes": 4096,
"class": "attested_enclave"
},
"energy_provenance": "HwShunt",
"grant_id": "685cbcf49dd4b21e0abd87f7ec5234fd77e7970d4e7b8b5d4d5b789aadaae87a",
"grounding": "hardware",
"input_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"joules_uj": 19538280,
"proof_cell_id": "9f75ae96831ee0be6c1b8e90c8ca55c6d45de3ac88327581f3ab8e900fc2ba2f",
"steward": "did:example:ar-reference",
"tier": "S5",
"verdict": "allow",
"work_receipt": "f249239465d48b76be158ce26f0827cec579fc49be83002750d5587f60ad564f"
}
}
]
}

View file

@ -0,0 +1,9 @@
{
"alg": "EdDSA (COSE -8)",
"negatives": 3,
"note": "Fixture key, published deliberately so third parties can verify. Never use it for anything real.",
"positives": 7,
"profile": "ar/1-draft",
"pubkey_hex": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61",
"steward": "did:example:ar-reference"
}

197
jcp/jcp-rs/Cargo.lock generated
View file

@ -2,17 +2,11 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "atomic-polyfill"
@ -43,17 +37,16 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "bitflags"
version = "2.13.0"
version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -87,9 +80,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.63"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -134,7 +127,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -220,7 +213,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -244,7 +237,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn",
"syn 2.0.119",
]
[[package]]
@ -255,7 +248,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -282,7 +275,7 @@ checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -331,9 +324,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.16.0"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
[[package]]
name = "embedded-io"
@ -355,9 +348,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "fnv"
@ -382,7 +375,7 @@ dependencies = [
"rand_core",
"serde",
"serdect",
"thiserror 2.0.18",
"thiserror 2.0.20",
"visibility",
"zeroize",
]
@ -507,7 +500,24 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
name = "jcp-action-receipt"
version = "0.1.0"
dependencies = [
"ed25519-dalek",
"hex",
"jcp-grant",
"jcp-receipt",
"jcp-runtime",
"jcp-schema",
"sandbox-meter",
"sandbox-schema",
"serde",
"serde_json",
"thiserror 2.0.20",
]
[[package]]
@ -520,7 +530,7 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -532,7 +542,7 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -545,7 +555,7 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -587,7 +597,7 @@ dependencies = [
"jcp-receipt",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -605,7 +615,7 @@ dependencies = [
"blake3",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -630,7 +640,7 @@ dependencies = [
"ed25519-dalek",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -643,7 +653,7 @@ dependencies = [
"jcp-receipt",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -655,7 +665,7 @@ dependencies = [
"jcp-receipt",
"jcp-runtime",
"jcp-schema",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -667,7 +677,7 @@ dependencies = [
"jcp-receipt",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -679,7 +689,7 @@ dependencies = [
"jcp-receipt",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -693,7 +703,7 @@ dependencies = [
"jcp-schema",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -716,7 +726,7 @@ dependencies = [
"hex",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -731,7 +741,7 @@ dependencies = [
"jcp-wire",
"rand_chacha",
"rand_core",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -745,7 +755,7 @@ dependencies = [
"jcp-schema",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -758,7 +768,7 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -772,14 +782,14 @@ dependencies = [
"jcp-runtime",
"jcp-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libloading"
@ -808,9 +818,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "nvml-wrapper"
@ -869,18 +879,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -922,7 +932,7 @@ dependencies = [
"libloading",
"sandbox-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -933,7 +943,7 @@ dependencies = [
"blake3",
"ciborium",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -950,9 +960,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -960,29 +970,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -1029,9 +1039,9 @@ dependencies = [
[[package]]
name = "spin"
version = "0.9.8"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
dependencies = [
"lock_api",
]
@ -1072,9 +1082,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -1092,11 +1113,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl 2.0.18",
"thiserror-impl 2.0.20",
]
[[package]]
@ -1107,25 +1128,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "tinyvec"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
dependencies = [
"tinyvec_macros",
]
@ -1162,7 +1183,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -1186,51 +1207,51 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zerocopy"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.3"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -5,6 +5,7 @@ members = [
"crates/jcp-grant",
"crates/jcp-runtime",
"crates/jcp-receipt",
"crates/jcp-action-receipt",
"crates/jcp-bridge",
"crates/jcp-energy",
"crates/jcp-wire",
@ -30,13 +31,14 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
jcp-schema = { path = "crates/jcp-schema" }
jcp-grant = { path = "crates/jcp-grant" }
jcp-runtime = { path = "crates/jcp-runtime" }
jcp-receipt = { path = "crates/jcp-receipt" }
jcp-action-receipt = { path = "crates/jcp-action-receipt" }
jcp-bridge = { path = "crates/jcp-bridge" }
jcp-energy = { path = "crates/jcp-energy" }

View file

@ -0,0 +1,25 @@
[package]
name = "jcp-action-receipt"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Action Receipt (AR-1) — the composition envelope binding authority, environment, work and effect into one verifiable artifact. Introduces no new cryptography: canonical det-CBOR and COSE_Sign1 are reused verbatim from JCR-1. Binds by content-id so each existing receipt family keeps its own encoding and signer."
[dependencies]
jcp-schema = { workspace = true }
jcp-receipt = { workspace = true }
ed25519-dalek = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
hex = { workspace = true }
thiserror = { workspace = true }
[dev-dependencies]
hex = { workspace = true }
jcp-receipt = { workspace = true }
jcp-grant = { workspace = true }
jcp-runtime = { workspace = true }
sandbox-meter = { path = "../../../../sandbox/sandbox-rs/crates/sandbox-meter" }
sandbox-schema = { path = "../../../../sandbox/sandbox-rs/crates/sandbox-schema" }

View file

@ -0,0 +1,208 @@
# Action Receipt Specification (AR-1) — Draft
**Status:** Draft. Profile tag `ar/1-draft`. Field names are settled against the
existing canonical projections; the tag becomes `ar/1` when the vector pack has
been reviewed.
**Conformance pack:** `jcp/conformance/v1/action_receipt.json`,
`action_receipt_meta.json` — 7 positive and 3 negative vectors, signed with a
published fixture key.
---
## 0. Why this exists
Three receipt families already ship in this tree. Each records one quarter of
what an audit actually asks for, and **none of them binds to the others**:
| Family | Records | Carries |
|---|---|---|
| `jcp-receipt` | authority | grant chain, verdict, budget drawn |
| `sandbox-proof` | environment | attestation, isolation tier, substrate |
| JCR-1 | work | input hash, measured joules, energy provenance |
| *(nothing)* | **effect** | what changed, and whether it can be undone |
So no single artifact answers: *under what authority did this agent do that,
where did it run, what did it cost, and what did it change?*
The receipt encoding is implemented six independent times across the tree. That
is evidence the **encoding** is portable, and evidence the **composition** was
never specified. AR-1 specifies it.
Two of the three families already gesture at the chain — the sandbox proof cell
carries a `receipt_id`, the authority receipt carries a `payload_hash`. The
intent was there. The binding was not.
## 1. Design invariants
1. **Envelope, not replacement.** Each family keeps its own canonical encoding
and its own signer. AR-1 reaches into them by content-id; they never reach
back. Every existing verifier continues to work unchanged.
2. **No new cryptography.** Canonical det-CBOR (RFC 8949 §4.2.1) and the tagged
COSE_Sign1 envelope are reused verbatim from JCR-1. If AR-1 ever appears to
need a novel primitive, the design has gone wrong.
3. **Refusal over record-keeping.** A format that merely records claims is a
log. AR-1 defines three shapes that MUST be refused at verification, so a
violation is *detectable* rather than a matter of trust.
4. **Never claim beyond the evidence.** Every field that asserts a property must
be falsifiable from the receipt itself or from an artifact it binds.
## 2. The signed core
Canonical projection, det-CBOR encoded, signed as COSE_Sign1 with EdDSA
(COSE `alg` −8). Absent optional fields are **omitted, not nulled** — JCR-1 §3.1
drops nulls from the signed core, so an emitted null would not round-trip.
```
ActionReceipt {
ar_receipt: "ar/1-draft" // profile tag
closed_at: Timestamp // RFC 3339
// binding 1 — authority
grant_id: ContentId
chain_ids: [ContentId]? // root first; omitted when empty
authority_receipt: ContentId
verdict: "allow" | "deny"
// binding 2 — environment
attestation_id: ContentId
proof_cell_id: ContentId?
tier: "S0".."S7"
grounding: "hardware" | "software"
// binding 3 — work
work_receipt: ContentId
input_hash: Hash
joules_uj: u64
energy_provenance: "HwShunt" | "ModelBased" | "Estimator"
// binding 4 — effect (new; nothing else records this)
effect: {
class: "none" | "reversible" | "compensable" | "irreversible"
target: ContentId
before: Hash?
after: Hash?
compensator: ContentId?
plan_receipt: ContentId?
}
// binding 5 — egress (the router's per-request privacy contract)
egress: {
class: "none" | "attested_enclave" | "third_party"
bytes: u64
peer: ContentId?
}
steward: String // REQUIRED, as in JCR-1 §2.1
}
```
**Receipt id** = BLAKE3 over the canonical signed core.
### 2.1 `grounding` is carried, never upgraded
`grounding` reports whether the bound attestation is rooted in silicon or in
software. It is copied verbatim from that attestation. An implementation MUST
NOT promote `software` to `hardware` under any circumstance — the field exists
precisely so that a software-rooted claim stays legible as one.
### 2.2 `energy_provenance` never collapses
`HwShunt`, `ModelBased` and `Estimator` are three different claims about how a
joule figure was obtained. An implementation MUST NOT sum or average across
them into a single undifferentiated number. A measured figure and an estimated
one are not interchangeable, and a receipt that treats them as such is lying by
arithmetic.
## 3. The three rules
These MUST be enforced at verification, re-derived from the wire projection —
**not** from a caller-supplied struct. A receipt hand-forged to violate them
signs correctly and must be rejected anyway. The negative vectors in the pack
exist to prove an implementation does this.
| # | Rule | Rationale |
|---|---|---|
| 1 | `effect.class == "irreversible"` REQUIRES `effect.plan_receipt` | The cascade's body-tier design already separates plan from commit for actions that touch the world. AR-1 binds that discipline into the evidence: an irreversible commit with no preceding plan is a protocol violation, not a missing nicety. |
| 2 | `egress.class == "none"` REQUIRES `egress.bytes == 0` | A claim that nothing left the machine is falsified by its own byte count. |
| 3 | `egress.class == "attested_enclave"` REQUIRES `egress.peer` | The router may never claim a stronger class than it can bind evidence for. An unattested destination is `third_party` even when the operator believes it trustworthy. **Trust is not an egress class.** |
## 4. Effect classes
| Class | Contract | Enforcement |
|---|---|---|
| `none` | Read-only. Nothing changed. | Trivially safe to replay |
| `reversible` | `before` recorded; prior state restorable. | Undo is a state transition |
| `compensable` | Cannot be undone, but a compensating action exists and **its grant is named at the time of acting** — not discovered afterwards. | `compensator` bound in the receipt |
| `irreversible` | Once committed, permanent. | Rule 1: plan/commit separation |
AR-1 does not solve effect revocation — **nothing does, in general**. Revoking
authority does not un-send an email or un-move funds. What AR-1 does is make the
distinction explicit and machine-readable *at the moment of action*, which is
the precondition for any system that wants to reason about it afterwards.
## 5. Egress classes
| Class | Means | Verifiable by |
|---|---|---|
| `none` | Resolved on-device. | Rule 2, plus tier and attestation |
| `attested_enclave` | Left the device to somewhere that proved what it was running. | Rule 3 — the peer attestation id |
| `third_party` | Left the device to an unattested destination. | Named and counted, honestly marked unverifiable |
## 6. Verification flow
1. Parse the tagged COSE_Sign1 envelope; reject any `alg` other than EdDSA (−8).
2. Check `kid` against the expected steward.
3. Verify the signature over the canonical signed core.
4. Decode the core as canonical det-CBOR. Reject trailing bytes — a signed core
is exactly one item, and anything appended is corruption or an attempt to
smuggle data past a verifier that stops at the first complete value.
5. Check the profile tag.
6. **Apply the three rules to the decoded projection.**
7. Optionally resolve each bound content-id and verify the underlying receipt in
its own family's verifier. AR-1 binds; it does not re-verify on their behalf.
Steps 1–6 require only the envelope and a public key. That is what makes a
standalone verifier possible, and shipping that verifier is what turns an
internal convention into something a third party can adopt.
## 7. Conformance
An implementation conforms at **AR-1/basic** when, given the published pack:
- every positive vector verifies, and the re-derived receipt id and canonical
core match the published `id_hex` and `core_hex` byte-for-byte;
- every negative vector is **rejected**, despite carrying a genuine signature.
The negatives are the substance. An implementation that checks signatures and
skips the structural rules passes the positives and fails the pack — which is
exactly the failure mode the pack is designed to catch.
## 8. What AR-1 deliberately does not do
- **Key custody and recovery.** Unsolved everywhere; AR-1 must not be built in a
way that presumes a solution.
- **Re-verifying bound receipts.** Each family owns its own verification. AR-1
binds content-ids and stops there.
- **Proving the energy figure is honest.** It carries provenance so a reader can
judge; it does not adjudicate.
- **Undoing effects.** See §4.
## 9. Security considerations
**A valid signature is not a valid receipt.** The three rules exist because
signature verification alone accepts well-formed lies. The negative vectors
demonstrate this concretely: each is signed with the real fixture key and each
must be refused.
**Content-id binding is only as strong as the bound artifacts.** AR-1 proves
*which* authority receipt, attestation and work receipt were referenced. It does
not prove those artifacts are themselves sound — that is their own verifiers'
job, and a complete audit runs all of them.
**The energy cross-check is a consistency check, not a proof.** An attestation
asserts; joules are measured. Binding both means a forged attestation must also
maintain a plausible energy profile across an independently sampled counter, and
that the failure is visible rather than silent. An adversary with physical
access who can forge a quote can also influence measurement. Claiming more than
this would be exactly the overreach the design exists to avoid.

View file

@ -0,0 +1,244 @@
//! Emit the AR-1 conformance vector pack.
//!
//! ```text
//! cargo run -p jcp-action-receipt --example emit_vectors -- jcp/conformance/v1
//! ```
//!
//! Writes `action_receipt.json` and `action_receipt_meta.json`, following the
//! shape the existing JCP packs use: a `meta` file declaring the algorithm,
//! profile, public key and steward, and a vectors file carrying signed
//! envelopes as hex.
//!
//! The signing key is a **published fixture**, deliberately: a conformance
//! vector nobody else can verify is not a conformance vector. It is the
//! all-`0x2a` key and must never be used for anything real.
//!
//! Both positive and negative vectors ship. The negatives are the point — they
//! pin the three structural rules, so an implementation that accepts a
//! well-signed but ill-formed receipt fails the pack rather than passing it.
use ed25519_dalek::SigningKey;
use jcp_action_receipt::{
ActionReceipt, Effect, EffectClass, Egress, EgressClass, verify,
};
use jcp_receipt::jcr1;
use jcp_schema::ContentId;
use serde_json::{Value, json};
/// Published fixture key. Not a secret; never use it for anything real.
const FIXTURE_SEED: [u8; 32] = [0x2a; 32];
const STEWARD: &str = "did:example:ar-reference";
fn cid(tag: &str) -> ContentId {
ContentId::of_bytes(tag.as_bytes())
}
fn base() -> ActionReceipt {
ActionReceipt {
closed_at: "2026-08-25T12:00:00Z".into(),
grant_id: cid("grant/root"),
chain_ids: vec![cid("grant/root"), cid("grant/delegated")],
authority_receipt: cid("jcp-receipt/allow"),
verdict: "allow".into(),
attestation_id: cid("attest/eat"),
proof_cell_id: Some(cid("proof/cell")),
tier: "S5".into(),
grounding: "hardware".into(),
work_receipt: cid("jcr1/resolution"),
input_hash: "a".repeat(64),
joules_uj: 19_538_280,
energy_provenance: "HwShunt".into(),
effect: Effect {
class: EffectClass::Reversible,
target: cid("target/document"),
before: Some("b".repeat(64)),
after: Some("c".repeat(64)),
compensator: None,
plan_receipt: None,
},
egress: Egress {
class: EgressClass::None,
bytes: 0,
peer: None,
},
steward: STEWARD.into(),
}
}
/// A signed vector plus the properties a verifier must reproduce.
fn positive(name: &str, note: &str, r: &ActionReceipt, key: &SigningKey) -> Value {
let env = r.seal(key).expect("valid receipt must seal");
// Prove the vector before publishing it — a pack that ships an
// unverifiable vector is worse than no pack.
let v = verify(&env, &key.verifying_key(), STEWARD).expect("emitted vector must verify");
assert_eq!(v.id, r.id().unwrap());
json!({
"name": name,
"note": note,
"expect": "verify",
"id_hex": r.id().unwrap().to_hex(),
"core_hex": hex::encode(r.signed_core().unwrap()),
"envelope_hex": hex::encode(&env),
"wire": r.to_wire(),
})
}
/// A negative vector: correctly signed, structurally invalid. Built by signing
/// a hand-edited projection so the signature is genuine — an implementation
/// that only checks signatures will accept it, which is exactly what the pack
/// is designed to catch.
fn negative(name: &str, note: &str, expect: &str, wire: Value, key: &SigningKey) -> Value {
let core = jcr1::signed_core_bytes(&wire).expect("core");
let env = jcr1::cose_sign1_envelope(&core, key, STEWARD);
// The signature really is valid...
jcr1::verify_cose_sign1(&env, STEWARD, key.verifying_key().as_bytes())
.expect("negative vector must carry a genuine signature");
// ...and AR-1 must still refuse it.
assert!(
verify(&env, &key.verifying_key(), STEWARD).is_err(),
"negative vector `{name}` was accepted — the rule it pins is not enforced"
);
json!({
"name": name,
"note": note,
"expect": expect,
"envelope_hex": hex::encode(&env),
"wire": wire,
})
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let out_dir = std::env::args().nth(1).unwrap_or_else(|| ".".into());
let key = SigningKey::from_bytes(&FIXTURE_SEED);
let mut vectors = Vec::new();
// ── positives: one per effect class, one per egress class ──────────
vectors.push(positive(
"reversible-local",
"Read-modify-write resolved on-device. Nothing left the machine, so egress is `none` with zero bytes.",
&base(),
&key,
));
let mut r = base();
r.effect.class = EffectClass::None;
r.effect.before = None;
r.effect.after = None;
vectors.push(positive(
"read-only",
"A query that changed nothing. Safe to replay; no before/after state to record.",
&r,
&key,
));
let mut r = base();
r.effect.class = EffectClass::Compensable;
r.effect.compensator = Some(cid("grant/refund"));
vectors.push(positive(
"compensable-with-compensator",
"Cannot be undone, but the grant that could compensate is named at the time of acting — not discovered afterwards.",
&r,
&key,
));
let mut r = base();
r.effect.class = EffectClass::Irreversible;
r.effect.plan_receipt = Some(cid("plan/receipt"));
vectors.push(positive(
"irreversible-with-plan",
"An irreversible commit carrying the plan receipt that preceded it. This is the only shape in which `irreversible` is well-formed.",
&r,
&key,
));
let mut r = base();
r.egress.class = EgressClass::AttestedEnclave;
r.egress.bytes = 4_096;
r.egress.peer = Some(cid("attest/peer-enclave"));
vectors.push(positive(
"egress-attested-enclave",
"Work left the device to somewhere that proved what it was running. The peer attestation is bound in the receipt.",
&r,
&key,
));
let mut r = base();
r.egress.class = EgressClass::ThirdParty;
r.egress.bytes = 8_192;
r.egress.peer = None;
r.tier = "S0".into();
r.grounding = "software".into();
vectors.push(positive(
"egress-third-party-honest",
"An unattested destination, honestly recorded rather than upgraded. Trust is not an egress class.",
&r,
&key,
));
let mut r = base();
r.energy_provenance = "Estimator".into();
r.joules_uj = 1_200_000;
vectors.push(positive(
"estimated-energy",
"Energy from an estimator, not a hardware counter. `HwShunt` and `Estimator` are different claims and must never collapse into one number.",
&r,
&key,
));
// ── negatives: the three structural rules ──────────────────────────
let mut w = base().to_wire();
w["effect"]["class"] = json!("irreversible");
vectors.push(negative(
"irreversible-without-plan",
"Correctly signed, structurally invalid: an irreversible effect with no plan receipt. A verifier that only checks signatures accepts this.",
"reject:irreversible-without-plan",
w,
&key,
));
let mut w = base().to_wire();
w["egress"]["bytes"] = json!(4_096u64);
vectors.push(negative(
"egress-none-with-bytes",
"Claims nothing left the device while counting 4096 bytes that did. The claim is falsified by its own byte count.",
"reject:egress-none-with-bytes",
w,
&key,
));
let mut w = base().to_wire();
w["egress"]["class"] = json!("attested_enclave");
w["egress"]["bytes"] = json!(4_096u64);
vectors.push(negative(
"attested-egress-without-peer",
"Claims an attested destination with no peer attestation to bind. The router may not claim a stronger class than its evidence supports.",
"reject:attested-egress-without-peer",
w,
&key,
));
let meta = json!({
"alg": "EdDSA (COSE -8)",
"profile": jcp_action_receipt::AR_PROFILE,
"pubkey_hex": hex::encode(key.verifying_key().as_bytes()),
"steward": STEWARD,
"note": "Fixture key, published deliberately so third parties can verify. Never use it for anything real.",
"positives": vectors.iter().filter(|v| v["expect"] == "verify").count(),
"negatives": vectors.iter().filter(|v| v["expect"] != "verify").count(),
});
let vpath = format!("{out_dir}/action_receipt.json");
let mpath = format!("{out_dir}/action_receipt_meta.json");
std::fs::write(&vpath, serde_json::to_string_pretty(&json!({ "vectors": vectors }))? + "\n")?;
std::fs::write(&mpath, serde_json::to_string_pretty(&meta)? + "\n")?;
println!("wrote {vpath}");
println!("wrote {mpath}");
println!(
" {} positive, {} negative",
meta["positives"], meta["negatives"]
);
Ok(())
}

View file

@ -0,0 +1,234 @@
//! End-to-end Action Receipt on real hardware.
//!
//! ```text
//! cargo run -p jcp-action-receipt --example end_to_end -- /tmp/action.hex
//! ```
//!
//! Implements §5 step 6 of the blueprint: **one agent action, under a real
//! delegated grant, with energy read off this host's own counters, sealed into
//! an AR-1 receipt that a third party verifies from the published spec alone.**
//!
//! Only the workload is a stand-in, so the example runs anywhere. Everything
//! around it is the real machinery:
//!
//! - the grant is **really issued** and **really attenuated**, and amplification
//! is really refused;
//! - the authorisation is a **real `decide` call** against a real budget, and
//! the receipt records the verdict that call returned;
//! - the joules are **measured**, and the meter's provenance is carried through
//! verbatim. On a host with no counter it reports `Estimator` and this example
//! says so rather than inventing `HwShunt`;
//! - the tier is stamped from what is **actually running**. This is in-process
//! with no isolation boundary crossed, so it is `S0`. Claiming `S5` without a
//! microVM is exactly the overreach the ladder exists to prevent.
use ed25519_dalek::SigningKey;
use jcp_action_receipt::{ActionReceipt, Effect, EffectClass, Egress, EgressClass, verify};
use jcp_grant::{attenuate, issue};
use jcp_receipt as authority;
use jcp_runtime::Runtime;
use jcp_schema::{
Capability, ContentId, Did, Energy, Frame, FrameKind, Grant, Trust, Verdict,
};
use sandbox_meter::{DeviceEnergy, PowerMeter, Receipt as WorkReceipt};
use sandbox_schema::Tier;
const STEWARD: &str = "did:example:ar-e2e";
fn main() -> Result<(), Box<dyn std::error::Error>> {
let out = std::env::args().nth(1).unwrap_or_else(|| "action.hex".into());
// ── 1. A real grant, really delegated ────────────────────────────
let issuer = SigningKey::from_bytes(&[11u8; 32]);
let agent = SigningKey::from_bytes(&[22u8; 32]);
let subagent = SigningKey::from_bytes(&[33u8; 32]);
let agent_did = Did::from_verifying_key(&agent.verifying_key());
let sub_did = Did::from_verifying_key(&subagent.verifying_key());
let resource = ContentId::of_bytes(b"resource/quarterly-report");
let root = Grant {
issuer: Did::from_verifying_key(&issuer.verifying_key()),
subject: agent_did,
capability: Capability::new(resource, ["read", "summarise"]),
budget_uj: 50_000_000,
budget_funds: None,
caveats: Vec::new(),
expiry: 0,
parent: None,
delegate_depth: None,
nonce: [1u8; 16],
};
let sg = issue(&issuer, root.clone())?;
// Strictly narrower: read only, one fifth of the ceiling.
let delegated = attenuate(
&sg,
&agent,
sub_did,
Capability::new(resource, ["read"]),
10_000_000,
0,
[2u8; 16],
)?;
// And prove the runtime really refuses amplification, rather than asserting it.
let amplified = attenuate(
&sg,
&agent,
sub_did,
Capability::new(resource, ["read", "delete"]),
10_000_000,
0,
[3u8; 16],
);
assert!(amplified.is_err(), "amplification must be refused");
println!("1. grant issued, attenuated to read-only — amplification refused: {}",
amplified.unwrap_err());
// ── 2. A real authorisation decision ─────────────────────────────
let mut rt = Runtime::new();
let frame = Frame {
kind: FrameKind::ToolCall,
trust: Trust::Control,
grant_id: delegated.grant.id(),
action: "read".into(),
resource,
payload_hash: ContentId::of_bytes(b"input/quarterly-report"),
};
let decision = rt.decide(&frame, &delegated, sub_did, Energy::measured(250_000), 0);
let verdict = match decision.verdict {
Verdict::Allow => "allow",
Verdict::Deny(_) => "deny",
};
// Seal the REAL authority receipt from the decision that just happened, and
// take its content id from the bytes rather than naming a placeholder.
let steward_key = SigningKey::from_bytes(&[44u8; 32]);
let authority_env =
authority::seal(&frame, &delegated.grant, &decision, &steward_key, STEWARD)?;
let authority_core =
authority::signed_core(&frame, &delegated.grant, &decision, STEWARD)?;
let authority_id = ContentId::of_bytes(&authority_core);
// Prove it verifies on its own terms before binding it.
authority::verify(
&frame,
&delegated.grant,
&decision,
&authority_env,
STEWARD,
steward_key.verifying_key().as_bytes(),
)?;
println!(
"2. decide() → {verdict}, {} µJ remaining; authority receipt sealed + verified, id {}",
decision.budget_remaining_uj,
&authority_id.to_hex()[..12]
);
// ── 3. Real work, really measured ────────────────────────────────
let mut meter = PowerMeter::detect();
let sources = meter.sources().join(",");
let is_hw = meter.is_hardware();
let span = meter.start();
let mut acc: u64 = 0;
for i in 0..40_000_000u64 {
acc = acc.wrapping_add(i ^ (acc >> 7)).rotate_left(3);
}
let measurement = span.stop(&mut meter);
std::hint::black_box(acc);
let joules_uj = measurement.total_uj();
let provenance = if is_hw { "HwShunt" } else { "Estimator" };
println!(
"3. work metered — {joules_uj} µJ [{provenance}] over {:.2}s via {sources}",
measurement.wall.as_secs_f64()
);
if !is_hw {
println!(" note: no hardware counter here; provenance is Estimator, not HwShunt");
}
// Build the REAL work receipt from the devices the meter actually reported.
// `Receipt::build` enforces the provenance/measured coupling itself, so a
// mislabelled device is refused here rather than propagating into AR-1.
let devices: Vec<DeviceEnergy> = measurement
.devices
.iter()
.map(|d| DeviceEnergy {
class: d.class,
measured_uj: d.measured_uj,
estimated_uj: d.estimated_uj,
provenance: d.provenance,
})
.collect();
let work = WorkReceipt::build(
sandbox_schema::ContentId::of_bytes(b"unit/quarterly-report-summarise"),
Tier::S0,
devices,
1,
[7u8; 8],
)?;
work.validate()?;
// The two families agree on BLAKE3 and disagree only on presentation:
// sandbox renders `b3:<base64url>`, jcp carries raw 32 bytes. Re-addressing
// the same canonical core with jcp's hasher yields the identical digest, so
// the binding is exact rather than a hash of a hash.
let work_id = ContentId::of_bytes(&work.canonical_core());
debug_assert_eq!(
work.content_id().as_str().trim_start_matches("b3:").len(),
43,
"sandbox content id should be b3:<base64url of 32 bytes>"
);
println!(
" work receipt sealed over {} metered device(s), id {}",
measurement.devices.len(),
&work_id.to_hex()[..12]
);
// ── 4. Seal the Action Receipt ───────────────────────────────────
let receipt = ActionReceipt {
closed_at: "2026-08-25T12:00:00Z".into(),
grant_id: delegated.grant.id(),
chain_ids: vec![sg.grant.id(), delegated.grant.id()],
authority_receipt: authority_id,
verdict: verdict.into(),
attestation_id: ContentId::of_bytes(b"attest/e2e-local"),
proof_cell_id: None,
tier: "S0".into(),
grounding: if is_hw { "hardware" } else { "software" }.into(),
work_receipt: work_id,
input_hash: ContentId::of_bytes(b"input/quarterly-report").to_hex(),
joules_uj,
energy_provenance: provenance.into(),
effect: Effect {
// read-and-summarise changed nothing in the world
class: EffectClass::None,
target: resource,
before: None,
after: None,
compensator: None,
plan_receipt: None,
},
egress: Egress {
// resolved entirely in this process
class: EgressClass::None,
bytes: 0,
peer: None,
},
steward: STEWARD.into(),
};
let envelope = receipt.seal(&steward_key)?;
println!("4. sealed — receipt id {}", receipt.id()?.to_hex());
// ── 5. Verify it back, as a third party would ────────────────────
let v = verify(&envelope, &steward_key.verifying_key(), STEWARD)?;
assert_eq!(v.id, receipt.id()?);
println!("5. verified from the envelope alone — {} byte canonical core", v.core.len());
std::fs::write(&out, hex::encode(&envelope))?;
println!();
println!("wrote {out}");
println!(
"verify independently:\n ar-verify {out} --pubkey {} --steward {STEWARD}",
hex::encode(steward_key.verifying_key().as_bytes())
);
Ok(())
}

View file

@ -0,0 +1,374 @@
//! `ar-verify` — the standalone Action Receipt verifier.
//!
//! This is the deliverable that makes AR-1 matter to anyone outside this tree.
//! A format nobody else can check is a convention; a format with a verifier a
//! third party can run is a standard. Everything it needs arrives on the command
//! line — an envelope, a public key, a steward — and it reaches the network
//! never.
//!
//! ```text
//! ar-verify <envelope.hex> --pubkey <hex> --steward <did>
//! ar-verify --pack <dir> # check a whole conformance pack
//! ar-verify <envelope.hex> ... --json
//! ```
//!
//! It reports **each binding separately**, because "invalid" is not a useful
//! audit finding. An auditor needs to know *which* claim failed and why.
//!
//! Exit codes: `0` all checks passed · `1` a check failed · `2` bad usage.
use ed25519_dalek::VerifyingKey;
use jcp_action_receipt::{ArError, verify};
use serde_json::Value;
use std::process::ExitCode;
fn main() -> ExitCode {
let args: Vec<String> = std::env::args().skip(1).collect();
if args.is_empty() || args.iter().any(|a| a == "-h" || a == "--help") {
usage();
return ExitCode::from(2);
}
let json_out = args.iter().any(|a| a == "--json");
if let Some(i) = args.iter().position(|a| a == "--pack") {
let Some(dir) = args.get(i + 1) else {
eprintln!("--pack needs a directory");
return ExitCode::from(2);
};
return verify_pack(dir, json_out);
}
let path = &args[0];
let Some(pubkey) = flag(&args, "--pubkey") else {
eprintln!("--pubkey <hex> is required");
return ExitCode::from(2);
};
let Some(steward) = flag(&args, "--steward") else {
eprintln!("--steward <did> is required");
return ExitCode::from(2);
};
let envelope = match read_envelope(path) {
Ok(b) => b,
Err(e) => {
eprintln!("{path}: {e}");
return ExitCode::from(2);
}
};
let vk = match parse_key(&pubkey) {
Ok(k) => k,
Err(e) => {
eprintln!("--pubkey: {e}");
return ExitCode::from(2);
}
};
verify_one(&envelope, &vk, &steward, json_out)
}
fn usage() {
eprintln!(
"ar-verify — independently check an Action Receipt (AR-1)\n\
\n\
USAGE\n \
ar-verify <envelope.hex|envelope.bin> --pubkey <hex> --steward <did> [--json]\n \
ar-verify --pack <conformance-dir> [--json]\n\
\n\
Reads only what you give it. Never touches the network."
);
}
fn flag(args: &[String], name: &str) -> Option<String> {
args.iter()
.position(|a| a == name)
.and_then(|i| args.get(i + 1))
.cloned()
}
/// Accept either a hex text file or raw envelope bytes — an auditor should not
/// have to know which form the sender chose.
fn read_envelope(path: &str) -> Result<Vec<u8>, String> {
let raw = std::fs::read(path).map_err(|e| e.to_string())?;
if let Ok(text) = std::str::from_utf8(&raw) {
let t: String = text.split_whitespace().collect();
if !t.is_empty() && t.len() % 2 == 0 && t.bytes().all(|c| c.is_ascii_hexdigit()) {
return hex::decode(&t).map_err(|e| e.to_string());
}
}
Ok(raw)
}
fn parse_key(hexstr: &str) -> Result<VerifyingKey, String> {
let raw = hex::decode(hexstr.trim()).map_err(|e| e.to_string())?;
let arr: [u8; 32] = raw
.as_slice()
.try_into()
.map_err(|_| format!("expected 32 bytes, got {}", raw.len()))?;
VerifyingKey::from_bytes(&arr).map_err(|e| e.to_string())
}
/// One line per checked property. `ok` is what an auditor reads; `detail` is
/// what they quote when it fails.
struct Check {
ok: bool,
name: &'static str,
detail: String,
}
fn verify_one(envelope: &[u8], vk: &VerifyingKey, steward: &str, json_out: bool) -> ExitCode {
let mut checks: Vec<Check> = Vec::new();
let result = verify(envelope, vk, steward);
match &result {
Ok(v) => {
checks.push(Check {
ok: true,
name: "signature",
detail: format!("COSE_Sign1 EdDSA verified, kid = {steward}"),
});
checks.push(Check {
ok: true,
name: "canonical-core",
detail: format!("{} bytes decoded as canonical det-CBOR, no trailing data", v.core.len()),
});
checks.push(Check {
ok: true,
name: "profile",
detail: v.wire["ar_receipt"].as_str().unwrap_or("?").to_string(),
});
checks.push(Check {
ok: true,
name: "receipt-id",
detail: v.id.to_hex(),
});
// The four bindings, reported individually.
let w = &v.wire;
checks.push(Check {
ok: true,
name: "binding:authority",
detail: format!(
"grant {} · verdict {} · chain depth {}",
short(w, "grant_id"),
w["verdict"].as_str().unwrap_or("?"),
w["chain_ids"].as_array().map(|a| a.len()).unwrap_or(0)
),
});
checks.push(Check {
ok: true,
name: "binding:environment",
detail: format!(
"tier {} · grounding {} · attestation {}",
w["tier"].as_str().unwrap_or("?"),
w["grounding"].as_str().unwrap_or("?"),
short(w, "attestation_id")
),
});
checks.push(Check {
ok: true,
name: "binding:work",
detail: format!(
"{} µJ [{}] · receipt {}",
w["joules_uj"].as_u64().unwrap_or(0),
w["energy_provenance"].as_str().unwrap_or("?"),
short(w, "work_receipt")
),
});
let eff = &w["effect"];
checks.push(Check {
ok: true,
name: "binding:effect",
detail: format!(
"class {}{}",
eff["class"].as_str().unwrap_or("?"),
if eff.get("plan_receipt").is_some() {
" · plan bound"
} else if eff.get("compensator").is_some() {
" · compensator bound"
} else {
""
}
),
});
let eg = &w["egress"];
checks.push(Check {
ok: true,
name: "binding:egress",
detail: format!(
"class {} · {} bytes{}",
eg["class"].as_str().unwrap_or("?"),
eg["bytes"].as_u64().unwrap_or(0),
if eg.get("peer").is_some() { " · peer attested" } else { "" }
),
});
// The three rules held, or verify() would have refused.
checks.push(Check {
ok: true,
name: "rule:irreversible-needs-plan",
detail: "satisfied".into(),
});
checks.push(Check {
ok: true,
name: "rule:egress-none-zero-bytes",
detail: "satisfied".into(),
});
checks.push(Check {
ok: true,
name: "rule:attested-needs-peer",
detail: "satisfied".into(),
});
// Honest caveat, always printed. AR-1 binds; it does not re-verify.
checks.push(Check {
ok: true,
name: "note:bound-artifacts",
detail: "content-ids bound but NOT resolved — run each family's own verifier for a complete audit".into(),
});
}
Err(e) => {
// Name the specific failure rather than a generic "invalid".
let (name, detail): (&'static str, String) = match e {
ArError::IrreversibleWithoutPlan => (
"rule:irreversible-needs-plan",
"REFUSED — irreversible effect with no plan receipt. The signature is valid; the receipt is not.".into(),
),
ArError::EgressNoneWithBytes(n) => (
"rule:egress-none-zero-bytes",
format!("REFUSED — egress class `none` while counting {n} bytes that left the device"),
),
ArError::AttestedEgressWithoutPeer => (
"rule:attested-needs-peer",
"REFUSED — `attested_enclave` claimed with no peer attestation to bind".into(),
),
ArError::UnknownProfile(p) => ("profile", format!("REFUSED — unknown profile `{p}`")),
ArError::Jcr1(inner) => ("signature", format!("REFUSED — {inner}")),
ArError::Decode(inner) => ("canonical-core", format!("REFUSED — {inner}")),
ArError::MissingField(f) => ("canonical-core", format!("REFUSED — missing field `{f}`")),
};
checks.push(Check { ok: false, name, detail });
}
}
let failed = checks.iter().filter(|c| !c.ok).count();
if json_out {
let arr: Vec<Value> = checks
.iter()
.map(|c| serde_json::json!({ "check": c.name, "ok": c.ok, "detail": c.detail }))
.collect();
println!(
"{}",
serde_json::to_string_pretty(&serde_json::json!({
"verified": failed == 0,
"checks": arr,
}))
.unwrap()
);
} else {
for c in &checks {
println!("{} {:<32} {}", if c.ok { " ok " } else { " FAIL " }, c.name, c.detail);
}
println!();
println!(
"{}",
if failed == 0 {
"VERIFIED — every binding and rule checked from the envelope alone."
} else {
"NOT VERIFIED"
}
);
}
if failed == 0 { ExitCode::SUCCESS } else { ExitCode::from(1) }
}
/// Verify a whole conformance pack: positives must verify, negatives must be
/// refused. This is how an implementer proves conformance to themselves.
fn verify_pack(dir: &str, json_out: bool) -> ExitCode {
let meta_p = format!("{dir}/action_receipt_meta.json");
let vec_p = format!("{dir}/action_receipt.json");
let meta: Value = match std::fs::read(&meta_p).ok().and_then(|b| serde_json::from_slice(&b).ok()) {
Some(v) => v,
None => {
eprintln!("cannot read {meta_p}");
return ExitCode::from(2);
}
};
let pack: Value = match std::fs::read(&vec_p).ok().and_then(|b| serde_json::from_slice(&b).ok()) {
Some(v) => v,
None => {
eprintln!("cannot read {vec_p}");
return ExitCode::from(2);
}
};
let vk = match meta["pubkey_hex"].as_str().map(parse_key) {
Some(Ok(k)) => k,
_ => {
eprintln!("{meta_p}: bad or missing pubkey_hex");
return ExitCode::from(2);
}
};
let steward = meta["steward"].as_str().unwrap_or_default().to_string();
let empty = vec![];
let vectors = pack["vectors"].as_array().unwrap_or(&empty);
let mut pass = 0usize;
let mut fail = 0usize;
let mut lines = Vec::new();
for v in vectors {
let name = v["name"].as_str().unwrap_or("<unnamed>");
let expect_verify = v["expect"].as_str().unwrap_or("verify") == "verify";
let Some(env) = v["envelope_hex"].as_str().and_then(|h| hex::decode(h).ok()) else {
lines.push((false, name.to_string(), "unreadable envelope_hex".to_string()));
fail += 1;
continue;
};
let got = verify(&env, &vk, &steward);
let ok = got.is_ok() == expect_verify;
let detail = match (&got, expect_verify) {
(Ok(_), true) => "verified as expected".to_string(),
(Err(e), false) => format!("refused as expected — {e}"),
(Ok(_), false) => "ACCEPTED a vector that must be refused".to_string(),
(Err(e), true) => format!("REJECTED a valid vector — {e}"),
};
if ok { pass += 1 } else { fail += 1 }
lines.push((ok, name.to_string(), detail));
}
if json_out {
let arr: Vec<Value> = lines
.iter()
.map(|(ok, n, d)| serde_json::json!({ "vector": n, "ok": ok, "detail": d }))
.collect();
println!(
"{}",
serde_json::to_string_pretty(&serde_json::json!({
"conformant": fail == 0, "pass": pass, "fail": fail, "vectors": arr
}))
.unwrap()
);
} else {
for (ok, n, d) in &lines {
println!("{} {:<34} {}", if *ok { " ok " } else { " FAIL " }, n, d);
}
println!();
println!("{pass} passed, {fail} failed");
if fail == 0 {
println!("CONFORMANT — AR-1/basic. Positives verify; negatives are refused despite valid signatures.");
}
}
if fail == 0 { ExitCode::SUCCESS } else { ExitCode::from(1) }
}
fn short(w: &Value, key: &str) -> String {
w[key]
.as_str()
.map(|s| s.chars().take(12).collect::<String>() + "…")
.unwrap_or_else(|| "?".into())
}

View file

@ -0,0 +1,228 @@
//! Canonical det-CBOR decoder for the AR-1 subset.
//!
//! `jcp_receipt::jcr1` ships a canonical *encoder* and no decoder, because
//! nothing downstream of it needed to read a signed core back. A verifier does:
//! the point of AR-1 is that a third party holding only an envelope can check
//! the structural rules for themselves, and that requires recovering the
//! projection from the bytes.
//!
//! Rather than take a CBOR dependency — AR-1's whole claim is that it adds no
//! new primitives — this is the exact inverse of the encoder's subset, and
//! nothing more. The encoder emits four major types (RFC 8949 §4.2.1: maps,
//! arrays, text strings, unsigned integers; no floats, bools, nulls or tags),
//! so those four are all this decodes. Anything else is refused rather than
//! guessed at, which is the same discipline the encoder applies on the way out.
//!
//! `decode_roundtrips_every_encoded_shape` pins the two halves together.
use serde_json::{Map, Value};
/// Why a canonical decode failed.
#[derive(Debug, thiserror::Error)]
pub enum DecodeError {
/// Input ended mid-item.
#[error("truncated input at byte {0}")]
Truncated(usize),
/// A major type outside the canonical subset appeared.
#[error("major type {0} is outside the canonical subset at byte {1}")]
UnsupportedMajor(u8, usize),
/// An additional-information value the canonical form never emits.
#[error("non-canonical length encoding at byte {0}")]
NonCanonicalLength(usize),
/// A text string was not valid UTF-8.
#[error("invalid utf-8 in text string at byte {0}")]
BadUtf8(usize),
/// A map key was not a text string.
#[error("non-text map key at byte {0}")]
NonTextKey(usize),
/// Bytes remained after the top-level item.
#[error("{0} trailing byte(s) after top-level item")]
Trailing(usize),
}
/// Decode canonical det-CBOR produced by `jcr1::canonical_cbor` back to JSON.
///
/// Rejects trailing bytes: a signed core is exactly one item, and anything
/// appended to it is either corruption or an attempt to smuggle data past a
/// verifier that stops reading at the first complete value.
pub fn from_canonical_cbor(bytes: &[u8]) -> Result<Value, DecodeError> {
let mut p = Parser { b: bytes, i: 0 };
let v = p.value()?;
if p.i != bytes.len() {
return Err(DecodeError::Trailing(bytes.len() - p.i));
}
Ok(v)
}
struct Parser<'a> {
b: &'a [u8],
i: usize,
}
impl<'a> Parser<'a> {
fn byte(&mut self) -> Result<u8, DecodeError> {
let b = *self.b.get(self.i).ok_or(DecodeError::Truncated(self.i))?;
self.i += 1;
Ok(b)
}
fn take(&mut self, n: usize) -> Result<&'a [u8], DecodeError> {
let end = self.i.checked_add(n).ok_or(DecodeError::Truncated(self.i))?;
let s = self.b.get(self.i..end).ok_or(DecodeError::Truncated(self.i))?;
self.i = end;
Ok(s)
}
/// Argument of a head byte, enforcing the shortest-form rule the canonical
/// encoder guarantees. A longer-than-necessary encoding is a different byte
/// string for the same value, which would break content addressing.
fn arg(&mut self, ai: u8) -> Result<u64, DecodeError> {
let at = self.i - 1;
Ok(match ai {
0..=23 => ai as u64,
24 => {
let v = self.byte()? as u64;
if v < 24 {
return Err(DecodeError::NonCanonicalLength(at));
}
v
}
25 => {
let s = self.take(2)?;
let v = u16::from_be_bytes([s[0], s[1]]) as u64;
if v <= u8::MAX as u64 {
return Err(DecodeError::NonCanonicalLength(at));
}
v
}
26 => {
let s = self.take(4)?;
let v = u32::from_be_bytes([s[0], s[1], s[2], s[3]]) as u64;
if v <= u16::MAX as u64 {
return Err(DecodeError::NonCanonicalLength(at));
}
v
}
27 => {
let s = self.take(8)?;
let v = u64::from_be_bytes([s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]]);
if v <= u32::MAX as u64 {
return Err(DecodeError::NonCanonicalLength(at));
}
v
}
_ => return Err(DecodeError::NonCanonicalLength(at)),
})
}
fn value(&mut self) -> Result<Value, DecodeError> {
let at = self.i;
let head = self.byte()?;
let major = head >> 5;
let ai = head & 0x1f;
match major {
0 => Ok(Value::from(self.arg(ai)?)),
3 => {
let n = self.arg(ai)? as usize;
let s = self.take(n)?;
Ok(Value::String(
std::str::from_utf8(s)
.map_err(|_| DecodeError::BadUtf8(at))?
.to_owned(),
))
}
4 => {
let n = self.arg(ai)? as usize;
let mut out = Vec::with_capacity(n.min(1024));
for _ in 0..n {
out.push(self.value()?);
}
Ok(Value::Array(out))
}
5 => {
let n = self.arg(ai)? as usize;
let mut out = Map::new();
for _ in 0..n {
let kat = self.i;
let k = match self.value()? {
Value::String(s) => s,
_ => return Err(DecodeError::NonTextKey(kat)),
};
out.insert(k, self.value()?);
}
Ok(Value::Object(out))
}
m => Err(DecodeError::UnsupportedMajor(m, at)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use jcp_receipt::jcr1;
use serde_json::json;
/// The property that matters: whatever the canonical encoder emits, this
/// reads back identically. If these two ever drift, a verifier and a signer
/// disagree about what a receipt says.
#[test]
fn decode_roundtrips_every_encoded_shape() {
let cases = vec![
json!({}),
json!({"a": 0}),
json!({"a": 23, "b": 24, "c": 255, "d": 256, "e": 65535, "f": 65536}),
json!({"big": 4_294_967_296u64, "huge": 19_538_280u64}),
json!({"s": "", "t": "hello", "u": "a".repeat(64)}),
json!({"arr": [1, 2, 3], "empty": []}),
json!({"nested": {"deep": {"deeper": [1, {"x": "y"}]}}}),
json!({"unicode": "joules — ⚡ 変換"}),
json!({"long": "x".repeat(300)}),
];
for c in cases {
let enc = jcr1::canonical_cbor(&c).expect("encode");
let dec = from_canonical_cbor(&enc).expect("decode");
assert_eq!(dec, c, "round-trip mismatch for {c}");
}
}
#[test]
fn rejects_trailing_bytes() {
let mut enc = jcr1::canonical_cbor(&json!({"a": 1})).unwrap();
enc.push(0x00);
assert!(matches!(
from_canonical_cbor(&enc),
Err(DecodeError::Trailing(1))
));
}
#[test]
fn rejects_truncated_input() {
let enc = jcr1::canonical_cbor(&json!({"key": "value"})).unwrap();
assert!(from_canonical_cbor(&enc[..enc.len() - 2]).is_err());
}
#[test]
fn rejects_non_canonical_length() {
// 0x18 0x05 encodes 5 in two bytes where one would do. Same value,
// different bytes — which would break content addressing.
assert!(matches!(
from_canonical_cbor(&[0x18, 0x05]),
Err(DecodeError::NonCanonicalLength(0))
));
}
#[test]
fn rejects_types_outside_the_subset() {
// 0xf5 is `true` (major 7), which the canonical encoder never emits.
assert!(matches!(
from_canonical_cbor(&[0xf5]),
Err(DecodeError::UnsupportedMajor(7, 0))
));
// 0x40 is a byte string (major 2) — also outside the subset.
assert!(matches!(
from_canonical_cbor(&[0x40]),
Err(DecodeError::UnsupportedMajor(2, 0))
));
}
}

View file

@ -0,0 +1,564 @@
//! # Action Receipt (AR-1)
//!
//! **The composition envelope.** Three receipt families already ship, and each
//! holds one quarter of the answer to the question an auditor actually asks —
//! *under what authority did this agent do that, where did it run, and what did
//! it cost?* None of them binds to the others.
//!
//! | Family | Records | Carries |
//! |---|---|---|
//! | `jcp-receipt` | authority | grant chain, verdict, budget drawn |
//! | `sandbox-proof` | environment | attestation, isolation tier, substrate |
//! | JCR-1 | work | input hash, measured joules, energy provenance |
//! | *(nothing)* | **effect** | what changed, and whether it can be undone |
//!
//! AR-1 binds the first three **by content-id** and supplies the fourth. It is
//! an envelope, not a replacement: every existing family keeps its own canonical
//! encoding and its own signer, and every existing verifier keeps working
//! unchanged.
//!
//! ## No new cryptography
//!
//! Canonical det-CBOR (RFC 8949 §4.2.1) and the tagged COSE_Sign1 envelope are
//! reused verbatim from [`jcp_receipt::jcr1`]. This crate adds a field layout
//! and three structural rules — nothing else. If AR-1 ever needs a novel
//! primitive, that is a signal the design went wrong.
//!
//! ## The three rules that carry the weight
//!
//! A receipt format that merely *records* claims is a log. What makes AR-1
//! evidence is that certain shapes are refused at verification, so a violation
//! is detectable rather than a matter of trust:
//!
//! 1. **`effect: irreversible` requires a prior plan receipt.** The cascade's
//! body-tier design already separates plan from commit for actions that touch
//! the world. AR-1 binds that discipline into the artifact: an irreversible
//! effect with no `plan_receipt` fails verification.
//! 2. **`egress: none` requires zero bytes.** A claim that nothing left the
//! machine is falsifiable by its own byte count.
//! 3. **`egress: attested_enclave` requires a peer attestation.** The router may
//! never claim a stronger class than it can bind evidence for. An unattested
//! destination is `third_party` even when the operator believes it
//! trustworthy — trust is not an egress class.
//!
//! ## Status
//!
//! Draft. Field names are settled against the existing canonical projections but
//! the profile tag is `ar/1-draft` until the vector pack is reviewed.
mod decode;
pub use decode::{DecodeError, from_canonical_cbor};
use jcp_receipt::jcr1::{self, Jcr1Error};
use jcp_schema::ContentId;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value, json};
/// Profile tag carried in every AR-1 receipt.
pub const AR_PROFILE: &str = "ar/1-draft";
/// Errors surfaced by AR-1 construction or verification.
#[derive(Debug, thiserror::Error)]
pub enum ArError {
/// The underlying JCR-1 canonical encoding or envelope layer failed.
#[error("jcr1: {0}")]
Jcr1(#[from] Jcr1Error),
/// An `irreversible` effect arrived without the plan receipt that the
/// plan/commit split requires. See the module docs, rule 1.
#[error("irreversible effect requires a plan receipt (AR-1 §4)")]
IrreversibleWithoutPlan,
/// `egress: none` was claimed alongside a non-zero byte count.
#[error("egress class `none` claims {0} bytes left the device (AR-1 §3)")]
EgressNoneWithBytes(u64),
/// `egress: attested_enclave` was claimed with no peer attestation to bind.
#[error("egress class `attested_enclave` requires a peer attestation (AR-1 §3)")]
AttestedEgressWithoutPeer,
/// The receipt did not carry the profile tag this crate understands.
#[error("unknown profile: expected `{AR_PROFILE}`, found `{0}`")]
UnknownProfile(String),
/// A field required by the canonical projection was absent.
#[error("missing required field: {0}")]
MissingField(&'static str),
/// The signed core did not decode as canonical CBOR.
#[error("canonical decode: {0}")]
Decode(#[from] DecodeError),
}
/// What an action did to the world, and whether it can be taken back.
///
/// This is the only genuinely new field group in AR-1 — nothing in the three
/// existing families records it. The classes are ordered by how much of the
/// action survives a change of mind.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum EffectClass {
/// Read-only. Nothing changed; the action is safe to replay.
None,
/// Prior state is recoverable. Undo is a state transition.
Reversible,
/// Cannot be undone, but a compensating action exists and its grant is
/// named at the time of acting — not discovered afterwards.
Compensable,
/// Once committed, permanent. Requires plan/commit separation.
Irreversible,
}
impl EffectClass {
/// Wire spelling, pinned so the projection cannot drift with serde config.
pub fn wire_tag(self) -> &'static str {
match self {
Self::None => "none",
Self::Reversible => "reversible",
Self::Compensable => "compensable",
Self::Irreversible => "irreversible",
}
}
}
/// Where the work went, and what evidence backs that claim.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EgressClass {
/// Resolved on-device. Nothing left the machine.
None,
/// Left the device to somewhere that proved what it was running.
AttestedEnclave,
/// Left the device to an unattested destination. Named and counted —
/// and honestly marked as unverifiable.
ThirdParty,
}
impl EgressClass {
/// Wire spelling, pinned.
pub fn wire_tag(self) -> &'static str {
match self {
Self::None => "none",
Self::AttestedEnclave => "attested_enclave",
Self::ThirdParty => "third_party",
}
}
}
/// The effect record: binding four, and the piece no existing family carries.
#[derive(Debug, Clone)]
pub struct Effect {
/// How much of this action survives a change of mind.
pub class: EffectClass,
/// What was acted on.
pub target: ContentId,
/// State hash before the action, where observable.
pub before: Option<String>,
/// State hash after the action, where observable.
pub after: Option<String>,
/// A grant that could undo this, for `Compensable` effects.
pub compensator: Option<ContentId>,
/// The plan receipt that preceded an `Irreversible` commit. Required for
/// that class; its absence is a protocol violation, not a missing nicety.
pub plan_receipt: Option<ContentId>,
}
/// The egress record: binding five, the router's per-request privacy contract.
#[derive(Debug, Clone)]
pub struct Egress {
/// The strongest class the available evidence supports — never stronger.
pub class: EgressClass,
/// Bytes that left the device.
pub bytes: u64,
/// Attestation of the receiving side, for `AttestedEnclave`.
pub peer: Option<ContentId>,
}
/// One agent action, with every binding needed to check it independently.
#[derive(Debug, Clone)]
pub struct ActionReceipt {
/// RFC 3339 close time.
pub closed_at: String,
// -- binding 1: authority -------------------------------------------
/// The grant that permitted this action.
pub grant_id: ContentId,
/// The full delegation chain, root first. Empty for a root grant.
pub chain_ids: Vec<ContentId>,
/// The `jcp-receipt` recording the authorisation decision.
pub authority_receipt: ContentId,
/// The decision itself, carried here so a verifier need not fetch the
/// authority receipt to learn whether the action was permitted.
pub verdict: String,
// -- binding 2: environment -----------------------------------------
/// The attestation covering the execution environment.
pub attestation_id: ContentId,
/// The signed sandbox proof cell, where one exists.
pub proof_cell_id: Option<ContentId>,
/// Isolation tier, `S0`..`S7`.
pub tier: String,
/// Whether the attestation is rooted in silicon or in software. Carried
/// verbatim from the attestation; never upgraded here.
pub grounding: String,
// -- binding 3: work ------------------------------------------------
/// The JCR-1 resolution receipt for the work performed.
pub work_receipt: ContentId,
/// Hash of the input the work consumed.
pub input_hash: String,
/// Measured cost in microjoules.
pub joules_uj: u64,
/// How that figure was obtained. Never collapsed into a single number:
/// `HwShunt` and `Estimator` are not the same claim.
pub energy_provenance: String,
// -- bindings 4 and 5 -----------------------------------------------
/// What changed in the world.
pub effect: Effect,
/// What left the device.
pub egress: Egress,
/// The party accountable for this receipt. Required, as in JCR-1 §2.1.
pub steward: String,
}
impl ActionReceipt {
/// Check the three structural rules. Called by both [`Self::seal`] and
/// [`verify`], so an invalid receipt can be neither produced nor accepted.
pub fn check_discipline(&self) -> Result<(), ArError> {
if self.effect.class == EffectClass::Irreversible && self.effect.plan_receipt.is_none() {
return Err(ArError::IrreversibleWithoutPlan);
}
if self.egress.class == EgressClass::None && self.egress.bytes != 0 {
return Err(ArError::EgressNoneWithBytes(self.egress.bytes));
}
if self.egress.class == EgressClass::AttestedEnclave && self.egress.peer.is_none() {
return Err(ArError::AttestedEgressWithoutPeer);
}
Ok(())
}
/// The canonical JSON projection a third party canonicalises and hashes.
///
/// Absent optionals are omitted rather than emitted as null, matching
/// JCR-1 §3.1 — `signed_core_bytes` drops nulls, so emitting them would
/// produce a projection that does not round-trip.
pub fn to_wire(&self) -> Value {
let mut o = Map::new();
o.insert("ar_receipt".into(), json!(AR_PROFILE));
o.insert("closed_at".into(), json!(self.closed_at));
o.insert("grant_id".into(), json!(self.grant_id.to_hex()));
if !self.chain_ids.is_empty() {
let chain: Vec<Value> = self.chain_ids.iter().map(|c| json!(c.to_hex())).collect();
o.insert("chain_ids".into(), Value::Array(chain));
}
o.insert("authority_receipt".into(), json!(self.authority_receipt.to_hex()));
o.insert("verdict".into(), json!(self.verdict));
o.insert("attestation_id".into(), json!(self.attestation_id.to_hex()));
if let Some(p) = &self.proof_cell_id {
o.insert("proof_cell_id".into(), json!(p.to_hex()));
}
o.insert("tier".into(), json!(self.tier));
o.insert("grounding".into(), json!(self.grounding));
o.insert("work_receipt".into(), json!(self.work_receipt.to_hex()));
o.insert("input_hash".into(), json!(self.input_hash));
o.insert("joules_uj".into(), json!(self.joules_uj));
o.insert("energy_provenance".into(), json!(self.energy_provenance));
let mut e = Map::new();
e.insert("class".into(), json!(self.effect.class.wire_tag()));
e.insert("target".into(), json!(self.effect.target.to_hex()));
if let Some(b) = &self.effect.before {
e.insert("before".into(), json!(b));
}
if let Some(a) = &self.effect.after {
e.insert("after".into(), json!(a));
}
if let Some(c) = &self.effect.compensator {
e.insert("compensator".into(), json!(c.to_hex()));
}
if let Some(p) = &self.effect.plan_receipt {
e.insert("plan_receipt".into(), json!(p.to_hex()));
}
o.insert("effect".into(), Value::Object(e));
let mut g = Map::new();
g.insert("class".into(), json!(self.egress.class.wire_tag()));
g.insert("bytes".into(), json!(self.egress.bytes));
if let Some(p) = &self.egress.peer {
g.insert("peer".into(), json!(p.to_hex()));
}
o.insert("egress".into(), Value::Object(g));
o.insert("steward".into(), json!(self.steward));
Value::Object(o)
}
/// Canonical signed-core bytes — det-CBOR over [`Self::to_wire`], via the
/// JCR-1 encoder. These are exactly the bytes the envelope signs.
pub fn signed_core(&self) -> Result<Vec<u8>, ArError> {
Ok(jcr1::signed_core_bytes(&self.to_wire())?)
}
/// Content id of this receipt: BLAKE3 over the canonical signed core.
pub fn id(&self) -> Result<ContentId, ArError> {
Ok(ContentId::of_bytes(&self.signed_core()?))
}
/// Seal into a tagged COSE_Sign1 envelope. Refuses to sign a receipt that
/// violates the discipline rules — an invalid AR-1 cannot be produced by
/// this crate, only hand-forged.
pub fn seal(
&self,
signing_key: &ed25519_dalek::SigningKey,
) -> Result<Vec<u8>, ArError> {
self.check_discipline()?;
let core = self.signed_core()?;
Ok(jcr1::cose_sign1_envelope(&core, signing_key, &self.steward))
}
}
/// The outcome of verifying an AR-1 envelope: the signed core it carried, plus
/// the wire projection parsed back out of it.
#[derive(Debug, Clone)]
pub struct Verified {
/// The canonical bytes that were signed.
pub core: Vec<u8>,
/// The projection recovered from those bytes.
pub wire: Value,
/// Content id of the receipt.
pub id: ContentId,
}
/// Verify an AR-1 envelope end to end.
///
/// Checks, in order: COSE_Sign1 signature and `kid` against `expected_steward`;
/// the profile tag; then the three discipline rules **re-derived from the wire
/// projection**, not from a caller-supplied struct. A receipt that was
/// hand-forged to violate them is rejected here even though it signs correctly.
pub fn verify(
envelope: &[u8],
verifying_key: &ed25519_dalek::VerifyingKey,
expected_steward: &str,
) -> Result<Verified, ArError> {
let core = jcr1::verify_cose_sign1(envelope, expected_steward, verifying_key.as_bytes())?;
// jcr1 exposes an encoder but no decoder, so the projection is read back
// here. The signature has already been checked against `core`; this only
// reads structure out of bytes that are known-good.
let wire: Value = from_canonical_cbor(&core)?;
let profile = wire
.get("ar_receipt")
.and_then(Value::as_str)
.ok_or(ArError::MissingField("ar_receipt"))?;
if profile != AR_PROFILE {
return Err(ArError::UnknownProfile(profile.to_string()));
}
let effect = wire.get("effect").ok_or(ArError::MissingField("effect"))?;
let eclass = effect
.get("class")
.and_then(Value::as_str)
.ok_or(ArError::MissingField("effect.class"))?;
if eclass == "irreversible" && effect.get("plan_receipt").is_none() {
return Err(ArError::IrreversibleWithoutPlan);
}
let egress = wire.get("egress").ok_or(ArError::MissingField("egress"))?;
let gclass = egress
.get("class")
.and_then(Value::as_str)
.ok_or(ArError::MissingField("egress.class"))?;
let bytes = egress.get("bytes").and_then(Value::as_u64).unwrap_or(0);
if gclass == "none" && bytes != 0 {
return Err(ArError::EgressNoneWithBytes(bytes));
}
if gclass == "attested_enclave" && egress.get("peer").is_none() {
return Err(ArError::AttestedEgressWithoutPeer);
}
let id = ContentId::of_bytes(&core);
Ok(Verified { core, wire, id })
}
#[cfg(test)]
mod tests {
use super::*;
use ed25519_dalek::SigningKey;
fn cid(b: u8) -> ContentId {
ContentId([b; 32])
}
fn key() -> SigningKey {
SigningKey::from_bytes(&[7u8; 32])
}
fn base() -> ActionReceipt {
ActionReceipt {
closed_at: "2026-08-25T00:00:00Z".into(),
grant_id: cid(1),
chain_ids: vec![cid(2)],
authority_receipt: cid(3),
verdict: "allow".into(),
attestation_id: cid(4),
proof_cell_id: Some(cid(5)),
tier: "S5".into(),
grounding: "hardware".into(),
work_receipt: cid(6),
input_hash: "a".repeat(64),
joules_uj: 19_538_280,
energy_provenance: "HwShunt".into(),
effect: Effect {
class: EffectClass::Reversible,
target: cid(7),
before: Some("b".repeat(64)),
after: Some("c".repeat(64)),
compensator: None,
plan_receipt: None,
},
egress: Egress {
class: EgressClass::None,
bytes: 0,
peer: None,
},
steward: "did:example:ar-reference".into(),
}
}
#[test]
fn seals_and_verifies_round_trip() {
let r = base();
let env = r.seal(&key()).unwrap();
let v = verify(&env, &key().verifying_key(), &r.steward).unwrap();
assert_eq!(v.core, r.signed_core().unwrap());
assert_eq!(v.id, r.id().unwrap());
assert_eq!(v.wire["tier"], "S5");
assert_eq!(v.wire["joules_uj"], 19_538_280u64);
}
#[test]
fn canonical_core_is_stable_across_encodes() {
let r = base();
assert_eq!(r.signed_core().unwrap(), r.signed_core().unwrap());
assert_eq!(r.id().unwrap(), r.id().unwrap());
}
#[test]
fn absent_optionals_are_omitted_not_nulled() {
// JCR-1 §3.1 drops nulls from the signed core, so emitting an explicit
// null would produce a projection that does not round-trip.
let r = base();
let w = r.to_wire();
assert!(w["effect"].get("compensator").is_none());
assert!(w["egress"].get("peer").is_none());
}
// ── rule 1: irreversible requires a plan ─────────────────────────
#[test]
fn irreversible_without_plan_refuses_to_seal() {
let mut r = base();
r.effect.class = EffectClass::Irreversible;
r.effect.plan_receipt = None;
assert!(matches!(
r.seal(&key()),
Err(ArError::IrreversibleWithoutPlan)
));
}
#[test]
fn irreversible_with_plan_seals() {
let mut r = base();
r.effect.class = EffectClass::Irreversible;
r.effect.plan_receipt = Some(cid(9));
let env = r.seal(&key()).unwrap();
let v = verify(&env, &key().verifying_key(), &r.steward).unwrap();
assert_eq!(v.wire["effect"]["class"], "irreversible");
}
// ── rule 2: egress none means zero bytes ─────────────────────────
#[test]
fn egress_none_with_bytes_refuses_to_seal() {
let mut r = base();
r.egress.bytes = 4096;
assert!(matches!(
r.seal(&key()),
Err(ArError::EgressNoneWithBytes(4096))
));
}
// ── rule 3: attested egress needs a peer ─────────────────────────
#[test]
fn attested_egress_without_peer_refuses_to_seal() {
let mut r = base();
r.egress.class = EgressClass::AttestedEnclave;
r.egress.bytes = 1024;
r.egress.peer = None;
assert!(matches!(
r.seal(&key()),
Err(ArError::AttestedEgressWithoutPeer)
));
}
#[test]
fn third_party_egress_needs_no_peer() {
// An unattested destination is honestly recorded, not blocked.
let mut r = base();
r.egress.class = EgressClass::ThirdParty;
r.egress.bytes = 1024;
r.egress.peer = None;
assert!(r.seal(&key()).is_ok());
}
// ── the rules bind at verification, not just construction ────────
#[test]
fn hand_forged_violation_is_rejected_at_verify() {
// Seal a valid receipt, then rebuild the core with an irreversible
// effect and no plan and sign it directly — bypassing `seal`. A verifier
// that only checked the signature would accept this.
let mut r = base();
r.effect.class = EffectClass::Reversible;
let mut wire = r.to_wire();
wire["effect"]["class"] = json!("irreversible");
let core = jcr1::signed_core_bytes(&wire).unwrap();
let forged = jcr1::cose_sign1_envelope(&core, &key(), &r.steward);
// The signature is perfectly valid...
assert!(jcr1::verify_cose_sign1(&forged, &r.steward, key().verifying_key().as_bytes()).is_ok());
// ...and AR-1 rejects it anyway.
assert!(matches!(
verify(&forged, &key().verifying_key(), &r.steward),
Err(ArError::IrreversibleWithoutPlan)
));
}
#[test]
fn wrong_steward_is_rejected() {
let r = base();
let env = r.seal(&key()).unwrap();
assert!(verify(&env, &key().verifying_key(), "did:example:someone-else").is_err());
}
#[test]
fn tampered_envelope_is_rejected() {
let r = base();
let mut env = r.seal(&key()).unwrap();
let n = env.len();
env[n - 1] ^= 0xff;
assert!(verify(&env, &key().verifying_key(), &r.steward).is_err());
}
#[test]
fn energy_provenance_survives_the_round_trip_verbatim() {
// HwShunt and Estimator are different claims and must never collapse.
for prov in ["HwShunt", "ModelBased", "Estimator"] {
let mut r = base();
r.energy_provenance = prov.into();
let env = r.seal(&key()).unwrap();
let v = verify(&env, &key().verifying_key(), &r.steward).unwrap();
assert_eq!(v.wire["energy_provenance"], prov);
}
}
}

View file

@ -0,0 +1,113 @@
//! Consume the published AR-1 conformance pack.
//!
//! This is the test that makes the pack mean something. It reads
//! `jcp/conformance/v1/action_receipt.json` from disk — the same bytes a third
//! party would download — resolves the public key from the meta file, and
//! checks every vector against the stated expectation.
//!
//! Crucially it consumes the *published artifact*, not in-memory values. A pack
//! that only its own generator can read is not a conformance pack.
use ed25519_dalek::VerifyingKey;
use jcp_action_receipt::verify;
use serde_json::Value;
fn pack_dir() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../../conformance/v1")
.canonicalize()
.expect("conformance dir must exist next to the spec")
}
fn load(name: &str) -> Value {
let p = pack_dir().join(name);
let bytes = std::fs::read(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()));
serde_json::from_slice(&bytes).unwrap_or_else(|e| panic!("parse {}: {e}", p.display()))
}
fn key_and_steward() -> (VerifyingKey, String) {
let meta = load("action_receipt_meta.json");
let hex_key = meta["pubkey_hex"].as_str().expect("meta.pubkey_hex");
let raw = hex::decode(hex_key).expect("pubkey hex");
let arr: [u8; 32] = raw.as_slice().try_into().expect("32-byte pubkey");
let steward = meta["steward"].as_str().expect("meta.steward").to_string();
(VerifyingKey::from_bytes(&arr).expect("valid pubkey"), steward)
}
#[test]
fn every_positive_vector_verifies() {
let (vk, steward) = key_and_steward();
let pack = load("action_receipt.json");
let vectors = pack["vectors"].as_array().expect("vectors array");
let mut checked = 0;
for v in vectors {
if v["expect"] != "verify" {
continue;
}
let name = v["name"].as_str().unwrap_or("<unnamed>");
let env = hex::decode(v["envelope_hex"].as_str().expect("envelope_hex"))
.unwrap_or_else(|e| panic!("{name}: envelope hex: {e}"));
let ok = verify(&env, &vk, &steward)
.unwrap_or_else(|e| panic!("positive vector `{name}` failed to verify: {e}"));
// The receipt id in the pack must match what a verifier re-derives from
// the bytes — otherwise the published id is decorative.
let want = v["id_hex"].as_str().expect("id_hex");
assert_eq!(ok.id.to_hex(), want, "{name}: id mismatch");
// And the canonical core must match byte-for-byte, which is what makes
// the content address reproducible on another implementation.
let want_core = v["core_hex"].as_str().expect("core_hex");
assert_eq!(hex::encode(&ok.core), want_core, "{name}: core mismatch");
checked += 1;
}
assert!(checked >= 7, "expected at least 7 positive vectors, saw {checked}");
}
#[test]
fn every_negative_vector_is_rejected_despite_a_valid_signature() {
let (vk, steward) = key_and_steward();
let pack = load("action_receipt.json");
let vectors = pack["vectors"].as_array().expect("vectors array");
let mut checked = 0;
for v in vectors {
let expect = v["expect"].as_str().unwrap_or("verify");
if expect == "verify" {
continue;
}
let name = v["name"].as_str().unwrap_or("<unnamed>");
let env = hex::decode(v["envelope_hex"].as_str().expect("envelope_hex"))
.unwrap_or_else(|e| panic!("{name}: envelope hex: {e}"));
// The signature is genuine — these vectors exist precisely because a
// signature-only verifier would accept them.
let sig_ok = jcp_receipt::jcr1::verify_cose_sign1(&env, &steward, vk.as_bytes());
assert!(
sig_ok.is_ok(),
"{name}: negative vector should carry a genuine signature"
);
// AR-1 must refuse it anyway.
assert!(
verify(&env, &vk, &steward).is_err(),
"negative vector `{name}` was accepted — the rule it pins is not enforced"
);
checked += 1;
}
assert!(checked >= 3, "expected at least 3 negative vectors, saw {checked}");
}
#[test]
fn pack_declares_the_profile_this_build_implements() {
let meta = load("action_receipt_meta.json");
assert_eq!(
meta["profile"].as_str().expect("meta.profile"),
jcp_action_receipt::AR_PROFILE,
"vector pack was generated for a different profile than this build implements"
);
assert_eq!(meta["alg"].as_str().expect("meta.alg"), "EdDSA (COSE -8)");
}

View file

@ -7,7 +7,7 @@
name = "l3-jouleclaw-binding"
version = "0.1.0"
edition = "2021"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
description = "Example binding: JouleClaw's L3 model tier (jouleclaw-llm LlmBackend) as a Joule Code cascade FnStage. Verified model-free via EchoBackend; a real backend (vLLM, or jouleclaw-runtime GGUF) drops into the same slot."
publish = false

View file

@ -8,7 +8,7 @@
name = "transport-moqt-binding"
version = "0.1.0"
edition = "2021"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
publish = false

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@ version = "0.2.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
joule-code-schema = { path = "crates/joule-code-schema" }

View file

@ -3,7 +3,7 @@ name = "joule-moq"
version = "0.1.0"
description = "MoQT (Media over QUIC Transport) wire protocol + JWP receipt extension for CommunicationOS broadcast media. Trait surface lets the Realtime stack publish, subscribe, and relay tracks with object-level signed provenance and joule receipts."
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"

View file

@ -3,7 +3,7 @@ name = "jwp"
version = "0.1.0"
description = "Joule Wire Protocol (JWP) — energy-aware binary framing protocol"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"

View file

@ -2,17 +2,11 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "base64"
@ -28,11 +22,10 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -60,9 +53,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.63"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -171,7 +164,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -227,9 +220,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "generic-array"
@ -384,9 +377,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libloading"
@ -400,9 +393,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "pkcs8"
@ -416,18 +409,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -481,9 +474,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -491,29 +484,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -566,9 +559,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -577,29 +581,29 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "tinyvec"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
dependencies = [
"tinyvec_macros",
]
@ -642,32 +646,32 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "zerocopy"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -13,7 +13,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["joule-ui Contributors"]

View file

@ -76,6 +76,8 @@ fn main() {
),
budget_uj: 15_000_000, // 15 J
expiry: 0,
budget_funds: None,
caveats: Vec::new(),
parent: None,
delegate_depth: None,
nonce: [0; 16],

File diff suppressed because it is too large Load diff

View file

@ -1153,7 +1153,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["JouleClaw Contributors"]

View file

@ -174,6 +174,13 @@ impl Default for L0Cache {
}
impl Tier for L0Cache {
/// An exact-match hit is served from this process's own memory, so L0 can
/// honestly declare that nothing left the device. This is the one tier in
/// the base cascade entitled to claim `None`.
fn egress(&self) -> crate::types::Egress {
crate::types::Egress::None
}
fn id(&self) -> TierId {
TierId::L0
}

View file

@ -44,6 +44,23 @@ pub trait Tier: Send {
budget_remaining: f64,
) -> Result<Answer, AnswerError>;
/// Where this tier's work goes.
///
/// The runtime stamps the returned value onto the trace of every answer
/// this tier produces, so declaring it is not optional in practice even
/// though the method is defaulted.
///
/// Default: [`Egress::Undeclared`]. Legacy tiers are recorded as
/// undeclared rather than assumed local — "we did not ask" and "nothing
/// left the device" are different facts, and only the second is a privacy
/// claim. A tier that resolves entirely in-process should override this
/// with [`Egress::None`]; one that calls out should return
/// [`Egress::AttestedEnclave`] or [`Egress::ThirdParty`] with a real byte
/// count.
fn egress(&self) -> crate::types::Egress {
crate::types::Egress::Undeclared
}
/// The Synthesis coordinate of this tier, if known.
/// `⟨Z, E, T, P, I, V, R⟩` from the Periodic Stack.
///
@ -419,6 +436,7 @@ impl Runtime {
let estimate = l0.estimate_cost(&q).unwrap();
let remaining = q.budget.remaining(spent);
if estimate.joules <= remaining {
let l0_egress = l0.egress();
let l0_answer = l0.try_answer(&q, remaining)?;
match &l0_answer.output {
AnswerOutput::Refused(_) => {
@ -430,8 +448,11 @@ impl Runtime {
});
}
_ => {
// L0 hit. Merge our walk's trace and return.
// L0 hit. Merge our walk's trace and return. The
// egress goes on the trace the runtime returns, not the
// tier's own — that one is discarded by the spread below.
spent += l0_answer.joules_spent;
trace.egress = l0_egress;
trace.attempts.push(TraceEntry {
tier: TierId::L0,
outcome: TraceOutcome::Hit,
@ -589,6 +610,7 @@ impl Runtime {
}
// Dispatch.
let tier_egress = tier.egress();
let dispatch_result = tier.try_answer(&q, remaining);
// Record calibration data on every dispatch outcome.
// The `actual` is the tier's self-reported spend; we charge
@ -664,6 +686,10 @@ impl Runtime {
continue;
}
spent += actual;
// The answering tier's declaration goes on the trace
// the runtime returns; the spread below discards the
// tier's own copy.
trace.egress = tier_egress;
trace.attempts.push(TraceEntry {
tier: tier_id,
outcome: TraceOutcome::Hit,

View file

@ -205,11 +205,73 @@ impl RefusalReason {
}
}
/// Where a resolution's work went, and what evidence backs that claim.
///
/// A router that decides between on-device and remote execution and never says
/// which is the gap this closes: today a user cannot tell, per request, whether
/// their query left the machine. Recording it only helps if the record is
/// trustworthy, so the single rule is that **a class is never stronger than the
/// evidence for it**.
///
/// [`Egress::Undeclared`] is the default, and exists so that silence cannot be
/// mistaken for `None`. A tier that has not declared its egress is recorded as
/// undeclared, never as "nothing left the device" — not knowing and knowing
/// nothing happened are different facts, and only one of them is a claim.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum Egress {
/// The tier has not declared a class. Never promote this to `None`: an
/// undeclared tier may well have made a network call.
#[default]
Undeclared,
/// Resolved on-device. Nothing left the machine.
None,
/// Left the device to a peer that attested what it was running. Carries
/// the peer's attestation id, so the claim is checkable rather than taken
/// on faith.
AttestedEnclave { peer: String, bytes: u64 },
/// Left the device to an unattested destination. Named and counted, and
/// honestly marked unverifiable. Trust is not an egress class: a
/// destination the operator believes reputable is still `ThirdParty`.
ThirdParty { destination: String, bytes: u64 },
}
impl Egress {
/// Bytes that left the device. Zero for `None`, and zero for `Undeclared`
/// too — which is exactly why `Undeclared` must never be read as `None`.
pub fn bytes(&self) -> u64 {
match self {
Self::Undeclared | Self::None => 0,
Self::AttestedEnclave { bytes, .. } | Self::ThirdParty { bytes, .. } => *bytes,
}
}
/// Whether this carries enough evidence to publish as a privacy claim.
/// `Undeclared` does not: a receipt built from it would assert something
/// nobody measured.
pub fn is_publishable(&self) -> bool {
!matches!(self, Self::Undeclared)
}
/// Stable wire spelling for receipts and logs.
pub fn wire_tag(&self) -> &'static str {
match self {
Self::Undeclared => "undeclared",
Self::None => "none",
Self::AttestedEnclave { .. } => "attested_enclave",
Self::ThirdParty { .. } => "third_party",
}
}
}
/// A record of which tier(s) were attempted, in order, with per-tier
/// joule spend. The successful tier (if any) is last.
#[derive(Debug, Clone, Default)]
pub struct ExecutionTrace {
pub attempts: Vec<TraceEntry>,
/// Where the answering tier's work went. Stamped by the runtime from the
/// tier's own declaration, so a tier cannot quietly omit it and a reader
/// cannot be misled by its absence.
pub egress: Egress,
}
#[derive(Debug, Clone)]
@ -672,3 +734,62 @@ impl std::fmt::Display for AnswerError {
}
impl std::error::Error for AnswerError {}
#[cfg(test)]
mod egress_tests {
use super::Egress;
#[test]
fn default_is_undeclared_not_none() {
// The whole point: silence must not read as a privacy claim.
assert_eq!(Egress::default(), Egress::Undeclared);
assert_ne!(Egress::default(), Egress::None);
}
#[test]
fn undeclared_is_not_publishable() {
// A receipt built from Undeclared would assert something nobody
// measured, so it must be refused upstream rather than defaulted.
assert!(!Egress::Undeclared.is_publishable());
assert!(Egress::None.is_publishable());
assert!(
Egress::ThirdParty { destination: "api.example".into(), bytes: 10 }.is_publishable()
);
}
#[test]
fn undeclared_and_none_both_report_zero_bytes() {
// They agree on the number and disagree on the meaning, which is
// exactly why the class must be read rather than the byte count.
assert_eq!(Egress::Undeclared.bytes(), 0);
assert_eq!(Egress::None.bytes(), 0);
}
#[test]
fn remote_classes_carry_their_byte_count() {
assert_eq!(
Egress::AttestedEnclave { peer: "b3:peer".into(), bytes: 4096 }.bytes(),
4096
);
assert_eq!(
Egress::ThirdParty { destination: "api.example".into(), bytes: 8192 }.bytes(),
8192
);
}
#[test]
fn wire_tags_are_pinned() {
// These strings cross a standards boundary into AR-1 receipts; drift
// here silently changes what a published receipt means.
assert_eq!(Egress::Undeclared.wire_tag(), "undeclared");
assert_eq!(Egress::None.wire_tag(), "none");
assert_eq!(
Egress::AttestedEnclave { peer: String::new(), bytes: 0 }.wire_tag(),
"attested_enclave"
);
assert_eq!(
Egress::ThirdParty { destination: String::new(), bytes: 0 }.wire_tag(),
"third_party"
);
}
}

View file

@ -344,3 +344,49 @@ fn print_trace(a: &Answer) {
format!("{:?}", entry.tier), entry.outcome, entry.joules);
}
}
// ── egress contract (AR-1 §3) ────────────────────────────────────────
#[test]
fn runtime_stamps_the_answering_tier_egress_onto_the_trace() {
use jouleclaw_cascade::types::Egress;
// MockL4 does not override `egress()`, so it is Undeclared — and the point
// is that this is NOT silently reported as "nothing left the device".
let mut cascade = Cascade::new();
cascade.register(Box::new(MockL4::new(0.5, "Paris")));
let mut rt = Runtime::new(cascade);
let a = rt.answer(text_query("capital of France?")).unwrap();
assert_eq!(a.tier_used, TierId::L4(L4ModelId(0)));
assert_eq!(
a.trace.egress,
Egress::Undeclared,
"a tier that never declared its egress must not be recorded as local"
);
assert!(
!a.trace.egress.is_publishable(),
"Undeclared carries no evidence, so it cannot become a privacy claim"
);
}
#[test]
fn a_local_cache_hit_is_recorded_as_local() {
use jouleclaw_cascade::types::Egress;
// L0 overrides `egress()` with None because a hit is served from this
// process's own memory. The runtime stamps it — the tier does not write it
// into its own Answer — so a tier cannot forge the claim by construction.
let mut cascade = Cascade::new();
cascade.register(Box::new(MockL4::new(0.5, "Paris")));
let mut rt = Runtime::new(cascade);
let q = text_query("capital of France?");
let _ = rt.answer(q.clone()).unwrap(); // miss → L4 populates the cache
let hit = rt.answer(q).unwrap(); // hit → served by L0
assert_eq!(hit.tier_used, TierId::L0);
assert_eq!(hit.trace.egress, Egress::None);
assert!(hit.trace.egress.is_publishable());
}

View file

@ -2,17 +2,11 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "base64"
@ -28,11 +22,10 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -51,9 +44,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.63"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -129,7 +122,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -185,9 +178,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "generic-array"
@ -311,15 +304,15 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "pkcs8"
@ -342,9 +335,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
@ -378,18 +371,18 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.6"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
dependencies = [
"libc",
"rand_chacha",
@ -432,9 +425,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -442,29 +435,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -517,9 +510,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -528,22 +532,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -572,32 +576,32 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "zerocopy"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.52"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -15,7 +15,7 @@ version = "0.6.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
joulecontract-schema = { path = "crates/joulecontract-schema" }

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[patch.crates-io]
# Work around the upstream livekit release skew: libwebrtc 0.3.38 omits the

View file

@ -313,7 +313,15 @@ mod tests {
other => panic!("expected budget Denied, got {other:?}"),
}
assert_eq!(t.spent_uj("summarizer"), 100_000, "only the funded task ran");
assert_eq!(t.verify_ledger(), Ok(1), "the one dispatched decision sealed + verifies");
// BOTH decisions seal. A budget refusal is a decision made against a real
// grant — the teammate held the capability and was stopped by the ceiling —
// so it is evidence and seals like any other (see `TagOutcome`: "every
// variant sealed to the ledger"). Contrast the unheld-capability case
// above, which never reaches dispatch and leaves the ledger empty. Only
// one task *ran*, which is what `spent_uj` asserts; two decisions were
// *made*, which is what the ledger records.
assert_eq!(t.ledger().len(), 2, "the allow and the budget denial both sealed");
assert_eq!(t.verify_ledger(), Ok(2), "and both verify under the steward key");
}
#[test]

View file

@ -8,12 +8,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.8"
@ -40,11 +34,10 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -72,9 +65,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.65"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -124,9 +117,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
dependencies = [
"cfg-if",
]
@ -165,7 +158,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -190,13 +183,13 @@ dependencies = [
[[package]]
name = "displaydoc"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -232,9 +225,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "flate2"
@ -290,9 +283,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "icu_collections"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513"
dependencies = [
"displaydoc",
"potential_utf",
@ -304,9 +297,9 @@ dependencies = [
[[package]]
name = "icu_locale_core"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb"
dependencies = [
"displaydoc",
"litemap",
@ -317,9 +310,9 @@ dependencies = [
[[package]]
name = "icu_normalizer"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f"
dependencies = [
"icu_collections",
"icu_normalizer_data",
@ -331,16 +324,17 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0"
[[package]]
name = "icu_properties"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locale_core",
"icu_properties_data",
@ -351,15 +345,15 @@ dependencies = [
[[package]]
name = "icu_properties_data"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa"
[[package]]
name = "icu_provider"
version = "2.2.0"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73"
dependencies = [
"displaydoc",
"icu_locale_core",
@ -510,27 +504,27 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "litemap"
version = "0.8.2"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae"
[[package]]
name = "log"
version = "0.4.33"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "memchr"
version = "2.8.2"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "miniz_oxide"
@ -566,27 +560,27 @@ dependencies = [
[[package]]
name = "potential_utf"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661"
dependencies = [
"zerovec",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.46"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -625,9 +619,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.41"
version = "0.23.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06"
dependencies = [
"log",
"once_cell",
@ -640,18 +634,18 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.15.0"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
version = "0.103.13"
version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"ring",
"rustls-pki-types",
@ -666,9 +660,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -676,29 +670,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -735,9 +729,9 @@ dependencies = [
[[package]]
name = "simd-adler32"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "smallvec"
@ -769,9 +763,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.118"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -786,27 +791,27 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -823,9 +828,9 @@ dependencies = [
[[package]]
name = "tinystr"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643"
dependencies = [
"displaydoc",
"zerovec",
@ -833,9 +838,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
dependencies = [
"tinyvec_macros",
]
@ -916,14 +921,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
"webpki-roots 1.0.8",
"webpki-roots 1.0.9",
]
[[package]]
name = "webpki-roots"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf"
checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
dependencies = [
"rustls-pki-types",
]
@ -1003,9 +1008,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "writeable"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc"
[[package]]
name = "yoke"
@ -1026,7 +1031,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
"synstructure",
]
@ -1047,7 +1052,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
"synstructure",
]
@ -1059,9 +1064,9 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zerotrie"
version = "0.2.4"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f"
dependencies = [
"displaydoc",
"yoke",
@ -1070,9 +1075,9 @@ dependencies = [
[[package]]
name = "zerovec"
version = "0.11.6"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8"
dependencies = [
"yoke",
"zerofrom",
@ -1081,17 +1086,17 @@ dependencies = [
[[package]]
name = "zerovec-derive"
version = "0.11.3"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -7,4 +7,4 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
rust-version = "1.97"
rust-version = "1.98"

466
map/map-rs/Cargo.lock generated
View file

@ -10,40 +10,28 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "android_system_properties"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "async-trait"
version = "0.1.89"
version = "0.1.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -121,17 +109,16 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "bitflags"
version = "2.12.1"
version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -156,9 +143,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "bytemuck"
version = "1.25.0"
version = "1.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
[[package]]
name = "byteorder-lite"
@ -168,15 +155,15 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.11.1"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
[[package]]
name = "cc"
version = "1.2.63"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -190,9 +177,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
version = "0.4.44"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"js-sys",
@ -267,9 +254,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
dependencies = [
"cfg-if",
]
@ -314,7 +301,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -362,12 +349,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fdeflate"
version = "0.3.7"
@ -385,9 +366,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "flate2"
@ -399,12 +380,6 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
@ -416,30 +391,30 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.32"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.32"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
[[package]]
name = "futures-task"
version = "0.3.32"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
[[package]]
name = "futures-util"
version = "0.3.32"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
dependencies = [
"futures-core",
"futures-task",
@ -470,15 +445,13 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasip2",
"wasip3",
]
[[package]]
@ -492,27 +465,6 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"foldhash",
]
[[package]]
name = "hashbrown"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hex"
version = "0.4.3"
@ -521,9 +473,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "http"
version = "1.4.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0"
checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0"
dependencies = [
"bytes",
"itoa",
@ -531,9 +483,9 @@ dependencies = [
[[package]]
name = "http-body"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c"
dependencies = [
"bytes",
"http",
@ -541,9 +493,9 @@ dependencies = [
[[package]]
name = "http-body-util"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c"
dependencies = [
"bytes",
"futures-core",
@ -566,9 +518,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.10.1"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
dependencies = [
"atomic-waker",
"bytes",
@ -623,12 +575,6 @@ dependencies = [
"cc",
]
[[package]]
name = "id-arena"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "image"
version = "0.25.10"
@ -653,18 +599,6 @@ dependencies = [
"quick-error",
]
[[package]]
name = "indexmap"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
[[package]]
name = "itoa"
version = "1.0.18"
@ -673,33 +607,26 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.99"
version = "0.3.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a"
dependencies = [
"cfg-if",
"futures-util",
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "leb128fmt"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "log"
version = "0.4.32"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "map-cascade"
@ -832,9 +759,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "mime"
@ -854,9 +781,9 @@ dependencies = [
[[package]]
name = "mio"
version = "1.2.1"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
dependencies = [
"libc",
"wasi",
@ -923,30 +850,20 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pxfm"
version = "0.1.29"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f"
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
[[package]]
name = "quick-error"
@ -956,9 +873,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -989,9 +906,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.22"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]]
name = "ryu"
@ -1007,9 +924,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -1017,29 +934,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -1099,9 +1016,9 @@ dependencies = [
[[package]]
name = "simd-adler32"
version = "0.3.9"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "slab"
@ -1111,15 +1028,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
version = "1.15.1"
version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "socket2"
version = "0.6.4"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [
"libc",
"windows-sys",
@ -1143,9 +1060,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -1160,29 +1088,29 @@ checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "tokio"
version = "1.52.3"
version = "1.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
dependencies = [
"libc",
"mio",
@ -1194,13 +1122,13 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "2.7.0"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -1263,19 +1191,13 @@ version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "uuid"
version = "1.23.2"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc"
dependencies = [
"getrandom 0.4.2",
"getrandom 0.4.3",
"js-sys",
"serde_core",
"wasm-bindgen",
@ -1293,29 +1215,11 @@ version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
"wit-bindgen 0.57.1",
]
[[package]]
name = "wasip3"
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen 0.51.0",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.122"
version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70"
dependencies = [
"cfg-if",
"once_cell",
@ -1326,9 +1230,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.122"
version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -1336,60 +1240,26 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.122"
version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.122"
version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf"
dependencies = [
"unicode-ident",
]
[[package]]
name = "wasm-encoder"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
dependencies = [
"leb128fmt",
"wasmparser",
]
[[package]]
name = "wasm-metadata"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
dependencies = [
"anyhow",
"indexmap",
"wasm-encoder",
"wasmparser",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
"bitflags",
"hashbrown 0.15.5",
"indexmap",
"semver",
]
[[package]]
name = "windows-core"
version = "0.62.2"
@ -1411,7 +1281,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -1422,7 +1292,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -1458,128 +1328,34 @@ dependencies = [
"windows-link",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
dependencies = [
"anyhow",
"heck",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
dependencies = [
"anyhow",
"heck",
"indexmap",
"prettyplease",
"syn",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
dependencies = [
"anyhow",
"prettyplease",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
]
[[package]]
name = "wit-component"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
"bitflags",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder",
"wasm-metadata",
"wasmparser",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
"wasmparser",
]
[[package]]
name = "zerocopy"
version = "0.8.50"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.50"
version = "0.8.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639"
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -19,7 +19,7 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
map-schema = { path = "crates/map-schema" }

168
mesh/mesh-rs/Cargo.lock generated
View file

@ -4,24 +4,18 @@ version = 4
[[package]]
name = "aho-corasick"
version = "1.1.4"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba"
dependencies = [
"memchr",
]
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.7"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "base64ct"
@ -52,17 +46,16 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.13.0"
version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -96,9 +89,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.65"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -169,9 +162,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
@ -179,18 +172,18 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
version = "0.9.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
[[package]]
name = "crypto-common"
@ -226,7 +219,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -250,7 +243,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn",
"syn 2.0.119",
]
[[package]]
@ -261,7 +254,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -311,9 +304,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.16.0"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
[[package]]
name = "fancy-regex"
@ -334,9 +327,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "fnv"
@ -356,13 +349,13 @@ dependencies = [
[[package]]
name = "foreign-types-macros"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -417,7 +410,7 @@ dependencies = [
"ed25519-dalek",
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -430,7 +423,7 @@ dependencies = [
"hex",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -446,7 +439,7 @@ dependencies = [
"nvml-wrapper",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
"tracing",
]
@ -464,15 +457,15 @@ dependencies = [
"regex",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
"windows-sys",
]
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libloading"
@ -486,9 +479,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.33"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "malloc_buf"
@ -501,9 +494,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.8.2"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "memmap2"
@ -544,7 +537,7 @@ dependencies = [
"mesh-router",
"mesh-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -569,7 +562,7 @@ dependencies = [
"mesh-router",
"mesh-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -594,7 +587,7 @@ dependencies = [
"mesh-router",
"mesh-schema",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -607,7 +600,7 @@ dependencies = [
"mesh-schema",
"serde",
"serde_json",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -623,7 +616,7 @@ version = "0.1.0"
dependencies = [
"jcp-schema",
"serde",
"thiserror 2.0.18",
"thiserror 2.0.20",
]
[[package]]
@ -632,7 +625,7 @@ version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e"
dependencies = [
"bitflags 2.13.0",
"bitflags 2.13.1",
"block",
"core-graphics-types",
"foreign-types",
@ -647,7 +640,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9bff0aa1d48904a1385ea2a8b97576fbdcbc9a3cfccd0d31fe978e1c4038c5"
dependencies = [
"bitflags 2.13.0",
"bitflags 2.13.1",
"libloading",
"nvml-wrapper-sys",
"static_assertions",
@ -703,9 +696,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
@ -721,9 +714,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.46"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -759,9 +752,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.12.4"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [
"aho-corasick",
"memchr",
@ -771,9 +764,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.14"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
dependencies = [
"aho-corasick",
"memchr",
@ -803,9 +796,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -813,29 +806,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -900,9 +893,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.118"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -920,11 +924,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl 2.0.18",
"thiserror-impl 2.0.20",
]
[[package]]
@ -935,25 +939,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "tinyvec"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
dependencies = [
"tinyvec_macros",
]
@ -983,7 +987,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -1107,7 +1111,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -1118,6 +1122,6 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -17,7 +17,7 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
# Mesh crates

View file

@ -76,6 +76,8 @@ fn main() {
capability: Capability::new(req.id(), [INFER_ACTION]),
budget_uj: 8_000_000,
expiry: 0,
budget_funds: None,
caveats: Vec::new(),
parent: None,
delegate_depth: None,
nonce: [0u8; 16],

1359
openpay/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -53,7 +53,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["OpenPay Contributors"]

View file

@ -14,6 +14,7 @@
//! deserialiser. Verification is constant-time via `subtle::ConstantTimeEq`.
use base64::{Engine as _, engine::general_purpose::STANDARD as B64};
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
@ -134,7 +135,7 @@ fn verify_hmac_sha256(secret: &[u8], body: &[u8], provided: &[u8]) -> Result<()>
if secret.is_empty() {
return Err(Error::MalformedSignatureHeader("empty secret".into()));
}
let mut mac = HmacSha256::new_from_slice(secret)
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret)
.map_err(|e| Error::MalformedSignatureHeader(format!("hmac init: {e}")))?;
mac.update(body);
let computed = mac.finalize().into_bytes();
@ -245,13 +246,13 @@ mod tests {
use super::*;
fn sign_b64(secret: &[u8], body: &[u8]) -> String {
let mut mac = HmacSha256::new_from_slice(secret).unwrap();
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret).unwrap();
mac.update(body);
B64.encode(mac.finalize().into_bytes())
}
fn sign_hex(secret: &[u8], body: &[u8]) -> String {
let mut mac = HmacSha256::new_from_slice(secret).unwrap();
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret).unwrap();
mac.update(body);
hex::encode(mac.finalize().into_bytes())
}

View file

@ -2,6 +2,8 @@
//! providers. Positive cases verify the round trip end-to-end; negative
//! cases exercise the constant-time signature comparison.
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use op_bnpl::{
BnplEventKind, WebhookProvider, verify_affirm_webhook, verify_afterpay_webhook,
@ -12,14 +14,14 @@ use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
fn sign_b64(secret: &[u8], body: &[u8]) -> String {
let mut mac = HmacSha256::new_from_slice(secret).expect("hmac");
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret).expect("hmac");
mac.update(body);
use base64::Engine;
base64::engine::general_purpose::STANDARD.encode(mac.finalize().into_bytes())
}
fn sign_hex(secret: &[u8], body: &[u8]) -> String {
let mut mac = HmacSha256::new_from_slice(secret).expect("hmac");
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret).expect("hmac");
mac.update(body);
hex::encode(mac.finalize().into_bytes())
}

View file

@ -268,9 +268,10 @@ pub fn verify_notify_hmac(
expected_b64: &str,
secret: &[u8],
) -> Result<()> {
use hmac::{Hmac, Mac};
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use sha2::Sha256;
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(secret)
let mut mac = <Hmac<Sha256> as KeyInit>::new_from_slice(secret)
.map_err(|e| crate::Error::ProviderRejected {
code: "hmac-init".into(),
message: e.to_string(),

View file

@ -84,6 +84,7 @@ fn jsapi_rejects_missing_openid() {
#[test]
fn notify_hmac_roundtrip() {
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use sha2::Sha256;
@ -93,7 +94,7 @@ fn notify_hmac_roundtrip() {
let body = r#"{"event_type":"TRANSACTION.SUCCESS"}"#;
// Compute expected the same way the verifier expects.
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(secret).unwrap();
let mut mac = <Hmac<Sha256> as KeyInit>::new_from_slice(secret).unwrap();
mac.update(timestamp.as_bytes());
mac.update(b"\n");
mac.update(nonce.as_bytes());

View file

@ -30,7 +30,7 @@ subtle = { workspace = true }
p256 = { version = "0.13", default-features = false, features = ["ecdh", "ecdsa", "std", "arithmetic", "pem"] }
hkdf = { version = "0.13", default-features = false }
aes-gcm = { version = "0.10", default-features = false, features = ["aes", "alloc"] }
aes = { version = "0.9", default-features = false }
aes = { version = "0.8", default-features = false }
ctr = { version = "0.9", default-features = false }
hmac = { version = "0.13", default-features = false }
sha2 = { version = "0.11", default-features = false }

View file

@ -47,6 +47,7 @@ use aes::cipher::{KeyIvInit, StreamCipher};
use base64::Engine as _;
use ctr::Ctr128BE;
use hkdf::Hkdf;
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use op_core::{Currency, Money};
use p256::SecretKey;
@ -331,7 +332,7 @@ pub fn decrypt(
let mac_tag = base64::engine::general_purpose::STANDARD
.decode(&sm.tag)
.map_err(|_| Error::MalformedPayload("tag not base64"))?;
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(mac_key)
let mut mac = <Hmac<Sha256> as KeyInit>::new_from_slice(mac_key)
.map_err(|_| Error::Internal("HMAC key length"))?;
mac.update(&ciphertext);
let expected = mac.finalize().into_bytes();
@ -544,7 +545,7 @@ pub mod test_support {
cipher.apply_keystream(&mut ciphertext);
// 5. HMAC tag.
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(mac_key).unwrap();
let mut mac = <Hmac<Sha256> as KeyInit>::new_from_slice(mac_key).unwrap();
mac.update(&ciphertext);
let tag = mac.finalize().into_bytes();

View file

@ -20,7 +20,7 @@ async-trait = "0.1"
# HTTP client for commercial backends. rustls-tls keeps the build
# OpenSSL-free; json bundles serde_json roundtrips. We omit blocking
# because every backend here is async-first.
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json"] }
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json", "form"] }
tokio = { workspace = true }
serde = { workspace = true }

View file

@ -31,6 +31,7 @@
//! latency can extract the correct signature byte-by-byte. The
//! `subtle` crate's `ct_eq` always processes the full input.
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use sha2::Sha256;
use subtle::ConstantTimeEq;
@ -90,7 +91,7 @@ pub fn compute_signature(secret: &[u8], payload: &SignedPayload<'_>) -> Result<S
if secret.is_empty() {
return Err(Error::InvalidInput("signing secret is empty".into()));
}
let mut mac = HmacSha256::new_from_slice(secret)
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(secret)
.map_err(|e| Error::InvalidInput(format!("HMAC key init: {e}")))?;
mac.update(payload.to_bytes().as_slice());
let bytes = mac.finalize().into_bytes();

View file

@ -2,17 +2,11 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "base64ct"
@ -22,11 +16,10 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -45,9 +38,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.63"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -123,7 +116,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -179,9 +172,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "generic-array"
@ -218,15 +211,15 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "memchr"
version = "2.8.1"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "pkcs8"
@ -240,9 +233,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
@ -314,9 +307,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -347,9 +340,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -357,29 +350,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -432,9 +425,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -443,22 +447,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -487,12 +491,12 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "zeroize"
version = "1.8.2"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -14,7 +14,7 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
proof-schema = { path = "crates/proof-schema" }

View file

@ -1,4 +1,4 @@
[toolchain]
channel = "1.97.1"
channel = "1.98.0"
components = ["rustc", "cargo", "rust-std", "rustfmt", "clippy"]
profile = "default"

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@ version = "0.1.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
sandbox-schema = { path = "crates/sandbox-schema" }

View file

@ -2,17 +2,11 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "base64ct"
@ -22,11 +16,10 @@ checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "blake3"
version = "1.8.5"
version = "1.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
@ -45,9 +38,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.64"
version = "1.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
dependencies = [
"find-msvc-tools",
"shlex",
@ -123,7 +116,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.119",
]
[[package]]
@ -179,9 +172,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
[[package]]
name = "generic-array"
@ -218,15 +211,15 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "libc"
version = "0.2.186"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "memchr"
version = "2.8.2"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "pkcs8"
@ -240,18 +233,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@ -360,9 +353,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
@ -370,29 +363,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
name = "serde_json"
version = "1.0.150"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@ -445,9 +438,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f"
dependencies = [
"proc-macro2",
"quote",
@ -456,22 +460,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.18"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 3.0.4",
]
[[package]]
@ -506,6 +510,6 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zmij"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"

View file

@ -15,7 +15,7 @@ version = "0.1.0"
edition = "2024"
license = "Apache-2.0"
repository = "https://github.com/transaction-science/open-standards"
rust-version = "1.97"
rust-version = "1.98"
[workspace.dependencies]
sense-schema = { path = "crates/sense-schema" }

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
repository = "https://github.com/Transaction-Science/open-standards"
authors = ["Smart Byte Contributors"]
@ -45,7 +45,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "serd
thiserror = "2"
uuid = { version = "1", features = ["v4", "serde"] }
data-encoding = "2"
rand = "0.10"
rand = "0.8"
# Networking
iroh = "1.0.0-rc.0"

View file

@ -23,7 +23,7 @@ sha2 = "0.11"
async-trait = "0.1"
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "sync", "io-util", "net", "time"] }
futures = { workspace = true }
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json"] }
reqwest = { version = "0.13", default-features = false, features = ["rustls", "json", "query"] }
url = "2"
chrono = { workspace = true }

View file

@ -38,5 +38,5 @@ thiserror = { workspace = true }
[dev-dependencies]
hex = "0.4"
rand_chacha = "0.10"
rand_chacha = "0.3"
chrono = { workspace = true }

View file

@ -14,6 +14,7 @@
use base64::Engine;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use sha2::Sha256;
@ -34,7 +35,7 @@ pub struct IndexKey {
impl IndexKey {
/// Compute the base64url HMAC-SHA-256 tag over `value`.
pub fn tag(&self, value: &[u8]) -> Result<String, EdvError> {
let mut mac = <HmacSha256 as Mac>::new_from_slice(&self.key)
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(&self.key)
.map_err(|e| EdvError::Crypto(format!("hmac key: {e}")))?;
mac.update(value);
let bytes = mac.finalize().into_bytes();

View file

@ -18,7 +18,7 @@ chrono = { workspace = true }
p256 = { version = "0.14.0-rc.9", default-features = false, features = ["ecdsa", "alloc", "pem"] }
ecdsa = { version = "0.17.0-rc.18", features = ["der"] }
ed25519-dalek = { workspace = true }
rand = "0.10"
rand = { workspace = true }
sha2 = "0.11"
base64 = "0.22"
thiserror = { workspace = true }

View file

@ -23,7 +23,7 @@ use p256::ecdsa::{
SigningKey as P256SigningKey, VerifyingKey as P256VerifyingKey,
signature::Signer,
};
use rand::TryRngCore;
use rand::RngCore;
use rand::rngs::OsRng;
use sha2::{Digest, Sha256};
@ -159,9 +159,7 @@ impl IssuerKey {
pub fn generate_es256() -> Self {
let mut buf = [0u8; 32];
loop {
OsRng
.try_fill_bytes(&mut buf)
.expect("OS RNG must provide entropy");
OsRng.fill_bytes(&mut buf);
if let Ok(sk) = P256SigningKey::from_slice(&buf) {
return Self {
alg: COSE_ALG_ES256,
@ -253,9 +251,7 @@ impl Issuer {
let id = idx as u64;
let salt = if salt_seed.is_empty() {
let mut buf = [0u8; 32];
OsRng
.try_fill_bytes(&mut buf)
.map_err(|e| MdlError::Signature(format!("os rng: {e}")))?;
OsRng.fill_bytes(&mut buf);
buf.to_vec()
} else {
let mut h = Sha256::new();

View file

@ -24,8 +24,8 @@ sha2 = "0.11"
hmac = "0.13"
hkdf = "0.13"
chacha20 = "0.10"
aes = "0.9"
cbc = { version = "0.2", features = ["std"] }
aes = "0.8"
cbc = { version = "0.1", features = ["alloc", "block-padding"] }
async-trait = "0.1"
[dev-dependencies]

View file

@ -22,14 +22,14 @@ pub struct NostrPublicKey {
impl NostrSecretKey {
/// Construct a secret key from 32 raw bytes.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, NostrError> {
let inner = SecretKey::from_byte_array(bytes)
let inner = SecretKey::from_byte_array(*bytes)
.map_err(|e| NostrError::InvalidKey(e.to_string()))?;
Ok(Self { inner })
}
/// Generate a random secret key.
pub fn generate() -> Self {
let (inner, _pk) = SECP256K1.generate_keypair(&mut rand::thread_rng());
let (inner, _pk) = SECP256K1.generate_keypair(&mut secp256k1::rand::thread_rng());
Self { inner }
}
@ -54,7 +54,7 @@ impl NostrSecretKey {
impl NostrPublicKey {
/// Construct an x-only public key from 32 raw bytes.
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, NostrError> {
let inner = XOnlyPublicKey::from_byte_array(bytes)
let inner = XOnlyPublicKey::from_byte_array(*bytes)
.map_err(|e| NostrError::InvalidKey(e.to_string()))?;
Ok(Self { inner })
}

View file

@ -27,6 +27,7 @@ use chacha20::ChaCha20;
use chacha20::cipher::{KeyIvInit, StreamCipher};
use data_encoding::BASE64;
use hkdf::Hkdf;
use hmac::digest::KeyInit;
use hmac::{Hmac, Mac};
use rand::RngCore;
use sha2::Sha256;
@ -56,7 +57,7 @@ pub fn encrypt(
let mut cipher = ChaCha20::new(&chacha_key.into(), &chacha_nonce12.into());
cipher.apply_keystream(&mut ct);
let mut mac = HmacSha256::new_from_slice(&hmac_key)
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(&hmac_key)
.map_err(|e| NostrError::Crypto(e.to_string()))?;
mac.update(&nonce);
mac.update(&ct);
@ -95,7 +96,7 @@ pub fn decrypt(
let shared = derive_shared_key(recipient_sk, sender_pk)?;
let (chacha_key, chacha_nonce12, hmac_key) = derive_keys(&shared, &nonce);
let mut mac = HmacSha256::new_from_slice(&hmac_key)
let mut mac = <HmacSha256 as KeyInit>::new_from_slice(&hmac_key)
.map_err(|e| NostrError::Crypto(e.to_string()))?;
mac.update(&nonce);
mac.update(ct);

View file

@ -15,7 +15,7 @@ merlin = { version = "3", default-features = false }
# Transcripts, RNG.
rand = { workspace = true }
rand_core = { version = "0.10", default-features = false, features = ["alloc"] }
rand_core = { version = "0.6", default-features = false }
sha2 = "0.11"
# Serialisation + errors.
@ -24,5 +24,5 @@ serde_bytes = { workspace = true }
thiserror = { workspace = true }
[dev-dependencies]
rand_chacha = "0.10"
rand_chacha = "0.3"
serde_cbor = { workspace = true }

View file

@ -9,7 +9,7 @@
name = "wai-byte-exact-conformance"
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
publish = false

View file

@ -2,7 +2,7 @@
name = "wai-world-relay"
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
description = "Reference relay for wai.world.live sessions. Transport is OUT of the interactive-worlds extension's scope — this is one honest carrier: a per-room WebSocket fan-out that retains the signed op log for late joiners and verifies every op's Ed25519 signature before forwarding. It adjudicates nothing: sinks converge because the math does."

554
wai/wai-rs/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
name = "wai"
version = "0.3.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
description = "WAI — Web AI media transport + execution. Capability-as-requirement envelope + neural shared-prior regenerate-at-sink path + always-available zeroth-condition wrappers around SOTA standard codecs (AVIF / JPEG-XL / PNG / Opus / FLAC / AV1 / zstd / LZMA)."

View file

@ -2,7 +2,7 @@
name = "wai-spz-gen"
version = "0.1.0"
edition = "2024"
rust-version = "1.97"
rust-version = "1.98"
license = "Apache-2.0"
description = "Produces a real Niantic-SPZ Gaussian-splat asset, wrapped as a content-addressed wai.splat.spz WAI object. Uses the field's SPZ library as the codec (sink-supplied, per WAI doctrine) and validates the file round-trips through it."