Skip to main content

pask_wire/
testvectors.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//! Compile-time test vectors required by the profile package.
7//!
8//! # The values are illustrative, and one of them is load-bearing
9//!
10//! Every value here is synthetic. Digests are repeated-nibble placeholders,
11//! the site is the RES-001 reference fixture, and `attestation.teeClass` is a
12//! conforming registry value chosen so the vector round-trips. No Pask witness
13//! device has been built and no confidential-compute silicon has been
14//! selected, so `teeClass` here discloses nothing and prefers nothing.
15//!
16//! The load-bearing part: `MINIMAL_VALID_JCS` is the source of the example
17//! figure carried by the profile document, emitted through
18//! [`crate::canonical_example`] and asserted byte-identical to the document in
19//! CI. Changing any value in this vector changes the published figure. Change
20//! it deliberately, and regenerate with
21//! `cargo run -p pask-wire-cli -- canonical-example`.
22
23/// Minimal valid unsigned payload with the package's placeholder chain hash.
24pub const MINIMAL_VALID_PAYLOAD: &str = r#"{
25  "spec": "wilder.pser/0.5",
26  "id": "uuid:00000000-0000-4000-8000-000000000001",
27  "ts": "2026-10-15T14:00:00Z",
28  "issuerAffiliation": "NOT_DISCLOSED",
29  "site": {
30    "id": "site:res-001",
31    "class": "residential",
32    "envelope": {
33      "id": "env:res-001:2026-Q4",
34      "digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000",
35      "geobounds": null,
36      "temporal": { "starts": "2026-10-01T00:00:00Z", "ends": null }
37    }
38  },
39  "actor": {
40    "id": "actor:robot-alpha-01",
41    "class": "AUTONOMOUS",
42    "operator": "operator:wilder-robotics"
43  },
44  "engagement": {
45    "id": "eng:res-001:20261015-140000",
46    "window": { "start": "2026-10-15T13:30:00Z", "end": "2026-10-15T14:00:00Z" },
47    "type": "patrol",
48    "outcomeClass": "COMPLETED",
49    "envelopeConformance": "WITHIN",
50    "evidenceDigest": "sha256:1111111111111111111111111111111111111111111111111111111111111111"
51  },
52  "attestation": {
53    "bindingMode": "DIRECT_WITNESS",
54    "teeClass": "arm.cca",
55    "measuredBoot": {
56      "chain": "sha256:98a6efd412bb768ea7f090e8228401c11bc72a7caae44170395445c097d5ffa1",
57      "components": [
58        {
59          "name": "bl1",
60          "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222"
61        }
62      ]
63    },
64    "platformEvidence": {
65      "encoding": "opaque/1",
66      "digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
67    },
68    "sealedEvidence": {
69      "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333",
70      "sizeBytes": 4096,
71      "encoding": "opaque/1"
72    },
73    "witnessKey": "key:tee:res-001-witness-01",
74    "validity": {
75      "notBefore": "2026-10-15T13:00:00Z",
76      "notAfter": "2026-10-15T15:00:00Z"
77    }
78  },
79  "adapter": {
80    "system": "example.ticketing",
81    "endpoint": "endpoint:res-001",
82    "postedAt": "2026-10-15T14:00:05Z",
83    "ackDigest": "sha256:4444444444444444444444444444444444444444444444444444444444444444",
84    "ackProvenance": "THIRD_PARTY",
85    "mode": "WRITE_ONLY"
86  },
87  "chain": {
88    "seq": 0,
89    "prevHash": null,
90    "hash": "sha256:5555555555555555555555555555555555555555555555555555555555555555"
91  }
92}"#;
93
94/// Correct chain digest for [`MINIMAL_VALID_PAYLOAD`] after production normalization.
95pub const MINIMAL_CHAIN_HASH: &str =
96    "sha256:6de1b8b2c641536b35fada1a7ee233c68284cf3788408a7160d5f525c309d2b3";
97
98/// Expected JCS bytes for the normalized minimal payload.
99pub const MINIMAL_VALID_JCS: &str = r#"{"actor":{"class":"AUTONOMOUS","id":"actor:robot-alpha-01","operator":"operator:wilder-robotics"},"adapter":{"ackDigest":"sha256:4444444444444444444444444444444444444444444444444444444444444444","ackProvenance":"THIRD_PARTY","endpoint":"endpoint:res-001","mode":"WRITE_ONLY","postedAt":"2026-10-15T14:00:05Z","system":"example.ticketing"},"attestation":{"bindingMode":"DIRECT_WITNESS","measuredBoot":{"chain":"sha256:98a6efd412bb768ea7f090e8228401c11bc72a7caae44170395445c097d5ffa1","components":[{"digest":"sha256:2222222222222222222222222222222222222222222222222222222222222222","name":"bl1"}]},"platformEvidence":{"digest":"sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","encoding":"opaque/1"},"sealedEvidence":{"digest":"sha256:3333333333333333333333333333333333333333333333333333333333333333","encoding":"opaque/1","sizeBytes":4096},"teeClass":"arm.cca","validity":{"notAfter":"2026-10-15T15:00:00Z","notBefore":"2026-10-15T13:00:00Z"},"witnessKey":"key:tee:res-001-witness-01"},"chain":{"hash":"sha256:6de1b8b2c641536b35fada1a7ee233c68284cf3788408a7160d5f525c309d2b3","prevHash":null,"seq":0},"engagement":{"envelopeConformance":"WITHIN","evidenceDigest":"sha256:1111111111111111111111111111111111111111111111111111111111111111","id":"eng:res-001:20261015-140000","outcomeClass":"COMPLETED","type":"patrol","window":{"end":"2026-10-15T14:00:00Z","start":"2026-10-15T13:30:00Z"}},"id":"uuid:00000000-0000-4000-8000-000000000001","issuerAffiliation":"NOT_DISCLOSED","site":{"class":"residential","envelope":{"digest":"sha256:0000000000000000000000000000000000000000000000000000000000000000","geobounds":null,"id":"env:res-001:2026-Q4","temporal":{"ends":null,"starts":"2026-10-01T00:00:00Z"}},"id":"site:res-001"},"spec":"wilder.pser/0.5","ts":"2026-10-15T14:00:00Z"}"#;
100
101/// Unsupported version used by malformed-payload tests.
102///
103/// MUST stay strictly below every version this profile has ever accepted, so
104/// that adopting a new `SPEC_VERSION` can never collide with the negative
105/// fixture the verifier is asserted to reject.
106pub const WRONG_SPEC: &str = "wilder.pser/0.0";
107/// Invalid actor class used by malformed-payload tests.
108pub const INVALID_ACTOR_CLASS: &str = "ROBOT";
109/// Reversed engagement end used by malformed-payload tests.
110pub const REVERSED_WINDOW_END: &str = "2026-10-15T13:00:00Z";
111/// Invalid digest used by malformed-payload tests.
112pub const INVALID_DIGEST: &str = "sha256:xyz";
113/// Reserved adapter mode used by malformed-payload tests.
114pub const INVALID_ADAPTER_MODE: &str = "WRITE_READ";
115/// Wrong protected content type used by malformed-envelope tests.
116pub const WRONG_CONTENT_TYPE: &str = "application/json";
117/// Wrong CWT subject used by malformed-envelope tests.
118pub const WRONG_CWT_SUBJECT: &[u8] = b"site:not-res-001";
119
120/// RFC 8785 number-serialization input.
121pub const JCS_NUMBERS_INPUT: &str =
122    r#"{"numbers":[333333333.33333329,1E30,4.50,2e-3,0.000000000000000000000000001]}"#;
123/// RFC 8785 number-serialization output.
124pub const JCS_NUMBERS_EXPECTED: &str = r#"{"numbers":[333333333.3333333,1e+30,4.5,0.002,1e-27]}"#;
125/// RFC 8785 property-order input.
126pub const JCS_ORDER_INPUT: &str = "{\"\\u20ac\":\"Euro Sign\",\"\\r\":\"Carriage Return\",\"\\ufb33\":\"Hebrew Letter Dalet With Dagesh\",\"1\":\"One\",\"\\ud83d\\ude00\":\"Emoji: Grinning Face\",\"\\u0080\":\"Control\",\"\\u00f6\":\"Latin Small Letter O With Diaeresis\"}";
127/// RFC 8785 property-order output.
128pub const JCS_ORDER_EXPECTED: &str = "{\"\\r\":\"Carriage Return\",\"1\":\"One\",\"\u{0080}\":\"Control\",\"\u{00f6}\":\"Latin Small Letter O With Diaeresis\",\"\u{20ac}\":\"Euro Sign\",\"\u{1f600}\":\"Emoji: Grinning Face\",\"\u{fb33}\":\"Hebrew Letter Dalet With Dagesh\"}";
129/// RFC 8785 literal-serialization input.
130pub const JCS_LITERALS_INPUT: &str = r#"{ "literals" : [ null, true, false ] }"#;
131/// RFC 8785 literal-serialization output.
132pub const JCS_LITERALS_EXPECTED: &str = r#"{"literals":[null,true,false]}"#;