1pub mod compiler;
2pub mod schema;
3
4pub use compiler::artifacts::ArtifactRef;
5pub use compiler::contradictions::detect_auto_contradictions;
6pub use compiler::evidence::{PacketValidationError, validate_packet_sources};
7pub use compiler::journal::{JournalEvent, append_decision_log, append_event_jsonl};
8pub use compiler::lookup::lookup_sources;
9pub use compiler::packets::{CompilerInputBundle, build_next_pass_packet};
10pub use compiler::promotion::{PromotionCandidate, promotion_record_from_candidate};
11pub use compiler::signals::detect_recurring_failure_patterns;
12pub use compiler::snapshot::{SnapshotValidationError, build_snapshot};
13pub use compiler::trust::{PacketizableItem, TrustAssessment, TrustDecision, assess_packet_item};
14
15#[cfg(test)]
16mod contract_tests {
17 use serde_json::Value;
18
19 #[test]
20 fn bundled_schemas_are_valid_json() {
21 for schema in [
22 include_str!("../schemas/next_pass_packet.schema.json"),
23 include_str!("../schemas/snapshot.schema.json"),
24 include_str!("../schemas/decision_log_record.schema.json"),
25 include_str!("../schemas/promotion_record.schema.json"),
26 ] {
27 let parsed: Value = serde_json::from_str(schema).expect("schema must parse");
28 assert_eq!(
29 parsed["$schema"],
30 "https://json-schema.org/draft/2020-12/schema"
31 );
32 }
33 }
34
35 #[test]
36 fn next_pass_packet_schema_exposes_evidence_contract() {
37 let parsed: Value =
38 serde_json::from_str(include_str!("../schemas/next_pass_packet.schema.json"))
39 .expect("schema must parse");
40
41 let required = parsed["required"].as_array().expect("required array");
42 assert!(required.iter().any(|value| value == "evidence"));
43 assert!(
44 required.iter().any(|value| value == "schema_version"),
45 "packet schema must require schema_version"
46 );
47 assert_eq!(
48 parsed["properties"]["schema_version"]["const"]
49 .as_str()
50 .unwrap_or_default(),
51 "1.1.0",
52 "packet schema_version must be pinned"
53 );
54 assert!(parsed["$defs"]["evidenceRecord"].is_object());
55 assert!(parsed["$defs"]["evidenceRecord"]["properties"]["source_refs"].is_object());
56 assert!(parsed["$defs"]["verifierFinding"]["properties"]["source_refs"].is_object());
57 let source_ref_required = parsed["$defs"]["sourceRef"]["required"]
58 .as_array()
59 .expect("sourceRef.required");
60 assert!(
61 source_ref_required.iter().any(|value| value == "hash_alg"),
62 "sourceRef must require hash_alg"
63 );
64 assert_eq!(
65 parsed["$defs"]["sourceRef"]["properties"]["hash"]["pattern"], "^[0-9a-f]{16}$",
66 "sourceRef.hash must be pinned to fnv1a-64 digest shape"
67 );
68 assert!(
69 parsed["$defs"]["haltSignal"]["required"]
70 .as_array()
71 .expect("halt signal required")
72 .iter()
73 .any(|value| value == "source_ids")
74 );
75 }
76
77 #[test]
78 fn snapshot_schema_exposes_source_integrity_contract() {
79 let parsed: Value = serde_json::from_str(include_str!("../schemas/snapshot.schema.json"))
80 .expect("snapshot schema must parse");
81
82 let required = parsed["required"].as_array().expect("required array");
83 assert!(
84 required.iter().any(|value| value == "schema_version"),
85 "snapshot schema must require schema_version"
86 );
87 assert_eq!(
88 parsed["$defs"]["sourceRef"]["properties"]["hash_alg"]["enum"][0]
89 .as_str()
90 .unwrap_or_default(),
91 "fnv1a-64",
92 "snapshot sourceRef.hash_alg must enumerate fnv1a-64"
93 );
94 }
95
96 #[test]
97 fn decision_log_schema_matches_raw_record_contract() {
98 let parsed: Value =
99 serde_json::from_str(include_str!("../schemas/decision_log_record.schema.json"))
100 .expect("schema must parse");
101
102 let required = parsed["required"].as_array().expect("required array");
103 assert!(required.iter().any(|value| value == "decision_kind"));
104 assert!(required.iter().all(|value| value != "payload"));
105 }
106}