lib

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

commit 53bbf9b0025a5d7a258d80a7e250a748abf3069a
parent 67b85e49a8c5870422ae5cf90f2488385ced1bd1
Author: triesap <tyson@radroots.org>
Date:   Tue, 28 Jul 2026 06:18:49 +0000

identity: document public api contract

- Make the package README the crate-level rustdoc authority.
- Add a compiling public-identity example and module guidance.
- Record the pinned, reviewable public API baseline.
- Verify features, no-std targets, docs, and the root contract.

Diffstat:
Mcrates/identity/README.md | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Acrates/identity/examples/public_identity.rs | 21+++++++++++++++++++++
Mcrates/identity/src/account.rs | 10++++++++++
Mcrates/identity/src/key.rs | 6++++++
Mcrates/identity/src/lib.rs | 14+-------------
Mcrates/identity/src/profile.rs | 8++++++++
Mcrates/identity/src/username.rs | 5+++++
Mdocs/api/README.md | 1+
Adocs/api/radroots_identity.txt | 378+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 567 insertions(+), 28 deletions(-)

diff --git a/crates/identity/README.md b/crates/identity/README.md @@ -1,24 +1,146 @@ # radroots_identity -This is the README for `radroots_identity`, which provides public identity, -account, and profile value types for the Radroots package family. +`radroots_identity` provides the portable public identity and account values +shared by Radroots packages: canonical public keys, identity and account IDs, +public profiles, normalized usernames, and transport-neutral account status. -## Overview +The crate supports `no_std` environments with `alloc`. It performs no I/O, +starts no tasks or threads, reads no clocks or process state, and owns no key +generation, secrets, signing, persistence, networking, or account selection. - * validated canonical public keys, identity IDs, and account IDs; - * public identity profiles and normalized usernames; - * no raw secret keys, key generation, nsec/NIP-49 helpers, or secret export; - * no filesystem, runtime-path, protected-store, or secret-vault behavior. +## Example -See `docs/migration/identity.md` in the repository for the approved signing, -Nostr-key, secrets, and storage ownership boundaries. +Construct public identities from validated keys and derive account identifiers +without exposing or inventing secret material: -## Copyright +```rust +use radroots_identity::{AccountId, Profile, PublicIdentity, PublicKey, Username}; -Except as otherwise noted, all files in the `radroots_identity` distribution -are +let public_key = PublicKey::from_hex( + "585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df", +)?; +let username = Username::parse(" Alice.Farm ")?; +let identity = PublicIdentity::new(public_key) + .with_profile(Profile::new().with_username(username)); +let account_id = AccountId::from_public_identity(&identity); - Copyright (c) 2025 Tyson Lupul +assert_eq!(identity.id().as_bytes(), public_key.as_bytes()); +assert_eq!(account_id.as_bytes(), public_key.as_bytes()); +assert_eq!( + identity.profile().and_then(Profile::username).map(Username::as_str), + Some("alice.farm"), +); +# Ok::<(), radroots_identity::Error>(()) +``` -For information on usage and redistribution, and for a DISCLAIMER OF ALL -WARRANTIES, see LICENSE included in the `radroots_identity` distribution. +The same program is available as the +[`public_identity`](examples/public_identity.rs) example. + +## Public API + +The crate root intentionally exports `AccountId`, `IdentityId`, +`PublicIdentity`, `PublicKey`, `Profile`, `Username`, and the aggregate +[`Error`](https://docs.rs/radroots_identity/latest/radroots_identity/enum.Error.html). +Focused values remain in these modules: + +- `account` — derived account IDs, public account records, and observable + readiness status; +- `key` — validated 32-byte x-only secp256k1 public keys and identity IDs; +- `profile` — public identity metadata and the invariant-matched public + identity aggregate; +- `username` — canonical username parsing, bounds, and normalization. + +The normative responsibility and dependency boundary are defined by the +[`radroots_identity` package charter](../../docs/specs/radroots_crates_release_v1.md). +The reviewed pre-release surface is recorded in +[`docs/api`](../../docs/api/README.md). Signing, Nostr-key, secret-provider, +and storage ownership is documented in the +[`identity` migration boundary](../../docs/migration/identity.md). + +## Features + +| Feature | Default | Effect | +| --- | --- | --- | +| `std` | yes | Implements the standard error integration; value behavior remains portable. | +| `serde` | yes | Implements checked canonical serialization and deserialization for public values. | + +Disabling default features leaves the `no_std` + `alloc` value model. Features +are additive; enabling one does not select a runtime, backend, global account, +secret source, or side effect. + +## Invariants and untrusted input + +`PublicKey`, `IdentityId`, and `AccountId` store exactly 32 validated bytes. +Text parsing accepts exact-width hexadecimal input and emits canonical +lowercase hexadecimal output. `PublicKey` validation confirms that the x-only +bytes identify a secp256k1 curve point. The three Rust types remain distinct so +callers cannot accidentally substitute an account identifier for a public key. + +`PublicIdentity` derives its `IdentityId` from its `PublicKey` and rejects +separately decoded parts that do not match. `account::Record` derives its +`AccountId` from its public identity and rejects mismatched IDs or an update +timestamp before creation. `Record::touch_updated` rejects time reversal and +leaves the timestamp unchanged on error. `Record::set_label` does not read a +clock or update the timestamp; the composing host owns clock policy and must +advance the timestamp explicitly when appropriate. + +`Username` trims surrounding whitespace, folds ASCII uppercase to lowercase, +enforces its byte bounds, and rejects unsupported characters or leading, +trailing, and consecutive dots. Account labels are opaque host-facing strings: +callers must apply their own content and resource limits before accepting them +from untrusted sources. + +## Serialization + +With `serde`, identifiers are canonical lowercase 64-character hexadecimal +strings and usernames are canonical strings. Profiles, public identities, and +account records use named fields and reject unknown fields. Deserializing a +public identity or account record re-applies identifier and timestamp +invariants; invalid native state is not admitted through the supported serde +surface. Account status variant names use `snake_case`. + +Serialization contains public metadata only and does not add confidentiality, +authenticity, event signing, or transport framing. Versioned cross-process wire +DTOs belong in `radroots_protocol` rather than this native value crate. + +## Execution and commit semantics + +Operations are synchronous and deterministic. Username parsing and account +record construction may allocate in proportion to caller-supplied username or +label text, so callers should cap untrusted input bytes before invoking them. +There are no asynchronous cancellation points, deadlines, retries, callbacks, +partial external effects, or durable commit points. A successful call returns +or updates the complete in-memory value; an error returns before any durable +commit because this crate owns no durable state. + +## Security boundary + +The crate forbids unsafe Rust. Public keys and identifiers are public data and +must not be treated as proof of control; authentication requires a verified +signature in the appropriate event or signing layer. This crate deliberately +has no raw secret keys, key generation, nsec/NIP-49 helpers, keyrings, vaults, +files, SQLite, runtime paths, signer sessions, or upstream Nostr events. + +```compile_fail +use radroots_identity::{SecretKey, generate_keypair}; +``` + +Do not recreate those responsibilities through compatibility wrappers around +this crate. Compose the signing, Nostr, secrets, and storage packages named by +the migration boundary instead. + +## Intended consumers + +`radroots_identity` is intended for lower-level Radroots event, signing, +transport, storage, and domain packages and for integrators that need the +portable public value model directly. Applications should normally begin with +the curated `radroots` crate or the advanced `radroots_sdk` composition +surface. + +The package is pre-1.0. Its durable responsibility and package identity are +fixed, while API-breaking changes follow the workspace's pre-1.0 versioning +policy. + +## License + +Licensed under either Apache-2.0 or MIT, at your option. diff --git a/crates/identity/examples/public_identity.rs b/crates/identity/examples/public_identity.rs @@ -0,0 +1,21 @@ +use radroots_identity::{AccountId, Profile, PublicIdentity, PublicKey, Username}; + +fn main() -> Result<(), radroots_identity::Error> { + let public_key = + PublicKey::from_hex("585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df")?; + let username = Username::parse(" Alice.Farm ")?; + let identity = + PublicIdentity::new(public_key).with_profile(Profile::new().with_username(username)); + let account_id = AccountId::from_public_identity(&identity); + + assert_eq!(identity.id().as_bytes(), public_key.as_bytes()); + assert_eq!(account_id.as_bytes(), public_key.as_bytes()); + assert_eq!( + identity + .profile() + .and_then(Profile::username) + .map(Username::as_str), + Some("alice.farm"), + ); + Ok(()) +} diff --git a/crates/identity/src/account.rs b/crates/identity/src/account.rs @@ -1,4 +1,14 @@ //! Public, transport-neutral account value types. +//! +//! [`AccountId`] is derived from the same canonical public bytes as an +//! identity. [`Record`] combines that identifier with a [`PublicIdentity`], an +//! optional host-facing label, and caller-supplied timestamps while preserving +//! their cross-field invariants. [`Status`] reports only observable readiness; +//! it contains no secret, signer, persistence, or host-selection state. +//! +//! This module does not read a clock or persist mutations. In particular, +//! [`Record::set_label`] and [`Record::touch_updated`] are separate operations +//! so the composing host retains explicit timestamp and commit policy. use alloc::string::String; diff --git a/crates/identity/src/key.rs b/crates/identity/src/key.rs @@ -1,4 +1,10 @@ //! Canonical public-key and identity identifier value types. +//! +//! [`PublicKey`] validates a 32-byte x-only secp256k1 public key. [`IdentityId`] +//! is a distinct Rust type derived from the same canonical bytes. Both values +//! parse exact-width hexadecimal text, preserve fixed-width binary form, and +//! emit lowercase hexadecimal text without exposing secret-key or Nostr +//! bech32 behavior. use crate::Error; diff --git a/crates/identity/src/lib.rs b/crates/identity/src/lib.rs @@ -1,19 +1,7 @@ +#![doc = include_str!("../README.md")] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(coverage_nightly, feature(coverage_attribute))] #![forbid(unsafe_code)] -//! Portable public identity and account values. -//! -//! Host filesystem and runtime-path APIs are intentionally absent: -//! -//! ```compile_fail -//! use radroots_identity::{storage, IdentityError}; -//! ``` -//! -//! Secret-bearing and upstream Nostr event APIs are intentionally absent: -//! -//! ```compile_fail -//! use radroots_identity::{NostrEvent, SecretKey}; -//! ``` extern crate alloc; diff --git a/crates/identity/src/profile.rs b/crates/identity/src/profile.rs @@ -1,4 +1,12 @@ //! Public, transport-neutral identity profiles. +//! +//! [`Profile`] contains optional public metadata only. [`PublicIdentity`] +//! couples a validated [`PublicKey`] to its derived [`IdentityId`] and rejects +//! mismatched separately decoded parts. Empty profiles are omitted so one +//! public identity has one canonical native representation. +//! +//! Profiles do not perform discovery, authorization, event verification, +//! persistence, or secret handling. use crate::{Error, IdentityId, PublicKey, Username}; diff --git a/crates/identity/src/username.rs b/crates/identity/src/username.rs @@ -1,4 +1,9 @@ //! Canonical public usernames. +//! +//! [`Username`] trims surrounding whitespace, lowercases ASCII input, enforces +//! [`MIN_LENGTH`] and [`MAX_LENGTH`], and accepts only the documented public +//! character set and dot placement. Parsing and serde decoding use the same +//! validator and always produce canonical text. use alloc::string::String; use core::{fmt, str::FromStr}; diff --git a/docs/api/README.md b/docs/api/README.md @@ -31,3 +31,4 @@ expand a package beyond its charter. | Package | Baseline | Charter | | --- | --- | --- | | `radroots_core` | [`radroots_core.txt`](radroots_core.txt) | [release V1 specification](../specs/radroots_crates_release_v1.md) | +| `radroots_identity` | [`radroots_identity.txt`](radroots_identity.txt) | [release V1 specification](../specs/radroots_crates_release_v1.md) | diff --git a/docs/api/radroots_identity.txt b/docs/api/radroots_identity.txt @@ -0,0 +1,378 @@ +pub mod radroots_identity +pub mod radroots_identity::account +#[non_exhaustive] pub enum radroots_identity::account::Status +pub radroots_identity::account::Status::NotConfigured +pub radroots_identity::account::Status::PublicOnly +pub radroots_identity::account::Status::PublicOnly::account: radroots_identity::account::Record +pub radroots_identity::account::Status::Ready +pub radroots_identity::account::Status::Ready::account: radroots_identity::account::Record +impl radroots_identity::account::Status +pub const fn radroots_identity::account::Status::account(&self) -> core::option::Option<&radroots_identity::account::Record> +pub const fn radroots_identity::account::Status::is_ready(&self) -> bool +#[repr(transparent)] pub struct radroots_identity::account::AccountId(_) +impl radroots_identity::account::AccountId +pub const radroots_identity::account::AccountId::BYTE_LENGTH: usize +pub const radroots_identity::account::AccountId::HEX_LENGTH: usize +pub const fn radroots_identity::account::AccountId::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::account::AccountId::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::account::AccountId::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::account::AccountId::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::account::AccountId::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::account::AccountId::to_hex(self) -> alloc::string::String +impl radroots_identity::account::AccountId +pub const fn radroots_identity::account::AccountId::from_identity_id(radroots_identity::key::IdentityId) -> Self +pub const fn radroots_identity::account::AccountId::from_public_identity(&radroots_identity::profile::PublicIdentity) -> Self +impl core::convert::AsRef<[u8]> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::as_ref(&self) -> &[u8] +impl core::convert::From<&radroots_identity::profile::PublicIdentity> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(&radroots_identity::profile::PublicIdentity) -> Self +impl core::convert::From<radroots_identity::key::IdentityId> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(radroots_identity::key::IdentityId) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Err = radroots_identity::Error +pub fn radroots_identity::account::AccountId::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub struct radroots_identity::account::Record +impl radroots_identity::account::Record +pub const fn radroots_identity::account::Record::created_at_unix(&self) -> u64 +pub const fn radroots_identity::account::Record::id(&self) -> radroots_identity::account::AccountId +pub fn radroots_identity::account::Record::label(&self) -> core::option::Option<&str> +pub fn radroots_identity::account::Record::new(radroots_identity::profile::PublicIdentity, core::option::Option<alloc::string::String>, u64) -> Self +pub const fn radroots_identity::account::Record::public_identity(&self) -> &radroots_identity::profile::PublicIdentity +pub fn radroots_identity::account::Record::set_label(&mut self, core::option::Option<alloc::string::String>) +pub fn radroots_identity::account::Record::touch_updated(&mut self, u64) -> core::result::Result<(), radroots_identity::Error> +pub fn radroots_identity::account::Record::try_from_parts(radroots_identity::account::AccountId, radroots_identity::profile::PublicIdentity, core::option::Option<alloc::string::String>, u64, u64) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::account::Record::updated_at_unix(&self) -> u64 +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::account::Record +pub fn radroots_identity::account::Record::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub mod radroots_identity::key +#[repr(transparent)] pub struct radroots_identity::key::IdentityId(_) +impl radroots_identity::key::IdentityId +pub const radroots_identity::key::IdentityId::BYTE_LENGTH: usize +pub const radroots_identity::key::IdentityId::HEX_LENGTH: usize +pub const fn radroots_identity::key::IdentityId::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::key::IdentityId::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::IdentityId::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::IdentityId::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::key::IdentityId::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::key::IdentityId::to_hex(self) -> alloc::string::String +impl radroots_identity::key::IdentityId +pub const fn radroots_identity::key::IdentityId::from_public_key(radroots_identity::key::PublicKey) -> Self +impl core::convert::AsRef<[u8]> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::as_ref(&self) -> &[u8] +impl core::convert::From<radroots_identity::key::IdentityId> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(radroots_identity::key::IdentityId) -> Self +impl core::convert::From<radroots_identity::key::PublicKey> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::from(radroots_identity::key::PublicKey) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Err = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +#[repr(transparent)] pub struct radroots_identity::key::PublicKey(_) +impl radroots_identity::key::PublicKey +pub const radroots_identity::key::PublicKey::BYTE_LENGTH: usize +pub const radroots_identity::key::PublicKey::HEX_LENGTH: usize +pub const fn radroots_identity::key::PublicKey::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::key::PublicKey::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::PublicKey::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::PublicKey::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::key::PublicKey::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::key::PublicKey::to_hex(self) -> alloc::string::String +impl core::convert::AsRef<[u8]> for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::as_ref(&self) -> &[u8] +impl core::convert::From<radroots_identity::key::PublicKey> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::from(radroots_identity::key::PublicKey) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Err = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub mod radroots_identity::profile +pub struct radroots_identity::profile::Profile +impl radroots_identity::profile::Profile +pub const fn radroots_identity::profile::Profile::is_empty(&self) -> bool +pub const fn radroots_identity::profile::Profile::new() -> Self +pub fn radroots_identity::profile::Profile::username(&self) -> core::option::Option<&radroots_identity::username::Username> +pub fn radroots_identity::profile::Profile::with_username(self, radroots_identity::username::Username) -> Self +pub struct radroots_identity::profile::PublicIdentity +impl radroots_identity::profile::PublicIdentity +pub const fn radroots_identity::profile::PublicIdentity::id(&self) -> radroots_identity::key::IdentityId +pub const fn radroots_identity::profile::PublicIdentity::new(radroots_identity::key::PublicKey) -> Self +pub fn radroots_identity::profile::PublicIdentity::profile(&self) -> core::option::Option<&radroots_identity::profile::Profile> +pub const fn radroots_identity::profile::PublicIdentity::public_key(&self) -> radroots_identity::key::PublicKey +pub fn radroots_identity::profile::PublicIdentity::try_from_parts(radroots_identity::key::IdentityId, radroots_identity::key::PublicKey, core::option::Option<radroots_identity::profile::Profile>) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::profile::PublicIdentity::with_profile(self, radroots_identity::profile::Profile) -> Self +impl core::convert::From<&radroots_identity::profile::PublicIdentity> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(&radroots_identity::profile::PublicIdentity) -> Self +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::profile::PublicIdentity +pub fn radroots_identity::profile::PublicIdentity::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub mod radroots_identity::username +#[repr(transparent)] pub struct radroots_identity::username::Username(_) +impl radroots_identity::username::Username +pub fn radroots_identity::username::Username::as_str(&self) -> &str +pub fn radroots_identity::username::Username::into_string(self) -> alloc::string::String +pub fn radroots_identity::username::Username::parse(&str) -> core::result::Result<Self, radroots_identity::Error> +impl core::convert::AsRef<str> for radroots_identity::username::Username +pub fn radroots_identity::username::Username::as_ref(&self) -> &str +impl core::convert::TryFrom<&str> for radroots_identity::username::Username +pub type radroots_identity::username::Username::Error = radroots_identity::Error +pub fn radroots_identity::username::Username::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::username::Username +pub type radroots_identity::username::Username::Error = radroots_identity::Error +pub fn radroots_identity::username::Username::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::username::Username +pub fn radroots_identity::username::Username::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::username::Username +pub fn radroots_identity::username::Username::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::username::Username +pub type radroots_identity::username::Username::Err = radroots_identity::Error +pub fn radroots_identity::username::Username::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::username::Username +pub fn radroots_identity::username::Username::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::username::Username +pub fn radroots_identity::username::Username::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub const radroots_identity::username::MAX_LENGTH: usize +pub const radroots_identity::username::MIN_LENGTH: usize +#[non_exhaustive] pub enum radroots_identity::Error +pub radroots_identity::Error::AccountIdMismatch +pub radroots_identity::Error::AccountUpdateRegressed +pub radroots_identity::Error::AccountUpdateRegressed::current_updated_at_unix: u64 +pub radroots_identity::Error::AccountUpdateRegressed::proposed_updated_at_unix: u64 +pub radroots_identity::Error::AccountUpdatedBeforeCreated +pub radroots_identity::Error::AccountUpdatedBeforeCreated::created_at_unix: u64 +pub radroots_identity::Error::AccountUpdatedBeforeCreated::updated_at_unix: u64 +pub radroots_identity::Error::IdentityIdMismatch +pub radroots_identity::Error::InvalidByteLength +pub radroots_identity::Error::InvalidByteLength::actual: usize +pub radroots_identity::Error::InvalidByteLength::expected: usize +pub radroots_identity::Error::InvalidHexCharacter +pub radroots_identity::Error::InvalidHexCharacter::index: usize +pub radroots_identity::Error::InvalidHexLength +pub radroots_identity::Error::InvalidHexLength::actual: usize +pub radroots_identity::Error::InvalidHexLength::expected: usize +pub radroots_identity::Error::InvalidPublicKeyBytes +pub radroots_identity::Error::InvalidUsernameCharacter +pub radroots_identity::Error::InvalidUsernameCharacter::index: usize +pub radroots_identity::Error::InvalidUsernameDotPlacement +pub radroots_identity::Error::InvalidUsernameLength +pub radroots_identity::Error::InvalidUsernameLength::actual: usize +pub radroots_identity::Error::InvalidUsernameLength::max: usize +pub radroots_identity::Error::InvalidUsernameLength::min: usize +#[repr(transparent)] pub struct radroots_identity::AccountId(_) +impl radroots_identity::account::AccountId +pub const radroots_identity::account::AccountId::BYTE_LENGTH: usize +pub const radroots_identity::account::AccountId::HEX_LENGTH: usize +pub const fn radroots_identity::account::AccountId::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::account::AccountId::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::account::AccountId::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::account::AccountId::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::account::AccountId::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::account::AccountId::to_hex(self) -> alloc::string::String +impl radroots_identity::account::AccountId +pub const fn radroots_identity::account::AccountId::from_identity_id(radroots_identity::key::IdentityId) -> Self +pub const fn radroots_identity::account::AccountId::from_public_identity(&radroots_identity::profile::PublicIdentity) -> Self +impl core::convert::AsRef<[u8]> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::as_ref(&self) -> &[u8] +impl core::convert::From<&radroots_identity::profile::PublicIdentity> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(&radroots_identity::profile::PublicIdentity) -> Self +impl core::convert::From<radroots_identity::key::IdentityId> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(radroots_identity::key::IdentityId) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Error = radroots_identity::Error +pub fn radroots_identity::account::AccountId::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::account::AccountId +pub type radroots_identity::account::AccountId::Err = radroots_identity::Error +pub fn radroots_identity::account::AccountId::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +#[repr(transparent)] pub struct radroots_identity::IdentityId(_) +impl radroots_identity::key::IdentityId +pub const radroots_identity::key::IdentityId::BYTE_LENGTH: usize +pub const radroots_identity::key::IdentityId::HEX_LENGTH: usize +pub const fn radroots_identity::key::IdentityId::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::key::IdentityId::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::IdentityId::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::IdentityId::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::key::IdentityId::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::key::IdentityId::to_hex(self) -> alloc::string::String +impl radroots_identity::key::IdentityId +pub const fn radroots_identity::key::IdentityId::from_public_key(radroots_identity::key::PublicKey) -> Self +impl core::convert::AsRef<[u8]> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::as_ref(&self) -> &[u8] +impl core::convert::From<radroots_identity::key::IdentityId> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(radroots_identity::key::IdentityId) -> Self +impl core::convert::From<radroots_identity::key::PublicKey> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::from(radroots_identity::key::PublicKey) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Error = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::key::IdentityId +pub type radroots_identity::key::IdentityId::Err = radroots_identity::Error +pub fn radroots_identity::key::IdentityId::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +pub struct radroots_identity::Profile +impl radroots_identity::profile::Profile +pub const fn radroots_identity::profile::Profile::is_empty(&self) -> bool +pub const fn radroots_identity::profile::Profile::new() -> Self +pub fn radroots_identity::profile::Profile::username(&self) -> core::option::Option<&radroots_identity::username::Username> +pub fn radroots_identity::profile::Profile::with_username(self, radroots_identity::username::Username) -> Self +pub struct radroots_identity::PublicIdentity +impl radroots_identity::profile::PublicIdentity +pub const fn radroots_identity::profile::PublicIdentity::id(&self) -> radroots_identity::key::IdentityId +pub const fn radroots_identity::profile::PublicIdentity::new(radroots_identity::key::PublicKey) -> Self +pub fn radroots_identity::profile::PublicIdentity::profile(&self) -> core::option::Option<&radroots_identity::profile::Profile> +pub const fn radroots_identity::profile::PublicIdentity::public_key(&self) -> radroots_identity::key::PublicKey +pub fn radroots_identity::profile::PublicIdentity::try_from_parts(radroots_identity::key::IdentityId, radroots_identity::key::PublicKey, core::option::Option<radroots_identity::profile::Profile>) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::profile::PublicIdentity::with_profile(self, radroots_identity::profile::Profile) -> Self +impl core::convert::From<&radroots_identity::profile::PublicIdentity> for radroots_identity::account::AccountId +pub fn radroots_identity::account::AccountId::from(&radroots_identity::profile::PublicIdentity) -> Self +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::profile::PublicIdentity +pub fn radroots_identity::profile::PublicIdentity::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +#[repr(transparent)] pub struct radroots_identity::PublicKey(_) +impl radroots_identity::key::PublicKey +pub const radroots_identity::key::PublicKey::BYTE_LENGTH: usize +pub const radroots_identity::key::PublicKey::HEX_LENGTH: usize +pub const fn radroots_identity::key::PublicKey::as_bytes(&self) -> &[u8; 32] +pub fn radroots_identity::key::PublicKey::from_bytes([u8; 32]) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::PublicKey::from_hex(&str) -> core::result::Result<Self, radroots_identity::Error> +pub fn radroots_identity::key::PublicKey::from_slice(&[u8]) -> core::result::Result<Self, radroots_identity::Error> +pub const fn radroots_identity::key::PublicKey::into_bytes(self) -> [u8; 32] +pub fn radroots_identity::key::PublicKey::to_hex(self) -> alloc::string::String +impl core::convert::AsRef<[u8]> for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::as_ref(&self) -> &[u8] +impl core::convert::From<radroots_identity::key::PublicKey> for radroots_identity::key::IdentityId +pub fn radroots_identity::key::IdentityId::from(radroots_identity::key::PublicKey) -> Self +impl core::convert::TryFrom<&[u8]> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(&[u8]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<&str> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<[u8; 32]> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from([u8; 32]) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Error = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::key::PublicKey +pub type radroots_identity::key::PublicKey::Err = radroots_identity::Error +pub fn radroots_identity::key::PublicKey::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::key::PublicKey +pub fn radroots_identity::key::PublicKey::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de> +#[repr(transparent)] pub struct radroots_identity::Username(_) +impl radroots_identity::username::Username +pub fn radroots_identity::username::Username::as_str(&self) -> &str +pub fn radroots_identity::username::Username::into_string(self) -> alloc::string::String +pub fn radroots_identity::username::Username::parse(&str) -> core::result::Result<Self, radroots_identity::Error> +impl core::convert::AsRef<str> for radroots_identity::username::Username +pub fn radroots_identity::username::Username::as_ref(&self) -> &str +impl core::convert::TryFrom<&str> for radroots_identity::username::Username +pub type radroots_identity::username::Username::Error = radroots_identity::Error +pub fn radroots_identity::username::Username::try_from(&str) -> core::result::Result<Self, Self::Error> +impl core::convert::TryFrom<alloc::string::String> for radroots_identity::username::Username +pub type radroots_identity::username::Username::Error = radroots_identity::Error +pub fn radroots_identity::username::Username::try_from(alloc::string::String) -> core::result::Result<Self, Self::Error> +impl core::fmt::Debug for radroots_identity::username::Username +pub fn radroots_identity::username::Username::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Display for radroots_identity::username::Username +pub fn radroots_identity::username::Username::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::str::traits::FromStr for radroots_identity::username::Username +pub type radroots_identity::username::Username::Err = radroots_identity::Error +pub fn radroots_identity::username::Username::from_str(&str) -> core::result::Result<Self, Self::Err> +impl serde_core::ser::Serialize for radroots_identity::username::Username +pub fn radroots_identity::username::Username::serialize<S>(&self, S) -> core::result::Result<<S as serde_core::ser::Serializer>::Ok, <S as serde_core::ser::Serializer>::Error> where S: serde_core::ser::Serializer +impl<'de> serde_core::de::Deserialize<'de> for radroots_identity::username::Username +pub fn radroots_identity::username::Username::deserialize<D>(D) -> core::result::Result<Self, <D as serde_core::de::Deserializer>::Error> where D: serde_core::de::Deserializer<'de>