Completes the three open items, with the rule "measured when the platform
exposes it, estimated when it doesn't — and the provenance always says which":
- jcp-energy (8th crate): the metering ladder. RAPL package counters (Linux
powercap, wraparound-corrected, HwShunt), NVML GPU energy behind the `nvml`
feature (HwShunt), a time×calibrated-power model (ModelBased, always
available), and a constant per-op estimator (Estimator). detect() never
fails; a hardware backend that dies mid-reading degrades honestly to the
model. SPEC §5.1.
- Revocation + multi-hop chains (SPEC §4.2–§4.3): a signed issuer-only
Revocation object; RevocationSet admits one only after authority checks;
verify_chain() validates root-first chains hop by hop; the runtime denies
`revoked` on the grant or any chain containing it, and decide_chained()
conserves energy across siblings — the cost must fit and is debited from
EVERY link, so delegation can never mint joules. New deny reasons: revoked,
chain-broken.
- jcp-wire (9th crate, SPEC §11): the jcp/1 wire binding — 4-byte length
prefix + canonical det-CBOR over TCP/Unix/any byte stream. The new
from_canonical_cbor decoder enforces canonicity by re-encoding, so a message
has exactly one wire form. Requests carry the full grant chain; responses
the decision + sealed JCR-1 receipt. Budget accounting holds across
connections.
- Conformance C6–C9 (revocation, chain conservation, live-socket wire
round-trip, energy honesty); CLI demo now shows the detected meter and the
issuer revoking the grant. 49 tests, clippy-clean incl. --features nvml.
Co-Authored-By: Claude Opus 4.8 <[email protected]>