# Conformance vectors — v1 Deterministic wire vectors for independent JouleContract implementations. Regenerate with: ``` cargo run -p joulecontract-conformance --bin gen_vectors ``` This pack is the **normative wire form** (SPEC §5.1): where prose and wire diverge, the wire rules. It was expanded at v0.8 after a clean-room implementability audit (round five, `../provenance/joulecontract-diff-v0.7-pack.md`) found that the composed validation path could not be built from the published artifacts alone — every input a composed verdict needs now ships in the pack. ## Reading the vectors - **Canonical JSON** (SPEC §7): UTF-8, code-point-sorted keys, no whitespace, shortest round-trip numbers **with float-ness preserved** (`3.0` stays `3.0` — this is deliberately *not* RFC 8785/JCS, which would collapse it to `3`). Content addresses are SHA-256 over the canonical form's bytes, written `sha2-256:`. - **Expected demotions are an ordered multiset**: per-discharge demotions appear once per affected discharge entry, in discharge order; receipt-level demotions appear once. A validator must reproduce the multiset; reproducing the exact order is RECOMMENDED but set-with-multiplicity equality is conformant. - **Demotion wire tokens** are the snake_case forms of the SPEC §15 names (`independent_false` for `independent:false`); `undischarged` serializes as an object carrying its reason. - **`claim` strings are informative**, not normative — match the verdict fields (`demotions`, `max_profile`, `permits_claimed_profile`), not the prose. - **Timestamps are integer seconds.** Obligation matching is exact `(kind, text)` equality; the contract's `frame` array declares one obligation with synthesized text `"frame: "` + entries joined by `"+"` (SPEC §5.1). - **`energy_anchor`** is the calibration-attestation reference required for `ModelBased` receipts; it is `null` on a `Metered` receipt because the meter binding plus the contract's ceiling-derivation attestation carry the anchoring there. **`recourse`** is a free-string regime identifier (`"ISAE3000"`, `"eIDAS-Art13"`, a bond reference); absence — not any particular value — is what serializes `recourse_undeclared`. - **Verifier-key disjointness** (SPEC §5.1.1) is computed against the effective generator key set; it does **not** require the verifier key to appear in the office key log — the log governs time coordinates (revocation windows, as-of membership), not the disjointness predicate. | Vector | What a conformant implementation must do | |---|---| | `contract.json` | Content-address it; derive **seven** obligations (two pre, two post, two inv, one frame). | | `receipt-conformant.json` | Two expected verdicts: receipt-local validation caps at **JR-2** (it cannot witness the JR-3+ gates), and composed validation over the embedded `sealed_context` grades **zero demotions**, the stated max profile, and permits the claimed `⟨JR-3 · Metered · certified⟩`. | | `receipt-jr4-conformant.json` | Grade **JR-4**: every obligation discharged twice by party-disjoint verifier entities. Quorum at JR-3 is receipt-scoped (k ≥ 2 distinct entities across the discharge log); at JR-4 it is per-obligation, expressed as multiple discharge entries per obligation (SPEC §10). | | `evidence-bundle.json` | Recompute every member address from the published bytes, recompute the bundle address (SHA-256 over the LF-joined, lexicographically sorted member address strings — SPEC §5.1.3), and match `receipt.evidence`. The transition record's bytes are included so `receipt.transition` is checkable too. | | `negative-*.json` (11) | Produce exactly the expected composed demotions and max profile against the **embedded** `sealed_context`. One case per load-bearing demotion: unbound meter, generator-key overlap (incl. the under-declared key set), entity-omission key-only independence, undischarged frame, stochastic-alone verdict, unattested generator, self-attested loop governance, undisclosed engagement, undeclared recourse, static-only frame, unterminated qualification chain. | | `context-*.json` (3) | The receipt is byte-identical to the conformant one; the demotion lives in the **context**: stale anchors (`timestamp_stale`), an open unamended breach (`breach_unamended`), and a key-log revocation window spanning the start anchor (`verifier_revoked_window`, exercising the two-timestamp `Revoked` event — SPEC §6.4). | | `malformed-missing-obligations.json` | **Reject** as malformed — an unmentioned obligation is a hole in the record, not a demotion. | | `malformed-inflated-allowance.json` | **Reject** as malformed — `joules_allowed` binds to the contract's ceiling; an inflated allowance is residual minting, not a demotion. | | `envelope-dsse.json` | Verify the DSSE envelope (Ed25519 over the PAE — formula in SPEC §7) with the published test key; recover the in-toto Statement; check `_type`, `predicateType`, and both subjects (in-toto digests use bare `sha256` hex; native fields keep the `sha2-256:` prefix). | | `amendment-chain.json` | Verify each digest against the byte-exact files in [`../archive/`](../archive/) — seven anchors, v0.1 through v0.7. | | `MANIFEST.json` | Verify every vector's content address before relying on it. | **Not yet vectored** (stated, not implied complete): composition/decomposition (SPEC §3.3), the ratchet (§5.3), re-anchor records (§3.1), sector-equivalence claims (§10), and the contract-amendment wire object (§5.2) — the reference implementation covers these in its test suite; pack vectors are future work. **The test key is not a trust root.** Vectors must be reproducible, so `envelope-dsse.json` is signed with a published seed (`0x2a` × 32). It attests nothing; treat any receipt signed with it as `generator_unattested` everything. The pack itself is integrity-checked by `MANIFEST.json` and, in-repo, by the conformance crate's tests on every run.