aph_core/lib.rs
1// Every public item in a protocol reference implementation is read by
2// implementers, so undocumented surface is a defect.
3#![warn(missing_docs)]
4
5//! APH (Agent per Human) protocol v0.1 core types.
6//!
7//! **Trust model, stated up front.** The human principal signs; the notary
8//! countersigns. An envelope is in one of two modes, and which one decides
9//! what a successful verification actually proves:
10//!
11//! - `PrincipalSigned` — `proof` is a two-element chain whose head was made
12//! by the human's own key. Verifying it proves *this human authorized
13//! this*.
14//! - `NotaryAttested` — a single notary proof, and what an ABSENT
15//! `attestationMode` means. Verifying it proves only *a notary asserts
16//! this human authorized this*, which is strictly weaker. The human's own
17//! authorization, if present at all, lives in the `principalSignature` of
18//! the Delegation Mandate embedded at `policy.delegation_mandate`.
19//!
20//! **Callers must never report the weaker claim as the stronger one.** Use
21//! [`verification::require_mode`] to refuse a downgrade rather than
22//! inspecting the shape by hand, and [`verification::verify_proof_structure`]
23//! to learn which mode an envelope is really in — the declared label is
24//! bound to the proof structure precisely so a notary key alone cannot
25//! forge the stronger claim (spec §7.1.11).
26//!
27//! Standalone implementation of the APH protocol: party roles, mandate
28//! types, notarization flow state machines, the W3C VC 2.0-shaped
29//! `NotarizationEnvelope` on-wire credential, the agent-credential-access
30//! envelope variant, the A2A extension descriptor, SD-JWT-VC profile
31//! pinning, and the JCS / detached-JWS / ECDSA signing helpers used to
32//! sign and verify envelopes.
33//!
34//! The normative protocol specification lives at `../../spec/aph-0.1.md`
35//! in this repository.
36//!
37//! Wire compatibility is this crate's primary invariant: every serde
38//! attribute on the wire types is load-bearing. Envelopes already signed
39//! by existing notaries MUST keep parsing and re-canonicalizing
40//! identically across releases.
41//!
42//! Registered optional extensions (spec §7.5): this implementation accepts
43//! and can emit `credentialSubject.appleAurAcceptance` (§7.5.1),
44//! `linkedMandate.ap2SignedPayloadB64` (§7.5.2), and
45//! `linkedMandate.vaultMutation` (§7.5.3). All are omitted when absent, so
46//! extension-free envelopes round-trip byte-identically. The
47//! `CredentialAccessNotarizationEnvelope` variant remains a spec v0.2
48//! candidate.
49//!
50//! Top-level `credentialStatus` (§6.3.3.1) is a CORE optional field rather
51//! than a registered extension, and it follows the same omit-when-absent
52//! rule for the same reason: an envelope with no status reference is
53//! byte-identical to one written before revocation had a transport, so every
54//! existing signature stays valid. [`credential_status`] holds the type, the
55//! derived-endpoint and same-origin rules, and the §6.3.3.4 trichotomy a
56//! recipient applies at §8.3 step 8a — all of it EXCEPT the status list's
57//! own §6.3.3.3 proof check, which needs a §8.4-resolved notary key this
58//! crate must not hold and is therefore the caller's step (that module's
59//! preamble and `check_envelope_status` state the obligation).
60
61pub mod a2a_extension;
62pub mod aph_config;
63pub mod communication_mandate;
64pub mod credential_access_envelope;
65pub mod credential_status;
66pub mod crypto;
67pub mod rotation;
68pub mod delegation_mandate;
69pub mod discovery;
70pub mod envelope;
71pub mod errors;
72pub mod human_not_present_flow;
73pub mod human_present_flow;
74pub mod roles;
75pub mod sd_jwt_profile;
76pub mod vault_mutation;
77pub mod verification;
78
79#[cfg(test)]
80mod prop_tests;
81
82// Re-exports — public surface.
83pub use a2a_extension::{APH_EXTENSION_URI, aph_a2a_extension};
84pub use aph_config::{
85 ALG_EDDSA, ALG_ES256, APH_CONTEXT_V1, APH_CREDENTIAL_TYPE, APH_DI_CRYPTOSUITE, APH_VERSION,
86 DEFAULT_MANDATE_TTL_SECONDS, MAX_BODY_PREVIEW_BYTES, MAX_PREVIEW_LINES, W3C_VC_CONTEXT_V2,
87};
88pub use communication_mandate::CommunicationMandate;
89pub use credential_status::{
90 CredentialStatusEntry, StatusCheck, StatusEntryType, StatusListCredential, StatusListSubject,
91 StatusPurpose, check_credential_status, check_envelope_status, decode_encoded_list,
92 parse_status_list_credential, revocation_bit, status_list_signing_base,
93};
94pub use delegation_mandate::DelegationMandate;
95pub use envelope::{
96 ActClassification, ActLabel, AgentRef, AttestationMode, ChannelDescriptor, ChannelKind,
97 CommunicationDescriptor, ContentClass, CredentialSubject, EnvelopeProof, EnvelopeProofs,
98 HumanPrincipalRef, LinkedMandate, NotarizationEnvelope, NotarizationMetadata, NotaryServiceRef,
99 Audience, AudienceChannelBinding, PolicyDecision, PolicyDescriptor, RecipientClass,
100 SealedPayload, SealedReader, VocabularyRef, parse_envelope_json, sealed_payload_is_declared,
101};
102pub use errors::AphError;
103pub use rotation::{
104 DID_DOC_ROTATION_PROPERTY, ROTATION_ATTESTATION_TYPE, RotationAttestation, RotationSuccessor,
105 sign_rotation_attestation, verify_rotation_attestation,
106};
107pub use human_not_present_flow::{
108 HumanNotPresentNotarizationFlow, HumanNotPresentNotarizationState,
109};
110pub use human_present_flow::{HumanPresentNotarizationFlow, HumanPresentNotarizationState};
111pub use roles::{AphOperation, AphPartyRole};
112pub use sd_jwt_profile::{
113 APH_SD_JWT_TYP, SD_JWT_BASE_DRAFT_PIN, SD_JWT_VC_DRAFT_PIN, SdJwtVcProfile, current_profile,
114};
115pub use vault_mutation::{VaultMutationKind, VaultMutationMandate};
116
117// Crypto re-exports — JCS canonicalization, detached JWS, and ECDSA
118// mandate signing/verification.
119pub use crate::discovery::{DidUrl, KeyAlgorithm, NotaryPublicKey, https_origin, same_origin};
120pub use crate::crypto::did_key::{DecodedDidKey, decode as decode_did_key, encode_ed25519 as did_key_from_ed25519};
121pub use crate::crypto::eddsa_jcs::{
122 countersign_as_notary, sign_as_principal, sign_envelope, signing_input, verify_envelope,
123 verify_envelope_did_key, verify_proof,
124};
125pub use crate::crypto::jcs::canonicalize_rfc8785;
126pub use crate::crypto::jws_detached::{create_detached_jws, verify_detached_jws};
127pub use crate::crypto::signing::{sign_mandate, verify_mandate};
128pub use crate::crypto::proof_base::{ProofRole, mandate_signing_base, signing_base};
129pub use crate::verification::{
130 require_mode, verify_embedded_mandate_binding, verify_proof_structure,
131 verify_timestamp_order,
132};