Skip to main content

aitp_session_bundle/
error.rs

1//! Session Trust Bundle errors (RFC-AITP-0010 §7 / `BUNDLE_*` codes
2//! tracked in `agentidentitytrustprotocol/plans/v0.2-conformance-followups.md`).
3
4/// Errors from session-bundle construction and verification.
5#[derive(Debug, thiserror::Error)]
6pub enum SessionBundleError {
7    /// `version` field was not `"aitp/0.3"`.
8    #[error("bundle version mismatch")]
9    VersionMismatch,
10    /// Outer bundle signature failed to verify against the
11    /// coordinator's pubkey.
12    #[error("bundle signature is invalid")]
13    InvalidSignature,
14    /// Bundle's `expires_at` is in the past.
15    #[error("bundle has expired")]
16    Expired,
17    /// `expires_at` did not equal `min(participants[*].tct.expires_at)`
18    /// (RFC-AITP-0010 §6).
19    #[error("bundle expires_at does not equal min(participant TCT expiries)")]
20    ExpiryWindowInvariant,
21    /// At least one participant TCT had a different `issuer` from the
22    /// bundle's `coordinator`.
23    #[error("participant TCT issuer does not match coordinator")]
24    CoordinatorIssuerMismatch,
25    /// At least one participant TCT had `audience` ≠ the entry's
26    /// declared `aid` (the bundle distributes participants' OWN TCTs
27    /// back to them, so audience and entry.aid must match).
28    #[error("participant TCT audience does not match entry AID")]
29    AudienceMismatch,
30    /// The coordinator's Manifest failed RFC-AITP-0003 §5 verification
31    /// (RFC-AITP-0010 §5 step 5).
32    #[error("coordinator manifest verification failed: {0}")]
33    CoordinatorManifest(aitp_manifest::ManifestError),
34    /// The supplied coordinator Manifest's `aid` is not the bundle's
35    /// `coordinator` (RFC-AITP-0010 §5 step 5).
36    #[error("coordinator manifest aid does not match bundle coordinator")]
37    CoordinatorManifestMismatch,
38    /// Verifier's AID is not present in `participants[]`.
39    #[error("verifier is not a member of this bundle")]
40    NotMember,
41    /// Builder was missing a required field.
42    #[error("missing required field: {0}")]
43    MissingField(&'static str),
44    /// Empty participants array — RFC-AITP-0010 §3 requires at least
45    /// one entry.
46    #[error("participants array is empty")]
47    EmptyParticipants,
48    /// JCS canonicalization failed.
49    #[error("canonicalization failed: {0}")]
50    Canonicalization(String),
51    /// TCT verification of an embedded participant TCT failed.
52    #[error("participant TCT verification failed: {0}")]
53    TctVerification(#[from] aitp_tct::TctError),
54    /// Crypto error (e.g. malformed AID-derived key).
55    #[error(transparent)]
56    Crypto(#[from] aitp_crypto::CryptoError),
57    /// The wire form was structurally invalid before any cryptographic
58    /// check could run: the `{"session_bundle": …}` transport wrapper
59    /// carried a member besides `session_bundle` (the pre-erratum shape
60    /// where `signature` sat as a SIBLING of the wrapper), or the inner
61    /// body did not deserialize as a `SessionTrustBundle`.
62    ///
63    /// RFC-AITP-0010 §3 fixes `signature` as a member of the signed body,
64    /// never a sibling of the wrapper, precisely because a bundle is
65    /// redistributable and must carry its own proof across any hop that
66    /// strips the transport wrapper (RFC-AITP-0001 §5.4.1). Maps to
67    /// `SESSION_BUNDLE_INVALID`.
68    #[error("session bundle wire form is invalid: {0}")]
69    WireFormInvalid(String),
70    /// A member outside the schema-declared member set was found on a
71    /// closed object — the wrapper's shape was fine, but the object
72    /// itself (the inner `session_bundle` body, or a nested closed
73    /// object such as a `participants[]` entry) carries a field the
74    /// schema does not define and which is not inside `extensions`.
75    ///
76    /// Distinct from [`SessionBundleError::WireFormInvalid`]: that
77    /// variant is for the wrapper-level defect where `signature` sits
78    /// beside `{"session_bundle": …}` instead of inside it
79    /// (RFC-AITP-0010 §3). This variant is the RFC-AITP-0001 §7 /
80    /// RFC-AITP-0010 §5 body-level check — checked ahead of any
81    /// cryptographic work, including the coordinator key resolution used
82    /// to verify the outer signature — and maps to the **core**
83    /// `UNKNOWN_FIELD` code rather than a `BUNDLE_*` draft code, even
84    /// though the session bundle artifact itself is draft.
85    #[error("unknown field: {0}")]
86    UnknownField(String),
87}