§6.5 previously said what the ledger was not: tamper-evident as a sequence, but unauthenticated, with the spec forbidding an implementation from calling an entry sealed until the signed form landed. It lands here, and §6.5 now says what the entry is. Each entry is a `pool/1` JCR-1 receipt — canonical det-CBOR (RFC 8949 §4.2.1: length-first key order, shortest integer form, no floats, bools or nulls) inside a COSE_Sign1 envelope (RFC 9052, EdDSA/Ed25519, `alg = -8`), the steward's identifier as `kid`. That is the wire format the rest of this family seals with, so a `pool/1` receipt verifies under a tool that has never heard of Pool. The JCR-1 primitives are **vendored**, which is what `mesh-receipt` documents doing for the same reason: the reference library stays self-contained while the bytes stay compatible with the family's cross-language verifiers. Vendoring also kept the dependency honest — `mesh-receipt` reaches into `jcp-schema` for the decoder, and taking that dependency here would have contradicted the "self-contained" rationale in the vendored header, so the decoder is written against JCR-1's own grammar instead. Two properties, checked separately because they fail separately: - **Authenticity** — every entry verifies under the steward's key. - **Sequence** — every `seq` is its position and every `prev` is the content address of the entry before it, from genesis. Neither alone is enough, and the tests say so rather than assuming it. `a_removed_entry_breaks_the_chain_though_each_entry_is_still_signed` deletes an entry, asserts the survivors STILL verify individually, and asserts the stream is refused anyway: signatures without a chain are a bag of receipts, not a ledger. §6.6 is new: canonicity is checked, not assumed. A signature covers exact bytes, so a verifier that accepted a non-canonical encoding of the same document would let two byte strings share one signature. The decoder re-encodes what it decoded and refuses any difference. The decoder is the one piece here that is new code rather than vendored, so it carries its own tests: round-trip, a non-shortest integer refused, map keys out of length-first order refused, trailing bytes refused, duplicate keys refused, every truncation of a valid core refused, and the types outside the core grammar (floats, bools, nulls, negative integers, byte strings) refused. §8 gains the limit this does NOT remove: the steward signs its own decisions, so a ledger is self-attested by default — it proves this steward wrote this sequence, not that the decisions were right or that a second party saw them. The family already holds the shape of the answer elsewhere, a meter attestation signed by a key distinct from the receipt signer, and `pool/1` has no analogue for the decision dimension yet. Said in the spec rather than left for a reader to discover. Conformance §7.13 is rewritten and §7.14 added. 31 tests. Co-Authored-By: Claude Opus 5 <[email protected]>
17 lines
575 B
TOML
17 lines
575 B
TOML
[package]
|
|
name = "pool-core"
|
|
version = "0.1.0"
|
|
description = "Pool — the reference admission and preemption kernel for energy-accounted multi-tenant scheduling (pool/1): joule-denominated entitlement, all-or-nothing gang admission, and preemption ordered by realised efficiency."
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
|
|
[dependencies]
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
blake3 = { workspace = true }
|
|
ed25519-dalek = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
|
|
[lints.rust]
|
|
missing_docs = "warn"
|