README.md (8579B)
1 # radroots_blossom 2 3 `radroots_blossom` provides portable Blossom protocol primitives for Radroots: 4 canonical SHA-256 values and root hash paths, blob URLs, media types, BUD-02 5 descriptors, byte-verification typestates, and pure BUD-11 authorization 6 claims. 7 8 The crate supports `no_std` environments with `alloc`. It performs no I/O, 9 starts no tasks or threads, reads no clocks or process state, and owns no HTTP 10 client, upload scheduler, cache, filesystem, credential, signer, or global 11 authentication state. 12 13 ## Example 14 15 Parse a BUD-02 descriptor, apply the Radroots reference policy, and prove that 16 its hash, size, and media type match locally available bytes: 17 18 ```rust 19 use radroots_blossom::{BlobDescriptor, BlobUrl, MediaType, Sha256}; 20 21 let bytes = b"hello"; 22 let hash = Sha256::digest(bytes); 23 let media_type = MediaType::parse("text/plain")?; 24 let url = BlobUrl::parse(&format!("https://media.example/{hash}.txt"))?; 25 let descriptor = BlobDescriptor::new( 26 url, 27 hash, 28 bytes.len() as u64, 29 media_type.clone(), 30 1_725_105_921, 31 )?; 32 33 let verified = descriptor 34 .approve_reference()? 35 .verify_bytes(bytes, &media_type)?; 36 37 assert_eq!(verified.sha256(), hash); 38 assert_eq!(verified.size(), 5); 39 assert_eq!(verified.url().as_str(), format!("https://media.example/{hash}.txt")); 40 # Ok::<(), radroots_blossom::Error>(()) 41 ``` 42 43 The same program is available as the 44 [`verified_descriptor`](examples/verified_descriptor.rs) example. 45 46 ## Public API 47 48 The crate root intentionally exports `AuthorizationClaim`, `BlobDescriptor`, 49 `BlobUrl`, `ByteVerifiedDescriptor`, `MediaType`, `Sha256`, and the aggregate 50 [`Error`](https://docs.rs/radroots_blossom/latest/radroots_blossom/enum.Error.html). 51 Supporting states and constructors remain in these modules: 52 53 - `authorization` — bounded BUD-11 claim parsing, endpoint-scope validation, 54 and upload-claim wire parts; 55 - `descriptor` — BUD-02 descriptors and the approved-reference, 56 byte-commitment, and byte-verified states; 57 - `hash` — SHA-256 values, safe file extensions, and root hash paths; 58 - `media_type` — parsed and deterministically canonicalized media types; 59 - `url` — structural blob URLs and the stricter approved-reference state. 60 61 The normative responsibility and dependency boundary are defined by the 62 [`radroots_blossom` package charter](../../contracts/crates/release_v1/radroots_crates_release_v1.toml). 63 The reviewed pre-release surface is recorded in the 64 [`radroots_blossom` API baseline](../../contracts/api_baselines/radroots_blossom.txt). 65 66 ## Features 67 68 | Feature | Default | Effect | 69 | --- | --- | --- | 70 | `std` | yes | Implements the standard error integration and enables standard-library support in dependencies; protocol behavior remains portable. | 71 | `serde` | yes | Implements checked string serialization for hashes, paths, URLs, and media types, plus checked BUD-02 descriptor serialization. | 72 73 Disabling default features leaves the `no_std` + `alloc` protocol model. 74 Features are additive; neither feature selects a runtime, transport, backend, 75 clock, signer, credential source, or side effect. 76 77 ## Protocol and validation boundaries 78 79 Protocol behavior is pinned to Blossom commit 80 `b5bd2801d1763aa635fc8fea7a76597e0eb18990`: 81 82 - [BUD-01](https://github.com/hzrd149/blossom/blob/b5bd2801d1763aa635fc8fea7a76597e0eb18990/buds/01.md) 83 defines root hash paths and basic blob retrieval; 84 - [BUD-02](https://github.com/hzrd149/blossom/blob/b5bd2801d1763aa635fc8fea7a76597e0eb18990/buds/02.md) 85 defines blob descriptors; 86 - [BUD-11](https://github.com/hzrd149/blossom/blob/b5bd2801d1763aa635fc8fea7a76597e0eb18990/buds/11.md) 87 defines Nostr authorization claims. 88 89 `Sha256`, `HashPath`, `BlobUrl`, and `MediaType` reject ambiguous encodings and 90 emit their documented canonical textual forms. A `BlobDescriptor` additionally 91 requires a URL file extension and the same hash in its URL and `sha256` field. 92 These checks establish structural protocol validity; they do not make a remote 93 reference trustworthy. 94 95 `BlobUrl::parse` accepts structurally valid public HTTP references so received 96 Blossom data can be represented faithfully. `BlobUrl::approve` advances only 97 HTTPS or loopback HTTP references to `ApprovedBlobUrl`. Callers must not fetch, 98 display, cache, or otherwise act on an unapproved URL. URL approval is a narrow 99 transport policy, not host reputation, content safety, malware scanning, or 100 application media policy. 101 102 `BlobUrl::upload_url` projects the BUD-02 `/upload` URL at the same scheme, 103 host and port. It preserves the canonical blob reference used for retrieval 104 verification and grants no transport authority. Upload callers must still 105 enforce their configured endpoint policy and bind authorization to exact bytes. 106 107 `ByteVerifiedDescriptor` can only be produced after an approved descriptor's 108 hash, byte length, and approved media type match supplied bytes or a locally 109 computed `ByteCommitment`. It proves local descriptor-to-byte agreement. It is 110 not a server receipt, upload acknowledgement, authenticity proof, or safe-media 111 classification. 112 113 ## Authorization and security 114 115 `AuthorizationClaim` parses the BUD-11 content and tags needed for endpoint 116 authorization. Validation checks caller-supplied current time, action, server, 117 hash, expiration, creation age, and lifetime policy. The crate never reads a 118 clock and never verifies a Nostr event signature or signer identity. The 119 composing Nostr layer must validate event kind `24242`, signature, author, 120 request association, and canonical `Authorization: Nostr` encoding before an 121 endpoint treats a validated claim as authenticated. Kind `24242` is ephemeral 122 HTTP authorization material and must not be published to relays. 123 124 `AuthoredUploadClaim` emits checked event wire parts; it does not sign them or 125 send a request. Authorization content is bounded to 4,096 bytes, server domains 126 use lowercase ASCII DNS, canonical IPv4, or bracketed canonical IPv6 forms, 127 timestamps are explicit 128 caller inputs, and authored lifetimes are limited to 300 seconds. 129 130 The crate forbids unsafe Rust. It does not provide confidentiality, 131 authentication, authorization storage, credential redaction, content scanning, 132 SSRF protection beyond its explicit URL approval rule, or resource limits for 133 the bytes callers choose to hash. Hosts must bound untrusted payload sizes 134 before hashing or retaining them and must enforce application policy at their 135 own trust boundaries. 136 137 ## Serialization 138 139 With `serde`, SHA-256 values are lowercase hexadecimal strings; file extensions, 140 hash paths, blob URLs, and media types use their canonical string forms; and 141 BUD-02 descriptors use the protocol fields `url`, `sha256`, `size`, `type`, and 142 `uploaded`. Deserialization re-runs the same parsers and descriptor constructor, 143 so malformed or cross-field-inconsistent values cannot enter through the 144 supported serde surface. 145 146 Authorization states and approved or byte-verified typestates intentionally do 147 not implement serde. Reconstruct them by parsing untrusted wire parts and 148 reapplying the current request, time, URL, and byte-verification policies. 149 Serialization alone never preserves an approval or authentication decision. 150 151 ## Execution and commit semantics 152 153 Operations are synchronous and deterministic. Hashing cost is linear in the 154 caller-supplied byte slice; parsing and authored authorization construction may 155 allocate in proportion to bounded input. There are no asynchronous cancellation 156 points, deadlines, retries, callbacks, network requests, partial external 157 effects, or durable commit points. A successful call returns its complete 158 in-memory value; an error returns without durable mutation because the crate 159 owns no external state. 160 161 HTTP-capable callers must define their own cancellation and commit boundary. 162 In particular, local byte verification does not authorize marking a BUD-02 163 upload complete: durable upload success may be committed only after the 164 composing transport has validated its successful server response. 165 166 ## Intended consumers 167 168 `radroots_blossom` is intended directly for `radroots_event`, 169 `radroots_event_codec`, `radroots_nostr`, and media clients that need portable 170 Blossom values. Applications should normally begin with the curated `radroots` 171 crate or the advanced `radroots_sdk` composition surface, where transport, 172 signing, storage, and application media policy can be supplied explicitly. 173 174 The package is pre-1.0. Its durable responsibility and package identity are 175 fixed, while API-breaking changes follow the workspace's pre-1.0 versioning 176 policy. 177 178 ## License 179 180 Licensed under either Apache-2.0 or MIT, at your option.