Skip to main content

treeship_core/vi/
mod.rs

1//! Verifiable Intent (VI) support: Treeship as one `agent_attestation`
2//! scheme inside a VI Layer 3 credential.
3//!
4//! [Verifiable Intent](https://verifiableintent.dev/) is an open, Mastercard-
5//! maintained credential standard for agent commerce (draft v0.1, February
6//! 2026). A user delegates bounded authority to an agent through a chain of
7//! SD-JWTs: L1 (issuer → user), L2 (user → agent, with constraints and the
8//! agent's key under `cnf`), and in autonomous mode two Layer 3 credentials
9//! the agent signs itself: L3a for the payment network and L3b for the
10//! merchant. Every layer is ES256 (ECDSA over P-256, SHA-256).
11//!
12//! This module is an independent implementation against the published draft
13//! and its Python reference SDK. It is not endorsed by, and does not speak
14//! for, the standard's maintainers. Byte formats follow the reference so that
15//! credentials built here verify with the reference `verify_chain`, and vice
16//! versa; the interop suite under `tests/vi-interop` holds that line.
17//!
18//! What Treeship adds is the value of the spec's own optional
19//! `agent_attestation` claim (§9.2 of the v0.1 README): a signed statement,
20//! chained into the agent's receipt chain, that names the session, the chain
21//! head, the Merkle checkpoint over that chain, and the approval use the
22//! action ran under. A verifier that does not know the scheme ignores the
23//! claim, as the spec requires. One that does can fetch the session package
24//! and check that the credential was minted at the end of exactly that
25//! sequence of signed steps.
26//!
27//! Layout:
28//! - [`jws`]: base64url, SHA-256, P-256 keys and ES256 compact JWS.
29//! - [`sd_jwt`]: SD-JWT serialization, disclosures, selective presentations.
30//! - [`mandate`]: a parsed view of an L2 mandate.
31//! - [`constraints`]: the eight registered constraint types, checked the way
32//!   the reference checks them.
33//! - [`l3`]: building L3a / L3b.
34//! - [`attestation`]: the Treeship attestation statement and claim.
35//! - [`verify`]: verifying L3 credentials against their L2 (and L2 against L1).
36//! - [`keys`]: the agent's P-256 key at rest, sealed by the ship keystore.
37
38pub mod attestation;
39pub mod constraints;
40pub mod jws;
41pub mod keys;
42pub mod l3;
43pub mod mandate;
44pub mod sd_jwt;
45pub mod verify;
46
47pub use attestation::{
48    attestation_payload_type, build_attestation_claim, verify_attestation_claim, AttestationClaim,
49    AttestationStatement, AttestationVerified, ATTESTATION_ACTION, ATTESTATION_SCHEME,
50    ATTESTATION_STATEMENT_TYPE,
51};
52pub use constraints::{check_constraints, CheckResult};
53pub use jws::{AgentKey, Jwk};
54pub use l3::{build_l3, L3Bundle, L3Request, LineItem};
55pub use mandate::L2View;
56pub use sd_jwt::SdJwt;
57pub use verify::{verify_l2_against_l1, verify_l3, Check, Report};
58
59/// Errors produced by the VI module.
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub enum ViError {
62    /// Malformed input: bad base64url, bad JSON, a token with the wrong shape.
63    Malformed(String),
64    /// A key could not be parsed, generated, sealed or unsealed.
65    Key(String),
66    /// A signature did not verify.
67    Signature(String),
68    /// The requested action falls outside the mandate, or the mandate is
69    /// unusable (empty allowlist, missing constraint).
70    Mandate(String),
71    /// A verification check failed (see [`Report`] for the full list).
72    Verification(String),
73}
74
75impl std::fmt::Display for ViError {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        match self {
78            Self::Malformed(m) => write!(f, "malformed: {m}"),
79            Self::Key(m) => write!(f, "key: {m}"),
80            Self::Signature(m) => write!(f, "signature: {m}"),
81            Self::Mandate(m) => write!(f, "mandate: {m}"),
82            Self::Verification(m) => write!(f, "verification: {m}"),
83        }
84    }
85}
86
87impl std::error::Error for ViError {}