lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

README.md (8025B)


      1 # radroots_event_codec
      2 
      3 `radroots_event_codec` is the portable, deterministic algorithm layer for
      4 Radroots events. It converts between bounded wire representations and native
      5 `radroots_event` values, computes canonical NIP-01 identifiers, verifies event
      6 identifiers and signatures, validates event contracts, admits typed event
      7 profiles, and generates governed contract manifests.
      8 
      9 The crate is pre-release and its Cargo version is frozen at `0.1.0-alpha`
     10 until explicitly changed. Serialized contract generations such as registry v7
     11 are versioned independently from the Cargo package.
     12 
     13 ## Canonical surface
     14 
     15 New code should enter through these modules:
     16 
     17 | Module | Responsibility |
     18 | --- | --- |
     19 | `authoring` | Freeze exact registry-authored event plans and distinct HTTP-only Blossom authorization plans with semantic digests. |
     20 | `canonical` | Compute canonical NIP-01 preimages and event identifiers without asserting trust. |
     21 | `decode` | Parse bounded wire data and domain projections without silently verifying later stages. |
     22 | `encode` | Produce deterministic JSON, tags, and unsigned wire parts from validated native inputs. |
     23 | `verify` | Advance explicit identifier, signature, and contract-validation typestates. |
     24 | `admission` | Apply typed or registry admission to an already verified event; available with `json`. |
     25 | `manifest` | Generate and validate registry and knowledge inventories; available with `manifests`. |
     26 
     27 The Release V1 canonical root consists of `Codec`, `DecodeError`,
     28 `EncodeError`, and `VerificationError`. Domain algorithms stay beneath the
     29 canonical modules so each import states whether it encodes, decodes, verifies,
     30 or admits data. Legacy top-level domain routes are not exposed. The canonical
     31 surface is recorded in the
     32 [public API baseline](../../contracts/api_baselines/radroots_event_codec.txt).
     33 
     34 ## Verification pipeline
     35 
     36 Wire parsing and cryptographic trust are separate operations. A successful
     37 decode returns a structurally valid `RawEvent`; it does not make the declared
     38 event ID, signature, contract, referenced events, relay hints, or remote media
     39 trustworthy.
     40 
     41 ```rust
     42 use radroots_event_codec::{admission, decode, verify};
     43 
     44 const PROFILE_EVENT: &str = r#"{"id":"762bee187e9e645b81ec26ade05a69b5e8398caf527be8de0d9a45311ed0c7a0","pubkey":"585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df","created_at":1800000100,"kind":0,"tags":[],"content":"{\"display_name\":\"Moss Street Farm\",\"bot\":false,\"website\":\"https://mossstreet.example\",\"picture\":42}","sig":"4290da0bb6422986647bc8cd5f63bd52d49f41e7b665d3b47105b8109183e8d596f322c531d4061df53e1d2b70fda12d5d1c14f3720d7a56d9d0a03746af5109"}"#;
     45 
     46 let raw = decode::event(PROFILE_EVENT)?;
     47 let verified = verify::verify_nip01_event(raw.into_event())?;
     48 let admitted = admission::admit_verified_event(verified)?;
     49 
     50 assert_eq!(admitted.event().kind_u32(), 0);
     51 # Ok::<(), Box<dyn std::error::Error>>(())
     52 ```
     53 
     54 A runnable version is available at
     55 [`examples/verify_profile.rs`](examples/verify_profile.rs).
     56 
     57 For capability-injected verification, use `verify::id`, then
     58 `verify::signature`, then `verify::contract`. Each function consumes its input
     59 typestate and returns the next, so callers cannot obtain a later state by
     60 accidentally skipping an earlier check.
     61 
     62 ## Features
     63 
     64 | Feature | Default | Effect |
     65 | --- | --- | --- |
     66 | `std` | yes | Standard-library error integration for the portable surface. |
     67 | `serde` | no | Serde support for native values used by codec contracts. |
     68 | `json` | yes | Bounded JSON parsing/encoding and JSON-backed typed profiles; enables `serde`. |
     69 | `knowledge` | no | Knowledge event codecs and verified decoding; enables `json`. |
     70 | `manifests` | no | Typed registry and knowledge manifest generation; enables `knowledge`. |
     71 
     72 `--no-default-features` keeps the portable allocation-backed canonical,
     73 encoding, decoding, and verification core. Feature-specific APIs disappear
     74 when their feature is disabled rather than installing a fallback with weaker
     75 guarantees.
     76 
     77 ## Serialization and canonicalization
     78 
     79 - `decode::event` accepts compact NIP-01 JSON only within the shared bounded
     80   wire limits. Unknown extension structure is bounded before it can consume
     81   unbounded memory or parser depth.
     82 - `encode::event` emits deterministic compact JSON from an existing event
     83   envelope. Encoding does not verify or alter the envelope.
     84 - `canonical::id_preimage` and `canonical::id` compute canonical bytes and the
     85   corresponding identifier. They do not compare the result with the event's
     86   declared ID.
     87 - Domain encoders accept checked `radroots_event` inputs and emit unsigned
     88   wire parts. Signing and publication belong to the owning runtime.
     89 - `authoring::BlossomAuthorizationPlan` binds a strict BUD-11 upload claim to
     90   an expected author and event ID under a domain-separated digest. Its
     91   distinct type cannot be passed to relay push APIs.
     92 - Manifest JSON and digests are generated from versioned contract authority;
     93   a manifest feature does not grant storage or publication authority.
     94 
     95 Serialized output is stable only where its event profile or manifest
     96 generation says it is stable. Rust data layout and the pre-release public API
     97 are not serialized contracts.
     98 
     99 ## Security and trust boundaries
    100 
    101 All public parsers treat their inputs as untrusted. They return structured
    102 errors for malformed or over-budget data and do not intentionally panic on
    103 untrusted input. Verification distinguishes these claims:
    104 
    105 1. structural decoding proves only bounded event shape;
    106 2. ID verification proves the declared identifier matches canonical bytes;
    107 3. signature verification proves the BIP-340 signature for that event and
    108    author;
    109 4. contract validation proves the event matches a registered shape;
    110 5. typed admission proves the selected Radroots profile.
    111 
    112 No stage proves referenced-event existence, relay availability, media upload
    113 or retrievability, actor authorization, business-policy approval, persistence,
    114 or publication. Inbound URLs and relay hints remain structural observations
    115 unless a higher layer explicitly establishes a stronger state.
    116 
    117 The crate never owns secret keys and does not sign events. Signature
    118 verification is deterministic and public-key-only. Callers must not interpret
    119 a successfully encoded unsigned event as signed or published.
    120 
    121 ## Side effects, cancellation, and commit points
    122 
    123 This crate performs no network access, filesystem access, database access,
    124 background work, executor installation, timer management, signing, or event
    125 publication. Its algorithms are synchronous and deterministic for the same
    126 inputs.
    127 
    128 There is therefore no asynchronous cancellation or deadline boundary and no
    129 durable commit point. Dropping a computation only discards in-memory work.
    130 Storage, signing, transport, SDK, and daemon callers own cancellation and must
    131 report success only after their own explicit commit boundary succeeds.
    132 
    133 ## Intended consumers
    134 
    135 Direct consumers are `radroots_nostr`, `radroots_storage_sqlite`,
    136 `radroots_transport_nostr`, `radroots_sync`, `radroots_sdk`, generated
    137 bindings, indexers, and conformance tooling. Applications should normally use
    138 the `radroots` or `radroots_sdk` front door and depend on this crate directly
    139 only when implementing a deterministic event boundary.
    140 
    141 This package must not acquire live relay clients, persistence, background
    142 workers, host configuration, SDK state, or upstream client error types. Those
    143 responsibilities belong to adapter and runtime crates.
    144 
    145 ## Package charter
    146 
    147 The authoritative Release V1 responsibility, dependency, feature, module, and
    148 forbidden-scope contract is the
    149 [Radroots crates Release V1 specification](../../contracts/crates/release_v1/radroots_crates_release_v1.toml).
    150 The reviewed surface is the
    151 [`radroots_event_codec` API baseline](../../contracts/api_baselines/radroots_event_codec.txt).
    152 
    153 ## Copyright
    154 
    155 Except as otherwise noted, all files in the `radroots_event_codec`
    156 distribution are copyright (c) 2025 Tyson Lupul. See `LICENSE` for usage,
    157 redistribution, and warranty terms.