Skip to main content

AphError

Enum AphError 

Source
pub enum AphError {
Show 24 variants InvalidEnvelopeSignature, InvalidFlowTransition { from: String, to: String, }, MandateExpired { mandate_id: String, }, RoleViolation { role: String, operation: String, }, ChannelNotAllowed { channel: String, }, NotarySignatureInvalid, HumanAuthenticationRequired, NotaryServiceUnreachable, EnvelopeBodyHashMismatch { expected: String, actual: String, }, UnsupportedAlgorithm { alg: String, }, PrincipalSignatureInvalid, AttestationModeRefused { required: String, actual: String, }, ProofChainInvalid { reason: String, }, NotaryKeyNotPublished { surface: String, }, MandateRevoked { mandate_id: String, }, MandateRequired { agent_did: String, channel_kind: String, }, AudienceMismatch { audience_id: String, verifier_id: String, }, EnvelopeAlreadySpent { envelope_id: String, }, EnvelopeWindowInvalid { valid_from: String, valid_until: String, observed_at: String, }, RecipientClassNotAllowed { declared: String, mandate_id: String, allowed: String, }, SealUnopenable { envelope_id: String, }, SealSuiteUnknown { suite: String, supported: String, }, SealReaderKeyUnpublished { reader_id: String, kid: String, }, RotationAttestationInvalid { reason: String, },
}
Expand description

APH protocol error with structured codes and suggestions.

Variants§

§

InvalidEnvelopeSignature

APH_E001 — the envelope’s proof.proofValue did not verify against the notary’s public key over the canonical form.

§

InvalidFlowTransition

APH_E002 — a notarization flow was driven along an edge the state machine does not define.

Fields

§from: String

State the flow was in.

§to: String

State the caller attempted to move to.

§

MandateExpired

APH_E003 — the referenced mandate is outside its validity window.

Fields

§mandate_id: String

Identifier of the expired mandate.

§

RoleViolation

APH_E004 — a party attempted an operation its role does not permit under the §5 permission matrix.

Fields

§role: String

Role of the party that made the attempt.

§operation: String

Operation that was attempted.

§

ChannelNotAllowed

APH_E005 — the channel is not listed in the delegation mandate’s allowedChannels.

Fields

§channel: String

Channel kind that fell outside the granted scope.

§

NotarySignatureInvalid

APH_E006 — a mandate’s notarySignature did not verify (distinct from APH_E001, which covers the envelope-level proof).

§

HumanAuthenticationRequired

APH_E007 — the operation requires a human decision that has not been obtained.

§

NotaryServiceUnreachable

APH_E008 — a protocol-mandated fetch from a notary-hosted surface did not succeed, so no decision could be made either way: the service itself could not be reached, or a document it is contracted to serve could not be reached, parsed, or validated — a DID Document (spec §8.4.4) or a revocation status list credential (spec §6.3.3.4 case 2, which folds TLS, parse, proof, issuer, purpose and freshness failures into this one code because the verifier’s action and the operator’s remedy are identical in all of them; log the specific cause, do not mint a code for it). Distinct from APH_E014, which means the surface ANSWERED and published nothing.

§

EnvelopeBodyHashMismatch

APH_E009 — the delivered body does not hash to the value the envelope attests, indicating tampering or a mismatched payload.

Fields

§expected: String

Hash recorded in communication.bodySha256.

§actual: String

Hash recomputed over the received body.

§

UnsupportedAlgorithm

APH_E010 — the declared algorithm is outside the allow-list (ES256, EdDSA); alg: none is always rejected here.

Fields

§alg: String

The rejected algorithm identifier.

§

PrincipalSignatureInvalid

APH_E011 — a signature made by the HUMAN’s key did not verify: the principal proof of a chain, or an embedded delegation mandate’s principalSignature. Deliberately distinct from APH_E001 and APH_E006, which are both NOTARY signatures — conflating them would report a forged authorization as a notary misconfiguration.

§

AttestationModeRefused

APH_E012 — the verifier requires PrincipalSigned and the envelope is NotaryAttested. Not a defect in the envelope: a refusal to accept the weaker claim, which the spec forbids doing silently.

Fields

§required: String

The mode the verifier’s policy demands.

§actual: String

The mode the envelope actually declares.

§

ProofChainInvalid

APH_E013 — the proof chain is malformed: wrong length, wrong proofPurpose for a position, or a previousProof that is missing, dangling, duplicated, or cyclic.

Fields

§reason: String

What specifically is wrong with the chain.

§

NotaryKeyNotPublished

APH_E014 — no notary key is published at the queried discovery surface: the DNS TXT name carries no APH record (or none matching the named kid), or a fetched DID Document names no key under the queried fragment. Deliberately distinct from APH_E008, which means the surface could not be REACHED: §8.4.6’s no-downgrade rule turns on exactly this distinction — absence advances the fallback sequence, failure must stop it — and a taxonomy that flattens the two forces every consumer’s error surface to flatten them again.

Fields

§surface: String

Which discovery surface answered “nothing is published here”.

§

MandateRevoked

APH_E015 — the parent delegation mandate’s bit is SET in the revocation status list its issuing notary publishes (spec §6.3.3): the human withdrew the standing authority this envelope was issued under. The signatures are still valid — this is a WITHDRAWN authorization, not a forged one, so reporting it as a signature failure would send an operator to inspect key material when the answer is a human decision. Deliberately distinct from APH_E003, which is authority that ran out on schedule rather than authority that was pulled.

Carries the mandate id alone, mirroring APH_E003: the revocation timestamp lives in the notary’s status state, not in the refusal.

Fields

§mandate_id: String

Identifier of the revoked delegation mandate.

§

MandateRequired

APH_E016 — a human-not-present notarization (§9.2) was attempted with no matching, unexpired delegation mandate: nothing authorized this act. Held distinct from THREE neighbours because the remedies differ completely — APH_E007 is nobody was asked (reach the human), APH_E011 is the authorization presented is invalid (inspect it), APH_E015 is the authorization was withdrawn (obtain a new one). Reporting an ABSENT mandate under any of those conflates absence with failure — the distinction this crate makes structural everywhere else (discovery::DiscoveryOutcome). Added 2026-08-23 from an implementer field report: the first production consumer had to misuse an invalid-mandate code for exactly this case.

Fields

§agent_did: String

DID of the agent that attempted the act.

§channel_kind: String

Channel kind the act targeted.

§

AudienceMismatch

APH_E017 — the envelope names an audience that is not this verifier: its audience.id differs from the verifier’s own identity, or a present channelBinding member differs from the delivery coordinates of the act being performed.

REGISTERED AHEAD OF ITS RFC. The audience field is RFC 0003 (Draft) and no type in this crate carries it yet — the code exists now, per the specification’s additive-codes rule, so an implementation exercising the draft ahead of ratification emits a stable code instead of minting a private one. That is the same reasoning that added APH_E016 from a field report: the first consumer to need a code should not have to misuse a neighbour. An envelope with no audience member never produces this code — absence is the producer’s decision to issue a bearer credential, and RFC 0003 is explicit that a verifier that cannot determine its OWN identity rejects rather than skips.

Fields

§audience_id: String

The audience the envelope names (credentialSubject.audience.id).

§verifier_id: String

The verifier’s own identity, as it knows itself.

§

EnvelopeAlreadySpent

APH_E018 — this envelope was already accepted once. RFC 0003’s single-use step: a verifier records id at the moment it commits to the act (acceptance in the RFC 5321 §6.1 sense) and refuses every later presentation of the same id. The record is the RECIPIENT’S ledger obligation — two independent verifiers each accept once, which is why audience binding (APH_E017) and single-use are load-bearing together and neither is sufficient alone.

Fields

§envelope_id: String

The id that was presented again after acceptance.

§

EnvelopeWindowInvalid

APH_E019 — the envelope’s OWN validity window fails against the verifier’s clock: validFrom is in the future or validUntil is in the past. Deliberately distinct from APH_E003, which is a mandate consulted past its expiry; before this code existed an implementer refusing an expired envelope had to invent a refusal or miscite APH_E003, and this crate’s own tests nearly did.

Fields

§valid_from: String

The envelope’s validFrom, verbatim.

§valid_until: String

The envelope’s validUntil, verbatim.

§observed_at: String

The instant the verifier judged the window at, RFC 3339.

§

RecipientClassNotAllowed

APH_E020 — the mandate constrains WHO may consume (RFC 0005’s allowedRecipientClasses) and this envelope either declares a class outside the grant or declares none at all. The second half is deliberate: a constraint the envelope lets nobody check would be escapable by omission, and the threat here is one’s own honest-but-over-broad agent — exactly the party the refusal teaches. Deliberately distinct from APH_E005, which is the MEDIUM being out of scope; this is the CONSUMER being out of scope on an allowed medium.

Fields

§declared: String

What the envelope’s channel declared — or the literal word nothing, when it declared no class at all.

§mandate_id: String

The constraining mandate’s id.

§allowed: String

The granted classes, comma-joined, so the refusal teaches the fix.

§

SealUnopenable

APH_E021 — a sealed payload addressed to THIS verifier did not open: wrong key, tampered ciphertext, or a seal staged under a different context (envelope, reader, or suite relabeled) — the four cases AEAD makes indistinguishable by design. Per RFC 0008 §4 this refuses the ENVELOPE, never the seal alone: an unopenable seal addressed to you is evidence, not an inconvenience.

DECLARED BY spec/aph-0.2.md, absent from v0.1.0’s closed twenty; emitted only on wires that declare sealedPayload.

Fields

§envelope_id: String

The envelope whose seal refused.

§

SealSuiteUnknown

APH_E022 — the sealed payload names a ciphersuite this verifier does not compile. One suite per draft, no negotiation; refused by name before any key material is touched. Declared by spec/aph-0.2.md.

Fields

§suite: String

The suite the payload claimed.

§supported: String

The one suite this build compiles.

§

SealReaderKeyUnpublished

APH_E023 — the seal’s reader key could not be discovered: the reader’s DID document publishes no matching keyAgreement entry for the named kid. Held distinct from APH_E014 exactly as E014 is held distinct from E008: WHICH surface came up empty is the repair. Declared by spec/aph-0.2.md.

Fields

§reader_id: String

The reader DID whose document was consulted.

§kid: String

The kid the sealed payload named.

§

RotationAttestationInvalid

APH_E024 — a rotation attestation (RFC 0001, v0.2) failed a structural rule or its predecessor signature. The message carries the SPECIFIC defect — which rule, which value — because “invalid” with no reason teaches an operator nothing about a statement whose entire job is auditability.

Fields

§reason: String

The specific rule that refused, with the offending values.

Implementations§

Source§

impl AphError

Source

pub fn code(&self) -> &'static str

Returns the APH error code string (e.g., "APH_E001").

Source

pub fn suggestion(&self) -> &'static str

Returns a human-readable suggestion for resolving this error.

Source

pub fn invalid_flow_transition( from: impl Into<String>, to: impl Into<String>, ) -> Self

Builds an APH_E002 naming the illegal edge that was attempted.

Source

pub fn mandate_expired(mandate_id: impl Into<String>) -> Self

Builds an APH_E003 naming the expired mandate.

Source

pub fn notary_key_not_published(surface: impl Into<String>) -> Self

Builds an APH_E014 naming the surface that published nothing.

Source

pub fn role_violation( role: impl Into<String>, operation: impl Into<String>, ) -> Self

Builds an APH_E004 naming the role and the denied operation.

Source

pub fn channel_not_allowed(channel: impl Into<String>) -> Self

Builds an APH_E005 naming the out-of-scope channel.

Source

pub fn envelope_body_hash_mismatch( expected: impl Into<String>, actual: impl Into<String>, ) -> Self

Builds an APH_E009 carrying both the attested and the recomputed hash so an investigator can tell which side diverged.

Source

pub fn unsupported_algorithm(alg: impl Into<String>) -> Self

Builds an APH_E010 naming the rejected algorithm.

Source

pub fn attestation_mode_refused( required: impl Into<String>, actual: impl Into<String>, ) -> Self

Builds an APH_E012 recording both modes, so an operator can see what was demanded and what arrived without re-parsing the envelope.

Source

pub fn proof_chain_invalid(reason: impl Into<String>) -> Self

Builds an APH_E013 naming what is wrong with the chain.

Source

pub fn mandate_revoked(mandate_id: impl Into<String>) -> Self

Builds an APH_E015 naming the revoked delegation mandate.

Source

pub fn mandate_required( agent_did: impl Into<String>, channel_kind: impl Into<String>, ) -> Self

Builds an APH_E016 naming the agent and channel nothing authorized, so the operator’s first question — WHO tried WHAT — is answered by the error itself rather than by log correlation.

Source

pub fn audience_mismatch( audience_id: impl Into<String>, verifier_id: impl Into<String>, ) -> Self

Builds an APH_E017 naming both identities, so the operator’s first question — for WHOM was this envelope, and who am I — is answered by the error itself.

Source

pub fn envelope_already_spent(envelope_id: impl Into<String>) -> Self

Builds an APH_E018 naming the id whose second presentation was refused, so an operator can find the first acceptance in their ledger.

Source

pub fn envelope_window_invalid( valid_from: impl Into<String>, valid_until: impl Into<String>, observed_at: impl Into<String>, ) -> Self

Builds an APH_E019 carrying the window verbatim and the instant it was judged at; without all three, “expired” is unactionable.

Source

pub fn recipient_class_not_allowed( declared: impl Into<String>, mandate_id: impl Into<String>, allowed: impl Into<String>, ) -> Self

Builds an APH_E020 naming what was declared (or nothing), which mandate constrained it, and what that mandate allows.

Source

pub fn seal_unopenable(envelope_id: impl Into<String>) -> Self

Builds an APH_E021 naming the envelope whose seal refused.

Source

pub fn seal_suite_unknown( suite: impl Into<String>, supported: impl Into<String>, ) -> Self

Builds an APH_E022 naming both the claimed and the supported suite.

Source

pub fn seal_reader_key_unpublished( reader_id: impl Into<String>, kid: impl Into<String>, ) -> Self

Builds an APH_E023 naming the reader and the missing kid.

Source

pub fn rotation_attestation_invalid(reason: impl Into<String>) -> Self

Builds an APH_E024 carrying the specific rule that refused.

Trait Implementations§

Source§

impl Clone for AphError

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AphError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for AphError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for AphError

Source§

impl Error for AphError

1.30.0 · Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl PartialEq for AphError

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for AphError

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.