Skip to main content

pask_wire/
canonical_example.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 Wilder Management Inc. (d/b/a Wilder Robotics) <rob@wilder-robotics.com>
3// pask-wire is licensed Apache-2.0. No commercial agreement is required to use,
4// modify or redistribute it; see LICENSING.md in the workspace root.
5
6//! The canonical example instance carried by the profile document.
7//!
8//! The example embedded in the Internet-Draft is emitted from this function,
9//! never typed by hand. A test asserts the two are byte-identical, so a change
10//! to the wire format that is not reflected in the document fails CI rather
11//! than shipping.
12//!
13//! This exists because the `-00` revision embedded a hand-written figure that
14//! used unquoted placeholders (`"sizeBytes": <int>`). It was a schema template
15//! presented in a JSON code block, and it was never parseable JSON, so nothing
16//! in the build could have caught the three attestation members that had
17//! drifted away from the implementation.
18
19use alloc::string::{String, ToString};
20
21use crate::{Error, Payload, Result, testvectors::MINIMAL_VALID_JCS};
22
23/// Emits the canonical example instance, pretty-printed for the document.
24///
25/// The value is parsed and validated as a [`Payload`], re-serialized to its
26/// JCS form, and then indented. Key order is JCS key order; indentation is two
27/// spaces. The output is deterministic.
28///
29/// # Errors
30///
31/// Returns an error if the canonical test vector fails payload validation or
32/// cannot be serialized — either of which is a defect in this crate.
33pub fn canonical_example() -> Result<String> {
34    let payload = Payload::from_json(MINIMAL_VALID_JCS.as_bytes())?;
35    let canonical = payload.to_jcs()?;
36    let value: serde_json::Value =
37        serde_json::from_slice(&canonical).map_err(|error| Error::Json(error.to_string()))?;
38    serde_json::to_string_pretty(&value).map_err(|error| Error::Json(error.to_string()))
39}
40
41/// Emits the canonical example instance for the 0.6 profile, pretty-printed.
42///
43/// Same construction as [`canonical_example`] but starts from the 0.5 minimal
44/// vector with `spec` changed to `wilder.pser/0.6`. Uses
45/// [`Payload::from_json_for_production`] so the `chain.hash` is recomputed
46/// for the 0.6 JCS form rather than inherited from the 0.5 vector.
47///
48/// # Errors
49///
50/// Returns an error if the 0.6 payload fails validation (including the
51/// timestamp containment check) or cannot be serialized.
52pub fn canonical_example_06() -> Result<String> {
53    let input_06 = MINIMAL_VALID_JCS.replace("wilder.pser/0.5", "wilder.pser/0.6");
54    let payload = Payload::from_json_for_production(input_06.as_bytes())?;
55    let canonical = payload.to_jcs()?;
56    let value: serde_json::Value =
57        serde_json::from_slice(&canonical).map_err(|error| Error::Json(error.to_string()))?;
58    serde_json::to_string_pretty(&value).map_err(|error| Error::Json(error.to_string()))
59}