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