open-standards/joule-code/joule-code-rs/crates/joule-code-schema/src/lib.rs
David Charlot b838b86a8b joule-code: stand up the Joule Code standard (v0.1.0 draft)
Joule Code is the coding cargo class of the substrate: a coding operation —
an edit, refactor, or generated function — is a content-addressed, signed
transition over a source tree, resolved through the energy-tiered cascade
(L0 Cache → L1 Lawful → L2 Embed → L3 Model → L4 Wire, stop-at-first-close)
with a signed JWP receipt (measured + estimated µJ, honest Provenance) per
operation. The agent schema is JouleClaw; L4 frontier agents are reached over
ACP with the credential held by the vendor's own client — no protocol token,
no required contact with any single company.

Stands up the standard to the family schema:
- README, SPEC.md (RFC-2119 normative), dual licence (Apache-2.0 code /
  CC-BY-4.0 spec), ROADMAP, CONTRIBUTING, CHANGELOG.
- spec/: cargo (the coding-operation type), cascade (the tier binding),
  receipt (the JWP energy record), collab (federated, interface-level/Research).
- vocab/LEXICON.md.
- conformance/v1/: C1 content-addressing, C2 signing, C3 receipt, C4 cascade
  vectors + VERSIONS + regeneration; real Ed25519 RFC-8032 KATs, derived
  fields regenerated against the reference library.
- joule-code-rs/: lean reference library (schema, cargo, receipt, cascade,
  conformance). cargo test --workspace passes; the conformance harness runs
  11 pass / 0 fail / 7 skip (derived fields pending regeneration).

Single-endpoint operation is the v0.1 surface; federated collaboration is
specified at interface level and classified Research. Registers the standard
in the family README.

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

113 lines
3.5 KiB
Rust

//! Joule Code schema: content addressing, canonical serialization, shared types.
//!
//! Implements SPEC §3 (identity / content addressing) and §4 (canonical
//! serialization), plus the shared [`Tier`] type used across the cargo,
//! receipt, and cascade crates.
use base64::Engine as _;
use serde::{Deserialize, Serialize};
/// Errors from canonical encoding / addressing.
#[derive(Debug, thiserror::Error)]
pub enum SchemaError {
/// Canonical CBOR encoding failed.
#[error("canonical encoding failed: {0}")]
Encode(String),
}
/// A content address: `BLAKE3-256` of a canonical serialization, rendered as
/// `"b3:" + unpadded base64url` (SPEC §3).
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ContentId(pub String);
impl ContentId {
/// The address of raw canonical bytes.
pub fn of_bytes(canonical: &[u8]) -> Self {
let hash = blake3::hash(canonical);
let b64 = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(hash.as_bytes());
ContentId(format!("b3:{b64}"))
}
/// The address of any value via its canonical CBOR form (SPEC §4).
pub fn of_canonical<T: Serialize>(value: &T) -> Result<Self, SchemaError> {
Ok(Self::of_bytes(&canonical_cbor(value)?))
}
/// The textual form, e.g. `"b3:AAAA..."`.
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for ContentId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
/// Canonical serialization (SPEC §4): deterministic CBOR. Our load-bearing
/// types are structs with a fixed field order and contain no floats and no
/// hash-randomized maps, so `ciborium`'s encoding is deterministic across
/// platforms for equal values.
pub fn canonical_cbor<T: Serialize>(value: &T) -> Result<Vec<u8>, SchemaError> {
let mut buf = Vec::new();
ciborium::ser::into_writer(value, &mut buf).map_err(|e| SchemaError::Encode(e.to_string()))?;
Ok(buf)
}
/// The energy-tiered cascade tiers (SPEC §1.1). Inherited from JouleClaw.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Tier {
/// Content-addressed cache hit (picojoules).
L0,
/// Deterministic primitive (nanojoules).
L1,
/// Embedding + hybrid retrieval (sub-millijoules).
L2,
/// Local model (joules).
L3,
/// Remote frontier agent over ACP (tens of joules); the escape hatch.
L4,
}
impl Tier {
/// The wire tag, e.g. `"L3"`.
pub fn wire_tag(self) -> &'static str {
match self {
Tier::L0 => "L0",
Tier::L1 => "L1",
Tier::L2 => "L2",
Tier::L3 => "L3",
Tier::L4 => "L4",
}
}
}
impl std::fmt::Display for Tier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.wire_tag())
}
}
/// The one-byte algorithm identifier for signatures (SPEC §2). `0x01` =
/// Ed25519 (RFC 8032). A verifier MUST fail closed on an unknown value.
pub const ALG_ED25519: u8 = 0x01;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn content_id_is_stable_and_prefixed() {
let a = ContentId::of_bytes(b"hello");
let b = ContentId::of_bytes(b"hello");
assert_eq!(a, b);
assert!(a.as_str().starts_with("b3:"));
}
#[test]
fn canonical_cbor_is_deterministic() {
let x = (1u8, Tier::L3, "edit");
assert_eq!(canonical_cbor(&x).unwrap(), canonical_cbor(&x).unwrap());
}
}