Skip to main content

exochain_sdk/
lib.rs

1// Copyright 2026 Exochain Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at:
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17//! # EXOCHAIN SDK — Rust
18//!
19//! Ergonomic Rust API for the **EXOCHAIN constitutional governance fabric** — a
20//! substrate for AI agents and data sovereignty built around decentralized
21//! identifiers (DIDs), scoped consent (bailments), authority-chain delegation,
22//! quorum-based governance, and a constitutional kernel that enforces policy
23//! *before* action rather than auditing it after.
24//!
25//! This crate re-exports and wraps the underlying `exo-*` workspace crates
26//! behind a single, developer-friendly surface so that applications built on
27//! EXOCHAIN can depend on one crate and use one coherent API. Each domain lives
28//! in its own module:
29//!
30//! - [`identity`] — DID-backed Ed25519 identities with sign/verify.
31//! - [`consent`] — scoped, time-bounded bailments (consent tokens).
32//! - [`governance`] — decisions, voting, quorum checks.
33//! - [`authority`] — validated delegation chains.
34//! - [`kernel`] — the Constitutional Governance Runtime (CGR) kernel.
35//! - [`crypto`] — hash / sign / verify primitives (BLAKE3 + Ed25519).
36//! - [`dagdb`] — DAG DB DTO re-exports and REST request helpers.
37//! - [`error`] — the single [`error::ExoError`] type returned by fallible ops.
38//!
39//! ## Why use this SDK
40//!
41//! EXOCHAIN turns policy into a *precondition* of action. Instead of shipping
42//! agents that do things and asking an auditor to catch violations, you
43//! express identity, consent, and delegation as first-class cryptographic
44//! objects and ask the kernel whether an action is permitted. If the
45//! [`kernel::ConstitutionalKernel`] denies an action, the action never runs.
46//!
47//! This SDK gives you:
48//!
49//! - Deterministic, content-addressed IDs for every object (bailments,
50//!   decisions, chains) so two parties independently building the same object
51//!   get the same ID.
52//! - Builder APIs that validate on `build()` so invalid states are not
53//!   representable downstream.
54//! - Pure types (no I/O) suitable for offline governance, test vectors, and
55//!   cross-language interop with the TypeScript and Python SDKs.
56//!
57//! ## End-to-end example
58//!
59//! The canonical lifecycle: two identities negotiate a bailment, propose a
60//! decision, reach quorum, build a delegation chain, and submit an action to
61//! the kernel for adjudication.
62//!
63//! ```
64//! use exochain_sdk::prelude::*;
65//! use exochain_sdk::governance::VoteChoice;
66//!
67//! // 1. Create identities for alice and bob.
68//! let alice = Identity::generate("alice");
69//! let bob = Identity::generate("bob");
70//! assert!(alice.did().as_str().starts_with("did:exo:"));
71//! assert_ne!(alice.did(), bob.did());
72//!
73//! // 2. Alice proposes a scoped bailment to bob.
74//! let proposal = BailmentBuilder::new(alice.did().clone(), bob.did().clone())
75//!     .scope("data:medical")
76//!     .duration_hours(24)
77//!     .build()?;
78//! assert_eq!(proposal.scope, "data:medical");
79//! assert_eq!(proposal.proposal_id.len(), 16);
80//!
81//! // 3. Alice proposes a decision; bob and a third voter approve.
82//! let carol = Identity::generate("carol");
83//! let mut decision = DecisionBuilder::new(
84//!     "Ratify bailment",
85//!     "Allow bob to read medical records for 24h",
86//!     alice.did().clone(),
87//! )
88//! .build()?;
89//! decision.cast_vote(Vote::new(bob.did().clone(), VoteChoice::Approve))?;
90//! decision.cast_vote(Vote::new(carol.did().clone(), VoteChoice::Approve))?;
91//! let quorum = decision.check_quorum(2);
92//! assert!(quorum.met);
93//! assert_eq!(quorum.approvals, 2);
94//!
95//! // 4. Build an authority chain: root -> alice -> bob.
96//! let root = Identity::generate("root");
97//! let chain = AuthorityChainBuilder::new()
98//!     .add_link(root.did().clone(), alice.did().clone(), vec!["delegate".into()])
99//!     .add_link(alice.did().clone(), bob.did().clone(), vec!["read".into()])
100//!     .build(bob.did())?;
101//! assert_eq!(chain.depth, 2);
102//! assert_eq!(&chain.terminal, bob.did());
103//!
104//! // 5. Ask the kernel whether bob may perform the action.
105//! // The SDK kernel requires caller-supplied authority signing material.
106//! let kernel = ConstitutionalKernel::with_authority_identity(root);
107//! let verdict = kernel.adjudicate(bob.did(), "data:medical:read");
108//! assert!(verdict.is_permitted(), "expected Permitted, got {verdict:?}");
109//! # Ok::<(), exochain_sdk::error::ExoError>(())
110//! ```
111//!
112//! ## Prelude
113//!
114//! Most applications want the common builders, [`Identity`](identity::Identity),
115//! the error type, and the kernel facade. Import the [`prelude`]:
116//!
117//! ```
118//! use exochain_sdk::prelude::*;
119//!
120//! let id = Identity::generate("agent");
121//! let sig = id.sign(b"payload");
122//! assert!(id.verify(b"payload", &sig));
123//! ```
124//!
125//! ## Error handling
126//!
127//! All fallible operations return [`error::ExoResult<T>`], an alias for
128//! `Result<T, ExoError>`. Each [`error::ExoError`] variant narrows the failure
129//! to a subsystem (consent, governance, authority, kernel, crypto, serialization)
130//! so callers can pattern-match without parsing strings.
131//!
132//! ```
133//! use exochain_sdk::prelude::*;
134//! use exochain_sdk::error::ExoError;
135//! # use exo_core::Did;
136//!
137//! let alice = Did::new("did:exo:alice").expect("valid");
138//! let bob = Did::new("did:exo:bob").expect("valid");
139//!
140//! // Forgetting to set `scope` produces a Consent error:
141//! let err = BailmentBuilder::new(alice, bob)
142//!     .duration_hours(1)
143//!     .build()
144//!     .unwrap_err();
145//! assert!(matches!(err, ExoError::Consent(_)));
146//! ```
147//!
148//! ## Cross-language notes
149//!
150//! The SDK distinguishes local deterministic IDs from canonical fabric IDs.
151//! [`identity::Identity::generate`] and [`identity::Identity::from_keypair`]
152//! derive local Rust SDK DIDs from `BLAKE3(public_key)[..8]`. Other language
153//! SDKs may use different local-only derivation primitives for zero-dependency
154//! client operation.
155//!
156//! Applications that need canonical DIDs across languages should resolve the
157//! DID from the fabric, then construct the local signing handle with
158//! [`identity::Identity::from_resolved_keypair`]. That path preserves the
159//! fabric DID and verifies that the supplied secret key matches the supplied
160//! public key before constructing the identity.
161
162#![deny(missing_docs)]
163#![cfg_attr(test, allow(clippy::expect_used, clippy::unwrap_used))]
164
165/// Fabric protocol version this SDK speaks (A-066).
166///
167/// Applications may probe a target gateway on init and warn when the
168/// server reports a different major/minor so users can distinguish
169/// protocol skew from transport errors. All three SDKs (Rust, TypeScript,
170/// Python) expose a matching `PROTOCOL_VERSION` constant.
171pub const PROTOCOL_VERSION: &str = "0.2.0-beta";
172
173pub mod authority;
174pub mod avc;
175pub mod consent;
176pub mod crypto;
177pub mod dagdb;
178pub mod economy;
179pub mod error;
180pub mod governance;
181pub mod identity;
182pub mod kernel;
183
184/// Prelude — the symbols most applications want.
185///
186/// ```
187/// use exochain_sdk::prelude::*;
188///
189/// let id = Identity::generate("agent");
190/// let sig = id.sign(b"hello");
191/// assert!(id.verify(b"hello", &sig));
192/// ```
193pub mod prelude {
194    pub use crate::{
195        authority::AuthorityChainBuilder,
196        consent::BailmentBuilder,
197        crypto::{hash, sign, verify},
198        error::{ExoError, ExoResult},
199        governance::{Decision, DecisionBuilder, Vote},
200        identity::Identity,
201        kernel::ConstitutionalKernel,
202    };
203}
204
205#[cfg(test)]
206mod tests {
207    use super::PROTOCOL_VERSION;
208
209    #[test]
210    fn protocol_version_is_stable() {
211        assert_eq!(PROTOCOL_VERSION, "0.2.0-beta");
212    }
213}