| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (push) Successful in 4s
standards workspaces build + test / jouleclaw-rs (push) Successful in 1m50s
standards workspaces build + test / eoc-rs (push) Successful in 1m54s
standards workspaces build + test / arl-rs (push) Successful in 2m10s
standards workspaces build + test / aac-rs (push) Successful in 40s
standards workspaces build + test / joule-code-rs (push) Successful in 38s
standards workspaces build + test / jcp-rs (push) Successful in 1m18s
standards workspaces build + test / joulecontract-rs (push) Successful in 30s
standards workspaces build + test / map-rs (push) Successful in 30s
standards workspaces build + test / proof-rs (push) Successful in 1m11s
standards workspaces build + test / mesh-rs (push) Successful in 26s
standards workspaces build + test / joule-ui-rs (push) Successful in 2m32s
standards workspaces build + test / openpay (push) Successful in 1m21s
standards workspaces build + test / sandbox-rs (push) Successful in 2m12s
WAI conformance / cargo-class corpora · linux-arm64 (push) Successful in 51s
WAI conformance / cross-arch byte-equality · linux-arm64 (push) Successful in 18s
standards workspaces build + test / jouledesk-rs (push) Successful in 2m39s
standards workspaces build + test / smart-byte-rs (push) Successful in 2m30s
WAI conformance / cargo-class corpora · linux (push) Successful in 1m11s
WAI conformance / cross-arch byte-equality · linux (push) Successful in 15s
standards workspaces build + test / joulehook-rs (push) Successful in 3m48s
WAI conformance / C2PA manifest emission · signed, read back, validated (push) Successful in 40s
standards workspaces build + test / sense-rs (push) Successful in 2m22s
standards workspaces build + test / macOS energy backend (jcp-energy) (push) Successful in 2m32s
WAI conformance / cargo-class corpora · macos (push) Successful in 55s
WAI conformance / cross-arch byte-equality · macos (push) Successful in 14s
WAI conformance / cargo-class corpora · windows (push) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (push) Has been cancelled
Departures from OER/2 draft 0.1, each in extensions/oer-receipts.md §9: - decisions are named oer.decision.*, not wai.settle.* (WAI's namespace is for payload formats) - the stage list behind bundle.provenance_root is serialised exactly as the body is, pinned by a non-ASCII fixture - the number profile is normative: I-JSON integers, decimal strings in JSON's number grammar (<=34 digits), anything else malformed - a document outside the document profile is refused whole: a number whose nearest binary64 is infinite, NaN/Infinity, an unpaired surrogate, a repeated member name, nesting past 64 - every composition check is exact (num-bigint / exact decimal context), ln 2 pinned as a decimal, every tolerance scaled by the figure's magnitude - the order of the reasons reported alone, and every member judged on its value, are stated, so each mistyped member has one named reason - published Ed25519 keys are decoded strictly: canonical encoding, not small order - abstention is its own outcome (abstain, no answer, no record), held by a new reason, abstention_settled; escalate is a verdict returned from upstream Four rounds of adversarial review with differential fuzzing drove this; the last fuzz found one remaining divergence (repeated member names), now refused by both. The edge corpus grows to 99 hand-declared vectors plus unreadable/ (11 documents every verifier must refuse); each rule was falsified in both verifiers. serde_json gains float_roundtrip under the oer feature so Rust rounds as Python does. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||
| .. | ||
| settle | ||
| unreadable | ||
| edge_vectors.json | ||
| firmware_vectors.json | ||
| generate_edge_vectors.py | ||
| generate_vectors.py | ||
| oer2_verify.py | ||
| README.md | ||
| sw_export.json | ||
| vectors.json | ||
oer-conformance
Reason-set-equivalence for OER receipts: for every vector, a conforming verifier reports exactly the reasons the vector declares — the valid vectors none, each tampered vector exactly its own. A verifier that fails a vector for the wrong reason does not conform.
Three implementations check this corpus, and they share no canonicalisation code:
the reference verifier here, the portable C kernel in settle/ that
produces receipts, and wai-rs (--features oer).
Files
| file | vectors | what it is |
|---|---|---|
vectors.json |
9 | OER/2 (draft 0.1, as the extension profiles it): the last 150 decision receipts of one simulated day of Settlement World's gatewayless corridor, signed with the Ed25519 ledger key published in the file, an hourly bundle with its provenance root, an Iridium anchor, and seven tampered twins |
firmware_vectors.json |
1 | 400 receipts written by the C kernel with its own SHA-256 and Ed25519 — pinned, and regenerated byte-for-byte in CI |
edge_vectors.json |
99 | one case for each behaviour the upstream nine never exercise — see below |
unreadable/ |
11 documents | one for each way the extension refuses a document whole — a number whose nearest binary64 is infinite (the midpoint above the largest, as a float and as an integer, and far past it), NaN, Infinity, -Infinity, an unpaired surrogate, a repeated member name (plain, and a second joules_total inside a sealed receipt), nesting 65 deep, and nesting 5000 deep |
sw_export.json |
— | the Settlement World export generate_vectors.py builds vectors.json from |
The upstream nine cover eight reason names. The edge vectors pin the rest:
- every remaining reason —
unknown_kind(also withkindabsent),boundary_missing,floor_mismatch,grade_unknown,signer_unknown,missing_capability(both routes),bundle_sum_mismatch,efficiency_missing,canonical_failure,abstention_settled, andmalformed(a missing member, a receipt that is not an object); - the rule that a repeated receipt id cannot hide a reason;
- the number profile — a float, an exponent on an integer, negative zero, a float
inside an array, and each I-JSON integer bound from both sides — and the
decimal-string grammar: a leading
+, surrounding space, a non-ASCII digit, 35 significand digits (also when the 35th is a leading zero), a four-digit exponent, and a ledger figure that is not one — and, from the accepting side, exactly 34 digits and a one- and a three-digit exponent; - the order of the reasons reported alone — each adjacent pair of the six steps
(
unknown_majorbeforecanonical_failure, before a forbidden number, before an unsupported hash, before a missing member), a version written as a JSON number, and an unsupportedsig_alg, which stops nothing; - every tolerance edge — the sum, the Landauer floor, the bundle and the ledger, each exactly at its edge (passes) and just past it, on both sides, with a negative figure, and with a small one or the figure that sets its base; and for each of the four a verdict that flips if it is computed to 34 digits (the sum also to 28: misses in the 33rd and the 60th decimal place), which such a verifier gets wrong;
- every member judged on its value — a
kind, signer or receipt id that is not a string, a boundary that is absent or not a string, anefficiencythat is not an object,stagesthat are not a list, records that are not an object, a record id that is absent or not a string, a record whose answer is not a string or whosecreatedis a boolean, a published key that is not a string, a member not listed forchainorchain.anchor, a chain link to a hash that is not a string — and, against those, a receipt id or signer that is absent, which ismalformed; - keys a signature cannot rest on — the identity point, canonically encoded (small order), with its sign bit set on x = 0, and encoded as y = p + 1, each under a signature that verifies over any message for a verifier that decodes leniently. All three are small-order points, so they do not separate the canonical-encoding rule from the small-order one, and no vector can: a non-canonical encoding exists only for a point with y < 19, and a valid signature under such a point that is not of small order needs its discrete log. Both verifiers enforce both rules;
- the extremes a document may hold — the largest binary64 as a float and as an integer, a float just below the midpoint above it, a surrogate pair, and nesting exactly 64 deep, all in one vector, so a verifier that refuses the document fails the whole file;
- abstention — the valid shape, and one each carrying an answer, a record id, a
record hash, and
served_from_record.
Each carries at most one defect. Where the edit leaves the seal intact the receipt
is re-sealed, with the published test seed, so the declared reason is the only one
it can honestly produce; a vector whose reason is reported alone before any hash is
checked is left unsealed. Some literals cannot be written by json.dump, so they
are swapped in after serialisation. -0 and 1e2 are sealed over the value a
lenient parser would read (0, 100): for -0, a verifier without the rule whose
parser reads it as the integer zero finds a valid receipt, and one whose parser reads
it as a float computes a different id — neither is the declared reason. The version
written as the number 2.99999999999999977 (e25) keeps the base receipt's seal,
since unknown_major is reported before any hash is checked. e79's float just
below the midpoint and its escaped surrogate pair sit in a note, outside any
receipt. Every expectation is written by hand from the extension, not copied from a
verifier.
Run against the verifier as it stood before this pack was ingested, the first
thirteen edge vectors find five defects the upstream nine could not: an unsupported
hash reported as 'missing_capability (a stray quote — str() of a KeyError),
three uncaught KeyError crashes on a receipt, record store or ledger missing a
member, and a repeated receipt id silently replacing an earlier receipt's reasons.
The rest found a sixth class, between the verifiers rather than in either: the
reference and wai-rs as they stood before the number profile, the decimal grammar,
exact arithmetic and the typing rules reported different reason sets for many of
them — integers wider than 64 bits and -0 (each parser read them its own way), a
version written as a number, an absent kind, lenient decimals, a receipt that is
not an object, sums decided past the 28th digit, members of the wrong type, and
documents at the edge of what a parser can read. All are fixed in both.
Running
# wai-rs — both fixtures, all three files, and every document in unreadable/
cargo run --no-default-features --features oer --bin wai_oer_vectors -- verify ../oer-conformance
# the reference verifier, one file at a time (needs `cryptography`)
python3 oer2_verify.py vectors.json
python3 oer2_verify.py firmware_vectors.json
python3 oer2_verify.py edge_vectors.json
python3 oer2_verify.py --unreadable unreadable # every document there must be refused
# the C kernel: rebuild and regenerate its vectors; the output is deterministic
make -C settle && ./settle/settle_host /tmp/fw.json 400 && cmp /tmp/fw.json firmware_vectors.json
Every run prints the fixture check first. The vectors cannot check the canonical
form themselves: generate_vectors.py imports this verifier's
canonicaliser, so a defect in the field order is baked into every receipt id and
then confirmed — reverse the declared order, regenerate, and all nine still pass
with different ids. The fixture pins the bytes of a small receipt whose members are
given in the wrong order at two levels, against a literal. The C kernel proves the
same property from the other side: it shares no code with either verifier, and a
verifier with a perturbed field order rejects every receipt it writes. A second
fixture pins the stage list bundle.provenance_root addresses: every stage list in
the corpus is ASCII, where escaped and unescaped serialisations agree, so only a
non-ASCII fixture can hold the rule that the stage list is serialised exactly as the
body is.
Regenerating
python3 generate_vectors.py and python3 generate_edge_vectors.py resolve their
inputs and outputs against their own directory and reproduce vectors.json and
edge_vectors.json byte for byte. The signing seed is published
(sha256("settlement world node ledger vector key")); it attests nothing and exists
only to make the vectors reproducible.