xytara 3.1.17 → 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 (390) hide show
  1. package/README.md +120 -92
  2. package/RELEASE_NOTES.md +7 -2
  3. package/START_HERE.md +56 -224
  4. package/bin/xytara.js +21 -8
  5. package/client.js +79 -1
  6. package/lib/{delivery_receipt.js → delivery_receipt_verify.js} +14 -100
  7. package/package.json +25 -35
  8. package/scripts/verify_client.js +418 -0
  9. package/scripts/verify_release_candidate.js +146 -45
  10. package/.env.example +0 -173
  11. package/ADAPTER_START_HERE.md +0 -56
  12. package/BSV_TERANODE_PLATFORM_DISCONTINUITY_RUNBOOK.md +0 -126
  13. package/CARRIED_HANDOFF_DEMO.md +0 -60
  14. package/EXAMPLE_PATHS.md +0 -53
  15. package/FINAL_CONTRACT.md +0 -498
  16. package/PARTNER_READY_PATH.md +0 -71
  17. package/PUBLIC_DEMO_SCRIPT.md +0 -78
  18. package/REAL_PAYMENT_SETUP.md +0 -320
  19. package/SERVICE_CONTRACT.md +0 -419
  20. package/SUPABASE_RUNTIME_STATE_SETUP.md +0 -61
  21. package/TERMINOLOGY.md +0 -50
  22. package/WHY_XYTARA_XOONYA.md +0 -63
  23. package/XT1_EXECUTION_TRUTH_STANDARD.md +0 -78
  24. package/XYTARA_ADAPTER_PROTOCOL_TRUTH_MODEL.md +0 -75
  25. package/XYTARA_AUTONOMOUS_ENTRY_MODEL.md +0 -124
  26. package/XYTARA_DEFAULT_PATH_MODEL.md +0 -84
  27. package/XYTARA_EXECUTION_TRUTH_MODEL.md +0 -171
  28. package/XYTARA_PAYMENT_RAIL_TRUTH_MODEL.md +0 -68
  29. package/adapters/AUTHORING_GUIDE.md +0 -244
  30. package/adapters/ONBOARDING_POSTURE.md +0 -61
  31. package/adapters/THIRD_PARTY_SUBMISSION_PROCESS.md +0 -84
  32. package/adapters/adapter-manifest.schema.json +0 -283
  33. package/adapters/examples/example-execution-adapter.js +0 -61
  34. package/adapters/examples/example-execution-adapter.manifest.json +0 -81
  35. package/adapters/examples/example-settlement-adapter.js +0 -55
  36. package/adapters/examples/example-settlement-adapter.manifest.json +0 -78
  37. package/adapters/examples/example-third-party-acp-registration.submission-bundle.json +0 -124
  38. package/adapters/examples/example-third-party-erc8004-registration.submission-bundle.json +0 -121
  39. package/adapters/examples/example-third-party-identity-registration.certification-pack.json +0 -22
  40. package/adapters/examples/example-third-party-identity-registration.record.json +0 -26
  41. package/adapters/examples/example-third-party-identity-registration.submission-bundle.json +0 -126
  42. package/adapters/examples/example-third-party-langchain-registration.submission-bundle.json +0 -124
  43. package/adapters/examples/example-third-party-mpp-registration.submission-bundle.json +0 -120
  44. package/adapters/examples/example-third-party-registration.certification-pack.json +0 -22
  45. package/adapters/examples/example-third-party-registration.record.json +0 -28
  46. package/adapters/examples/example-third-party-registration.submission-bundle.json +0 -126
  47. package/adapters/examples/example-third-party-settlement-registration.certification-pack.json +0 -22
  48. package/adapters/examples/example-third-party-settlement-registration.record.json +0 -26
  49. package/adapters/examples/example-third-party-settlement-registration.submission-bundle.json +0 -127
  50. package/adapters/examples/langchain-reference-execution-adapter.js +0 -81
  51. package/adapters/examples/langchain-reference-execution-adapter.manifest.json +0 -79
  52. package/adapters/examples/langgraph-reference-execution-adapter.js +0 -81
  53. package/adapters/examples/langgraph-reference-execution-adapter.manifest.json +0 -79
  54. package/adapters/examples/minimal-third-party-execution-adapter.js +0 -61
  55. package/adapters/examples/minimal-third-party-execution-adapter.manifest.json +0 -79
  56. package/adapters/examples/minimal-third-party-execution-registration.record.json +0 -26
  57. package/adapters/examples/minimal-third-party-execution.certification-pack.json +0 -22
  58. package/adapters/examples/minimal-third-party-execution.submission-bundle.json +0 -126
  59. package/adapters/integration-certification-pack.schema.json +0 -82
  60. package/adapters/integration-registration-record.schema.json +0 -114
  61. package/adapters/integration-submission-bundle-set.schema.json +0 -39
  62. package/adapters/integration-submission-bundle.schema.json +0 -34
  63. package/adapters/interfaces.js +0 -56
  64. package/bin/xytara-release.js +0 -1429
  65. package/examples/_demo_env.js +0 -40
  66. package/examples/adapter_review_walkthrough.js +0 -54
  67. package/examples/export_carried_handoff.js +0 -81
  68. package/examples/funded_runtime_walkthrough.js +0 -71
  69. package/examples/partner_launch_walkthrough.js +0 -44
  70. package/examples/quickstart.js +0 -3256
  71. package/fixtures/catalog.js +0 -1156
  72. package/index.js +0 -395
  73. package/integrations/dispatch.js +0 -276
  74. package/integrations/registry-snapshot.schema.json +0 -36
  75. package/integrations/registry.js +0 -2261
  76. package/integrations/views.js +0 -28
  77. package/lib/a2a_lane_contract.js +0 -104
  78. package/lib/a2a_rpc.js +0 -287
  79. package/lib/a2c_lane_contract.js +0 -111
  80. package/lib/account_auth.js +0 -585
  81. package/lib/acp_lane_contract.js +0 -54
  82. package/lib/activity_audit_contract.js +0 -322
  83. package/lib/adapter_certification_contract.js +0 -130
  84. package/lib/adapter_depth_contract.js +0 -218
  85. package/lib/adapter_pack.js +0 -118
  86. package/lib/adapter_partner_pack.js +0 -89
  87. package/lib/adapter_promotion_pack.js +0 -89
  88. package/lib/adapter_protocol_truth_contract.js +0 -229
  89. package/lib/agent_identity.js +0 -162
  90. package/lib/announcement_pack.js +0 -61
  91. package/lib/artifact_distribution_lane_contract.js +0 -54
  92. package/lib/asyncapi_contract.js +0 -150
  93. package/lib/auth_interop_contract.js +0 -80
  94. package/lib/authority_binding_lifecycle_contract.js +0 -182
  95. package/lib/autonomous_entry_contract.js +0 -409
  96. package/lib/bolt_adapter.js +0 -187
  97. package/lib/bolt_lane_contract.js +0 -55
  98. package/lib/bolt_payment_front.js +0 -224
  99. package/lib/business_cockpit.js +0 -378
  100. package/lib/buyer_event_log.js +0 -230
  101. package/lib/buyer_safety_policy.js +0 -132
  102. package/lib/capability_execution_truth.js +0 -276
  103. package/lib/capability_registry.js +0 -633
  104. package/lib/catalog_contract.js +0 -966
  105. package/lib/catalog_family_model.js +0 -193
  106. package/lib/catalog_views.js +0 -55
  107. package/lib/cdp_jwt.js +0 -57
  108. package/lib/checkout_event_security.js +0 -142
  109. package/lib/checkout_processor_adapter.js +0 -217
  110. package/lib/cloudevents_contract.js +0 -80
  111. package/lib/command_flow.js +0 -911
  112. package/lib/commerce_artifacts.js +0 -591
  113. package/lib/commerce_authority.js +0 -449
  114. package/lib/commerce_bridge.js +0 -274
  115. package/lib/commerce_cases.js +0 -399
  116. package/lib/commerce_checkout.js +0 -509
  117. package/lib/commerce_coordination.js +0 -346
  118. package/lib/commerce_economics.js +0 -4017
  119. package/lib/commerce_identity.js +0 -578
  120. package/lib/commerce_quotes.js +0 -266
  121. package/lib/commerce_reports.js +0 -14461
  122. package/lib/commerce_runtime.js +0 -322
  123. package/lib/commerce_shell.js +0 -257
  124. package/lib/crypto_agility_matrix.js +0 -125
  125. package/lib/default_path_contract.js +0 -412
  126. package/lib/delivery_summary_contract.js +0 -95
  127. package/lib/ecosystem_entry.js +0 -64
  128. package/lib/erc8004_lane_contract.js +0 -65
  129. package/lib/event_system_lane_contract.js +0 -75
  130. package/lib/execution_dedupe.js +0 -86
  131. package/lib/execution_truth_contract.js +0 -234
  132. package/lib/external_credit_bridge.js +0 -142
  133. package/lib/external_execution_policy.js +0 -143
  134. package/lib/external_execution_runtime.js +0 -238
  135. package/lib/feature_control_lane_contract.js +0 -54
  136. package/lib/first_run_conversion_contract.js +0 -290
  137. package/lib/framework_lane_contract.js +0 -89
  138. package/lib/framework_provider_promotion.js +0 -235
  139. package/lib/full_catalog_contract.js +0 -525
  140. package/lib/go_live_operator_pack.js +0 -391
  141. package/lib/http_transport.js +0 -99
  142. package/lib/identity_auth.js +0 -175
  143. package/lib/identity_interop_contract.js +0 -82
  144. package/lib/integration_matrix_contract.js +0 -102
  145. package/lib/l402_adapter.js +0 -241
  146. package/lib/l402_lane_contract.js +0 -55
  147. package/lib/l402_payment_front.js +0 -265
  148. package/lib/launch_narrative.js +0 -53
  149. package/lib/lifecycle_continuity_contract.js +0 -115
  150. package/lib/machine_identity_registry_contract.js +0 -199
  151. package/lib/major_rails_lane_contract.js +0 -150
  152. package/lib/market_lane_contract.js +0 -467
  153. package/lib/market_lane_depth_contract.js +0 -182
  154. package/lib/market_lane_promotion_contract.js +0 -210
  155. package/lib/market_lane_trace_contract.js +0 -278
  156. package/lib/mcp_lane_contract.js +0 -137
  157. package/lib/mpp_adapter.js +0 -237
  158. package/lib/network_transport.js +0 -110
  159. package/lib/offline_verifiability_recovery_contract.js +0 -155
  160. package/lib/openapi_contract.js +0 -300
  161. package/lib/operational_receipt_contract.js +0 -165
  162. package/lib/operator_intelligence.js +0 -407
  163. package/lib/outreach_copy_pack.js +0 -51
  164. package/lib/outreach_message_pack.js +0 -71
  165. package/lib/outreach_proof.js +0 -71
  166. package/lib/outreach_target_pack.js +0 -60
  167. package/lib/partner_intelligence.js +0 -105
  168. package/lib/payment_config.js +0 -257
  169. package/lib/payment_front_registry.js +0 -53
  170. package/lib/payment_protocol_contract.js +0 -165
  171. package/lib/payment_rail_truth_contract.js +0 -324
  172. package/lib/payment_verification.js +0 -357
  173. package/lib/phase_10_closeout_pack.js +0 -45
  174. package/lib/phase_10_completion_pack.js +0 -76
  175. package/lib/phase_10_decision_record_pack.js +0 -54
  176. package/lib/phase_10_decision_resolution_pack.js +0 -53
  177. package/lib/phase_10_demand_signal_adapters_runtime_pack.js +0 -74
  178. package/lib/phase_10_ecosystem_backlog_triage_runtime_pack.js +0 -74
  179. package/lib/phase_10_freeze_baseline_pack.js +0 -67
  180. package/lib/phase_10_freeze_review_pack.js +0 -64
  181. package/lib/phase_10_gate_pack.js +0 -57
  182. package/lib/phase_10_long_tail_continuity_pack.js +0 -80
  183. package/lib/phase_10_long_tail_ecosystem_pack.js +0 -66
  184. package/lib/phase_10_niche_extension_registry_runtime_pack.js +0 -74
  185. package/lib/phase_1_claude_mcp_pack.js +0 -60
  186. package/lib/phase_1_claude_mcp_runtime_pack.js +0 -52
  187. package/lib/phase_1_ecosystem_pack.js +0 -67
  188. package/lib/phase_1_openai_codex_pack.js +0 -60
  189. package/lib/phase_1_openai_codex_runtime_pack.js +0 -52
  190. package/lib/phase_2_base_runtime_pack.js +0 -71
  191. package/lib/phase_2_base_usdc_runtime_pack.js +0 -72
  192. package/lib/phase_2_closeout_pack.js +0 -65
  193. package/lib/phase_2_completion_pack.js +0 -113
  194. package/lib/phase_2_decision_record_pack.js +0 -66
  195. package/lib/phase_2_decision_resolution_pack.js +0 -69
  196. package/lib/phase_2_eth_runtime_pack.js +0 -70
  197. package/lib/phase_2_evm_base_runtime_pack.js +0 -73
  198. package/lib/phase_2_evm_runtime_pack.js +0 -71
  199. package/lib/phase_2_flip_preview_pack.js +0 -60
  200. package/lib/phase_2_freeze_review_pack.js +0 -99
  201. package/lib/phase_2_gate_pack.js +0 -77
  202. package/lib/phase_2_payment_rails_pack.js +0 -71
  203. package/lib/phase_2_usdc_runtime_pack.js +0 -71
  204. package/lib/phase_3_brc_runtime_pack.js +0 -81
  205. package/lib/phase_3_bsv_teranode_runtime_pack.js +0 -83
  206. package/lib/phase_3_closeout_pack.js +0 -62
  207. package/lib/phase_3_completion_pack.js +0 -94
  208. package/lib/phase_3_decision_record_pack.js +0 -64
  209. package/lib/phase_3_decision_resolution_pack.js +0 -69
  210. package/lib/phase_3_freeze_baseline_pack.js +0 -67
  211. package/lib/phase_3_freeze_review_pack.js +0 -80
  212. package/lib/phase_3_gate_pack.js +0 -76
  213. package/lib/phase_3_metanet_runtime_pack.js +0 -81
  214. package/lib/phase_3_native_bsv_pack.js +0 -91
  215. package/lib/phase_3_native_continuity_pack.js +0 -82
  216. package/lib/phase_4_attestation_runtime_pack.js +0 -75
  217. package/lib/phase_4_closeout_pack.js +0 -45
  218. package/lib/phase_4_completion_pack.js +0 -94
  219. package/lib/phase_4_decision_record_pack.js +0 -54
  220. package/lib/phase_4_decision_resolution_pack.js +0 -45
  221. package/lib/phase_4_erc8004_runtime_pack.js +0 -76
  222. package/lib/phase_4_freeze_baseline_pack.js +0 -67
  223. package/lib/phase_4_freeze_review_pack.js +0 -68
  224. package/lib/phase_4_gate_pack.js +0 -58
  225. package/lib/phase_4_identity_registry_runtime_pack.js +0 -75
  226. package/lib/phase_4_identity_trust_pack.js +0 -73
  227. package/lib/phase_4_trust_continuity_pack.js +0 -86
  228. package/lib/phase_5_antelope_runtime_pack.js +0 -76
  229. package/lib/phase_5_closeout_pack.js +0 -44
  230. package/lib/phase_5_completion_pack.js +0 -82
  231. package/lib/phase_5_constellation_dag_runtime_pack.js +0 -76
  232. package/lib/phase_5_decision_record_pack.js +0 -54
  233. package/lib/phase_5_decision_resolution_pack.js +0 -45
  234. package/lib/phase_5_digibyte_dgb_runtime_pack.js +0 -76
  235. package/lib/phase_5_freeze_baseline_pack.js +0 -67
  236. package/lib/phase_5_freeze_review_pack.js +0 -68
  237. package/lib/phase_5_gate_pack.js +0 -58
  238. package/lib/phase_5_hedera_hbar_runtime_pack.js +0 -76
  239. package/lib/phase_5_kaspa_kas_runtime_pack.js +0 -76
  240. package/lib/phase_5_major_rails_continuity_pack.js +0 -86
  241. package/lib/phase_5_major_rails_pack.js +0 -110
  242. package/lib/phase_5_metal_runtime_pack.js +0 -76
  243. package/lib/phase_5_polkadot_dot_runtime_pack.js +0 -76
  244. package/lib/phase_5_proton_xpr_runtime_pack.js +0 -76
  245. package/lib/phase_5_solana_runtime_pack.js +0 -76
  246. package/lib/phase_6_autogen_runtime_pack.js +0 -72
  247. package/lib/phase_6_closeout_pack.js +0 -46
  248. package/lib/phase_6_completion_pack.js +0 -77
  249. package/lib/phase_6_decision_record_pack.js +0 -54
  250. package/lib/phase_6_decision_resolution_pack.js +0 -53
  251. package/lib/phase_6_framework_continuity_pack.js +0 -81
  252. package/lib/phase_6_framework_runtime_pack.js +0 -68
  253. package/lib/phase_6_freeze_baseline_pack.js +0 -68
  254. package/lib/phase_6_freeze_review_pack.js +0 -65
  255. package/lib/phase_6_gate_pack.js +0 -59
  256. package/lib/phase_6_langchain_runtime_pack.js +0 -72
  257. package/lib/phase_6_langgraph_runtime_pack.js +0 -72
  258. package/lib/phase_6_semantic_kernel_runtime_pack.js +0 -72
  259. package/lib/phase_7_closeout_pack.js +0 -45
  260. package/lib/phase_7_completion_pack.js +0 -85
  261. package/lib/phase_7_decision_record_pack.js +0 -53
  262. package/lib/phase_7_decision_resolution_pack.js +0 -53
  263. package/lib/phase_7_event_system_continuity_pack.js +0 -89
  264. package/lib/phase_7_event_system_pack.js +0 -76
  265. package/lib/phase_7_freeze_baseline_pack.js +0 -74
  266. package/lib/phase_7_freeze_review_pack.js +0 -65
  267. package/lib/phase_7_gate_pack.js +0 -58
  268. package/lib/phase_7_kafka_runtime_pack.js +0 -74
  269. package/lib/phase_7_mqtt_runtime_pack.js +0 -74
  270. package/lib/phase_7_nats_runtime_pack.js +0 -74
  271. package/lib/phase_7_webhook_event_bus_runtime_pack.js +0 -74
  272. package/lib/phase_8_closeout_pack.js +0 -46
  273. package/lib/phase_8_completion_pack.js +0 -82
  274. package/lib/phase_8_decision_record_pack.js +0 -54
  275. package/lib/phase_8_decision_resolution_pack.js +0 -53
  276. package/lib/phase_8_external_receipt_import_runtime_pack.js +0 -74
  277. package/lib/phase_8_external_result_import_runtime_pack.js +0 -74
  278. package/lib/phase_8_freeze_baseline_pack.js +0 -71
  279. package/lib/phase_8_freeze_review_pack.js +0 -64
  280. package/lib/phase_8_gate_pack.js +0 -58
  281. package/lib/phase_8_proof_bridge_continuity_pack.js +0 -86
  282. package/lib/phase_8_proof_bridges_pack.js +0 -72
  283. package/lib/phase_8_proof_bundle_normalization_runtime_pack.js +0 -74
  284. package/lib/phase_9_closeout_pack.js +0 -46
  285. package/lib/phase_9_completion_pack.js +0 -82
  286. package/lib/phase_9_custody_refs_runtime_pack.js +0 -74
  287. package/lib/phase_9_decision_record_pack.js +0 -54
  288. package/lib/phase_9_decision_resolution_pack.js +0 -53
  289. package/lib/phase_9_freeze_baseline_pack.js +0 -71
  290. package/lib/phase_9_freeze_review_pack.js +0 -64
  291. package/lib/phase_9_gate_pack.js +0 -58
  292. package/lib/phase_9_operator_accounting_bridges_runtime_pack.js +0 -74
  293. package/lib/phase_9_treasury_connectivity_pack.js +0 -72
  294. package/lib/phase_9_treasury_continuity_pack.js +0 -86
  295. package/lib/phase_9_treasury_destinations_runtime_pack.js +0 -74
  296. package/lib/phase_program_pack.js +0 -120
  297. package/lib/pricing_optimization_contract.js +0 -775
  298. package/lib/protocol_lane_contract.js +0 -117
  299. package/lib/provenance_lane_contract.js +0 -54
  300. package/lib/provider_lane_contract.js +0 -240
  301. package/lib/provider_network_contract.js +0 -149
  302. package/lib/provider_payout_execution.js +0 -155
  303. package/lib/provider_registry.js +0 -852
  304. package/lib/provider_runtime_journey_contract.js +0 -183
  305. package/lib/public_surface_policy_contract.js +0 -111
  306. package/lib/publish_plan.js +0 -51
  307. package/lib/rate_limiter.js +0 -81
  308. package/lib/record_queries.js +0 -48
  309. package/lib/release_candidate.js +0 -50
  310. package/lib/release_center.js +0 -1093
  311. package/lib/release_history.js +0 -205
  312. package/lib/release_manifest.js +0 -113
  313. package/lib/release_pack.js +0 -453
  314. package/lib/request_rate_limit.js +0 -144
  315. package/lib/resource_views.js +0 -31
  316. package/lib/revenue_launch_path_contract.js +0 -326
  317. package/lib/route_matchers.js +0 -34
  318. package/lib/route_params.js +0 -19
  319. package/lib/runtime_bridge.js +0 -124
  320. package/lib/runtime_operations_worker.js +0 -282
  321. package/lib/runtime_state_store.js +0 -495
  322. package/lib/settlement_bsv_live.js +0 -600
  323. package/lib/settlement_bsv_teranode.js +0 -117
  324. package/lib/settlement_lane_contract.js +0 -111
  325. package/lib/shared_signals_lane_contract.js +0 -54
  326. package/lib/signed_audit_provenance_contract.js +0 -83
  327. package/lib/soft_launch_pack.js +0 -78
  328. package/lib/stablecoin_lane_contract.js +0 -76
  329. package/lib/stripe_mpp_lane_contract.js +0 -96
  330. package/lib/stripe_mpp_payment_front.js +0 -258
  331. package/lib/telemetry_lane_contract.js +0 -54
  332. package/lib/treasury_destinations_contract.js +0 -764
  333. package/lib/treasury_egress_policy_contract.js +0 -91
  334. package/lib/treasury_lane_contract.js +0 -84
  335. package/lib/trust_portability_boundary_contract.js +0 -72
  336. package/lib/x402_facilitator.js +0 -198
  337. package/lib/x402_lane_contract.js +0 -136
  338. package/lib/x402_settlement_recovery.js +0 -175
  339. package/scripts/buyer_events_daily_report.js +0 -79
  340. package/scripts/registry_cli.js +0 -275
  341. package/scripts/state_backup_offsite.js +0 -196
  342. package/scripts/verify_a2a_rpc.js +0 -131
  343. package/scripts/verify_adapters.js +0 -554
  344. package/scripts/verify_agent_identity.js +0 -153
  345. package/scripts/verify_all.js +0 -4963
  346. package/scripts/verify_bolt_adapter.js +0 -128
  347. package/scripts/verify_buyer_event_log.js +0 -128
  348. package/scripts/verify_buyer_safety.js +0 -141
  349. package/scripts/verify_cdp_facilitator.js +0 -110
  350. package/scripts/verify_checkout_processor.js +0 -109
  351. package/scripts/verify_commerce_bridge.js +0 -177
  352. package/scripts/verify_control_plane_contracts.js +0 -34
  353. package/scripts/verify_control_plane_routes.js +0 -70
  354. package/scripts/verify_delivery_summary.js +0 -112
  355. package/scripts/verify_examples.js +0 -19
  356. package/scripts/verify_execution_dedupe.js +0 -189
  357. package/scripts/verify_execution_surfacing.js +0 -76
  358. package/scripts/verify_external_execution_retry.js +0 -140
  359. package/scripts/verify_final_activation.js +0 -191
  360. package/scripts/verify_first_run_conversions.js +0 -81
  361. package/scripts/verify_framework_provider_promotion.js +0 -152
  362. package/scripts/verify_full_catalog.js +0 -174
  363. package/scripts/verify_integrations.js +0 -620
  364. package/scripts/verify_l402_adapter.js +0 -86
  365. package/scripts/verify_lifecycle_continuity.js +0 -96
  366. package/scripts/verify_lifecycle_spend_binding.js +0 -88
  367. package/scripts/verify_market_lane_depth.js +0 -94
  368. package/scripts/verify_market_lane_promotion.js +0 -103
  369. package/scripts/verify_market_lane_traces.js +0 -98
  370. package/scripts/verify_market_lanes.js +0 -102
  371. package/scripts/verify_mpp_adapter.js +0 -128
  372. package/scripts/verify_operator_observability_boundary.js +0 -83
  373. package/scripts/verify_pricing_experiment_plan.js +0 -124
  374. package/scripts/verify_production_readiness.js +0 -268
  375. package/scripts/verify_provider_network.js +0 -819
  376. package/scripts/verify_provider_runtime_breadth.js +0 -109
  377. package/scripts/verify_provider_runtime_journeys.js +0 -111
  378. package/scripts/verify_rate_limiter.js +0 -52
  379. package/scripts/verify_refund_credit.js +0 -106
  380. package/scripts/verify_revenue_launch_paths.js +0 -105
  381. package/scripts/verify_runtime_durability.js +0 -52
  382. package/scripts/verify_runtime_state_guard.js +0 -117
  383. package/scripts/verify_service.js +0 -15421
  384. package/scripts/verify_settlement.js +0 -116
  385. package/scripts/verify_tooling.js +0 -1412
  386. package/scripts/verify_treasury_public_boundary.js +0 -97
  387. package/scripts/verify_verify_execute_settle.js +0 -209
  388. package/scripts/verify_x402_facilitator.js +0 -307
  389. package/scripts/verify_x402_settlement_recovery.js +0 -153
  390. package/server.js +0 -12245
@@ -0,0 +1,418 @@
1
+ "use strict";
2
+
3
+ // Offline verification of the xytara client package. Node built-ins only; no network.
4
+ //
5
+ // 1. The package surface: CommerceClient, the receipt verification API, the x402 header helpers,
6
+ // the hosted endpoints and the package version.
7
+ // 2. Signed delivery receipts: a receipt built in the documented canonical form and signed with an
8
+ // Ed25519 key generated here verifies; tampered, stripped, unsigned and wrong-key copies do not.
9
+ // 3. The paid command path against a local stub of the hosted runtime: discover -> 402 challenge
10
+ // with x402 accepts -> pay with an x402 payment header -> 200 with the result, the settlement
11
+ // response and a signed delivery receipt that verifies against the stub's published keys.
12
+ // 4. The CLIs start: `xytara start-here`, `xytara-run --help`, `xytara first-run --json --offline`,
13
+ // and `xytara-run --quote-only` against the stub.
14
+
15
+ const assert = require("assert");
16
+ const crypto = require("crypto");
17
+ const fs = require("fs");
18
+ const http = require("http");
19
+ const path = require("path");
20
+ const { spawn, spawnSync } = require("child_process");
21
+
22
+ const PACKAGE_DIR = path.resolve(__dirname, "..");
23
+ const packageJson = JSON.parse(fs.readFileSync(path.join(PACKAGE_DIR, "package.json"), "utf8"));
24
+ const client = require(path.join(PACKAGE_DIR, "client.js"));
25
+ const {
26
+ CommerceClient,
27
+ RECEIPT_VERSION,
28
+ canonicalize,
29
+ hashCanonical,
30
+ keyRef,
31
+ verifyDeliveryReceipt,
32
+ verificationRecipe,
33
+ encodeX402PaymentHeader,
34
+ decodeX402Header,
35
+ summarizeCommandResultPayload,
36
+ endpoints,
37
+ version
38
+ } = client;
39
+
40
+ const checks = [];
41
+ function check(name, fn) {
42
+ fn();
43
+ checks.push(name);
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------------------------
47
+ // Receipt issuing, as the hosted runtime does it (kept in-test: the client never issues receipts).
48
+ function signReceipt(body, signer) {
49
+ const unsigned = {
50
+ ...body,
51
+ v: RECEIPT_VERSION,
52
+ hashing: { algorithm: "sha256", canonicalization: "JCS (RFC 8785)" },
53
+ signing: {
54
+ canonicalization: "JCS (RFC 8785) of the receipt without `sig`",
55
+ suite: [signer.alg],
56
+ kids: [signer.kid],
57
+ policy: "every_listed_signature_must_verify"
58
+ }
59
+ };
60
+ const signedBytes = Buffer.from(canonicalize(unsigned), "utf8");
61
+ return {
62
+ ...unsigned,
63
+ sig: {
64
+ state: "signed",
65
+ signatures: [{ alg: signer.alg, kid: signer.kid, value: crypto.sign(null, signedBytes, signer.privateKey).toString("base64") }]
66
+ }
67
+ };
68
+ }
69
+
70
+ function makeSigner() {
71
+ const { privateKey, publicKey } = crypto.generateKeyPairSync("ed25519");
72
+ const kid = keyRef(publicKey);
73
+ return {
74
+ alg: "EdDSA",
75
+ kid,
76
+ privateKey,
77
+ publicKey,
78
+ trustedKey: { kid, alg: "EdDSA", public_key_spki_der_base64: publicKey.export({ type: "spki", format: "der" }).toString("base64") }
79
+ };
80
+ }
81
+
82
+ // ---------------------------------------------------------------------------------------------
83
+ // A local stub of the hosted runtime's buyer-facing routes (x402 facilitator lane). It plays the
84
+ // facilitator too: any well-formed x402 v2 payment that matches the advertised accepts settles.
85
+ const ACCEPTS = [{
86
+ scheme: "exact",
87
+ network: "eip155:8453",
88
+ asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
89
+ amount: "10000",
90
+ payTo: "0x" + "ab".repeat(20),
91
+ maxTimeoutSeconds: 60,
92
+ extra: { name: "USD Coin", version: "2" }
93
+ }];
94
+ const PAYER = "0x" + "11".repeat(20);
95
+ const SETTLEMENT_TX = "0x" + "5e".repeat(32);
96
+
97
+ function readJsonBody(request) {
98
+ return new Promise((resolve) => {
99
+ const chunks = [];
100
+ request.on("data", (chunk) => chunks.push(chunk));
101
+ request.on("end", () => {
102
+ try {
103
+ resolve(JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}"));
104
+ } catch (_) {
105
+ resolve({});
106
+ }
107
+ });
108
+ });
109
+ }
110
+
111
+ function sendJson(response, status, payload, headers) {
112
+ const text = JSON.stringify(payload);
113
+ response.writeHead(status, { "content-type": "application/json", "content-length": Buffer.byteLength(text), ...(headers || {}) });
114
+ response.end(text);
115
+ }
116
+
117
+ function startStubRuntime(signer) {
118
+ const quotes = new Map();
119
+ const keys = [signer.trustedKey];
120
+ const toolOutput = (body) => ({ summary: `Summary of: ${body && body.arguments && body.arguments.text ? body.arguments.text : ""}`.slice(0, 120) });
121
+
122
+ const server = http.createServer(async (request, response) => {
123
+ const url = new URL(request.url, "http://127.0.0.1");
124
+ if (request.method === "GET" && url.pathname === "/health") return sendJson(response, 200, { ok: true, status: "ok" });
125
+ if (request.method === "GET" && url.pathname === "/v1/catalog") {
126
+ return sendJson(response, 200, {
127
+ ok: true,
128
+ tasks: [{ task_ref: "adapter.mcp.invoke", category: "mcp", description: "Invoke a tool on the pay-per-call MCP server", price_minor: 1, currency: "USD_CENTS" }],
129
+ workflows: []
130
+ });
131
+ }
132
+ if (request.method === "GET" && url.pathname === "/.well-known/delivery-receipt-keys") {
133
+ return sendJson(response, 200, {
134
+ ok: true,
135
+ issuer: "xytara-runtime",
136
+ receipt_version: RECEIPT_VERSION,
137
+ signing_state: "signing",
138
+ suite: ["EdDSA"],
139
+ keys,
140
+ verification: verificationRecipe("/.well-known/delivery-receipt-keys")
141
+ });
142
+ }
143
+ if (request.method === "POST" && url.pathname === "/v1/delivery-receipts/verify") {
144
+ const body = await readJsonBody(request);
145
+ const receipt = body && body.receipt && typeof body.receipt === "object" ? body.receipt : body;
146
+ return sendJson(response, 200, { ok: true, ...verifyDeliveryReceipt(receipt, keys), issuer_expected: "xytara-runtime" });
147
+ }
148
+ if (request.method === "POST" && url.pathname === "/x402/commands/execute") {
149
+ const body = await readJsonBody(request);
150
+ if (!body.account_id || body.task_ref !== "adapter.mcp.invoke") return sendJson(response, 400, { ok: false, reason: "task_not_executable" });
151
+ const header = request.headers["payment-signature"];
152
+ if (!header) {
153
+ const quoteId = `quote_${crypto.randomBytes(6).toString("hex")}`;
154
+ quotes.set(quoteId, body);
155
+ const paymentRequired = {
156
+ x402Version: 2,
157
+ scheme: "exact",
158
+ resource: { url: `http://127.0.0.1:${server.address().port}/x402/commands/execute`, mimeType: "application/json", description: "naxytra runtime paid execution" },
159
+ accepts: ACCEPTS,
160
+ price: ACCEPTS.map((accept) => ({ network: accept.network, asset: accept.asset, amount: accept.amount, usd: "0.01" })),
161
+ quote: { quote_id: quoteId, status: "quoted", task_refs: ["adapter.mcp.invoke"], amount_minor: 1, currency: "USD_CENTS", payment_protocol: "x402", expires_at_iso: new Date(Date.now() + 60000).toISOString() }
162
+ };
163
+ return sendJson(response, 402, { ok: false, payment_required: paymentRequired }, {
164
+ "PAYMENT-REQUIRED": Buffer.from(JSON.stringify(paymentRequired), "utf8").toString("base64url"),
165
+ "WWW-Authenticate": "x402"
166
+ });
167
+ }
168
+ const payment = decodeX402Header(header);
169
+ if (!payment || Number(payment.x402Version) !== 2 || !payment.accepted || !payment.payload) {
170
+ return sendJson(response, 402, { ok: false, reason: "payment_signature_invalid" });
171
+ }
172
+ const accepted = ACCEPTS.find((entry) => entry.network === payment.accepted.network && entry.asset === payment.accepted.asset && entry.payTo === payment.accepted.payTo && String(entry.amount) === String(payment.accepted.amount));
173
+ if (!accepted) return sendJson(response, 402, { ok: false, reason: "payment_requirements_mismatch" });
174
+ if (!payment.payload.signature || !payment.payload.authorization) return sendJson(response, 402, { ok: false, reason: "payment_verification_failed" });
175
+ if (!quotes.has(body.quote_id)) return sendJson(response, 402, { ok: false, reason: "quote_not_found" });
176
+ const output = toolOutput(body.body);
177
+ const transactionId = `txn_${crypto.randomBytes(6).toString("hex")}`;
178
+ const runtimeReceiptId = `rcpt_${crypto.randomBytes(6).toString("hex")}`;
179
+ const settlement = { success: true, transaction: SETTLEMENT_TX, network: accepted.network, payer: PAYER };
180
+ const deliveryReceipt = signReceipt({
181
+ receipt_id: `drcpt_${runtimeReceiptId.replace(/^rcpt_/, "")}`,
182
+ issuer: "xytara-runtime",
183
+ issued_at: new Date().toISOString(),
184
+ call: { quote_id: body.quote_id, transaction_id: transactionId, runtime_receipt_id: runtimeReceiptId, task_ref: body.task_ref, tool_name: body.body && body.body.tool_name ? body.body.tool_name : null },
185
+ payment: { protocol: "x402", scheme: "exact", network: accepted.network, asset: accepted.asset, amount: accepted.amount, payer: PAYER, pay_to: accepted.payTo, settlement_tx: SETTLEMENT_TX, settled: true },
186
+ delivery: {
187
+ status: "completed",
188
+ provider_id: null,
189
+ routing: "runtime_native",
190
+ execution_target_id: null,
191
+ request_sha256: hashCanonical(body.body || {}),
192
+ request_hash_input: "the request `body` object (e.g. { tool_name, arguments })",
193
+ output_sha256: hashCanonical(output),
194
+ output_hash_input: "command.deliverables[0].output_payload (null when the task returns no payload)",
195
+ completed_at: new Date().toISOString()
196
+ }
197
+ }, signer);
198
+ return sendJson(response, 200, {
199
+ ok: true,
200
+ transaction: { transaction_id: transactionId, quote_id: body.quote_id, status: "completed", payment: { verification_mode: "x402_facilitator" } },
201
+ receipt: { receipt_id: runtimeReceiptId, settlement: { rail: "x402", mode: "x402_facilitator", txid: SETTLEMENT_TX, network: accepted.network, pay_to: accepted.payTo, status: "settled" } },
202
+ command: { deliverables: [{ task_ref: body.task_ref, output_payload: output }] },
203
+ delivery_receipt: deliveryReceipt
204
+ }, { "PAYMENT-RESPONSE": Buffer.from(JSON.stringify(settlement), "utf8").toString("base64") });
205
+ }
206
+ sendJson(response, 404, { ok: false, reason: "not_found" });
207
+ });
208
+ return new Promise((resolve) => server.listen(0, "127.0.0.1", () => resolve({ server, baseUrl: `http://127.0.0.1:${server.address().port}` })));
209
+ }
210
+
211
+ // ---------------------------------------------------------------------------------------------
212
+ function runCli(args, options) {
213
+ return spawnSync(process.execPath, args, { cwd: PACKAGE_DIR, encoding: "utf8", ...(options || {}) });
214
+ }
215
+
216
+ // Non-blocking variant for a CLI that must talk to the stub runtime served by THIS process
217
+ // (spawnSync would block the event loop and deadlock the stub).
218
+ function runCliAsync(args) {
219
+ return new Promise((resolve, reject) => {
220
+ const child = spawn(process.execPath, args, { cwd: PACKAGE_DIR });
221
+ let stdout = "";
222
+ let stderr = "";
223
+ child.stdout.on("data", (chunk) => { stdout += chunk; });
224
+ child.stderr.on("data", (chunk) => { stderr += chunk; });
225
+ child.on("error", reject);
226
+ child.on("close", (status) => resolve({ status, stdout, stderr }));
227
+ });
228
+ }
229
+
230
+ async function main() {
231
+ check("package_surface", () => {
232
+ assert.strictEqual(typeof CommerceClient, "function", "CommerceClient export missing");
233
+ for (const name of ["verifyDeliveryReceipt", "canonicalize", "hashCanonical", "keyRef", "verificationRecipe", "encodeX402PaymentHeader", "decodeX402Header", "summarizeCommandResultPayload", "summarizeCatalogPayload", "summarizeReceiptPayload"]) {
234
+ assert.strictEqual(typeof client[name], "function", `${name} export missing`);
235
+ }
236
+ assert.strictEqual(RECEIPT_VERSION, "naxytra-delivery-receipt/1", "receipt version mismatch");
237
+ assert.strictEqual(endpoints.runtime, "https://xytara.onrender.com", "runtime endpoint mismatch");
238
+ assert.strictEqual(endpoints.mcp, "https://xytara-mcp-executor.onrender.com/mcp", "mcp endpoint mismatch");
239
+ assert.strictEqual(endpoints.website, "https://www.naxytra.com", "website endpoint mismatch");
240
+ assert.strictEqual(version, packageJson.version, "version export must come from package.json");
241
+ assert.strictEqual(require(path.join(PACKAGE_DIR, "client.js")), client, "client entry is a stable singleton");
242
+ });
243
+
244
+ check("canonical_form", () => {
245
+ assert.strictEqual(canonicalize({ b: 1, a: [1, { d: 2, c: 3 }], u: undefined, n: null }), "{\"a\":[1,{\"c\":3,\"d\":2}],\"b\":1,\"n\":null}", "JCS key ordering / undefined handling");
246
+ assert.strictEqual(hashCanonical({ a: 1, b: "x" }), hashCanonical({ b: "x", a: 1 }), "hashCanonical must be key-order independent");
247
+ assert.strictEqual(hashCanonical({ a: 1 }), crypto.createHash("sha256").update("{\"a\":1}").digest("hex"), "hashCanonical is sha256 over JCS");
248
+ const signer = makeSigner();
249
+ assert.ok(/^ed25519-spki-sha256:[0-9a-f]{64}$/.test(signer.kid), "key ref format");
250
+ const recipe = verificationRecipe("/.well-known/delivery-receipt-keys");
251
+ assert.strictEqual(recipe.keys, "/.well-known/delivery-receipt-keys", "recipe keys url");
252
+ assert.strictEqual(recipe.steps.length, 4, "recipe has four steps");
253
+ });
254
+
255
+ const signer = makeSigner();
256
+ const genuine = signReceipt({
257
+ receipt_id: "drcpt_test",
258
+ issuer: "xytara-runtime",
259
+ issued_at: "2026-01-01T00:00:00.000Z",
260
+ call: { quote_id: "quote_test", transaction_id: "txn_test", runtime_receipt_id: "rcpt_test", task_ref: "adapter.mcp.invoke", tool_name: "summarize" },
261
+ payment: { protocol: "x402", scheme: "exact", network: "eip155:8453", asset: ACCEPTS[0].asset, amount: "10000", payer: PAYER, pay_to: ACCEPTS[0].payTo, settlement_tx: SETTLEMENT_TX, settled: true },
262
+ delivery: { status: "completed", routing: "runtime_native", request_sha256: hashCanonical({ tool_name: "summarize", arguments: { text: "hi" } }), output_sha256: hashCanonical({ summary: "hi" }), completed_at: "2026-01-01T00:00:01.000Z" }
263
+ }, signer);
264
+
265
+ check("receipt_offline_verification", () => {
266
+ const result = verifyDeliveryReceipt(genuine, [signer.trustedKey]);
267
+ assert.strictEqual(result.valid, true, `genuine receipt must verify: ${JSON.stringify(result)}`);
268
+ assert.strictEqual(result.signatures[0].alg, "EdDSA", "signature algorithm");
269
+ assert.strictEqual(result.signed_bytes_sha256.length, 64, "signed bytes hash reported");
270
+ const reordered = JSON.parse(JSON.stringify({ sig: genuine.sig, delivery: genuine.delivery, ...genuine }));
271
+ assert.strictEqual(verifyDeliveryReceipt(reordered, [signer.trustedKey]).valid, true, "key order must not matter (JCS)");
272
+ const tampered = JSON.parse(JSON.stringify(genuine));
273
+ tampered.payment.amount = "1";
274
+ assert.strictEqual(verifyDeliveryReceipt(tampered, [signer.trustedKey]).valid, false, "tampered receipt must fail");
275
+ const stripped = JSON.parse(JSON.stringify(genuine));
276
+ stripped.sig.signatures = [];
277
+ assert.strictEqual(verifyDeliveryReceipt(stripped, [signer.trustedKey]).signatures[0].reason, "signature_missing_for_signed_suite", "stripped signature must fail");
278
+ const other = makeSigner();
279
+ assert.strictEqual(verifyDeliveryReceipt(genuine, [other.trustedKey]).signatures[0].reason, "kid_not_in_trusted_key_set", "untrusted kid must fail");
280
+ const unsigned = { ...genuine, sig: { state: "unsigned_signing_key_not_configured", signatures: [] } };
281
+ assert.strictEqual(verifyDeliveryReceipt(unsigned, [signer.trustedKey]).reason, "receipt_unsigned", "unsigned receipt must fail");
282
+ assert.strictEqual(verifyDeliveryReceipt({ ...genuine, v: "other/1" }, [signer.trustedKey]).reason, "unsupported_receipt_version", "unknown version must fail");
283
+ assert.strictEqual(verifyDeliveryReceipt(null, [signer.trustedKey]).reason, "receipt_required", "missing receipt must fail");
284
+ });
285
+
286
+ check("x402_header_helpers", () => {
287
+ const authorization = { from: PAYER, to: ACCEPTS[0].payTo, value: ACCEPTS[0].amount, validAfter: "0", validBefore: "9999999999", nonce: "0x" + "00".repeat(32) };
288
+ const header = encodeX402PaymentHeader({ accepted: ACCEPTS[0], authorization, signature: "0x" + "11".repeat(65) });
289
+ const decoded = decodeX402Header(header);
290
+ assert.strictEqual(decoded.x402Version, 2, "x402 v2");
291
+ assert.deepStrictEqual(decoded.accepted, ACCEPTS[0], "accepted roundtrip");
292
+ assert.deepStrictEqual(decoded.payload.authorization, authorization, "authorization roundtrip");
293
+ assert.strictEqual(decodeX402Header(Buffer.from("{\"a\":1}").toString("base64url")).a, 1, "base64url decodes too");
294
+ assert.strictEqual(decodeX402Header("not base64 json"), null, "garbage decodes to null");
295
+ assert.throws(() => encodeX402PaymentHeader({ accepted: ACCEPTS[0], authorization }), /signature/, "signature required");
296
+ });
297
+
298
+ const issuer = makeSigner();
299
+ const { server, baseUrl } = await startStubRuntime(issuer);
300
+ let paidResult = null;
301
+ try {
302
+ const runtime = new CommerceClient({ baseUrl, accountId: "acct_client_check" });
303
+ const payload = { command: "mcp.invoke:summarize", task_ref: "adapter.mcp.invoke", body: { tool_name: "summarize", arguments: { text: "Summarize the naxytra first-run path in one sentence." } } };
304
+
305
+ await (async () => {
306
+ const health = await runtime.getHealth();
307
+ assert.strictEqual(health.ok, true, "health");
308
+ const task = await runtime.getTask("adapter.mcp.invoke");
309
+ assert.ok(task && task.task_ref === "adapter.mcp.invoke", "catalog discovery");
310
+ const tasks = await runtime.listTasks();
311
+ assert.strictEqual(tasks.length, 1, "listTasks");
312
+ checks.push("runtime_discover");
313
+ })();
314
+
315
+ const quote = await runtime.previewExecutionQuote(payload, { instant: true });
316
+ assert.strictEqual(quote.payment_required, true, "quote preview must report payment_required");
317
+ assert.strictEqual(quote.x402Version, 2, "challenge is x402 v2");
318
+ assert.strictEqual(quote.accepts[0].amount, "10000", "challenge advertises the price");
319
+ assert.ok(quote.quote && quote.quote.quote_id, "challenge carries a quote id");
320
+ const raw = await runtime.postJson("/x402/commands/execute", {}, { account_id: "acct_client_check", ...payload });
321
+ assert.strictEqual(raw.status, 402, "raw challenge status");
322
+ assert.strictEqual(decodeX402Header(raw.headers.get("payment-required")).accepts[0].payTo, ACCEPTS[0].payTo, "PAYMENT-REQUIRED header decodes");
323
+ checks.push("runtime_402_challenge");
324
+
325
+ const accepted = quote.accepts[0];
326
+ const authorization = { from: PAYER, to: accepted.payTo, value: accepted.amount, validAfter: "0", validBefore: String(Math.floor(Date.now() / 1000) + 600), nonce: "0x" + crypto.randomBytes(32).toString("hex") };
327
+ const paymentHeader = encodeX402PaymentHeader({ accepted, authorization, signature: "0x" + crypto.randomBytes(65).toString("hex") });
328
+ const paid = await runtime.postJson("/x402/commands/execute", { "payment-signature": paymentHeader }, { account_id: "acct_client_check", ...payload, quote_id: quote.quote.quote_id });
329
+ assert.strictEqual(paid.status, 200, `paid call must succeed: ${JSON.stringify(paid.data)}`);
330
+ paidResult = paid.data;
331
+ assert.strictEqual(paid.data.transaction.status, "completed", "transaction completed");
332
+ assert.strictEqual(paid.data.command.deliverables[0].output_payload.summary.startsWith("Summary of:"), true, "deliverable returned");
333
+ const settlement = decodeX402Header(paid.headers.get("payment-response"));
334
+ assert.strictEqual(settlement.success, true, "PAYMENT-RESPONSE decodes to the settlement");
335
+ assert.strictEqual(settlement.transaction, SETTLEMENT_TX, "settlement tx");
336
+ const summary = summarizeCommandResultPayload(paid.data);
337
+ assert.ok(summary && typeof summary === "object", "summarizeCommandResultPayload");
338
+ checks.push("runtime_paid_execute");
339
+
340
+ const mismatched = await runtime.postJson("/x402/commands/execute", { "payment-signature": encodeX402PaymentHeader({ accepted: { ...accepted, amount: "1" }, authorization, signature: "0x00" }) }, { account_id: "acct_client_check", ...payload, quote_id: quote.quote.quote_id });
341
+ assert.strictEqual(mismatched.status, 402, "underpayment rejected");
342
+ assert.strictEqual(mismatched.data.reason, "payment_requirements_mismatch", "underpayment reason");
343
+ checks.push("runtime_underpayment_rejected");
344
+
345
+ const receipt = paid.data.delivery_receipt;
346
+ assert.strictEqual(receipt.v, RECEIPT_VERSION, "receipt version");
347
+ assert.strictEqual(receipt.payment.settlement_tx, SETTLEMENT_TX, "receipt binds the settlement tx");
348
+ assert.strictEqual(receipt.call.quote_id, quote.quote.quote_id, "receipt binds the quote");
349
+ assert.strictEqual(receipt.delivery.request_sha256, hashCanonical(payload.body), "request hash recomputes from the request body");
350
+ assert.strictEqual(receipt.delivery.output_sha256, hashCanonical(paid.data.command.deliverables[0].output_payload), "output hash recomputes from the deliverable");
351
+ const keys = await runtime.getJson("/.well-known/delivery-receipt-keys");
352
+ assert.strictEqual(keys.data.signing_state, "signing", "keys endpoint");
353
+ assert.strictEqual(verifyDeliveryReceipt(receipt, keys.data.keys).valid, true, "receipt verifies against the published keys");
354
+ const tamperedReceipt = JSON.parse(JSON.stringify(receipt));
355
+ tamperedReceipt.delivery.output_sha256 = hashCanonical({ summary: "something else" });
356
+ assert.strictEqual(verifyDeliveryReceipt(tamperedReceipt, keys.data.keys).valid, false, "tampered receipt rejected offline");
357
+ const remote = await runtime.postJson("/v1/delivery-receipts/verify", {}, { receipt });
358
+ assert.strictEqual(remote.data.valid, true, "remote verify endpoint accepts the receipt");
359
+ assert.strictEqual((await runtime.postJson("/v1/delivery-receipts/verify", {}, { receipt: tamperedReceipt })).data.valid, false, "remote verify rejects the tampered receipt");
360
+ checks.push("runtime_receipt_verification");
361
+
362
+ const quoteOnly = await runCliAsync([path.join(PACKAGE_DIR, "bin", "xytara-run.js"), "--url", baseUrl, "--account", "acct_client_check", "--task", "adapter.mcp.invoke", "--command", "mcp.invoke:summarize", "--body-json", JSON.stringify(payload.body), "--quote-only"]);
363
+ assert.strictEqual(quoteOnly.status, 0, `xytara-run --quote-only failed: ${quoteOnly.stderr}`);
364
+ const quoteOutput = JSON.parse(quoteOnly.stdout);
365
+ assert.strictEqual(quoteOutput.payment_required.accepts[0].amount, "10000", "xytara-run --quote-only returns the challenge");
366
+ checks.push("cli_run_quote_only");
367
+ } finally {
368
+ server.close();
369
+ }
370
+
371
+ check("cli_start_here", () => {
372
+ const result = runCli([path.join(PACKAGE_DIR, "bin", "xytara.js"), "start-here"]);
373
+ assert.strictEqual(result.status, 0, `xytara start-here failed: ${result.stderr}`);
374
+ assert.ok(result.stdout.includes("quote -> pay/credits -> execute -> prove"), "start-here spine line");
375
+ assert.ok(result.stdout.includes("xytara"), "start-here names the package");
376
+ assert.ok(result.stdout.includes("https://www.naxytra.com"), "start-here links the website");
377
+ });
378
+
379
+ check("cli_run_help", () => {
380
+ const result = runCli([path.join(PACKAGE_DIR, "bin", "xytara-run.js"), "--help"]);
381
+ assert.strictEqual(result.status, 0, "xytara-run --help failed");
382
+ assert.ok(result.stdout.includes("Usage: xytara-run"), "xytara-run usage text");
383
+ const viaDispatcher = runCli([path.join(PACKAGE_DIR, "bin", "xytara.js"), "run", "--help"]);
384
+ assert.strictEqual(viaDispatcher.status, 0, "xytara run --help failed");
385
+ assert.ok(viaDispatcher.stdout.includes("Usage: xytara-run"), "xytara run --help usage text");
386
+ });
387
+
388
+ check("cli_first_run_offline", () => {
389
+ const result = runCli([path.join(PACKAGE_DIR, "bin", "xytara.js"), "first-run", "--json", "--offline"]);
390
+ assert.strictEqual(result.status, 0, `xytara first-run --json --offline failed: ${result.stderr}`);
391
+ const guide = JSON.parse(result.stdout);
392
+ assert.strictEqual(guide.ok, true, "first-run guide ok");
393
+ assert.strictEqual(guide.product, "xytara", "first-run guide product");
394
+ assert.ok(String(guide.safe_quote_command).includes("--quote-only"), "first-run safe command is quote-only");
395
+ });
396
+
397
+ if (!fs.existsSync(path.join(PACKAGE_DIR, "bin", "xytara-release.js"))) {
398
+ check("cli_release_not_shipped", () => {
399
+ const result = runCli([path.join(PACKAGE_DIR, "bin", "xytara.js"), "release", "--summary"]);
400
+ assert.strictEqual(result.status, 2, "xytara release must exit 2 in the client package");
401
+ assert.ok(result.stderr.includes("not part of the xytara client package"), "xytara release notice");
402
+ });
403
+ }
404
+
405
+ console.log(JSON.stringify({
406
+ ok: true,
407
+ product: "xytara",
408
+ category: "xytara-client-verification",
409
+ version,
410
+ checks,
411
+ paid_receipt_id: paidResult && paidResult.delivery_receipt ? paidResult.delivery_receipt.receipt_id : null
412
+ }));
413
+ }
414
+
415
+ main().catch((error) => {
416
+ process.stderr.write(`${error && error.stack ? error.stack : error}\n`);
417
+ process.exitCode = 1;
418
+ });
@@ -1,23 +1,84 @@
1
1
  "use strict";
2
2
 
3
+ // Release-candidate gate for the xytara CLIENT package. Node built-ins only, so it runs both in
4
+ // the private repository checkout (prepublishOnly) and inside an installed node_modules/xytara.
5
+ //
6
+ // In-repo mode (server.js present next to package.json): the npm tarball must contain EXACTLY the
7
+ // thin client allowlist below — any extra file fails the gate — and package.json must point at
8
+ // the client entry and the client bins.
9
+ // Installed mode (no server.js): the installed package must carry nothing from the runtime side.
10
+ // Both modes run scripts/verify_client.js (offline client tests) and check RELEASE_NOTES.md.
11
+
3
12
  const assert = require("assert");
4
13
  const fs = require("fs");
5
14
  const path = require("path");
6
- const { execFileSync, execSync } = require("child_process");
7
- const packageJson = require("../package.json");
15
+ const { spawnSync } = require("child_process");
8
16
 
9
- function parsePackDryRun() {
10
- const output = execSync("npm pack --dry-run --json", {
11
- cwd: path.resolve(__dirname, ".."),
12
- encoding: "utf8"
13
- });
14
- const parsed = JSON.parse(output);
15
- return Array.isArray(parsed) ? parsed[0] : parsed;
17
+ const PACKAGE_DIR = path.resolve(__dirname, "..");
18
+ const packageJson = JSON.parse(fs.readFileSync(path.join(PACKAGE_DIR, "package.json"), "utf8"));
19
+
20
+ // The complete published surface (package.json is always added by npm).
21
+ const SHIPPED_FILES = [
22
+ "client.js",
23
+ "lib/commerce_client.js",
24
+ "lib/delivery_receipt_verify.js",
25
+ "bin/xytara.js",
26
+ "bin/xytara-run.js",
27
+ "bin/xytara-first-run.js",
28
+ "scripts/verify_release_candidate.js",
29
+ "scripts/verify_client.js",
30
+ "README.md",
31
+ "START_HERE.md",
32
+ "RELEASE_NOTES.md",
33
+ "LICENSE",
34
+ "NOTICE"
35
+ ];
36
+ const TARBALL_FILES = ["package.json", ...SHIPPED_FILES];
37
+ const SHIPPED_BINS = { xytara: "bin/xytara.js", "xytara-run": "bin/xytara-run.js" };
38
+
39
+ // Nothing from the hosted service may be present in an installed copy.
40
+ const FORBIDDEN_INSTALLED_PATHS = [
41
+ "server.js",
42
+ "index.js",
43
+ ".env.example",
44
+ "bin/xytara-release.js",
45
+ "fixtures",
46
+ "adapters",
47
+ "integrations",
48
+ "services",
49
+ "examples"
50
+ ];
51
+ const ALLOWED_DIR_CONTENTS = {
52
+ lib: ["commerce_client.js", "delivery_receipt_verify.js"],
53
+ bin: ["xytara.js", "xytara-run.js", "xytara-first-run.js"],
54
+ scripts: ["verify_release_candidate.js", "verify_client.js"]
55
+ };
56
+
57
+ function sorted(list) {
58
+ return list.slice().sort();
59
+ }
60
+
61
+ function isRepoCheckout() {
62
+ return fs.existsSync(path.join(PACKAGE_DIR, "server.js"));
63
+ }
64
+
65
+ function verifyManifest() {
66
+ assert.strictEqual(packageJson.name, "xytara", "package name mismatch");
67
+ assert.strictEqual(packageJson.main, "client.js", "package.json main must be the client entry (client.js)");
68
+ assert.deepStrictEqual(packageJson.bin, SHIPPED_BINS, "package.json bin must be exactly xytara and xytara-run");
69
+ assert.deepStrictEqual(sorted(packageJson.files || []), sorted(SHIPPED_FILES), "package.json files must equal the thin client allowlist");
70
+ assert.strictEqual(packageJson.license, "Apache-2.0", "client package license must stay Apache-2.0");
71
+ assert.strictEqual(packageJson.publishConfig && packageJson.publishConfig.access, "public", "publishConfig.access must be public");
72
+ assert.strictEqual(packageJson.scripts && packageJson.scripts.prepublishOnly, "npm run verify:release-candidate", "prepublishOnly must run this gate");
73
+ assert.strictEqual(packageJson.exports && packageJson.exports["."], "./client.js", "exports['.'] must resolve to client.js");
74
+ assert.strictEqual(packageJson.exports && packageJson.exports["./package.json"], "./package.json", "exports must keep ./package.json reachable");
75
+ for (const relative of SHIPPED_FILES) {
76
+ assert.strictEqual(fs.existsSync(path.join(PACKAGE_DIR, relative)), true, `shipped file missing on disk: ${relative}`);
77
+ }
16
78
  }
17
79
 
18
80
  function verifyReleaseNotes() {
19
- const notesPath = path.resolve(__dirname, "..", "RELEASE_NOTES.md");
20
- const notes = fs.readFileSync(notesPath, "utf8");
81
+ const notes = fs.readFileSync(path.join(PACKAGE_DIR, "RELEASE_NOTES.md"), "utf8");
21
82
  assert.strictEqual(
22
83
  /^#\s+xytara\s+\d+\.\d+\.\d+\s+Release Notes\s*$/m.test(notes),
23
84
  false,
@@ -26,7 +87,7 @@ function verifyReleaseNotes() {
26
87
  assert.strictEqual(
27
88
  notes.includes(`xytara\` ${packageJson.version}`),
28
89
  true,
29
- "RELEASE_NOTES.md must mention the current package version"
90
+ `RELEASE_NOTES.md must mention the current package version (${packageJson.version})`
30
91
  );
31
92
  const mentionedVersions = notes.match(/\b\d+\.\d+\.\d+\b/g) || [];
32
93
  assert.strictEqual(
@@ -36,46 +97,86 @@ function verifyReleaseNotes() {
36
97
  );
37
98
  }
38
99
 
39
- function main() {
40
- const releaseOutput = execFileSync(process.execPath, [
41
- path.resolve(__dirname, "..", "bin", "xytara-release.js"),
42
- "--candidate",
43
- "--summary"
44
- ], {
45
- cwd: path.resolve(__dirname, ".."),
46
- encoding: "utf8"
100
+ function parsePackDryRun() {
101
+ const result = spawnSync("npm pack --dry-run --json", {
102
+ cwd: PACKAGE_DIR,
103
+ encoding: "utf8",
104
+ shell: true,
105
+ maxBuffer: 16 * 1024 * 1024
47
106
  });
48
- const releaseCandidate = JSON.parse(releaseOutput);
49
- assert.strictEqual(releaseCandidate.product, "xytara", "release candidate product mismatch");
50
- assert.strictEqual(releaseCandidate.publish_access, "public", "release candidate publish access mismatch");
51
- assert.strictEqual(releaseCandidate.checklist_count >= 5, true, "release candidate checklist count mismatch");
52
- verifyReleaseNotes();
107
+ assert.strictEqual(result.status, 0, `npm pack --dry-run failed: ${result.stderr || result.stdout}`);
108
+ const parsed = JSON.parse(result.stdout);
109
+ return Array.isArray(parsed) ? parsed[0] : parsed;
110
+ }
53
111
 
112
+ function verifyTarball() {
54
113
  const dryRun = parsePackDryRun();
55
114
  assert.strictEqual(dryRun.name, packageJson.name, "npm pack dry-run name mismatch");
56
115
  assert.strictEqual(dryRun.version, packageJson.version, "npm pack dry-run version mismatch");
57
116
  assert.strictEqual(Array.isArray(dryRun.files), true, "npm pack dry-run file list missing");
58
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-run.js"), true, "npm pack dry-run missing xytara-run");
59
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-first-run.js"), true, "npm pack dry-run missing xytara-first-run");
60
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "bin/xytara-release.js"), true, "npm pack dry-run missing xytara-release");
61
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_release_candidate.js"), true, "npm pack dry-run missing release verifier script");
62
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion verifier script");
63
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_operator_observability_boundary.js"), true, "npm pack dry-run missing operator observability boundary verifier script");
64
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_pricing_experiment_plan.js"), true, "npm pack dry-run missing pricing experiment verifier script");
65
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_treasury_public_boundary.js"), true, "npm pack dry-run missing treasury public boundary verifier script");
66
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_full_catalog.js"), true, "npm pack dry-run missing full catalog verifier script");
67
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "scripts/verify_all.js"), true, "npm pack dry-run missing package verifier script");
68
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "lib/framework_provider_promotion.js"), true, "npm pack dry-run missing framework provider promotion pack");
69
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "README.md"), true, "npm pack dry-run missing README");
70
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "RELEASE_NOTES.md"), true, "npm pack dry-run missing release notes");
71
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "START_HERE.md"), true, "npm pack dry-run missing start-here");
72
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "SERVICE_CONTRACT.md"), true, "npm pack dry-run missing service contract");
73
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "OPERATOR_START_HERE.md"), false, "npm pack dry-run should not ship operator start-here");
74
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "OPERATIONS_RUNBOOK.md"), false, "npm pack dry-run should not ship operations runbook");
75
- assert.strictEqual(dryRun.files.some((entry) => entry.path === "PUBLISH_PLAN.md"), false, "npm pack dry-run should not ship publish plan");
76
- assert.strictEqual(dryRun.files.length >= 10, true, "npm pack dry-run file count too small");
117
+ const packed = sorted(dryRun.files.map((entry) => String(entry.path).replace(/\\/g, "/")));
118
+ const expected = sorted(TARBALL_FILES);
119
+ const extra = packed.filter((file) => !expected.includes(file));
120
+ const missing = expected.filter((file) => !packed.includes(file));
121
+ assert.deepStrictEqual(
122
+ { extra, missing },
123
+ { extra: [], missing: [] },
124
+ `npm tarball must contain exactly the thin client files (extra: ${JSON.stringify(extra)}, missing: ${JSON.stringify(missing)})`
125
+ );
126
+ return packed;
127
+ }
128
+
129
+ function verifyInstalledLayout() {
130
+ for (const relative of FORBIDDEN_INSTALLED_PATHS) {
131
+ assert.strictEqual(fs.existsSync(path.join(PACKAGE_DIR, relative)), false, `installed client package must not contain ${relative}`);
132
+ }
133
+ for (const [dir, allowed] of Object.entries(ALLOWED_DIR_CONTENTS)) {
134
+ const entries = fs.readdirSync(path.join(PACKAGE_DIR, dir));
135
+ const unexpected = entries.filter((entry) => !allowed.includes(entry));
136
+ assert.deepStrictEqual(unexpected, [], `installed client package carries unexpected files in ${dir}/: ${JSON.stringify(unexpected)}`);
137
+ }
138
+ }
77
139
 
78
- console.log("xytara verify:release-candidate passed");
140
+ function runClientVerification() {
141
+ const result = spawnSync(process.execPath, [path.join(__dirname, "verify_client.js")], {
142
+ cwd: PACKAGE_DIR,
143
+ stdio: ["ignore", "pipe", "inherit"],
144
+ encoding: "utf8"
145
+ });
146
+ assert.strictEqual(result.status, 0, "scripts/verify_client.js failed");
147
+ const lastLine = String(result.stdout || "").trim().split(/\r?\n/).pop();
148
+ let summary = null;
149
+ try {
150
+ summary = JSON.parse(lastLine);
151
+ } catch (_) {
152
+ summary = null;
153
+ }
154
+ assert.ok(summary && summary.ok === true, "verify_client.js did not report ok");
155
+ return summary;
156
+ }
157
+
158
+ function main() {
159
+ const mode = isRepoCheckout() ? "repo" : "installed";
160
+ verifyManifest();
161
+ verifyReleaseNotes();
162
+ let tarballFiles = null;
163
+ if (mode === "repo") {
164
+ tarballFiles = verifyTarball();
165
+ } else {
166
+ verifyInstalledLayout();
167
+ }
168
+ const clientSummary = runClientVerification();
169
+ console.log(JSON.stringify({
170
+ ok: true,
171
+ product: "xytara",
172
+ category: "xytara-release-candidate-verification",
173
+ mode,
174
+ version: packageJson.version,
175
+ main: packageJson.main,
176
+ bins: Object.keys(packageJson.bin),
177
+ tarball_file_count: tarballFiles ? tarballFiles.length : null,
178
+ client_checks: clientSummary.checks
179
+ }));
79
180
  }
80
181
 
81
182
  main();