use crate::disclosure::{Disclosure, PASSPORT_FIELD_DISCLOSURE};
use crate::passport::PASSPORT_PROOF_FIELDS;
#[test]
fn passport_every_wire_key_is_classified() {
const PUBLICLY_SERVED: &[(&str, &str)] = &[
(
"id",
"the passport identifier is what a QR code resolves to",
),
("productName", "Annex III basic product information"),
(
"productGroup",
"the dispatch key; a reader needs it to interpret the rest",
),
(
"applicableInstruments",
"which law governs this product is not a secret",
),
(
"granularity",
"model/batch/item — states what the record describes",
),
(
"manufacturer",
"Annex III(k): name and contact details of the operator",
),
("materials", "Annex III material content is consumer-facing"),
("co2ePerUnit", "a declared environmental figure"),
("repairabilityScore", "a declared repairability figure"),
(
"complianceResult",
"the determination itself; withholding it defeats the passport",
),
(
"productGroupData",
"filtered field-by-field by the product group's own policy",
),
(
"status",
"whether the passport is live, suspended or archived",
),
("qrCodeUrl", "the public address of this passport"),
("createdAt", "record lifecycle timestamp"),
("updatedAt", "record lifecycle timestamp"),
("publishedAt", "record lifecycle timestamp"),
(
"placedOnMarketDate",
"the regulated triggering event that fixes governing law",
),
(
"schemaVersion",
"a reader needs it to interpret productGroupData",
),
("version", "monotonic version counter"),
("supersedesId", "lineage: which passport this replaces"),
(
"parentPassportRef",
"ESPR Art. 11(d) linkage to the original passport",
),
("componentRefs", "bill-of-materials linkage"),
(
"retentionUntil",
"how long this record must remain reachable",
),
(
"productId",
"opaque internal template link, not a legal identifier",
),
(
"commodityCode",
"customs classification, registered publicly anyway",
),
(
"operatorIdentifier",
"Annex III(k) unique operator identifier",
),
("facility", "Annex III facility snapshot"),
];
let classified: std::collections::BTreeSet<&str> = PASSPORT_FIELD_DISCLOSURE
.iter()
.map(|(f, _)| *f)
.chain(PASSPORT_PROOF_FIELDS.iter().copied())
.chain(PUBLICLY_SERVED.iter().map(|(f, _)| *f))
.collect();
let unclassified: Vec<&str> = crate::passport::PASSPORT_WIRE_KEYS
.iter()
.copied()
.filter(|k| !classified.contains(k))
.collect();
assert!(
unclassified.is_empty(),
"these Passport fields are classified nowhere, so redaction defaults them \
to Public and no test would notice: {unclassified:?}\n\n\
Put each one in exactly one of:\n \
- PASSPORT_FIELD_DISCLOSURE, if some audiences may not see it\n \
- PASSPORT_PROOF_FIELDS, if it is a signature, seal or other proof\n \
- PUBLICLY_SERVED in this test, with the reason it is safe for everyone"
);
let wire: std::collections::BTreeSet<&str> = crate::passport::PASSPORT_WIRE_KEYS
.iter()
.copied()
.collect();
for (field, _) in PUBLICLY_SERVED {
assert!(
wire.contains(field),
"'{field}' is allowlisted as publicly served but is not a Passport wire key"
);
}
for field in PASSPORT_PROOF_FIELDS {
assert!(
wire.contains(field),
"'{field}' is listed as a proof field but is not a Passport wire key"
);
}
}
#[test]
fn a_passport_field_is_never_classified_as_both_proof_and_public() {
let public_ok: std::collections::BTreeSet<&str> = PASSPORT_PROOF_FIELDS
.iter()
.copied()
.collect::<std::collections::BTreeSet<_>>();
for (field, _) in PASSPORT_FIELD_DISCLOSURE {
if public_ok.contains(field) {
let class = PASSPORT_FIELD_DISCLOSURE
.iter()
.find(|(f, _)| f == field)
.map(|(_, c)| *c)
.expect("just found it");
assert_eq!(
class,
Disclosure::Conformity,
"'{field}' is a proof field, so its defence-in-depth class must be \
the most restrictive available, not {class:?}"
);
}
}
}