open-standards/map/map-rs/crates/map-conformance/src/lib.rs
Transaction Science ba1212361f Add aac, map, sandbox standards; catalog the standards family
Commit the previously-untracked standard directories and catalog them in the
root README alongside proof:

- aac/    — communication cargo class: portable boards + a ten-level
            offline-first cascade (Apache-2.0 code / CC-BY-4.0 spec).
- map/    — geospatial cargo class: range-requestable signed tilesets +
            an F0–F4 fidelity cascade (Apache-2.0 code / CC-BY-4.0 spec).
- sandbox/— isolated, metered, attested execution across the heterogeneous
            compute fabric (Apache-2.0 code / CC-BY-4.0 spec).
- jouleclaw-otel-authz, jouleclaw-trust — new jouleclaw reference crates.

Root README now lists aac, map, sandbox, and proof in the catalog, the tree,
and the contribution guide.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-07 17:04:36 -04:00

256 lines
9.5 KiB
Rust

//! Map conformance harness (SPEC §8).
//!
//! Runs five positive suites and a negative pack against deterministic,
//! real-crypto vectors. Every check runs for real — there are no placeholder
//! SKIPs. Any FAIL makes the run non-zero (CI-ready). The same vectors are
//! emitted to `conformance/v1/*.json` by the `gen-vectors` binary so a
//! third-party implementation in any language can certify against the published
//! bytes.
use ed25519_dalek::SigningKey;
use map_cascade::{resolve, CascadeError, Resolution, TileSource};
use map_receipt::{Energy, Provenance, Receipt};
use map_schema::{
verify_chain, AltBand, AltSchedule, CellKey, ContentId, DirEntry, Directory, Lod, Manifest,
ManifestBody, RevisionBody, S2CellId, SchemaError, Tier, TimeBucket,
};
pub const STEWARD: &str = "did:example:map-reference";
#[derive(Default, Debug)]
pub struct Report {
pub pass: u32,
pub fail: u32,
pub lines: Vec<String>,
}
impl Report {
fn ok(&mut self, name: &str) {
self.pass += 1;
self.lines.push(format!(" PASS {name}"));
}
fn bad(&mut self, name: &str, why: impl std::fmt::Display) {
self.fail += 1;
self.lines.push(format!(" FAIL {name}: {why}"));
}
/// `check(true, …)` passes; `check(false, …)` fails.
fn check(&mut self, name: &str, cond: bool, why: &str) {
if cond {
self.ok(name);
} else {
self.bad(name, why);
}
}
}
fn test_key(seed: u8) -> SigningKey {
SigningKey::from_bytes(&[seed; 32])
}
fn cell(s2: u64, lod: u8) -> CellKey {
CellKey { s2: S2CellId(s2), alt: AltBand(0), time: TimeBucket::ATEMPORAL, lod: Lod(lod) }
}
/// A tier-presence map for the cascade suite.
struct FixtureSource {
present: Vec<(u64, Vec<Tier>)>,
}
impl TileSource for FixtureSource {
fn cached(&self, _c: &CellKey) -> Option<ContentId> {
None
}
fn tile(&self, c: &CellKey, tier: Tier) -> Option<ContentId> {
self.present
.iter()
.find(|(s2, _)| *s2 == c.s2.0)
.filter(|(_, tiers)| tiers.contains(&tier))
.map(|_| ContentId::of_bytes(&[c.s2.0 as u8, tier.rank()]))
}
}
/// Build the canonical sample tileset directory shared by C2/C3.
fn sample_directory() -> Directory {
Directory::new(vec![
DirEntry { key: cell(0x10, 0), offset: 0, len: 128, content_id: ContentId::of_bytes(b"a") },
DirEntry { key: cell(0x20, 0), offset: 128, len: 64, content_id: ContentId::of_bytes(b"b") },
DirEntry { key: cell(0x30, 0), offset: 256, len: 32, content_id: ContentId::of_bytes(b"c") },
])
}
fn sample_manifest(sk: &SigningKey, dir: &Directory) -> Result<Manifest, SchemaError> {
ManifestBody {
spec_version: "0.1.0".into(),
datum: "WGS84".into(),
alt_schedule: AltSchedule::default(),
dir_root: dir.root()?,
bounds: Some((cell(0x10, 0), cell(0x30, 0))),
disclaimer: None,
publisher: sk.verifying_key(),
}
.sign(sk)
}
/// Run all suites. Returns the report; caller decides exit code.
pub fn run() -> Report {
let mut r = Report::default();
c1_cell_key(&mut r);
c2_directory(&mut r);
c3_manifest_revision(&mut r);
c4_cascade(&mut r);
c5_receipt(&mut r);
c_neg(&mut r);
r
}
/// C1 — cell key canonical serialization + content id is deterministic.
fn c1_cell_key(r: &mut Report) {
let k = cell(0x1234_0000_0000_0001, 5);
match (ContentId::of(&k), ContentId::of(&k)) {
(Ok(a), Ok(b)) => r.check("C1.cell_key_deterministic", a == b, "content id not stable"),
_ => r.bad("C1.cell_key_deterministic", "serialization failed"),
}
// Distinct axes -> distinct ids (the time axis is first-class).
let t1 = CellKey { time: TimeBucket { start_tai_ms: 1, width_ms: 3_600_000 }, ..k };
let t2 = CellKey { time: TimeBucket { start_tai_ms: 2, width_ms: 3_600_000 }, ..k };
r.check(
"C1.time_axis_distinguishes",
ContentId::of(&t1).ok() != ContentId::of(&t2).ok(),
"different time buckets hashed equal",
);
}
/// C2 — directory sorts, coalesces ranges, and a reader can verify payloads.
fn c2_directory(r: &mut Report) {
let dir = sample_directory();
r.check("C2.directory_sorted", dir.is_sorted(), "directory not Hilbert-sorted");
// Two adjacent cells -> one coalesced byte span.
let ranges = dir.ranges_for(&[cell(0x10, 0), cell(0x20, 0)]);
r.check("C2.range_coalesced", ranges == vec![(0, 192)], "range planner did not coalesce");
// Payload hash check: the directory's content_id must match the bytes.
let entry = dir.locate(&cell(0x10, 0)).expect("located");
r.check(
"C2.payload_hash_verifies",
entry.content_id == ContentId::of_bytes(b"a"),
"payload hash mismatch",
);
}
/// C3 — manifest signs/verifies; revision chain validates; tamper fails.
fn c3_manifest_revision(r: &mut Report) {
let sk = test_key(7);
let dir = sample_directory();
let m = match sample_manifest(&sk, &dir) {
Ok(m) => m,
Err(e) => return r.bad("C3.manifest_sign", e),
};
r.check("C3.manifest_verifies", m.verify().is_ok(), "good manifest failed to verify");
// A revision chains onto the manifest root.
let root0 = m.root().unwrap();
let root1 = ContentId::of_bytes(b"next-cycle-root");
let rev = RevisionBody { prev_root: root0, new_root: root1, timestamp_tai_ms: 1, publisher: sk.verifying_key() }
.sign(&sk)
.unwrap();
match verify_chain(root0, &[rev]) {
Ok(head) => r.check("C3.revision_chain", head == root1, "chain head wrong"),
Err(e) => r.bad("C3.revision_chain", e),
}
}
/// C4 — cascade closes at the right tier and falls back to F1.
fn c4_cascade(r: &mut Report) {
let src = FixtureSource {
present: vec![
(0xAA, vec![Tier::Base, Tier::Field, Tier::Feature, Tier::Photoreal]),
(0xBB, vec![Tier::Base]), // floor only -> must fall back
],
};
let close = |s2, req| resolve(&src, &cell(s2, 0), req);
match close(0xAA, Tier::Field) {
Ok(Resolution { tier, fell_back, .. }) => {
r.check("C4.respects_ceiling", tier == Tier::Field && !fell_back, "did not stop at ceiling");
}
Err(e) => r.bad("C4.respects_ceiling", e),
}
match close(0xBB, Tier::Photoreal) {
Ok(Resolution { tier, fell_back, .. }) => {
r.check("C4.falls_back_to_floor", tier == Tier::Base && fell_back, "did not fall back to F1");
}
Err(e) => r.bad("C4.falls_back_to_floor", e),
}
}
/// C5 — receipts seal, verify, and enforce the provenance coupling.
fn c5_receipt(r: &mut Report) {
let sk = test_key(9);
let rcpt = Receipt {
cell: cell(0x42, 0),
content_id: ContentId::of_bytes(b"tile"),
tier: Tier::Photoreal,
energy: Energy::estimate_tier(Tier::Photoreal),
sequence: 1,
nonce: [0, 0, 0, 0, 0, 0, 0, 1],
};
match rcpt.seal(&sk, STEWARD) {
Ok(env) => {
let ok = rcpt.verify_envelope(&env, STEWARD, &sk.verifying_key().to_bytes()).is_ok();
r.check("C5.receipt_roundtrip", ok, "sealed receipt failed to verify");
let wrong = rcpt.verify_envelope(&env, "did:example:other", &sk.verifying_key().to_bytes()).is_err();
r.check("C5.receipt_rejects_wrong_steward", wrong, "verified under wrong steward");
}
Err(e) => r.bad("C5.receipt_roundtrip", e),
}
}
/// C-neg — the negative pack: tampered directory root, broken chain, dishonest receipt.
fn c_neg(r: &mut Report) {
let sk = test_key(7);
let dir = sample_directory();
let mut m = sample_manifest(&sk, &dir).unwrap();
m.body.dir_root = ContentId::of_bytes(b"tampered");
r.check("Cneg.tampered_manifest_fails", m.verify().is_err(), "tampered manifest verified");
// Revision signed by an unendorsed key.
let attacker = test_key(66);
let root0 = ContentId::of_bytes(b"r0");
let bad_rev = RevisionBody { prev_root: root0, new_root: ContentId::of_bytes(b"r1"), timestamp_tai_ms: 1, publisher: sk.verifying_key() }
.sign(&attacker) // signed by the wrong key
.unwrap();
r.check("Cneg.unendorsed_revision_fails", verify_chain(root0, &[bad_rev]).is_err(), "unendorsed revision verified");
// Receipt claiming HwShunt with no measured figure.
let rcpt = Receipt {
cell: cell(1, 0),
content_id: ContentId::of_bytes(b"x"),
tier: Tier::Base,
energy: Energy { measured_uj: None, estimated_uj: 1, provenance: Provenance::HwShunt },
sequence: 1,
nonce: [0; 8],
};
r.check("Cneg.hwshunt_without_measured_fails", rcpt.seal(&test_key(9), STEWARD).is_err(), "dishonest receipt sealed");
// An out-of-order directory must refuse to produce a root.
let unsorted = Directory {
entries: vec![
DirEntry { key: cell(0x30, 0), offset: 0, len: 1, content_id: ContentId::of_bytes(b"c") },
DirEntry { key: cell(0x10, 0), offset: 1, len: 1, content_id: ContentId::of_bytes(b"a") },
],
};
r.check(
"Cneg.unsorted_directory_refuses_root",
matches!(unsorted.root(), Err(SchemaError::Unsorted)),
"unsorted directory produced a root",
);
let _ = CascadeError::UncoveredRegion; // referenced for completeness
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_suites_pass() {
let report = run();
assert_eq!(report.fail, 0, "conformance failures:\n{}", report.lines.join("\n"));
assert!(report.pass >= 12, "expected the full suite to run, got {} checks", report.pass);
}
}