Skip to main content

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};