xoonya 3.1.16 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +97 -74
  2. package/RELEASE_NOTES.md +7 -1
  3. package/START_HERE.md +38 -134
  4. package/bin/xoonya-first-run.js +22 -10
  5. package/bin/xoonya.js +61 -29
  6. package/lib/native_verify.js +1918 -0
  7. package/package.json +19 -42
  8. package/scripts/verify_release_candidate.js +243 -116
  9. package/scripts/verify_vectors.js +351 -104
  10. package/verify.js +95 -0
  11. package/.env.example +0 -10
  12. package/CARRIED_HANDOFF_DEMO.md +0 -60
  13. package/COMPATIBILITY_NOTE.md +0 -27
  14. package/CROSS_RUNTIME_POSTURE.md +0 -77
  15. package/EXAMPLE_PATHS.md +0 -53
  16. package/FINAL_CONTRACT.md +0 -445
  17. package/PARTNER_READY_PATH.md +0 -67
  18. package/PUBLIC_DEMO_SCRIPT.md +0 -79
  19. package/SERVICE_CONTRACT.md +0 -207
  20. package/TERMINOLOGY.md +0 -55
  21. package/WHY_XYTARA_XOONYA.md +0 -43
  22. package/XNYA_CONFORMANCE_MARK.md +0 -78
  23. package/XNYA_REFERENCE_IMPLEMENTATIONS.md +0 -157
  24. package/XOONYA_DEFAULT_PATH_MODEL.md +0 -63
  25. package/XOONYA_FOLLOWTHROUGH_TRUTH_MODEL.md +0 -63
  26. package/XOONYA_NATIVE_ATOM_SPEC.md +0 -184
  27. package/XOONYA_NATIVE_PROOF_FORMAT.md +0 -570
  28. package/XOONYA_NATIVE_STANDARD_GOVERNANCE.md +0 -119
  29. package/XOONYA_PROOF_TRUTH_MODEL.md +0 -58
  30. package/bin/xoonya-release.js +0 -1367
  31. package/bin/xoonya-review.js +0 -70
  32. package/examples/integration_boundary_walkthrough.js +0 -37
  33. package/examples/package_quickstart.js +0 -1007
  34. package/examples/partner_proof_walkthrough.js +0 -68
  35. package/examples/proof_review_walkthrough.js +0 -66
  36. package/examples/review_carried_handoff.js +0 -72
  37. package/index.js +0 -31
  38. package/integrations/PROOF_INTEGRATION_PROCESS.md +0 -45
  39. package/integrations/examples/example-third-party-verifier-registration.record.json +0 -22
  40. package/integrations/registration-record.schema.json +0 -99
  41. package/integrations/registry-snapshot.schema.json +0 -36
  42. package/integrations/registry.js +0 -636
  43. package/integrations/views.js +0 -36
  44. package/lib/adapter_certification_contract.js +0 -90
  45. package/lib/announcement_pack.js +0 -61
  46. package/lib/artifact_distribution_lane_contract.js +0 -54
  47. package/lib/asyncapi_contract.js +0 -135
  48. package/lib/auth_interop_contract.js +0 -69
  49. package/lib/authority_binding_lifecycle_contract.js +0 -182
  50. package/lib/bridge_intelligence.js +0 -102
  51. package/lib/cloudevents_contract.js +0 -79
  52. package/lib/crypto_agility_matrix.js +0 -131
  53. package/lib/default_path_contract.js +0 -380
  54. package/lib/ecosystem_entry.js +0 -64
  55. package/lib/erc8004_proof_lane_contract.js +0 -64
  56. package/lib/event_system_lane_contract.js +0 -76
  57. package/lib/external_proof_import_lane_contract.js +0 -87
  58. package/lib/feature_control_lane_contract.js +0 -54
  59. package/lib/followthrough_truth_contract.js +0 -214
  60. package/lib/framework_lane_contract.js +0 -76
  61. package/lib/governance_disputes_summary.js +0 -36
  62. package/lib/governance_intelligence.js +0 -108
  63. package/lib/identity_interop_contract.js +0 -83
  64. package/lib/integration_matrix_contract.js +0 -81
  65. package/lib/launch_narrative.js +0 -53
  66. package/lib/machine_identity_registry_contract.js +0 -199
  67. package/lib/major_rails_proof_lane_contract.js +0 -87
  68. package/lib/offline_verifiability_recovery_contract.js +0 -155
  69. package/lib/openapi_contract.js +0 -227
  70. package/lib/operational_receipt_contract.js +0 -165
  71. package/lib/outreach_proof.js +0 -71
  72. package/lib/phase_10_closeout_pack.js +0 -45
  73. package/lib/phase_10_completion_pack.js +0 -76
  74. package/lib/phase_10_decision_record_pack.js +0 -54
  75. package/lib/phase_10_decision_resolution_pack.js +0 -53
  76. package/lib/phase_10_demand_signal_adapters_proof_pack.js +0 -74
  77. package/lib/phase_10_ecosystem_backlog_triage_proof_pack.js +0 -74
  78. package/lib/phase_10_freeze_baseline_pack.js +0 -67
  79. package/lib/phase_10_freeze_review_pack.js +0 -64
  80. package/lib/phase_10_gate_pack.js +0 -57
  81. package/lib/phase_10_long_tail_continuity_pack.js +0 -80
  82. package/lib/phase_10_long_tail_ecosystem_pack.js +0 -68
  83. package/lib/phase_10_niche_extension_registry_proof_pack.js +0 -74
  84. package/lib/phase_1_claude_mcp_pack.js +0 -60
  85. package/lib/phase_1_claude_mcp_proof_pack.js +0 -57
  86. package/lib/phase_1_ecosystem_pack.js +0 -51
  87. package/lib/phase_1_openai_codex_pack.js +0 -60
  88. package/lib/phase_1_openai_codex_proof_pack.js +0 -57
  89. package/lib/phase_2_base_proof_pack.js +0 -71
  90. package/lib/phase_2_base_usdc_proof_pack.js +0 -72
  91. package/lib/phase_2_closeout_pack.js +0 -65
  92. package/lib/phase_2_completion_pack.js +0 -113
  93. package/lib/phase_2_decision_record_pack.js +0 -66
  94. package/lib/phase_2_decision_resolution_pack.js +0 -69
  95. package/lib/phase_2_eth_proof_pack.js +0 -70
  96. package/lib/phase_2_evm_base_proof_pack.js +0 -73
  97. package/lib/phase_2_evm_proof_pack.js +0 -71
  98. package/lib/phase_2_flip_preview_pack.js +0 -60
  99. package/lib/phase_2_freeze_review_pack.js +0 -99
  100. package/lib/phase_2_gate_pack.js +0 -77
  101. package/lib/phase_2_payment_rails_pack.js +0 -71
  102. package/lib/phase_2_usdc_proof_pack.js +0 -71
  103. package/lib/phase_3_brc_proof_pack.js +0 -81
  104. package/lib/phase_3_bsv_teranode_proof_pack.js +0 -81
  105. package/lib/phase_3_closeout_pack.js +0 -62
  106. package/lib/phase_3_completion_pack.js +0 -92
  107. package/lib/phase_3_decision_record_pack.js +0 -64
  108. package/lib/phase_3_decision_resolution_pack.js +0 -69
  109. package/lib/phase_3_freeze_baseline_pack.js +0 -67
  110. package/lib/phase_3_freeze_review_pack.js +0 -80
  111. package/lib/phase_3_gate_pack.js +0 -76
  112. package/lib/phase_3_metanet_proof_pack.js +0 -81
  113. package/lib/phase_3_native_bsv_pack.js +0 -89
  114. package/lib/phase_3_native_continuity_pack.js +0 -82
  115. package/lib/phase_4_attestation_proof_pack.js +0 -75
  116. package/lib/phase_4_closeout_pack.js +0 -45
  117. package/lib/phase_4_completion_pack.js +0 -82
  118. package/lib/phase_4_decision_record_pack.js +0 -54
  119. package/lib/phase_4_decision_resolution_pack.js +0 -45
  120. package/lib/phase_4_erc8004_proof_pack.js +0 -76
  121. package/lib/phase_4_freeze_baseline_pack.js +0 -67
  122. package/lib/phase_4_freeze_review_pack.js +0 -68
  123. package/lib/phase_4_gate_pack.js +0 -58
  124. package/lib/phase_4_identity_registry_proof_pack.js +0 -75
  125. package/lib/phase_4_identity_trust_pack.js +0 -73
  126. package/lib/phase_4_trust_continuity_pack.js +0 -86
  127. package/lib/phase_5_antelope_proof_pack.js +0 -76
  128. package/lib/phase_5_closeout_pack.js +0 -44
  129. package/lib/phase_5_completion_pack.js +0 -82
  130. package/lib/phase_5_decision_record_pack.js +0 -54
  131. package/lib/phase_5_decision_resolution_pack.js +0 -45
  132. package/lib/phase_5_freeze_baseline_pack.js +0 -67
  133. package/lib/phase_5_freeze_review_pack.js +0 -68
  134. package/lib/phase_5_gate_pack.js +0 -58
  135. package/lib/phase_5_major_rails_continuity_pack.js +0 -86
  136. package/lib/phase_5_major_rails_pack.js +0 -74
  137. package/lib/phase_5_proton_xpr_proof_pack.js +0 -76
  138. package/lib/phase_5_solana_proof_pack.js +0 -76
  139. package/lib/phase_6_autogen_proof_pack.js +0 -74
  140. package/lib/phase_6_closeout_pack.js +0 -46
  141. package/lib/phase_6_completion_pack.js +0 -77
  142. package/lib/phase_6_decision_record_pack.js +0 -54
  143. package/lib/phase_6_decision_resolution_pack.js +0 -53
  144. package/lib/phase_6_framework_continuity_pack.js +0 -81
  145. package/lib/phase_6_framework_runtime_pack.js +0 -68
  146. package/lib/phase_6_freeze_baseline_pack.js +0 -68
  147. package/lib/phase_6_freeze_review_pack.js +0 -65
  148. package/lib/phase_6_gate_pack.js +0 -59
  149. package/lib/phase_6_langchain_proof_pack.js +0 -74
  150. package/lib/phase_6_langgraph_proof_pack.js +0 -74
  151. package/lib/phase_6_semantic_kernel_proof_pack.js +0 -74
  152. package/lib/phase_7_closeout_pack.js +0 -45
  153. package/lib/phase_7_completion_pack.js +0 -85
  154. package/lib/phase_7_decision_record_pack.js +0 -53
  155. package/lib/phase_7_decision_resolution_pack.js +0 -53
  156. package/lib/phase_7_event_system_continuity_pack.js +0 -89
  157. package/lib/phase_7_event_system_pack.js +0 -76
  158. package/lib/phase_7_freeze_baseline_pack.js +0 -74
  159. package/lib/phase_7_freeze_review_pack.js +0 -65
  160. package/lib/phase_7_gate_pack.js +0 -58
  161. package/lib/phase_7_kafka_proof_pack.js +0 -76
  162. package/lib/phase_7_mqtt_proof_pack.js +0 -76
  163. package/lib/phase_7_nats_proof_pack.js +0 -76
  164. package/lib/phase_7_webhook_event_bus_proof_pack.js +0 -76
  165. package/lib/phase_8_closeout_pack.js +0 -46
  166. package/lib/phase_8_completion_pack.js +0 -82
  167. package/lib/phase_8_decision_record_pack.js +0 -54
  168. package/lib/phase_8_decision_resolution_pack.js +0 -53
  169. package/lib/phase_8_external_receipt_import_proof_pack.js +0 -74
  170. package/lib/phase_8_external_result_import_proof_pack.js +0 -74
  171. package/lib/phase_8_freeze_baseline_pack.js +0 -71
  172. package/lib/phase_8_freeze_review_pack.js +0 -64
  173. package/lib/phase_8_gate_pack.js +0 -58
  174. package/lib/phase_8_proof_bridge_continuity_pack.js +0 -86
  175. package/lib/phase_8_proof_bridges_pack.js +0 -72
  176. package/lib/phase_8_proof_bundle_normalization_proof_pack.js +0 -74
  177. package/lib/phase_9_closeout_pack.js +0 -46
  178. package/lib/phase_9_completion_pack.js +0 -82
  179. package/lib/phase_9_custody_refs_proof_pack.js +0 -74
  180. package/lib/phase_9_decision_record_pack.js +0 -54
  181. package/lib/phase_9_decision_resolution_pack.js +0 -53
  182. package/lib/phase_9_freeze_baseline_pack.js +0 -71
  183. package/lib/phase_9_freeze_review_pack.js +0 -64
  184. package/lib/phase_9_gate_pack.js +0 -58
  185. package/lib/phase_9_operator_accounting_bridges_proof_pack.js +0 -74
  186. package/lib/phase_9_treasury_connectivity_pack.js +0 -72
  187. package/lib/phase_9_treasury_continuity_pack.js +0 -86
  188. package/lib/phase_9_treasury_destinations_proof_pack.js +0 -74
  189. package/lib/phase_program_pack.js +0 -47
  190. package/lib/proof_bridge_lane_contract.js +0 -82
  191. package/lib/proof_truth_contract.js +0 -224
  192. package/lib/provenance_lane_contract.js +0 -54
  193. package/lib/provider_lane_contract.js +0 -67
  194. package/lib/public_surface_policy_contract.js +0 -111
  195. package/lib/publish_plan.js +0 -51
  196. package/lib/release_candidate.js +0 -50
  197. package/lib/release_center.js +0 -1037
  198. package/lib/release_history.js +0 -206
  199. package/lib/release_manifest.js +0 -114
  200. package/lib/release_pack.js +0 -391
  201. package/lib/result_package_trust_lane_contract.js +0 -74
  202. package/lib/review_intelligence.js +0 -100
  203. package/lib/role_freeze.js +0 -436
  204. package/lib/shared_signals_lane_contract.js +0 -54
  205. package/lib/signed_audit_provenance_contract.js +0 -93
  206. package/lib/telemetry_lane_contract.js +0 -54
  207. package/lib/treasury_proof_lane_contract.js +0 -83
  208. package/lib/trust_intelligence.js +0 -106
  209. package/lib/trust_portability_boundary_contract.js +0 -66
  210. package/lib/trust_portability_pack.js +0 -224
  211. package/lib/verification_service_pack.js +0 -149
  212. package/proof_sdk.js +0 -6692
  213. package/reference/python/README.md +0 -35
  214. package/reference/python/requirements-optional.txt +0 -1
  215. package/reference/python/verify_vectors.py +0 -223
  216. package/reference/python/xnya_reference.py +0 -810
  217. package/reference/rust/Cargo.toml +0 -11
  218. package/reference/rust/README.md +0 -28
  219. package/reference/rust/src/lib.rs +0 -87
  220. package/scripts/registry_cli.js +0 -157
  221. package/scripts/verify_all.js +0 -603
  222. package/scripts/verify_control_plane_contracts.js +0 -34
  223. package/scripts/verify_control_plane_routes.js +0 -70
  224. package/scripts/verify_examples.js +0 -19
  225. package/scripts/verify_external_proof_import_gate.js +0 -84
  226. package/scripts/verify_external_proof_signature.js +0 -142
  227. package/scripts/verify_forgery_resistance.js +0 -281
  228. package/scripts/verify_integrations.js +0 -170
  229. package/scripts/verify_native_hybrid_design_gate.js +0 -114
  230. package/scripts/verify_paid_execute.js +0 -133
  231. package/scripts/verify_paywall_flag.js +0 -86
  232. package/scripts/verify_reference_promotion_gate.js +0 -74
  233. package/scripts/verify_reference_python.js +0 -49
  234. package/scripts/verify_reference_python_crypto.js +0 -87
  235. package/scripts/verify_reference_rust_scaffold.js +0 -50
  236. package/scripts/verify_service.js +0 -3038
  237. package/scripts/verify_tooling.js +0 -1251
  238. package/scripts/verify_trust_portability.js +0 -56
  239. package/scripts/verify_verification_services.js +0 -56
  240. package/server.js +0 -4430
@@ -1,170 +1,412 @@
1
1
  "use strict";
2
2
 
3
+ // Conformance + adversarial vector run for the xoonya verifier.
4
+ //
5
+ // Runs on the standalone verifier (lib/native_verify.js + lib/external_proof_verify.js)
6
+ // with Node built-ins only, so it works identically from the published package and
7
+ // from the source checkout. When the proof engine is present next to this script
8
+ // (source checkout only; proof_sdk.js is never published), it additionally runs an
9
+ // engine-parity cross-check: every vector, every option variant, every freshly
10
+ // emitted bundle and every mutation is verified by BOTH the engine and the
11
+ // standalone verifier and the full result objects must be deep-equal.
12
+
3
13
  const assert = require("assert");
14
+ const crypto = require("crypto");
4
15
  const fs = require("fs");
5
16
  const path = require("path");
6
- const sdk = require("..");
7
-
8
- const conformanceVectors = JSON.parse(
9
- fs.readFileSync(path.resolve(__dirname, "..", "vectors", "conformance-vectors.json"), "utf8")
10
- );
11
- const adversarialVectors = JSON.parse(
12
- fs.readFileSync(path.resolve(__dirname, "..", "vectors", "adversarial-vectors.json"), "utf8")
13
- );
14
- const nativeAtomVectors = JSON.parse(
15
- fs.readFileSync(path.resolve(__dirname, "..", "vectors", "native-atom-vectors.json"), "utf8")
16
- );
17
+ const nv = require("../lib/native_verify");
18
+ const external = require("../lib/external_proof_verify");
19
+
20
+ const ROOT = path.resolve(__dirname, "..");
21
+ const ENGINE_FILE = path.join(ROOT, "proof_sdk.js");
22
+ const REQUIRED_NATIVE_METHODS = Object.freeze([
23
+ "xoonya-native-sha256-v1",
24
+ "xoonya-native-signed-v1",
25
+ "xoonya-native-anchored-v1"
26
+ ]);
27
+
28
+ function loadVectors(name) {
29
+ return JSON.parse(fs.readFileSync(path.join(ROOT, "vectors", name), "utf8"));
30
+ }
31
+
32
+ const conformanceVectors = loadVectors("conformance-vectors.json");
33
+ const adversarialVectors = loadVectors("adversarial-vectors.json");
34
+ const nativeAtomVectors = loadVectors("native-atom-vectors.json");
35
+ const nativePayloadProfileVectors = loadVectors("native-payload-profile-vectors.json");
17
36
 
18
37
  function unique(values) {
19
38
  return Array.from(new Set(values.filter(Boolean))).sort();
20
39
  }
21
40
 
22
- function runVectorVerification() {
23
- assert.strictEqual(conformanceVectors.version, "proof-conformance-v1", "conformance vector version mismatch");
24
- assert.strictEqual(adversarialVectors.version, "proof-adversarial-v1", "adversarial vector version mismatch");
25
- assert.strictEqual(nativeAtomVectors.version, "xoonya-native-atom-vectors-v1", "native atom vector version mismatch");
41
+ function clone(value) {
42
+ return JSON.parse(JSON.stringify(value));
43
+ }
44
+
45
+ function flipLastChar(text) {
46
+ const value = String(text || "");
47
+ if (!value) return "A";
48
+ const last = value[value.length - 1];
49
+ return `${value.slice(0, -1)}${last === "A" ? "B" : "A"}`;
50
+ }
26
51
 
27
- const conformanceResults = [];
52
+ function conformanceBundle(vector) {
53
+ return {
54
+ version: vector.expected.proof_bundle_version,
55
+ ceb: nv.canonicalizeEvent(vector.event),
56
+ receipt: vector.expected.receipt,
57
+ anchors: Array.isArray(vector.anchors) ? vector.anchors : undefined
58
+ };
59
+ }
60
+
61
+ function atomOptions(vector, defaults) {
62
+ const hasPayload = vector.payload_ascii
63
+ ? true
64
+ : vector.payload_hash_sha256 && vector.payload_hash_sha256 !== "00".repeat(32);
65
+ return {
66
+ identity_material_hex: vector.identity_material_hex || defaults.identity_material_hex,
67
+ ...(hasPayload ? { payload_bytes: Buffer.from(vector.payload_ascii || defaults.payload_ascii, "utf8") } : {})
68
+ };
69
+ }
70
+
71
+ // Option variants every conformance bundle is verified under (standalone and, in
72
+ // parity mode, engine). Trust-root variants must reject signed/hybrid proofs whose
73
+ // key is not the declared one and leave digest/structural results untouched.
74
+ function verificationOptionVariants(receipt) {
75
+ return [
76
+ {},
77
+ { strict: true },
78
+ { expected_public_key_ref: "ed25519-spki-sha256:" + "00".repeat(32) },
79
+ { trusted_public_key_refs: { [receipt.agent_identity]: { classical: "none", pq: "none" } } }
80
+ ];
81
+ }
82
+
83
+ function verifyConformance() {
84
+ const results = [];
85
+ let strictModeChecks = 0;
28
86
  for (const vector of conformanceVectors.vectors) {
29
- const eventCommitment = sdk.hashEvent(vector.event);
30
- assert.strictEqual(eventCommitment, vector.expected.event_commitment, `${vector.id} event commitment mismatch`);
87
+ assert.strictEqual(nv.hashEvent(vector.event), vector.expected.event_commitment, `${vector.id} event commitment mismatch`);
88
+ const bundle = conformanceBundle(vector);
89
+ const receipt = bundle.receipt;
90
+ assert.strictEqual(receipt.event_commitment, vector.expected.event_commitment, `${vector.id} receipt commitment mismatch`);
91
+ const verification = nv.verifyProofBundle(bundle);
92
+ assert.strictEqual(verification.valid, true, `${vector.id} proof bundle should verify (${verification.reason})`);
93
+ assert.strictEqual(verification.verification_method, receipt.algorithm, `${vector.id} verification method mismatch`);
94
+ assert.strictEqual(verification.receipt_id, receipt.receipt_id, `${vector.id} receipt id mismatch`);
31
95
 
32
- const receipt = sdk.emitReceipt(vector.event, vector.receipt_options || {});
33
- if (vector.expected.receipt.algorithm === "xoonya-native-hybrid-v1") {
34
- assert.strictEqual(receipt.version, vector.expected.receipt.version, `${vector.id} hybrid receipt version mismatch`);
35
- assert.strictEqual(receipt.receipt_id, vector.expected.receipt.receipt_id, `${vector.id} hybrid receipt id mismatch`);
36
- assert.strictEqual(receipt.agent_identity, vector.expected.receipt.agent_identity, `${vector.id} hybrid agent mismatch`);
37
- assert.strictEqual(receipt.domain_id, vector.expected.receipt.domain_id, `${vector.id} hybrid domain mismatch`);
38
- assert.strictEqual(receipt.sequence, vector.expected.receipt.sequence, `${vector.id} hybrid sequence mismatch`);
39
- assert.strictEqual(receipt.event_commitment, vector.expected.receipt.event_commitment, `${vector.id} hybrid event commitment mismatch`);
40
- assert.strictEqual(receipt.algorithm, vector.expected.receipt.algorithm, `${vector.id} hybrid algorithm mismatch`);
41
- assert.strictEqual(receipt.native_proof.method, vector.expected.receipt.native_proof.method, `${vector.id} hybrid method mismatch`);
42
- assert.strictEqual(receipt.native_proof.hybrid_suite, vector.expected.receipt.native_proof.hybrid_suite, `${vector.id} hybrid suite mismatch`);
43
- assert.strictEqual(receipt.native_proof.identity_ref, vector.expected.receipt.native_proof.identity_ref, `${vector.id} hybrid identity ref mismatch`);
44
- assert.strictEqual(receipt.native_proof.hybrid_public_key_ref, vector.expected.receipt.native_proof.hybrid_public_key_ref, `${vector.id} hybrid public key ref mismatch`);
45
- assert.strictEqual(receipt.native_proof.classical_public_key_ref, vector.expected.receipt.native_proof.classical_public_key_ref, `${vector.id} hybrid classical key ref mismatch`);
46
- assert.strictEqual(receipt.native_proof.pq_public_key_ref, vector.expected.receipt.native_proof.pq_public_key_ref, `${vector.id} hybrid pq key ref mismatch`);
47
- assert.deepStrictEqual(receipt.native_proof.classical_public_key_material, vector.expected.receipt.native_proof.classical_public_key_material, `${vector.id} hybrid classical key material mismatch`);
48
- assert.deepStrictEqual(receipt.native_proof.pq_public_key_material, vector.expected.receipt.native_proof.pq_public_key_material, `${vector.id} hybrid pq key material mismatch`);
49
- assert.strictEqual(receipt.native_proof.proof_material.signing_material_sha256, vector.expected.receipt.native_proof.proof_material.signing_material_sha256, `${vector.id} hybrid signing material hash mismatch`);
50
- assert.strictEqual(typeof receipt.native_proof.proof_material.classical_signature, "string", `${vector.id} hybrid classical signature missing`);
51
- assert.strictEqual(receipt.native_proof.proof_material.classical_signature.length > 10, true, `${vector.id} hybrid classical signature too small`);
52
- assert.strictEqual(typeof receipt.native_proof.proof_material.pq_signature, "string", `${vector.id} hybrid pq signature missing`);
53
- assert.strictEqual(receipt.native_proof.proof_material.pq_signature.length > 100, true, `${vector.id} hybrid pq signature too small`);
54
- assert.strictEqual(
55
- receipt.signature,
56
- `xoonya-native-hybrid-v1:${receipt.native_proof.hybrid_suite}:${receipt.native_proof.proof_material.classical_signature}.${receipt.native_proof.proof_material.pq_signature}`,
57
- `${vector.id} hybrid compact signature mismatch`
58
- );
96
+ const strict = nv.verifyProofBundle(bundle, { strict: true });
97
+ if (verification.cryptographically_verified) {
98
+ assert.strictEqual(strict.valid, true, `${vector.id} cryptographic method must pass strict mode`);
59
99
  } else {
60
- assert.deepStrictEqual(receipt, vector.expected.receipt, `${vector.id} receipt mismatch`);
100
+ assert.strictEqual(strict.valid, false, `${vector.id} non-cryptographic method must fail strict mode`);
101
+ assert.strictEqual(nv.PROOF_VERIFICATION_STRICT_REJECTION_CODES.includes(strict.reason), true, `${vector.id} strict rejection code mismatch`);
61
102
  }
103
+ strictModeChecks += 1;
62
104
 
63
- const bundle = sdk.buildProofBundle({
64
- ceb: vector.event,
65
- receipt,
66
- anchors: Array.isArray(vector.anchors) ? vector.anchors : undefined
67
- });
68
- assert.strictEqual(bundle.version, vector.expected.proof_bundle_version, `${vector.id} proof bundle version mismatch`);
69
- const verification = sdk.verifyProofBundle(bundle);
70
- assert.strictEqual(verification.valid, true, `${vector.id} proof bundle should verify`);
71
- conformanceResults.push({
105
+ const untrusted = nv.verifyProofBundle(bundle, { expected_public_key_ref: "ed25519-spki-sha256:" + "00".repeat(32) });
106
+ if (verification.cryptographically_verified) {
107
+ assert.strictEqual(untrusted.valid, false, `${vector.id} undeclared key must be rejected under a trust root`);
108
+ assert.strictEqual(nv.PROOF_VERIFICATION_TRUST_ROOT_REJECTION_CODES.includes(untrusted.reason), true, `${vector.id} trust root rejection code mismatch`);
109
+ } else {
110
+ assert.strictEqual(untrusted.valid, true, `${vector.id} trust root must not affect non-keyed methods`);
111
+ }
112
+
113
+ results.push({
72
114
  id: vector.id,
73
115
  verification_method: verification.verification_method,
74
- verification_state: verification.verification_state
116
+ verification_state: verification.verification_state,
117
+ verification_class: verification.verification_class,
118
+ cryptographically_verified: verification.cryptographically_verified
75
119
  });
76
120
  }
121
+ return { results, strictModeChecks };
122
+ }
77
123
 
78
- const adversarialResults = [];
124
+ function verifyAdversarial() {
125
+ const results = [];
79
126
  for (const vector of adversarialVectors.vectors) {
80
127
  if (vector.kind === "canonicalize_event_error") {
81
128
  assert.throws(
82
- () => sdk.canonicalizeEvent(vector.event),
129
+ () => nv.canonicalizeEvent(vector.event),
83
130
  (error) => error && error.message === vector.expected_reason,
84
131
  `${vector.id} should throw expected reason`
85
132
  );
86
- adversarialResults.push({
87
- id: vector.id,
88
- kind: vector.kind,
89
- reason: vector.expected_reason
90
- });
133
+ results.push({ id: vector.id, kind: vector.kind, reason: vector.expected_reason });
91
134
  continue;
92
135
  }
93
136
  if (vector.kind === "verify_bundle_reason") {
94
- const result = sdk.verifyProofBundle(vector.bundle);
137
+ const result = nv.verifyProofBundle(vector.bundle);
95
138
  assert.strictEqual(result.valid, false, `${vector.id} should fail`);
96
139
  assert.strictEqual(result.reason, vector.expected_reason, `${vector.id} failure reason mismatch`);
97
- adversarialResults.push({
98
- id: vector.id,
99
- kind: vector.kind,
100
- reason: result.reason
101
- });
140
+ results.push({ id: vector.id, kind: vector.kind, reason: result.reason });
102
141
  continue;
103
142
  }
104
143
  throw new Error(`${vector.id} has unsupported vector kind`);
105
144
  }
145
+ return results;
146
+ }
106
147
 
107
- const nativeAtomResults = [];
108
- const nativeAtomPayload = Buffer.from(nativeAtomVectors.payload_ascii, "utf8");
148
+ function verifyNativeAtoms() {
149
+ const results = [];
109
150
  for (const vector of nativeAtomVectors.vectors) {
110
- const parsed = sdk.parsexoonyaNativeAtom(vector.atom_hex);
151
+ const parsed = nv.parsexoonyaNativeAtom(vector.atom_hex);
111
152
  assert.strictEqual(parsed.atom_version, vector.atom_version, `${vector.id} atom version mismatch`);
112
153
  assert.strictEqual(parsed.byte_length, vector.byte_length, `${vector.id} byte length mismatch`);
113
154
  assert.strictEqual(parsed.agent_id, vector.agent_id, `${vector.id} agent id mismatch`);
114
155
  assert.strictEqual(parsed.payload_hash_sha256, vector.payload_hash_sha256, `${vector.id} payload hash mismatch`);
115
- const hasPayload = vector.payload_hash_sha256 !== "00".repeat(32);
116
- const verification = sdk.verifyxoonyaNativeAtom(vector.atom_hex, {
117
- identity_material_hex: nativeAtomVectors.identity_material_hex,
118
- ...(hasPayload ? { payload_bytes: nativeAtomPayload } : {})
119
- });
156
+ const verification = nv.verifyxoonyaNativeAtom(vector.atom_hex, atomOptions(vector, nativeAtomVectors));
120
157
  assert.strictEqual(verification.valid, true, `${vector.id} should verify`);
121
158
  assert.strictEqual(verification.error_code, null, `${vector.id} should not have error code`);
122
- nativeAtomResults.push({
123
- id: vector.id,
124
- atom_version: vector.atom_version,
125
- byte_length: vector.byte_length
126
- });
159
+ results.push({ id: vector.id, atom_version: vector.atom_version, byte_length: vector.byte_length });
127
160
  }
128
-
129
- const nativeAtomAdversarialResults = [];
161
+ const adversarial = [];
130
162
  for (const vector of nativeAtomVectors.adversarial) {
131
- const verification = sdk.verifyxoonyaNativeAtom(vector.atom_hex, {
132
- identity_material_hex: vector.identity_material_hex || nativeAtomVectors.identity_material_hex,
133
- ...(vector.payload_ascii ? { payload_bytes: Buffer.from(vector.payload_ascii, "utf8") } : {})
134
- });
163
+ const verification = nv.verifyxoonyaNativeAtom(vector.atom_hex, atomOptions(vector, nativeAtomVectors));
135
164
  assert.strictEqual(verification.valid, false, `${vector.id} should fail`);
136
165
  assert.strictEqual(verification.reason, vector.expected_reason, `${vector.id} failure reason mismatch`);
137
166
  assert.strictEqual(verification.error_code, vector.expected_error_code, `${vector.id} error code mismatch`);
138
- nativeAtomAdversarialResults.push({
139
- id: vector.id,
140
- reason: verification.reason,
141
- error_code: verification.error_code
167
+ adversarial.push({ id: vector.id, reason: verification.reason, error_code: verification.error_code });
168
+ }
169
+ return { results, adversarial };
170
+ }
171
+
172
+ function verifyPayloadProfileAndFrame() {
173
+ const profileVector = nativePayloadProfileVectors.profile_vector;
174
+ const parsed = nv.parsexoonyaNativePayloadProfileV1(profileVector.expected.canonical_bytes_hex);
175
+ assert.strictEqual(parsed.payload_hash_sha256, profileVector.expected.payload_hash_sha256, `${profileVector.id} payload hash mismatch`);
176
+ assert.strictEqual(parsed.schema_hash_sha256, profileVector.expected.schema_hash_sha256, `${profileVector.id} schema hash mismatch`);
177
+ assert.deepStrictEqual(parsed.fields.map((field) => field.field_id), profileVector.expected.field_order, `${profileVector.id} field order mismatch`);
178
+ const profileVerification = nv.verifyxoonyaNativePayloadProfileV1(profileVector.expected.canonical_bytes_hex, {
179
+ payload_hash_sha256: profileVector.expected.payload_hash_sha256,
180
+ schema_ref: profileVector.input.schema_ref,
181
+ allowed_field_ids: profileVector.expected.field_order
182
+ });
183
+ assert.strictEqual(profileVerification.valid, true, `${profileVector.id} should verify`);
184
+ const unknownField = nv.verifyxoonyaNativePayloadProfileV1(profileVector.expected.canonical_bytes_hex, {
185
+ allowed_field_ids: profileVector.expected.field_order.slice(0, -1)
186
+ });
187
+ assert.strictEqual(unknownField.reason, "payload_profile_unknown_field", `${profileVector.id} unknown field policy mismatch`);
188
+
189
+ const frameVector = nativePayloadProfileVectors.line_rate_frame_vector;
190
+ const payloadBytes = Buffer.from(profileVector.expected.canonical_bytes_hex, "hex");
191
+ const frameVerification = nv.verifyxoonyaNativeLineRateFrameV1(frameVector.frame_hex, {
192
+ identity_material_hex: frameVector.identity_material_hex,
193
+ payload_bytes: payloadBytes
194
+ });
195
+ assert.strictEqual(frameVerification.valid, true, `${frameVector.id} should verify (${frameVerification.reason})`);
196
+ assert.strictEqual(frameVerification.parsed_frame.atom_hex, frameVector.atom_hex, `${frameVector.id} atom mismatch`);
197
+ assert.strictEqual(frameVerification.parsed_frame.checksum_hex, frameVector.checksum_hex, `${frameVector.id} checksum mismatch`);
198
+ assert.strictEqual(frameVerification.parsed_frame.frame_byte_length, frameVector.frame_byte_length, `${frameVector.id} frame length mismatch`);
199
+ const tamperedFrame = `${frameVector.frame_hex.slice(0, -1)}${frameVector.frame_hex.endsWith("0") ? "1" : "0"}`;
200
+ const tamperedVerification = nv.verifyxoonyaNativeLineRateFrameV1(tamperedFrame, {
201
+ identity_material_hex: frameVector.identity_material_hex,
202
+ payload_bytes: payloadBytes
203
+ });
204
+ assert.strictEqual(tamperedVerification.reason, "line_rate_frame_checksum_mismatch", `${frameVector.id} tamper reason mismatch`);
205
+ return {
206
+ profile_results: [{ id: profileVector.id, field_count: parsed.field_count }],
207
+ frame_results: [{ id: frameVector.id, frame_byte_length: frameVector.frame_byte_length }]
208
+ };
209
+ }
210
+
211
+ // Self-test of the detached-signature verifier with throwaway keys: Ed25519 and
212
+ // ML-DSA-65 (FIPS 204) signatures must verify, a flipped signature must not, and a
213
+ // declared trusted-key fingerprint must bind.
214
+ function verifyExternalSignatureSelfTest() {
215
+ const material = Buffer.from("xoonya-verifier-external-signature-self-test", "utf8");
216
+ const checks = {};
217
+ for (const [alg, keyType] of [["EdDSA", "ed25519"], ["ML-DSA-65", "ml-dsa-65"]]) {
218
+ const pair = crypto.generateKeyPairSync(keyType);
219
+ const signature = crypto.sign(null, material, pair.privateKey).toString("base64");
220
+ const publicKeyPem = pair.publicKey.export({ type: "spki", format: "pem" });
221
+ const ok = external.verifyDetachedSignature({ material, signature, public_key: publicKeyPem, algorithm: alg });
222
+ assert.strictEqual(ok.signature_valid, true, `${alg} detached signature should verify`);
223
+ assert.strictEqual(ok.expected_key_match, null, `${alg} no expectation declared`);
224
+ const anchored = external.verifyDetachedSignature({ material, signature, public_key: publicKeyPem, algorithm: alg, expected_key_ref: ok.signing_key_ref });
225
+ assert.strictEqual(anchored.trust_anchored, true, `${alg} declared key must anchor`);
226
+ const wrongKey = external.verifyDetachedSignature({ material, signature, public_key: publicKeyPem, algorithm: alg, expected_key_ref: "nope" });
227
+ assert.strictEqual(wrongKey.trust_anchored, false, `${alg} wrong declared key must not anchor`);
228
+ const tampered = external.verifyDetachedSignature({ material: Buffer.concat([material, Buffer.from("x")]), signature, public_key: publicKeyPem, algorithm: alg });
229
+ assert.strictEqual(tampered.signature_valid, false, `${alg} tampered material must fail`);
230
+ const privateRefused = external.toPublicKeyObject(pair.privateKey.export({ type: "pkcs8", format: "pem" }));
231
+ assert.strictEqual(privateRefused, null, `${alg} private key material must be refused`);
232
+ checks[alg] = true;
233
+ }
234
+ return checks;
235
+ }
236
+
237
+ // Engine-parity cross-check (source checkout only).
238
+ function runEngineParity() {
239
+ // eslint-disable-next-line global-require
240
+ const engine = require(ENGINE_FILE);
241
+ let comparisons = 0;
242
+ const compare = (label, standalone, fromEngine) => {
243
+ assert.deepStrictEqual(standalone, fromEngine, `engine parity mismatch: ${label}`);
244
+ comparisons += 1;
245
+ };
246
+
247
+ for (const vector of conformanceVectors.vectors) {
248
+ const bundle = conformanceBundle(vector);
249
+ compare(`${vector.id} hashEvent`, nv.hashEvent(vector.event), engine.hashEvent(vector.event));
250
+ compare(`${vector.id} canonicalizeEvent`, nv.canonicalizeEvent(vector.event), engine.canonicalizeEvent(vector.event));
251
+ for (const options of verificationOptionVariants(bundle.receipt)) {
252
+ compare(`${vector.id} ${JSON.stringify(options)}`, nv.verifyProofBundle(bundle, options), engine.verifyProofBundle(bundle, options));
253
+ }
254
+
255
+ // Freshly emitted by the engine (new ML-DSA randomness for hybrid), verified by both.
256
+ const fresh = engine.buildProofBundle({
257
+ ceb: vector.event,
258
+ receipt_options: vector.receipt_options || {},
259
+ anchors: Array.isArray(vector.anchors) ? vector.anchors : undefined
142
260
  });
261
+ const freshStandalone = nv.verifyProofBundle(fresh);
262
+ assert.strictEqual(freshStandalone.valid, true, `${vector.id} engine-emitted bundle must verify standalone (${freshStandalone.reason})`);
263
+ compare(`${vector.id} fresh engine bundle`, freshStandalone, engine.verifyProofBundle(fresh));
264
+ if (vector.expected.receipt.algorithm === "xoonya-native-hybrid-v1") {
265
+ const strip = (receipt) => {
266
+ const copy = clone(receipt);
267
+ delete copy.signature;
268
+ delete copy.native_proof.proof_material.classical_signature;
269
+ delete copy.native_proof.proof_material.pq_signature;
270
+ return copy;
271
+ };
272
+ compare(`${vector.id} fresh hybrid receipt (minus randomized signatures)`, strip(fresh.receipt), strip(vector.expected.receipt));
273
+ } else {
274
+ compare(`${vector.id} fresh receipt equals vector receipt`, fresh.receipt, vector.expected.receipt);
275
+ }
276
+
277
+ // Mutations: both verifiers must reject identically.
278
+ const mutations = {
279
+ signature_flipped: (b) => { b.receipt.signature = flipLastChar(b.receipt.signature); },
280
+ sequence_replayed: (b) => { b.receipt.sequence = `${b.receipt.sequence}0`; },
281
+ algorithm_none: (b) => { b.receipt.algorithm = "none"; },
282
+ algorithm_unknown: (b) => { b.receipt.algorithm = "not-a-method"; },
283
+ agent_identity_swapped: (b) => { b.receipt.agent_identity = `${b.receipt.agent_identity}-other`; },
284
+ event_hash_swapped: (b) => { b.ceb.event_hash = "ff".repeat(32); },
285
+ native_proof_dropped: (b) => { delete b.receipt.native_proof; },
286
+ anchors_dropped: (b) => { delete b.anchors; },
287
+ downgrade_to_digest: (b) => { b.receipt.algorithm = "xoonya-native-sha256-v1"; },
288
+ bundle_version_bad: (b) => { b.version = "proof-bundle/v0"; }
289
+ };
290
+ for (const [name, mutate] of Object.entries(mutations)) {
291
+ const mutated = clone(bundle);
292
+ mutate(mutated);
293
+ compare(`${vector.id} mutation ${name}`, nv.verifyProofBundle(mutated), engine.verifyProofBundle(mutated));
294
+ }
295
+ }
296
+
297
+ for (const vector of adversarialVectors.vectors) {
298
+ if (vector.kind === "canonicalize_event_error") {
299
+ let standaloneMessage = null;
300
+ let engineMessage = null;
301
+ try { nv.canonicalizeEvent(vector.event); } catch (error) { standaloneMessage = error.message; }
302
+ try { engine.canonicalizeEvent(vector.event); } catch (error) { engineMessage = error.message; }
303
+ compare(`${vector.id} canonicalize error`, standaloneMessage, engineMessage);
304
+ continue;
305
+ }
306
+ for (const options of verificationOptionVariants(vector.bundle.receipt || {})) {
307
+ compare(`${vector.id} ${JSON.stringify(options)}`, nv.verifyProofBundle(vector.bundle, options), engine.verifyProofBundle(vector.bundle, options));
308
+ }
309
+ }
310
+
311
+ for (const vector of [...nativeAtomVectors.vectors, ...nativeAtomVectors.adversarial]) {
312
+ const options = atomOptions(vector, nativeAtomVectors);
313
+ compare(`${vector.id} atom verify`, nv.verifyxoonyaNativeAtom(vector.atom_hex, options), engine.verifyxoonyaNativeAtom(vector.atom_hex, options));
314
+ let standaloneParsed;
315
+ let engineParsed;
316
+ try { standaloneParsed = nv.parsexoonyaNativeAtom(vector.atom_hex); } catch (error) { standaloneParsed = { error: error.message, code: error.code }; }
317
+ try { engineParsed = engine.parsexoonyaNativeAtom(vector.atom_hex); } catch (error) { engineParsed = { error: error.message, code: error.code }; }
318
+ compare(`${vector.id} atom parse`, standaloneParsed, engineParsed);
319
+ }
320
+
321
+ const profileHex = nativePayloadProfileVectors.profile_vector.expected.canonical_bytes_hex;
322
+ compare("payload profile parse", nv.parsexoonyaNativePayloadProfileV1(profileHex), engine.parsexoonyaNativePayloadProfileV1(profileHex));
323
+ const frameVector = nativePayloadProfileVectors.line_rate_frame_vector;
324
+ const frameOptions = { identity_material_hex: frameVector.identity_material_hex, payload_bytes: Buffer.from(profileHex, "hex") };
325
+ compare("line-rate frame verify", nv.verifyxoonyaNativeLineRateFrameV1(frameVector.frame_hex, frameOptions), engine.verifyxoonyaNativeLineRateFrameV1(frameVector.frame_hex, frameOptions));
326
+
327
+ // Compatibility receipt verifiers share bytes with the legacy-opreturn vector.
328
+ const legacy = conformanceVectors.vectors.find((vector) => vector.expected.receipt.algorithm === "legacy-opreturn-v1");
329
+ if (legacy) {
330
+ const opreturnHex = legacy.expected.receipt.compatibility.legacy_receipt.opreturn_hex;
331
+ const payload = Buffer.from(nv.canonicalize(nv.canonicalizeEvent(legacy.event)), "utf8");
332
+ compare("legacy receipt verify", nv.verifyReceipt(opreturnHex, payload), engine.verifyReceipt(opreturnHex, payload));
333
+ compare("legacy receipt parse", nv.parseReceipt(opreturnHex), engine.parseReceipt(opreturnHex));
334
+ }
335
+
336
+ compare("verification method registry", nv.listProofVerificationMethods(), engine.listProofVerificationMethods());
337
+ compare("verification class registry", nv.listProofVerificationClasses(), engine.listProofVerificationClasses());
338
+ compare("native signature suite registry", nv.listNativeSignatureSuites(), engine.listNativeSignatureSuites());
339
+ compare("native identity type registry", nv.listxoonyaNativeIdentityTypes(), engine.listxoonyaNativeIdentityTypes());
340
+
341
+ return { checked: true, engine_file: path.basename(ENGINE_FILE), comparisons };
342
+ }
343
+
344
+ function runVectorVerification(options = {}) {
345
+ assert.strictEqual(conformanceVectors.version, "proof-conformance-v1", "conformance vector version mismatch");
346
+ assert.strictEqual(adversarialVectors.version, "proof-adversarial-v1", "adversarial vector version mismatch");
347
+ assert.strictEqual(nativeAtomVectors.version, "xoonya-native-atom-vectors-v1", "native atom vector version mismatch");
348
+ assert.strictEqual(nativePayloadProfileVectors.version, "xoonya-native-payload-profile-vectors-v1", "native payload profile vector version mismatch");
349
+
350
+ const conformance = verifyConformance();
351
+ const adversarialResults = verifyAdversarial();
352
+ const atoms = verifyNativeAtoms();
353
+ const profileAndFrame = verifyPayloadProfileAndFrame();
354
+ const externalSignatureChecks = verifyExternalSignatureSelfTest();
355
+
356
+ const verificationMethods = unique(conformance.results.map((result) => result.verification_method));
357
+ for (const method of REQUIRED_NATIVE_METHODS) {
358
+ assert.strictEqual(verificationMethods.includes(method), true, `required native method missing: ${method}`);
359
+ }
360
+
361
+ const enginePresent = fs.existsSync(ENGINE_FILE);
362
+ let engineParity;
363
+ if (options.engine_parity === false) {
364
+ engineParity = { checked: false, reason: "disabled" };
365
+ } else if (enginePresent) {
366
+ engineParity = runEngineParity();
367
+ } else {
368
+ engineParity = { checked: false, reason: "engine_not_present" };
369
+ }
370
+ if (options.require_engine_parity === true) {
371
+ assert.strictEqual(engineParity.checked, true, "engine parity check required but not run");
143
372
  }
144
373
 
145
374
  return {
146
375
  ok: true,
147
376
  product: "xoonya",
377
+ role: "verifier",
148
378
  suite: "proof-conformance-and-adversarial-vectors",
149
379
  conformance_version: conformanceVectors.version,
150
380
  adversarial_version: adversarialVectors.version,
151
- conformance_count: conformanceResults.length,
381
+ native_atom_version: nativeAtomVectors.version,
382
+ native_payload_profile_version: nativePayloadProfileVectors.version,
383
+ conformance_count: conformance.results.length,
152
384
  adversarial_count: adversarialResults.length,
153
- native_atom_vector_count: nativeAtomResults.length,
154
- native_atom_adversarial_count: nativeAtomAdversarialResults.length,
155
- verification_methods: unique(conformanceResults.map((result) => result.verification_method)),
385
+ native_atom_vector_count: atoms.results.length,
386
+ native_atom_adversarial_count: atoms.adversarial.length,
387
+ native_payload_profile_vector_count: profileAndFrame.profile_results.length,
388
+ line_rate_frame_vector_count: profileAndFrame.frame_results.length,
389
+ strict_mode_checks: conformance.strictModeChecks,
390
+ verification_methods: verificationMethods,
391
+ required_native_methods_present: REQUIRED_NATIVE_METHODS.every((method) => verificationMethods.includes(method)),
156
392
  adversarial_reasons: unique(adversarialResults.map((result) => result.reason)),
157
- native_atom_error_codes: unique(nativeAtomAdversarialResults.map((result) => result.error_code)),
158
- conformance_results: conformanceResults,
393
+ native_atom_error_codes: unique(atoms.adversarial.map((result) => result.error_code)),
394
+ external_signature_checks: externalSignatureChecks,
395
+ engine_parity: engineParity,
396
+ conformance_results: conformance.results,
159
397
  adversarial_results: adversarialResults,
160
- native_atom_results: nativeAtomResults,
161
- native_atom_adversarial_results: nativeAtomAdversarialResults
398
+ native_atom_results: atoms.results,
399
+ native_atom_adversarial_results: atoms.adversarial
162
400
  };
163
401
  }
164
402
 
165
403
  function main() {
166
- const json = process.argv.includes("--json");
167
- const summary = runVectorVerification();
404
+ const argv = process.argv.slice(2);
405
+ const json = argv.includes("--json");
406
+ const summary = runVectorVerification({
407
+ engine_parity: argv.includes("--no-engine-parity") ? false : undefined,
408
+ require_engine_parity: argv.includes("--require-engine-parity")
409
+ });
168
410
  if (json) {
169
411
  process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
170
412
  return;
@@ -176,9 +418,13 @@ function main() {
176
418
  `adversarial vectors: ${summary.adversarial_count}`,
177
419
  `native atom vectors: ${summary.native_atom_vector_count}`,
178
420
  `native atom adversarial vectors: ${summary.native_atom_adversarial_count}`,
421
+ `native payload profile vectors: ${summary.native_payload_profile_vector_count}`,
422
+ `line-rate frame vectors: ${summary.line_rate_frame_vector_count}`,
179
423
  `verification methods: ${summary.verification_methods.join(", ")}`,
180
424
  `adversarial reasons: ${summary.adversarial_reasons.join(", ")}`,
181
- `native atom error codes: ${summary.native_atom_error_codes.join(", ")}`
425
+ `native atom error codes: ${summary.native_atom_error_codes.join(", ")}`,
426
+ `external signature checks: ${Object.keys(summary.external_signature_checks).join(", ")}`,
427
+ `engine parity: ${summary.engine_parity.checked ? `${summary.engine_parity.comparisons} comparisons identical` : summary.engine_parity.reason}`
182
428
  ].join("\n") + "\n"
183
429
  );
184
430
  }
@@ -188,5 +434,6 @@ if (require.main === module) {
188
434
  }
189
435
 
190
436
  module.exports = {
191
- runVectorVerification
437
+ runVectorVerification,
438
+ REQUIRED_NATIVE_METHODS
192
439
  };
package/verify.js ADDED
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ // xoonya verifier package entry.
4
+ //
5
+ // This package verifies xoonya proofs and naxytra delivery evidence. It carries
6
+ // the verifier only: the proof engine (receipt emission, signing, review,
7
+ // governance, bridges) and the server are a hosted service and are not
8
+ // distributed. Everything here runs on Node built-ins.
9
+
10
+ const nativeVerify = require("./lib/native_verify");
11
+ const externalProofVerify = require("./lib/external_proof_verify");
12
+ const packageJson = require("./package.json");
13
+
14
+ const endpoints = Object.freeze({
15
+ hosted_service: "https://xoonya.onrender.com",
16
+ website: "https://www.naxytra.com",
17
+ product: "https://www.naxytra.com/xoonya",
18
+ agents: "https://www.naxytra.com/agents",
19
+ first_run_kit: "https://www.naxytra.com/v1/first-run-kit"
20
+ });
21
+
22
+ function normalizeString(value) {
23
+ return String(value == null ? "" : value).trim();
24
+ }
25
+
26
+ // Verify an external (non-native) signature: a compact JWS, or a detached
27
+ // signature over supplied material. Mirrors the hosted service's
28
+ // proof.verify-signature lane. Reports what can be established from the request
29
+ // alone (signature_valid under signing_key_ref); trust in that key is yours to
30
+ // declare through expected_key_ref.
31
+ function verifyExternalProofSignature(input) {
32
+ const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
33
+ const sv = body.signature_verification && typeof body.signature_verification === "object" ? body.signature_verification : body;
34
+ const jws = normalizeString(sv.jws || sv.compact_jws);
35
+ if (jws) {
36
+ return {
37
+ ok: true,
38
+ product: "xoonya",
39
+ category: "xoonya-external-proof-signature-verification",
40
+ method: "jws",
41
+ ...externalProofVerify.verifyJws(jws, {
42
+ trusted_public_key: sv.trusted_public_key || sv.public_key || null,
43
+ expected_key_ref: sv.expected_key_ref
44
+ })
45
+ };
46
+ }
47
+ if (sv.signature) {
48
+ return {
49
+ ok: true,
50
+ product: "xoonya",
51
+ category: "xoonya-external-proof-signature-verification",
52
+ method: "detached",
53
+ ...externalProofVerify.verifyDetachedSignature({
54
+ material: sv.material !== undefined ? sv.material : body.material,
55
+ signature: sv.signature,
56
+ signature_encoding: sv.signature_encoding,
57
+ public_key: sv.public_key || sv.trusted_public_key,
58
+ algorithm: sv.algorithm,
59
+ expected_key_ref: sv.expected_key_ref
60
+ })
61
+ };
62
+ }
63
+ return {
64
+ ok: false,
65
+ product: "xoonya",
66
+ category: "xoonya-external-proof-signature-verification",
67
+ reason: "no_signature_verification_input"
68
+ };
69
+ }
70
+
71
+ // Run the shipped conformance + adversarial vectors through this verifier and
72
+ // return the summary (ok, counts, verification_methods, ...).
73
+ function verifyVectors(options) {
74
+ // eslint-disable-next-line global-require
75
+ return require("./scripts/verify_vectors").runVectorVerification(options || {});
76
+ }
77
+
78
+ module.exports = {
79
+ name: packageJson.name,
80
+ version: packageJson.version,
81
+ role: "verifier",
82
+ endpoints,
83
+
84
+ // Native proof bundles, receipts, atoms, payload profiles, line-rate frames.
85
+ ...nativeVerify,
86
+
87
+ // External signatures (compact JWS and detached; Ed25519, ECDSA, RSA, ML-DSA-44/65/87).
88
+ verifyJws: externalProofVerify.verifyJws,
89
+ verifyDetachedSignature: externalProofVerify.verifyDetachedSignature,
90
+ verifyExternalProofSignature,
91
+ toPublicKeyObject: externalProofVerify.toPublicKeyObject,
92
+ looksLikeCompactJws: externalProofVerify.looksLikeCompactJws,
93
+
94
+ verifyVectors
95
+ };
package/.env.example DELETED
@@ -1,10 +0,0 @@
1
- XOONYA_HOST=127.0.0.1
2
- XOONYA_PORT=4310
3
- # Set to 1 to make every proof-bundle verification strict: only cryptographically verified
4
- # (native signed / native hybrid) results are valid; digest and structural results are rejected.
5
- # XOONYA_STRICT_VERIFY=1
6
- # Whether POST /v1/receipts/emit, /v1/proof-bundles/build, and the proof-center run routes may
7
- # receive private key material (private_key_pem, classical_private_key_pem, pq_private_key_pem).
8
- # Unset = accepted locally, rejected when RENDER is set. Set to false on any shared deployment
9
- # and sign locally with the xoonya SDK or CLI instead.
10
- # XOONYA_ACCEPT_PRIVATE_KEY_MATERIAL=false