Skip to Content

Examples

Verify a single APL receipt

The most common use case — verify a receipt against a carrier and a local set of frames:

use apl_core::prelude::*; fn verify_single(receipt_bytes: &[u8], carrier: &dyn CarrierVerifier) -> AplResult<()> { let frames = InMemoryFrameResolver::new(); let bridges = InMemoryBridgeResolver::new(); let (output, verified) = verify_receipt( receipt_bytes, carrier, &frames, &bridges, None, // no vertical profile ); match output.core_outcome { CoreOutcome::AplValid => { println!("apl-valid"); println!("{}", output.to_json_pretty()); // `verified` is `Some(VerifiedReceipt)` on apl-valid let _token: VerifiedReceipt = verified.unwrap(); } CoreOutcome::AplInvalid => { println!("apl-invalid"); println!("failure classes: {:?}", output.failure_classes); for d in &output.diagnostics { println!(" - {d}"); } } } Ok(()) }

Pairwise relation evaluation

Given two receipts and a relation query, decide whether the protocol licenses the comparison:

use apl_core::prelude::*; fn evaluate_pair( left_bytes: &[u8], right_bytes: &[u8], query_value: &serde_json::Value, carrier: &dyn CarrierVerifier, ) -> AplResult<()> { let frames = InMemoryFrameResolver::new(); let bridges = InMemoryBridgeResolver::new(); let input = PairwiseInput { left: ReceiptInput::Bytes(left_bytes), right: ReceiptInput::Bytes(right_bytes), query: RelationQuery::parse(query_value) // `RelationQueryParseError` only derives Debug — format it via `{:?}`. .map_err(|e| AplError::InvalidArgument(format!("{e:?}")))?, supplied_bridges: Vec::new(), }; let output = evaluate_relation(input, carrier, &frames, &bridges, None); match output.relation_outcome { RelationOutcome::SameFrameComparable => { println!("same-frame-comparable"); } RelationOutcome::BridgedComparable => { println!("bridged-comparable"); } RelationOutcome::Incomparable => { println!("incomparable — comparison not licensed"); } RelationOutcome::RelationNotEvaluated => { println!("relation-not-evaluated (precondition failure)"); for d in &output.diagnostics { println!(" - {d}"); } } } Ok(()) }

Reusing a verified receipt

On apl-valid, verify_receipt returns a VerifiedReceipt token that can be fed into pairwise evaluation without re-running carrier validation:

use apl_core::prelude::*; fn compare_verified( left_bytes: &[u8], right_bytes: &[u8], query: RelationQuery, carrier: &dyn CarrierVerifier, ) { let frames = InMemoryFrameResolver::new(); let bridges = InMemoryBridgeResolver::new(); let (_, left_token) = verify_receipt(left_bytes, carrier, &frames, &bridges, None); let (_, right_token) = verify_receipt(right_bytes, carrier, &frames, &bridges, None); let (Some(left), Some(right)) = (left_token, right_token) else { eprintln!("one of the receipts is apl-invalid; cannot evaluate relation"); return; }; let input = PairwiseInput { left: ReceiptInput::Prevalidated(left), right: ReceiptInput::Prevalidated(right), query, supplied_bridges: Vec::new(), }; let output = evaluate_relation(input, carrier, &frames, &bridges, None); println!("{:?}", output.relation_outcome); }

Canonical equality

Compare two JSON objects after stripping designated fields, using the protocol-mandated JCS canonicalization:

use apl_core::prelude::*; use serde_json::json; fn strip_and_compare() { let a = json!({ "observer": "acme", "notes": "draft" }); let b = json!({ "observer": "acme", "notes": "final" }); let equal_after_strip = canonical_equal_after_strip(&a, &b, &["notes"]); assert!(equal_after_strip); let h = canonical_hash(&a); // `Hash` is a newtype; its Display impl already renders `sha256:<hex>`. println!("{h}"); }

Using a vertical profile

Plug in the reference APL/AI-Eval profile:

use apl_core::prelude::*; use apl_ai_eval::AiEvalProfile; fn verify_with_profile(receipt_bytes: &[u8], carrier: &dyn CarrierVerifier) { let frames = InMemoryFrameResolver::new(); let bridges = InMemoryBridgeResolver::new(); // `AiEvalProfile` is a unit struct — no constructor. let profile = AiEvalProfile; let (output, _) = verify_receipt( receipt_bytes, carrier, &frames, &bridges, Some(&profile), ); println!("{}", output.to_json_pretty()); }

The profile tightens bridge applicability and adds AI-Eval-specific diagnostics beyond APL Core.

Last updated on