README.md (8388B)
1 # radroots_nostr 2 3 `radroots_nostr` is the portable Nostr protocol adapter for Radroots. It 4 converts between canonical Radroots identity/event values and Nostr protocol 5 values, provides typed NIP helpers, and supplies an optional concrete local 6 implementation of the `radroots_signing` SPI. 7 8 This crate owns no relay client. It owns no sockets, HTTP client, relay pool, 9 database, account store, retry loop, scheduler, executor, or process-global 10 state. Live Nostr transport belongs in `radroots_transport_nostr`; application 11 composition belongs in `radroots_sdk` or an advanced host. 12 13 The authoritative package charter is the 14 [`radroots_nostr` section of the Release V1 specification](../../contracts/crates/release_v1/radroots_crates_release_v1.toml). 15 16 ## Quick start 17 18 Convert a canonical Radroots public key to and from its NIP-19 `npub` 19 representation: 20 21 ```rust 22 use radroots_identity::PublicKey; 23 use radroots_nostr::key::{public_key_from_npub, public_key_to_npub}; 24 25 let public_key = PublicKey::from_hex( 26 "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 27 )?; 28 let npub = public_key_to_npub(public_key)?; 29 30 assert_eq!(public_key_from_npub(&npub)?, public_key); 31 # Ok::<(), Box<dyn core::error::Error>>(()) 32 ``` 33 34 The same flow is available as a standalone example: 35 36 ```sh 37 cargo run -p radroots_nostr --example identity_conversion 38 ``` 39 40 ## Public boundary 41 42 The durable public modules are organized by responsibility: 43 44 - `event` converts event identifiers, coordinates, and signed NIP-01 values. 45 - `filter` constructs explicit Nostr subscription filters. 46 - `key` converts public identities, provides NIP-19 helpers, and—with 47 `signing`—owns opaque local secret-key handling and NIP-49 operations. 48 - `tag` converts ordered tag parts and exposes focused tag inspection helpers. 49 - `signing` implements `radroots_signing::Signer` for local Nostr keys. 50 - `nip17` wraps and unwraps typed Radroots message events with NIP-17/NIP-59. 51 - `blossom` signs and verifies BUD-11 HTTP authorization values. 52 53 `Error` is the only intended root export. Protocol representations that must 54 cross the adapter are exposed from the module that owns the conversion, rather 55 than through a root prelude or wildcard alias set. 56 57 ## Event model and typed authoring 58 59 Canonical product drafts and verified events belong to `radroots_event`. 60 Encoding, signature verification, contract admission, and typed inbound 61 projection belong to `radroots_event_codec`. This crate performs the explicit 62 translation to or from Nostr protocol values. 63 64 With `events`, typed builders cover the supported Profile, Update, 65 PhotoUpdate, Ask, Reply, Comment, deletion-request, NIP-52 date/time Event, and 66 FoodAvailability authoring profiles. Sealed focused builders fix the event kind and canonical 67 tag model before signer access. Generic builders reject reserved typed kinds; 68 relaying an already signed event is a transport operation and does not grant a 69 typed Radroots authoring claim. 70 71 Conversion and verification are deterministic for their inputs. Inbound 72 admission proves the received event and its typed projection; it does not prove 73 that referenced events, authors, addresses, relays, or external resources 74 exist. 75 76 ## Local signing 77 78 The `signing` feature provides an opaque `key::SecretKey` and a concrete local 79 signer adapter. Secret-bearing values are single-owner, are not serializable, 80 and always redact `Debug` output. Public identities are converted to the 81 canonical `radroots_identity::PublicKey` boundary before they leave the 82 adapter. 83 84 NIP-19 `nsec` export and NIP-49 encryption/decryption are explicit operations. 85 `secret_key_to_nsec` deliberately returns plaintext secret material; callers 86 must treat that string as a credential, avoid logs and serialization, and 87 zeroize or discard it promptly. Password, ciphertext, and plaintext failures 88 are normalized so error values do not retain caller-supplied secret text. 89 90 ## Side effects, cancellation, and commit points 91 92 This crate performs in-memory parsing, validation, encoding, cryptography, and 93 local signing only. It never opens a network connection, writes a file or 94 database, selects an account, publishes an event, or installs a runtime. 95 96 Some cryptographic adapters are async because their upstream protocol 97 operations are async. Dropping one of those futures cancels local computation 98 and creates no external durable effect. The crate has no remote publication or 99 persistence commit point: the only successful result is the value returned to 100 the caller. A transport or host that later publishes or stores that value owns 101 its own cancellation and commit semantics. 102 103 The `blossom` module converts exact, verified signer output into and from 104 signed `Authorization: Nostr` values but never sends an HTTP request. BUD-11 105 plans remain distinct from relay-authored plans. The `nip17` module creates and 106 opens gift-wrap events. It does not select relays, deliver events, retry 107 operations, or persist message state. 108 109 ## Serialization contract 110 111 - Canonical durable Radroots data should be serialized through 112 `radroots_event`, `radroots_event_codec`, or versioned `radroots_protocol` 113 contracts. 114 - Explicit Nostr boundary aliases use the upstream NIP-01 JSON representation. 115 - `event::ExternalSigningRequest` serializes only as the standard 116 unsigned Nostr event after reserved-kind and authoring-policy validation. 117 - Returned externally signed events are accepted only when author, canonical 118 event ID, and the complete NIP-01 signature verify against the request. 119 - Secret-bearing key and local-signer values do not implement serialization. 120 121 Deserializing protocol data never establishes product admission, account 122 authority, upload completion, referenced-event existence, or relay trust. 123 124 ## Security guidance 125 126 - Parse untrusted protocol data through the checked conversion/admission 127 functions; do not infer Radroots product validity from a syntactically valid 128 upstream event. 129 - Treat event content, tags, relay hints, Blossom claims, and NIP-17 plaintext 130 as untrusted input even after signature verification. 131 - BUD-11 authorization events are ephemeral credentials for a specific HTTP 132 operation. This crate does not transmit them or manage replay protection for 133 a server. 134 - Typed media descriptors prove bytes and metadata, not successful BUD-02 135 upload. The composing runtime must establish upload completion separately. 136 - NIP-49 protects exported key material at rest; callers still own password 137 handling, ciphertext storage, memory hygiene, and access control. 138 - The crate forbids unsafe code and does not expose a live Nostr client or an 139 ambient authority boundary. 140 141 ## Features 142 143 | Feature | Default | Contract | 144 | --- | --- | --- | 145 | `std` | yes | Enables standard-library support required by selected upstream protocol operations; it adds no network, storage, runtime, or global initialization. | 146 | `events` | yes | Enables typed event builders, deterministic Radroots/Nostr event conversion, and verified event adapters. | 147 | `signing` | no | Adds opaque local secret handling, NIP-49 helpers, draft signing, and the concrete local `radroots_signing::Signer` adapter. | 148 | `nip17` | no | Adds focused NIP-17/NIP-59 typed message and message-file wrapping/unwrapping; no delivery or persistence. | 149 | `blossom` | no | Adds BUD-11 signed HTTP authorization value creation and verification; no HTTP client or endpoint operation. | 150 151 Features are additive. `--no-default-features` provides the portable 152 `no_std + alloc` conversion core. 153 154 ## Intended consumers 155 156 - `radroots_nostr_connect` uses explicit Nostr conversion while owning NIP-46 157 protocol state. 158 - `radroots_transport_nostr` performs live relay I/O behind the generic 159 transport contracts. 160 - `radroots_sdk` composes local or remote signing, storage, and transport. 161 - Myc and `radrootsd` consume focused protocol adapters without moving their 162 host authority into this crate. 163 - Advanced Rust hosts may use this package directly for offline conversion, 164 verification, or a local signer adapter. 165 166 Applications that only need ordinary Radroots workflows should normally use 167 `radroots` or `radroots_sdk`. 168 169 ## Copyright 170 171 Except as otherwise noted, all files in the `radroots_nostr` distribution are 172 173 Copyright (c) 2025 Tyson Lupul 174 175 For information on usage and redistribution, and for a DISCLAIMER OF ALL 176 WARRANTIES, see LICENSE included in the `radroots_nostr` distribution.