shardline_protocol/lib.rs
1#![deny(unsafe_code)]
2#![cfg_attr(
3 test,
4 allow(
5 clippy::unwrap_used,
6 clippy::expect_used,
7 clippy::indexing_slicing,
8 clippy::shadow_unrelated,
9 clippy::let_underscore_must_use,
10 clippy::format_push_string
11 )
12)]
13
14//! Shared protocol-facing types used by Shardline clients, storage adapters, and the
15//! HTTP server.
16//!
17//! This crate keeps the wire-level contracts small and explicit:
18//!
19//! - [`ShardlineHash`] stores validated 32-byte hashes and canonical lowercase
20//! hexadecimal text.
21//! - [`ByteRange`] and [`ChunkRange`] validate range boundaries before they reach
22//! storage code.
23//! - [`TokenSigner`] signs and verifies scoped bearer tokens without exposing
24//! secret material in debug output.
25//! - [`RepositoryScope`] ties provider-issued tokens to one repository and,
26//! optionally, one revision.
27//!
28//! # Example
29//!
30//! ```
31//! use shardline_protocol::{
32//! RepositoryProvider, RepositoryScope, TokenClaims, TokenScope, TokenSigner,
33//! };
34//!
35//! let repository =
36//! RepositoryScope::new(RepositoryProvider::GitHub, "acme", "assets", Some("main"))?;
37//! let claims = TokenClaims::new(
38//! "shardline",
39//! "alice",
40//! TokenScope::Read,
41//! repository,
42//! 1_700_000_600,
43//! )?;
44//!
45//! let signer = TokenSigner::new(b"development-only-signing-key-32bytes")?;
46//! let token = signer.sign(&claims)?;
47//! let verified = signer.verify_at(&token, 1_700_000_000)?;
48//!
49//! assert_eq!(verified.subject(), "alice");
50//! assert_eq!(verified.repository().owner(), "acme");
51//! assert!(verified.scope().allows_read());
52//! # Ok::<(), Box<dyn std::error::Error>>(())
53//! ```
54
55mod hash;
56mod ranges;
57mod security;
58mod text;
59mod time;
60mod token;
61pub use hash::{HashParseError, ShardlineHash};
62pub use ranges::{ByteRange, ChunkRange, HttpRangeParseError, RangeError, parse_http_byte_range};
63pub use security::{SecretBytes, SecretString};
64pub use text::parse_bool;
65pub use time::unix_now_seconds_lossy;
66pub use token::{
67 MAX_TOKEN_STRING_BYTES, RepositoryProvider, RepositoryScope, TokenClaims, TokenClaimsError,
68 TokenCodecError, TokenScope, TokenSigner, decode_and_validate_claims, encode_token_claims,
69 format_signed_token, split_token,
70};