xytara 3.1.0 → 3.1.2

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 (373) hide show
  1. package/.env.example +67 -58
  2. package/ADAPTER_START_HERE.md +56 -56
  3. package/CARRIED_HANDOFF_DEMO.md +60 -60
  4. package/EXAMPLE_PATHS.md +53 -53
  5. package/FINAL_CONTRACT.md +498 -498
  6. package/LICENSE +201 -201
  7. package/NOTICE +3 -3
  8. package/PARTNER_READY_PATH.md +71 -71
  9. package/PUBLIC_DEMO_SCRIPT.md +78 -78
  10. package/README.md +6 -1
  11. package/REAL_PAYMENT_SETUP.md +32 -3
  12. package/RELEASE_NOTES.md +14 -14
  13. package/SERVICE_CONTRACT.md +419 -419
  14. package/START_HERE.md +1 -1
  15. package/SUPABASE_RUNTIME_STATE_SETUP.md +61 -61
  16. package/TERMINOLOGY.md +50 -50
  17. package/WHY_XYTARA_XOONYA.md +63 -63
  18. package/XT1_EXECUTION_TRUTH_STANDARD.md +78 -78
  19. package/XYTARA_ADAPTER_PROTOCOL_TRUTH_MODEL.md +75 -75
  20. package/XYTARA_AUTONOMOUS_ENTRY_MODEL.md +124 -124
  21. package/XYTARA_DEFAULT_PATH_MODEL.md +84 -84
  22. package/XYTARA_EXECUTION_TRUTH_MODEL.md +171 -171
  23. package/XYTARA_PAYMENT_RAIL_TRUTH_MODEL.md +68 -68
  24. package/adapters/AUTHORING_GUIDE.md +243 -243
  25. package/adapters/ONBOARDING_POSTURE.md +61 -61
  26. package/adapters/THIRD_PARTY_SUBMISSION_PROCESS.md +84 -84
  27. package/adapters/adapter-manifest.schema.json +283 -283
  28. package/adapters/examples/example-execution-adapter.js +61 -61
  29. package/adapters/examples/example-execution-adapter.manifest.json +81 -81
  30. package/adapters/examples/example-settlement-adapter.js +55 -55
  31. package/adapters/examples/example-settlement-adapter.manifest.json +78 -78
  32. package/adapters/examples/example-third-party-acp-registration.submission-bundle.json +124 -124
  33. package/adapters/examples/example-third-party-erc8004-registration.submission-bundle.json +121 -121
  34. package/adapters/examples/example-third-party-identity-registration.certification-pack.json +22 -22
  35. package/adapters/examples/example-third-party-identity-registration.record.json +26 -26
  36. package/adapters/examples/example-third-party-identity-registration.submission-bundle.json +126 -126
  37. package/adapters/examples/example-third-party-langchain-registration.submission-bundle.json +124 -124
  38. package/adapters/examples/example-third-party-mpp-registration.submission-bundle.json +120 -120
  39. package/adapters/examples/example-third-party-registration.certification-pack.json +22 -22
  40. package/adapters/examples/example-third-party-registration.record.json +28 -28
  41. package/adapters/examples/example-third-party-registration.submission-bundle.json +126 -126
  42. package/adapters/examples/example-third-party-settlement-registration.certification-pack.json +22 -22
  43. package/adapters/examples/example-third-party-settlement-registration.record.json +26 -26
  44. package/adapters/examples/example-third-party-settlement-registration.submission-bundle.json +127 -127
  45. package/adapters/examples/langchain-reference-execution-adapter.js +81 -81
  46. package/adapters/examples/langchain-reference-execution-adapter.manifest.json +79 -79
  47. package/adapters/examples/langgraph-reference-execution-adapter.js +81 -81
  48. package/adapters/examples/langgraph-reference-execution-adapter.manifest.json +79 -79
  49. package/adapters/examples/minimal-third-party-execution-adapter.js +61 -61
  50. package/adapters/examples/minimal-third-party-execution-adapter.manifest.json +79 -79
  51. package/adapters/examples/minimal-third-party-execution-registration.record.json +26 -26
  52. package/adapters/examples/minimal-third-party-execution.certification-pack.json +22 -22
  53. package/adapters/examples/minimal-third-party-execution.submission-bundle.json +126 -126
  54. package/adapters/integration-certification-pack.schema.json +82 -82
  55. package/adapters/integration-registration-record.schema.json +114 -114
  56. package/adapters/integration-submission-bundle-set.schema.json +39 -39
  57. package/adapters/integration-submission-bundle.schema.json +34 -34
  58. package/adapters/interfaces.js +56 -56
  59. package/bin/xytara-first-run.js +244 -244
  60. package/bin/xytara-release.js +1429 -1429
  61. package/bin/xytara-run.js +186 -186
  62. package/bin/xytara.js +80 -80
  63. package/client.js +3 -3
  64. package/examples/_demo_env.js +40 -0
  65. package/examples/adapter_review_walkthrough.js +54 -53
  66. package/examples/export_carried_handoff.js +81 -80
  67. package/examples/funded_runtime_walkthrough.js +71 -70
  68. package/examples/generated.carried-handoff.json +30 -0
  69. package/examples/partner_launch_walkthrough.js +44 -43
  70. package/examples/quickstart.js +3256 -3255
  71. package/fixtures/catalog.js +1134 -1134
  72. package/index.js +395 -395
  73. package/integrations/dispatch.js +276 -276
  74. package/integrations/registry-snapshot.schema.json +36 -36
  75. package/integrations/registry.js +2261 -2261
  76. package/integrations/views.js +28 -28
  77. package/lib/a2a_lane_contract.js +104 -104
  78. package/lib/a2c_lane_contract.js +111 -111
  79. package/lib/account_auth.js +518 -518
  80. package/lib/acp_lane_contract.js +54 -54
  81. package/lib/activity_audit_contract.js +322 -322
  82. package/lib/adapter_certification_contract.js +130 -130
  83. package/lib/adapter_depth_contract.js +156 -156
  84. package/lib/adapter_pack.js +118 -118
  85. package/lib/adapter_partner_pack.js +89 -89
  86. package/lib/adapter_promotion_pack.js +89 -89
  87. package/lib/adapter_protocol_truth_contract.js +229 -229
  88. package/lib/announcement_pack.js +61 -61
  89. package/lib/artifact_distribution_lane_contract.js +54 -54
  90. package/lib/asyncapi_contract.js +150 -150
  91. package/lib/auth_interop_contract.js +80 -80
  92. package/lib/authority_binding_lifecycle_contract.js +182 -182
  93. package/lib/autonomous_entry_contract.js +409 -409
  94. package/lib/bolt_lane_contract.js +55 -55
  95. package/lib/bolt_payment_front.js +172 -172
  96. package/lib/business_cockpit.js +378 -378
  97. package/lib/capability_execution_truth.js +272 -272
  98. package/lib/capability_registry.js +633 -633
  99. package/lib/catalog_contract.js +966 -966
  100. package/lib/catalog_family_model.js +193 -193
  101. package/lib/catalog_views.js +55 -55
  102. package/lib/checkout_event_security.js +142 -142
  103. package/lib/cloudevents_contract.js +80 -80
  104. package/lib/command_flow.js +411 -406
  105. package/lib/commerce_artifacts.js +503 -503
  106. package/lib/commerce_authority.js +449 -449
  107. package/lib/commerce_cases.js +317 -317
  108. package/lib/commerce_checkout.js +509 -509
  109. package/lib/commerce_client.js +7687 -7676
  110. package/lib/commerce_coordination.js +346 -346
  111. package/lib/commerce_economics.js +4017 -4016
  112. package/lib/commerce_identity.js +578 -578
  113. package/lib/commerce_quotes.js +237 -237
  114. package/lib/commerce_reports.js +14461 -14461
  115. package/lib/commerce_runtime.js +315 -315
  116. package/lib/commerce_shell.js +257 -257
  117. package/lib/crypto_agility_matrix.js +125 -125
  118. package/lib/default_path_contract.js +412 -412
  119. package/lib/delivery_summary_contract.js +95 -95
  120. package/lib/ecosystem_entry.js +64 -64
  121. package/lib/erc8004_lane_contract.js +65 -65
  122. package/lib/event_system_lane_contract.js +75 -75
  123. package/lib/execution_truth_contract.js +234 -234
  124. package/lib/external_credit_bridge.js +142 -142
  125. package/lib/external_execution_runtime.js +132 -132
  126. package/lib/feature_control_lane_contract.js +54 -54
  127. package/lib/first_run_conversion_contract.js +290 -290
  128. package/lib/framework_lane_contract.js +89 -89
  129. package/lib/framework_provider_promotion.js +235 -235
  130. package/lib/full_catalog_contract.js +525 -525
  131. package/lib/go_live_operator_pack.js +391 -391
  132. package/lib/http_transport.js +73 -73
  133. package/lib/identity_auth.js +175 -175
  134. package/lib/identity_interop_contract.js +82 -82
  135. package/lib/integration_matrix_contract.js +102 -102
  136. package/lib/l402_lane_contract.js +55 -55
  137. package/lib/l402_payment_front.js +192 -192
  138. package/lib/launch_narrative.js +53 -53
  139. package/lib/lifecycle_continuity_contract.js +115 -115
  140. package/lib/machine_identity_registry_contract.js +199 -199
  141. package/lib/major_rails_lane_contract.js +150 -150
  142. package/lib/market_lane_contract.js +467 -467
  143. package/lib/market_lane_depth_contract.js +182 -182
  144. package/lib/market_lane_promotion_contract.js +210 -210
  145. package/lib/market_lane_trace_contract.js +278 -278
  146. package/lib/mcp_lane_contract.js +137 -137
  147. package/lib/network_transport.js +110 -110
  148. package/lib/offline_verifiability_recovery_contract.js +155 -155
  149. package/lib/openapi_contract.js +296 -296
  150. package/lib/operational_receipt_contract.js +165 -165
  151. package/lib/operator_intelligence.js +407 -407
  152. package/lib/outreach_copy_pack.js +51 -51
  153. package/lib/outreach_message_pack.js +71 -71
  154. package/lib/outreach_proof.js +71 -71
  155. package/lib/outreach_target_pack.js +60 -60
  156. package/lib/partner_intelligence.js +105 -105
  157. package/lib/payment_config.js +239 -191
  158. package/lib/payment_front_registry.js +53 -53
  159. package/lib/payment_protocol_contract.js +165 -165
  160. package/lib/payment_rail_truth_contract.js +324 -324
  161. package/lib/payment_verification.js +312 -264
  162. package/lib/phase_10_closeout_pack.js +45 -45
  163. package/lib/phase_10_completion_pack.js +76 -76
  164. package/lib/phase_10_decision_record_pack.js +54 -54
  165. package/lib/phase_10_decision_resolution_pack.js +53 -53
  166. package/lib/phase_10_demand_signal_adapters_runtime_pack.js +74 -74
  167. package/lib/phase_10_ecosystem_backlog_triage_runtime_pack.js +74 -74
  168. package/lib/phase_10_freeze_baseline_pack.js +67 -67
  169. package/lib/phase_10_freeze_review_pack.js +64 -64
  170. package/lib/phase_10_gate_pack.js +57 -57
  171. package/lib/phase_10_long_tail_continuity_pack.js +80 -80
  172. package/lib/phase_10_long_tail_ecosystem_pack.js +66 -66
  173. package/lib/phase_10_niche_extension_registry_runtime_pack.js +74 -74
  174. package/lib/phase_1_claude_mcp_pack.js +60 -60
  175. package/lib/phase_1_claude_mcp_runtime_pack.js +52 -52
  176. package/lib/phase_1_ecosystem_pack.js +67 -67
  177. package/lib/phase_1_openai_codex_pack.js +60 -60
  178. package/lib/phase_1_openai_codex_runtime_pack.js +52 -52
  179. package/lib/phase_2_base_runtime_pack.js +71 -71
  180. package/lib/phase_2_base_usdc_runtime_pack.js +72 -72
  181. package/lib/phase_2_closeout_pack.js +65 -65
  182. package/lib/phase_2_completion_pack.js +113 -113
  183. package/lib/phase_2_decision_record_pack.js +66 -66
  184. package/lib/phase_2_decision_resolution_pack.js +69 -69
  185. package/lib/phase_2_eth_runtime_pack.js +70 -70
  186. package/lib/phase_2_evm_base_runtime_pack.js +73 -73
  187. package/lib/phase_2_evm_runtime_pack.js +71 -71
  188. package/lib/phase_2_flip_preview_pack.js +60 -60
  189. package/lib/phase_2_freeze_review_pack.js +99 -99
  190. package/lib/phase_2_gate_pack.js +77 -77
  191. package/lib/phase_2_payment_rails_pack.js +71 -71
  192. package/lib/phase_2_usdc_runtime_pack.js +71 -71
  193. package/lib/phase_3_brc_runtime_pack.js +81 -81
  194. package/lib/phase_3_bsv_teranode_runtime_pack.js +83 -83
  195. package/lib/phase_3_closeout_pack.js +62 -62
  196. package/lib/phase_3_completion_pack.js +94 -94
  197. package/lib/phase_3_decision_record_pack.js +64 -64
  198. package/lib/phase_3_decision_resolution_pack.js +69 -69
  199. package/lib/phase_3_freeze_baseline_pack.js +67 -67
  200. package/lib/phase_3_freeze_review_pack.js +80 -80
  201. package/lib/phase_3_gate_pack.js +76 -76
  202. package/lib/phase_3_metanet_runtime_pack.js +81 -81
  203. package/lib/phase_3_native_bsv_pack.js +91 -91
  204. package/lib/phase_3_native_continuity_pack.js +82 -82
  205. package/lib/phase_4_attestation_runtime_pack.js +75 -75
  206. package/lib/phase_4_closeout_pack.js +45 -45
  207. package/lib/phase_4_completion_pack.js +94 -94
  208. package/lib/phase_4_decision_record_pack.js +54 -54
  209. package/lib/phase_4_decision_resolution_pack.js +45 -45
  210. package/lib/phase_4_erc8004_runtime_pack.js +76 -76
  211. package/lib/phase_4_freeze_baseline_pack.js +67 -67
  212. package/lib/phase_4_freeze_review_pack.js +68 -68
  213. package/lib/phase_4_gate_pack.js +58 -58
  214. package/lib/phase_4_identity_registry_runtime_pack.js +75 -75
  215. package/lib/phase_4_identity_trust_pack.js +73 -73
  216. package/lib/phase_4_trust_continuity_pack.js +86 -86
  217. package/lib/phase_5_antelope_runtime_pack.js +76 -76
  218. package/lib/phase_5_closeout_pack.js +44 -44
  219. package/lib/phase_5_completion_pack.js +82 -82
  220. package/lib/phase_5_constellation_dag_runtime_pack.js +76 -76
  221. package/lib/phase_5_decision_record_pack.js +54 -54
  222. package/lib/phase_5_decision_resolution_pack.js +45 -45
  223. package/lib/phase_5_digibyte_dgb_runtime_pack.js +76 -76
  224. package/lib/phase_5_freeze_baseline_pack.js +67 -67
  225. package/lib/phase_5_freeze_review_pack.js +68 -68
  226. package/lib/phase_5_gate_pack.js +58 -58
  227. package/lib/phase_5_hedera_hbar_runtime_pack.js +76 -76
  228. package/lib/phase_5_kaspa_kas_runtime_pack.js +76 -76
  229. package/lib/phase_5_major_rails_continuity_pack.js +86 -86
  230. package/lib/phase_5_major_rails_pack.js +110 -110
  231. package/lib/phase_5_metal_runtime_pack.js +76 -76
  232. package/lib/phase_5_polkadot_dot_runtime_pack.js +76 -76
  233. package/lib/phase_5_proton_xpr_runtime_pack.js +76 -76
  234. package/lib/phase_5_solana_runtime_pack.js +76 -76
  235. package/lib/phase_6_autogen_runtime_pack.js +72 -72
  236. package/lib/phase_6_closeout_pack.js +46 -46
  237. package/lib/phase_6_completion_pack.js +77 -77
  238. package/lib/phase_6_decision_record_pack.js +54 -54
  239. package/lib/phase_6_decision_resolution_pack.js +53 -53
  240. package/lib/phase_6_framework_continuity_pack.js +81 -81
  241. package/lib/phase_6_framework_runtime_pack.js +68 -68
  242. package/lib/phase_6_freeze_baseline_pack.js +68 -68
  243. package/lib/phase_6_freeze_review_pack.js +65 -65
  244. package/lib/phase_6_gate_pack.js +59 -59
  245. package/lib/phase_6_langchain_runtime_pack.js +72 -72
  246. package/lib/phase_6_langgraph_runtime_pack.js +72 -72
  247. package/lib/phase_6_semantic_kernel_runtime_pack.js +72 -72
  248. package/lib/phase_7_closeout_pack.js +45 -45
  249. package/lib/phase_7_completion_pack.js +85 -85
  250. package/lib/phase_7_decision_record_pack.js +53 -53
  251. package/lib/phase_7_decision_resolution_pack.js +53 -53
  252. package/lib/phase_7_event_system_continuity_pack.js +89 -89
  253. package/lib/phase_7_event_system_pack.js +76 -76
  254. package/lib/phase_7_freeze_baseline_pack.js +74 -74
  255. package/lib/phase_7_freeze_review_pack.js +65 -65
  256. package/lib/phase_7_gate_pack.js +58 -58
  257. package/lib/phase_7_kafka_runtime_pack.js +74 -74
  258. package/lib/phase_7_mqtt_runtime_pack.js +74 -74
  259. package/lib/phase_7_nats_runtime_pack.js +74 -74
  260. package/lib/phase_7_webhook_event_bus_runtime_pack.js +74 -74
  261. package/lib/phase_8_closeout_pack.js +46 -46
  262. package/lib/phase_8_completion_pack.js +82 -82
  263. package/lib/phase_8_decision_record_pack.js +54 -54
  264. package/lib/phase_8_decision_resolution_pack.js +53 -53
  265. package/lib/phase_8_external_receipt_import_runtime_pack.js +74 -74
  266. package/lib/phase_8_external_result_import_runtime_pack.js +74 -74
  267. package/lib/phase_8_freeze_baseline_pack.js +71 -71
  268. package/lib/phase_8_freeze_review_pack.js +64 -64
  269. package/lib/phase_8_gate_pack.js +58 -58
  270. package/lib/phase_8_proof_bridge_continuity_pack.js +86 -86
  271. package/lib/phase_8_proof_bridges_pack.js +72 -72
  272. package/lib/phase_8_proof_bundle_normalization_runtime_pack.js +74 -74
  273. package/lib/phase_9_closeout_pack.js +46 -46
  274. package/lib/phase_9_completion_pack.js +82 -82
  275. package/lib/phase_9_custody_refs_runtime_pack.js +74 -74
  276. package/lib/phase_9_decision_record_pack.js +54 -54
  277. package/lib/phase_9_decision_resolution_pack.js +53 -53
  278. package/lib/phase_9_freeze_baseline_pack.js +71 -71
  279. package/lib/phase_9_freeze_review_pack.js +64 -64
  280. package/lib/phase_9_gate_pack.js +58 -58
  281. package/lib/phase_9_operator_accounting_bridges_runtime_pack.js +74 -74
  282. package/lib/phase_9_treasury_connectivity_pack.js +72 -72
  283. package/lib/phase_9_treasury_continuity_pack.js +86 -86
  284. package/lib/phase_9_treasury_destinations_runtime_pack.js +74 -74
  285. package/lib/phase_program_pack.js +120 -120
  286. package/lib/pricing_optimization_contract.js +775 -775
  287. package/lib/protocol_lane_contract.js +117 -117
  288. package/lib/provenance_lane_contract.js +54 -54
  289. package/lib/provider_lane_contract.js +240 -240
  290. package/lib/provider_runtime_journey_contract.js +183 -183
  291. package/lib/public_surface_policy_contract.js +111 -111
  292. package/lib/publish_plan.js +51 -51
  293. package/lib/record_queries.js +48 -48
  294. package/lib/release_candidate.js +50 -50
  295. package/lib/release_center.js +1093 -1093
  296. package/lib/release_history.js +205 -205
  297. package/lib/release_manifest.js +113 -113
  298. package/lib/release_pack.js +453 -453
  299. package/lib/request_rate_limit.js +144 -144
  300. package/lib/resource_views.js +31 -31
  301. package/lib/revenue_launch_path_contract.js +326 -326
  302. package/lib/route_matchers.js +34 -34
  303. package/lib/route_params.js +19 -19
  304. package/lib/runtime_bridge.js +124 -124
  305. package/lib/runtime_operations_worker.js +282 -282
  306. package/lib/runtime_state_store.js +354 -354
  307. package/lib/settlement_lane_contract.js +111 -111
  308. package/lib/shared_signals_lane_contract.js +54 -54
  309. package/lib/signed_audit_provenance_contract.js +83 -83
  310. package/lib/soft_launch_pack.js +78 -78
  311. package/lib/stablecoin_lane_contract.js +76 -76
  312. package/lib/stripe_mpp_lane_contract.js +96 -96
  313. package/lib/stripe_mpp_payment_front.js +158 -158
  314. package/lib/telemetry_lane_contract.js +54 -54
  315. package/lib/treasury_destinations_contract.js +764 -764
  316. package/lib/treasury_egress_policy_contract.js +91 -91
  317. package/lib/treasury_lane_contract.js +84 -84
  318. package/lib/trust_portability_boundary_contract.js +72 -72
  319. package/lib/x402_facilitator.js +155 -0
  320. package/lib/x402_lane_contract.js +118 -118
  321. package/package.json +106 -105
  322. package/scripts/registry_cli.js +275 -275
  323. package/scripts/verify_adapters.js +554 -554
  324. package/scripts/verify_all.js +4962 -4962
  325. package/scripts/verify_control_plane_contracts.js +34 -34
  326. package/scripts/verify_control_plane_routes.js +70 -70
  327. package/scripts/verify_delivery_summary.js +112 -112
  328. package/scripts/verify_examples.js +19 -19
  329. package/scripts/verify_first_run_conversions.js +81 -81
  330. package/scripts/verify_framework_provider_promotion.js +152 -152
  331. package/scripts/verify_full_catalog.js +174 -174
  332. package/scripts/verify_integrations.js +620 -620
  333. package/scripts/verify_lifecycle_continuity.js +96 -96
  334. package/scripts/verify_market_lane_depth.js +94 -94
  335. package/scripts/verify_market_lane_promotion.js +103 -103
  336. package/scripts/verify_market_lane_traces.js +98 -98
  337. package/scripts/verify_market_lanes.js +102 -102
  338. package/scripts/verify_operator_observability_boundary.js +83 -83
  339. package/scripts/verify_pricing_experiment_plan.js +124 -124
  340. package/scripts/verify_provider_runtime_breadth.js +109 -109
  341. package/scripts/verify_provider_runtime_journeys.js +111 -111
  342. package/scripts/verify_revenue_launch_paths.js +105 -105
  343. package/scripts/verify_runtime_durability.js +52 -52
  344. package/scripts/verify_service.js +15410 -15250
  345. package/scripts/verify_tooling.js +1412 -1412
  346. package/scripts/verify_treasury_public_boundary.js +97 -97
  347. package/scripts/verify_x402_facilitator.js +174 -0
  348. package/server.js +11117 -11006
  349. package/.env.production.checklist +0 -77
  350. package/.env.production.template +0 -54
  351. package/.github/workflows/publish-mcp-executor.yml +0 -43
  352. package/ADAPTER_PARTNER_PATH.md +0 -47
  353. package/ADAPTER_PROMOTION_START_HERE.md +0 -44
  354. package/BOLT_BINDINGS.production.worksheet.json +0 -31
  355. package/EXECUTION_TARGETS.production.worksheet.json +0 -73
  356. package/GO_LIVE_OPERATOR_PACK.md +0 -412
  357. package/L402_BINDINGS.production.worksheet.json +0 -30
  358. package/OPERATIONS_RUNBOOK.md +0 -115
  359. package/OPERATOR_START_HERE.md +0 -63
  360. package/OUTREACH_MESSAGES.md +0 -19
  361. package/OUTREACH_START_HERE.md +0 -36
  362. package/PRODUCTION_MANUAL_CLOSEOUT_SEQUENCE.md +0 -172
  363. package/PROGRAM_COMPLETE_RELEASE.md +0 -63
  364. package/PROGRAM_STATUS.md +0 -57
  365. package/PUBLISH_PLAN.md +0 -26
  366. package/RELEASE_CHECKLIST.md +0 -16
  367. package/SOFT_LAUNCH_KIT.md +0 -47
  368. package/services/mcp-execution-target/DISCOVERY_REGISTRY_PLAYBOOK.md +0 -141
  369. package/services/mcp-execution-target/README.md +0 -319
  370. package/services/mcp-execution-target/package.json +0 -14
  371. package/services/mcp-execution-target/server.js +0 -1031
  372. package/services/mcp-execution-target/server.json +0 -16
  373. package/services/mcp-execution-target/verify.js +0 -308
@@ -1,518 +1,518 @@
1
- "use strict";
2
-
3
- const crypto = require("crypto");
4
-
5
- function normalizeString(value, fallback = null) {
6
- const trimmed = typeof value === "string" ? value.trim() : "";
7
- return trimmed || fallback;
8
- }
9
-
10
- function ensureObject(value) {
11
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
12
- }
13
-
14
- function ensureArray(value) {
15
- return Array.isArray(value) ? value : [];
16
- }
17
-
18
- function nowIso() {
19
- return new Date().toISOString();
20
- }
21
-
22
- function buildCredentialPublicView(credential, includeToken = false) {
23
- if (!credential) return null;
24
- const view = {
25
- credential_id: credential.credential_id,
26
- account_id: credential.account_id,
27
- status: credential.status,
28
- spend_posture: credential.spend_posture,
29
- effective_pool_binding_mode: credential.entitlement_id ? "entitlement_bound" : credential.pack_id ? "pack_bound" : "unbound",
30
- scope: credential.scope,
31
- agent_id: credential.agent_id,
32
- budget_id: credential.budget_id,
33
- pack_id: credential.pack_id || null,
34
- entitlement_id: credential.entitlement_id || null,
35
- expires_at_iso: credential.expires_at_iso,
36
- created_at_iso: credential.created_at_iso,
37
- updated_at_iso: credential.updated_at_iso,
38
- issued_by: credential.issued_by || null,
39
- labels: ensureArray(credential.labels)
40
- };
41
- if (includeToken) {
42
- view.bearer_token = credential.bearer_token;
43
- }
44
- return view;
45
- }
46
-
47
- function buildAuthorityBindingPublicView(binding, credential, includeToken = false) {
48
- if (!binding) return null;
49
- const view = {
50
- binding_id: binding.binding_id,
51
- account_id: binding.account_id,
52
- status: binding.status,
53
- authority_kind: binding.authority_kind,
54
- spend_posture: binding.spend_posture,
55
- scope: binding.scope,
56
- authority_scope: ensureArray(binding.authority_scope),
57
- allowed_consequence_families: ensureArray(binding.allowed_consequence_families),
58
- consequence_bounds: binding.consequence_bounds || {
59
- max_commit_units: null,
60
- max_reserve_units: null,
61
- max_reversal_units: null
62
- },
63
- agent_id: binding.agent_id,
64
- budget_id: binding.budget_id,
65
- pack_id: binding.pack_id || null,
66
- entitlement_id: binding.entitlement_id || null,
67
- credential_id: binding.credential_id || null,
68
- issued_by: binding.issued_by || null,
69
- labels: ensureArray(binding.labels),
70
- expires_at_iso: binding.expires_at_iso || null,
71
- rotated_from_binding_id: binding.rotated_from_binding_id || null,
72
- replaced_by_binding_id: binding.replaced_by_binding_id || null,
73
- created_at_iso: binding.created_at_iso,
74
- updated_at_iso: binding.updated_at_iso,
75
- revoked_at_iso: binding.revoked_at_iso || null,
76
- revoke_reason: binding.revoke_reason || null,
77
- spend_credential: buildCredentialPublicView(credential, includeToken)
78
- };
79
- return view;
80
- }
81
-
82
- function buildAuthorityBindingContractSummary(binding, credential) {
83
- if (!binding) return null;
84
- const publicView = buildAuthorityBindingPublicView(binding, credential, false);
85
- return {
86
- summary_version: "xytara-authority-binding-contract-summary-v1",
87
- binding_id: binding.binding_id,
88
- account_id: binding.account_id,
89
- authority_kind: binding.authority_kind,
90
- spend_posture: binding.spend_posture,
91
- authority_scope: ensureArray(binding.authority_scope),
92
- allowed_consequence_families: ensureArray(binding.allowed_consequence_families),
93
- consequence_bounds: publicView.consequence_bounds,
94
- linked_credential_id: binding.credential_id || null,
95
- contract_state: binding.status === "active" ? "active_contract" : "inactive_contract",
96
- linked_surfaces: {
97
- binding_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}`,
98
- spend_credential_ref: binding.credential_id ? `/v1/account-auth/spend-credentials/${encodeURIComponent(binding.credential_id)}` : null
99
- }
100
- };
101
- }
102
-
103
- function buildAuthorityBindingRotationSummary(binding, credential) {
104
- if (!binding) return null;
105
- const active = binding.status === "active";
106
- return {
107
- summary_version: "xytara-authority-binding-rotation-summary-v1",
108
- binding_id: binding.binding_id,
109
- account_id: binding.account_id,
110
- status: binding.status,
111
- renewable_state: active ? "renewable" : "inactive",
112
- rotatable_state: active ? "rotatable" : "inactive",
113
- expires_at_iso: binding.expires_at_iso || null,
114
- rotated_from_binding_id: binding.rotated_from_binding_id || null,
115
- replaced_by_binding_id: binding.replaced_by_binding_id || null,
116
- linked_credential_id: binding.credential_id || null,
117
- linked_surfaces: {
118
- binding_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}`,
119
- contract_summary_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}/contract-summary`,
120
- spend_credential_ref: binding.credential_id ? `/v1/account-auth/spend-credentials/${encodeURIComponent(binding.credential_id)}` : null
121
- }
122
- };
123
- }
124
-
125
- function isCredentialExpired(credential) {
126
- if (!credential || !credential.expires_at_iso) return false;
127
- const expiresAt = Date.parse(credential.expires_at_iso);
128
- return Number.isFinite(expiresAt) ? Date.now() >= expiresAt : false;
129
- }
130
-
131
- function createSpendCredential(state, body) {
132
- const payload = ensureObject(body);
133
- const credentialId = normalizeString(payload.credential_id, `spend_credential_${state.accountSpendCredentials.size + 1}`);
134
- const accountId = normalizeString(payload.account_id, "acct_demo");
135
- const agentId = normalizeString(payload.agent_id, null);
136
- const budgetId = normalizeString(payload.budget_id, null);
137
- const packId = normalizeString(payload.pack_id, null);
138
- const entitlementId = normalizeString(payload.entitlement_id, null);
139
- const createdAtIso = nowIso();
140
- const expiresAtIso = normalizeString(payload.expires_at_iso, null);
141
- const credential = {
142
- credential_id: credentialId,
143
- bearer_token: normalizeString(payload.bearer_token, `xytara_spend_${crypto.randomBytes(18).toString("hex")}`),
144
- account_id: accountId,
145
- agent_id: agentId,
146
- budget_id: budgetId,
147
- pack_id: packId,
148
- entitlement_id: entitlementId,
149
- spend_posture: agentId || budgetId ? "bounded_spend" : "open_spend",
150
- scope: normalizeString(payload.scope, "runtime_spend"),
151
- labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean),
152
- status: normalizeString(payload.status, "active"),
153
- issued_by: normalizeString(payload.issued_by, "operator"),
154
- expires_at_iso: expiresAtIso,
155
- created_at_iso: createdAtIso,
156
- updated_at_iso: createdAtIso,
157
- revoked_at_iso: null,
158
- revoke_reason: null
159
- };
160
- state.accountSpendCredentials.set(credentialId, credential);
161
- state.accountSpendCredentialsByToken.set(credential.bearer_token, credentialId);
162
- return buildCredentialPublicView(credential, true);
163
- }
164
-
165
- function createAuthorityBinding(state, body) {
166
- const payload = ensureObject(body);
167
- const bindingId = normalizeString(payload.binding_id, `authority_binding_${state.accountAuthorityBindings.size + 1}`);
168
- const credential = createSpendCredential(state, {
169
- credential_id: normalizeString(payload.credential_id, `spend_for_${bindingId}`),
170
- bearer_token: normalizeString(payload.bearer_token, null),
171
- account_id: normalizeString(payload.account_id, "acct_demo"),
172
- agent_id: normalizeString(payload.agent_id, null),
173
- budget_id: normalizeString(payload.budget_id, null),
174
- pack_id: normalizeString(payload.pack_id, null),
175
- entitlement_id: normalizeString(payload.entitlement_id, null),
176
- scope: normalizeString(payload.scope, "runtime_spend"),
177
- labels: ensureArray(payload.labels),
178
- status: normalizeString(payload.status, "active"),
179
- issued_by: normalizeString(payload.issued_by, "operator"),
180
- expires_at_iso: normalizeString(payload.expires_at_iso, null)
181
- });
182
- const createdAtIso = nowIso();
183
- const binding = {
184
- binding_id: bindingId,
185
- account_id: credential.account_id,
186
- credential_id: credential.credential_id,
187
- authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
188
- spend_posture: credential.spend_posture,
189
- scope: credential.scope,
190
- authority_scope: ensureArray(payload.authority_scope).map((value) => String(value || "").trim()).filter(Boolean),
191
- allowed_consequence_families: ensureArray(payload.allowed_consequence_families).map((value) => String(value || "").trim()).filter(Boolean),
192
- consequence_bounds: {
193
- max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : null,
194
- max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : null,
195
- max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : null
196
- },
197
- agent_id: credential.agent_id,
198
- budget_id: credential.budget_id,
199
- pack_id: credential.pack_id || null,
200
- entitlement_id: credential.entitlement_id || null,
201
- status: normalizeString(payload.status, "active"),
202
- issued_by: normalizeString(payload.issued_by, "operator"),
203
- labels: ensureArray(payload.labels),
204
- expires_at_iso: credential.expires_at_iso,
205
- rotated_from_binding_id: normalizeString(payload.rotated_from_binding_id, null),
206
- replaced_by_binding_id: normalizeString(payload.replaced_by_binding_id, null),
207
- created_at_iso: createdAtIso,
208
- updated_at_iso: createdAtIso,
209
- revoked_at_iso: null,
210
- revoke_reason: null
211
- };
212
- state.accountAuthorityBindings.set(bindingId, binding);
213
- return buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(credential.credential_id), true);
214
- }
215
-
216
- function listSpendCredentials(state, filters) {
217
- const payload = ensureObject(filters);
218
- const accountId = normalizeString(payload.account_id, null);
219
- const status = normalizeString(payload.status, null);
220
- return Array.from(state.accountSpendCredentials.values())
221
- .filter((credential) => {
222
- if (accountId && credential.account_id !== accountId) return false;
223
- if (status && credential.status !== status) return false;
224
- return true;
225
- })
226
- .map((credential) => buildCredentialPublicView(credential, false));
227
- }
228
-
229
- function getSpendCredential(state, credentialId) {
230
- if (!credentialId || !state.accountSpendCredentials.has(credentialId)) return null;
231
- return buildCredentialPublicView(state.accountSpendCredentials.get(credentialId), false);
232
- }
233
-
234
- function listAuthorityBindings(state, filters) {
235
- const payload = ensureObject(filters);
236
- const accountId = normalizeString(payload.account_id, null);
237
- const status = normalizeString(payload.status, null);
238
- return Array.from(state.accountAuthorityBindings.values())
239
- .filter((binding) => {
240
- if (accountId && binding.account_id !== accountId) return false;
241
- if (status && binding.status !== status) return false;
242
- return true;
243
- })
244
- .map((binding) => buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(binding.credential_id), false));
245
- }
246
-
247
- function getAuthorityBinding(state, bindingId) {
248
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
249
- const binding = state.accountAuthorityBindings.get(bindingId);
250
- return buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(binding.credential_id), false);
251
- }
252
-
253
- function getAuthorityBindingContractSummary(state, bindingId) {
254
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
255
- const binding = state.accountAuthorityBindings.get(bindingId);
256
- return buildAuthorityBindingContractSummary(binding, state.accountSpendCredentials.get(binding.credential_id));
257
- }
258
-
259
- function getAuthorityBindingRotationSummary(state, bindingId) {
260
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
261
- const binding = state.accountAuthorityBindings.get(bindingId);
262
- return buildAuthorityBindingRotationSummary(binding, state.accountSpendCredentials.get(binding.credential_id));
263
- }
264
-
265
- function evaluateAuthorityBindingAction(binding, action, units) {
266
- const target = binding && typeof binding === "object" ? binding : null;
267
- const numericUnits = Number.isFinite(Number(units)) ? Number(units) : 0;
268
- const allowedScopes = target ? ensureArray(target.authority_scope) : [];
269
- const allowedFamilies = target ? ensureArray(target.allowed_consequence_families) : [];
270
- const bounds = target && target.consequence_bounds ? target.consequence_bounds : {};
271
-
272
- if (!target) {
273
- return { ok: true };
274
- }
275
- if (target.status !== "active") {
276
- return { ok: false, reason: "authority_binding_inactive", binding_id: target.binding_id };
277
- }
278
-
279
- const scopeMap = {
280
- delegated_credit_spend: "runtime.execute",
281
- reserve: "economics.reserve",
282
- release: "economics.release",
283
- reverse: "economics.reverse"
284
- };
285
- const familyMap = {
286
- delegated_credit_spend: "commit",
287
- reserve: "reserve",
288
- release: "release",
289
- reverse: "reverse"
290
- };
291
- const boundKeyMap = {
292
- delegated_credit_spend: "max_commit_units",
293
- reserve: "max_reserve_units",
294
- reverse: "max_reversal_units"
295
- };
296
-
297
- const requiredScope = scopeMap[action] || null;
298
- if (requiredScope && allowedScopes.length > 0 && !allowedScopes.includes(requiredScope)) {
299
- return {
300
- ok: false,
301
- reason: "authority_scope_not_allowed",
302
- binding_id: target.binding_id,
303
- required_scope: requiredScope,
304
- authority_scope: allowedScopes
305
- };
306
- }
307
-
308
- const requiredFamily = familyMap[action] || null;
309
- if (requiredFamily && allowedFamilies.length > 0 && !allowedFamilies.includes(requiredFamily)) {
310
- return {
311
- ok: false,
312
- reason: "authority_consequence_family_not_allowed",
313
- binding_id: target.binding_id,
314
- required_consequence_family: requiredFamily,
315
- allowed_consequence_families: allowedFamilies
316
- };
317
- }
318
-
319
- const boundKey = boundKeyMap[action] || null;
320
- if (boundKey && Number.isFinite(Number(bounds[boundKey])) && numericUnits > Number(bounds[boundKey])) {
321
- return {
322
- ok: false,
323
- reason: "authority_consequence_bound_exceeded",
324
- binding_id: target.binding_id,
325
- bound_key: boundKey,
326
- max_units: Number(bounds[boundKey]),
327
- attempted_units: numericUnits
328
- };
329
- }
330
-
331
- return {
332
- ok: true,
333
- binding_id: target.binding_id,
334
- authority_scope: allowedScopes,
335
- allowed_consequence_families: allowedFamilies,
336
- consequence_bounds: {
337
- max_commit_units: Number.isFinite(Number(bounds.max_commit_units)) ? Number(bounds.max_commit_units) : null,
338
- max_reserve_units: Number.isFinite(Number(bounds.max_reserve_units)) ? Number(bounds.max_reserve_units) : null,
339
- max_reversal_units: Number.isFinite(Number(bounds.max_reversal_units)) ? Number(bounds.max_reversal_units) : null
340
- }
341
- };
342
- }
343
-
344
- function revokeSpendCredential(state, credentialId, body) {
345
- if (!credentialId || !state.accountSpendCredentials.has(credentialId)) return null;
346
- const payload = ensureObject(body);
347
- const current = state.accountSpendCredentials.get(credentialId);
348
- const next = {
349
- ...current,
350
- status: "revoked",
351
- revoked_at_iso: nowIso(),
352
- revoke_reason: normalizeString(payload.reason, "operator_revoked"),
353
- updated_at_iso: nowIso()
354
- };
355
- state.accountSpendCredentials.set(credentialId, next);
356
- return buildCredentialPublicView(next, false);
357
- }
358
-
359
- function revokeAuthorityBinding(state, bindingId, body) {
360
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
361
- const payload = ensureObject(body);
362
- const current = state.accountAuthorityBindings.get(bindingId);
363
- const next = {
364
- ...current,
365
- status: "revoked",
366
- revoked_at_iso: nowIso(),
367
- revoke_reason: normalizeString(payload.reason, "operator_revoked"),
368
- updated_at_iso: nowIso()
369
- };
370
- state.accountAuthorityBindings.set(bindingId, next);
371
- if (current.credential_id) {
372
- revokeSpendCredential(state, current.credential_id, payload);
373
- }
374
- return buildAuthorityBindingPublicView(next, current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false);
375
- }
376
-
377
- function renewAuthorityBinding(state, bindingId, body) {
378
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
379
- const payload = ensureObject(body);
380
- const current = state.accountAuthorityBindings.get(bindingId);
381
- const nextExpiresAtIso = normalizeString(payload.expires_at_iso, current.expires_at_iso || null);
382
- const updatedAtIso = nowIso();
383
- const next = {
384
- ...current,
385
- expires_at_iso: nextExpiresAtIso,
386
- updated_at_iso: updatedAtIso
387
- };
388
- state.accountAuthorityBindings.set(bindingId, next);
389
- if (current.credential_id && state.accountSpendCredentials.has(current.credential_id)) {
390
- const credential = state.accountSpendCredentials.get(current.credential_id);
391
- state.accountSpendCredentials.set(current.credential_id, {
392
- ...credential,
393
- expires_at_iso: nextExpiresAtIso,
394
- updated_at_iso: updatedAtIso
395
- });
396
- }
397
- return buildAuthorityBindingPublicView(next, current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false);
398
- }
399
-
400
- function rotateAuthorityBinding(state, bindingId, body) {
401
- if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
402
- const payload = ensureObject(body);
403
- const current = state.accountAuthorityBindings.get(bindingId);
404
- const currentCredential = current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null;
405
- const successorBindingId = normalizeString(payload.successor_binding_id, `${bindingId}_rotated`);
406
- const successorCredentialId = normalizeString(payload.successor_credential_id, current.credential_id ? `${current.credential_id}_rotated` : `spend_for_${successorBindingId}`);
407
- const successor = createAuthorityBinding(state, {
408
- binding_id: successorBindingId,
409
- credential_id: successorCredentialId,
410
- bearer_token: normalizeString(payload.bearer_token, null),
411
- account_id: current.account_id,
412
- agent_id: normalizeString(payload.agent_id, current.agent_id),
413
- budget_id: normalizeString(payload.budget_id, current.budget_id),
414
- pack_id: normalizeString(payload.pack_id, current.pack_id),
415
- entitlement_id: normalizeString(payload.entitlement_id, current.entitlement_id),
416
- scope: normalizeString(payload.scope, current.scope),
417
- authority_kind: normalizeString(payload.authority_kind, current.authority_kind),
418
- authority_scope: ensureArray(payload.authority_scope).length > 0 ? ensureArray(payload.authority_scope) : ensureArray(current.authority_scope),
419
- allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0 ? ensureArray(payload.allowed_consequence_families) : ensureArray(current.allowed_consequence_families),
420
- max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : current.consequence_bounds.max_commit_units,
421
- max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : current.consequence_bounds.max_reserve_units,
422
- max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : current.consequence_bounds.max_reversal_units,
423
- labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
424
- issued_by: normalizeString(payload.issued_by, current.issued_by || "operator"),
425
- expires_at_iso: normalizeString(payload.expires_at_iso, current.expires_at_iso || (currentCredential ? currentCredential.expires_at_iso : null)),
426
- rotated_from_binding_id: current.binding_id
427
- });
428
- const revoked = revokeAuthorityBinding(state, bindingId, {
429
- reason: normalizeString(payload.reason, "rotated_to_successor")
430
- });
431
- const successorRecord = state.accountAuthorityBindings.get(successor.binding_id);
432
- state.accountAuthorityBindings.set(successor.binding_id, {
433
- ...successorRecord,
434
- rotated_from_binding_id: current.binding_id
435
- });
436
- state.accountAuthorityBindings.set(bindingId, {
437
- ...state.accountAuthorityBindings.get(bindingId),
438
- replaced_by_binding_id: successor.binding_id
439
- });
440
- return {
441
- rotated_binding: buildAuthorityBindingPublicView(state.accountAuthorityBindings.get(bindingId), current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false),
442
- successor_authority_binding: buildAuthorityBindingPublicView(state.accountAuthorityBindings.get(successor.binding_id), state.accountSpendCredentials.get(successor.credential_id), true),
443
- previous_view: revoked
444
- };
445
- }
446
-
447
- function resolveSpendCredential(state, bearerToken) {
448
- const token = normalizeString(bearerToken, null);
449
- if (!token) {
450
- return {
451
- ok: false,
452
- reason: "missing_spend_credential"
453
- };
454
- }
455
- const credentialId = state.accountSpendCredentialsByToken.get(token);
456
- if (!credentialId || !state.accountSpendCredentials.has(credentialId)) {
457
- return {
458
- ok: false,
459
- reason: "spend_credential_not_found"
460
- };
461
- }
462
- const credential = state.accountSpendCredentials.get(credentialId);
463
- if (credential.status !== "active") {
464
- return {
465
- ok: false,
466
- reason: "spend_credential_inactive",
467
- credential: buildCredentialPublicView(credential, false)
468
- };
469
- }
470
- if (isCredentialExpired(credential)) {
471
- return {
472
- ok: false,
473
- reason: "spend_credential_expired",
474
- credential: buildCredentialPublicView(credential, false)
475
- };
476
- }
477
- const binding = Array.from(state.accountAuthorityBindings.values()).find((entry) => entry && entry.credential_id === credentialId && entry.status === "active") || null;
478
- return {
479
- ok: true,
480
- credential,
481
- binding,
482
- authorization_context: {
483
- verification_mode: "delegated_spend_credential",
484
- wallet_id: credential.credential_id,
485
- payment_payload: {
486
- binding_id: binding ? binding.binding_id : null,
487
- credential_id: credential.credential_id,
488
- spend_posture: credential.spend_posture,
489
- pack_id: credential.pack_id || null,
490
- entitlement_id: credential.entitlement_id || null,
491
- authority_scope: binding ? ensureArray(binding.authority_scope) : [],
492
- allowed_consequence_families: binding ? ensureArray(binding.allowed_consequence_families) : [],
493
- consequence_bounds: binding && binding.consequence_bounds ? binding.consequence_bounds : {
494
- max_commit_units: null,
495
- max_reserve_units: null,
496
- max_reversal_units: null
497
- }
498
- }
499
- }
500
- };
501
- }
502
-
503
- module.exports = {
504
- createAuthorityBinding,
505
- createSpendCredential,
506
- evaluateAuthorityBindingAction,
507
- getAuthorityBinding,
508
- getAuthorityBindingContractSummary,
509
- getAuthorityBindingRotationSummary,
510
- getSpendCredential,
511
- listAuthorityBindings,
512
- listSpendCredentials,
513
- renewAuthorityBinding,
514
- resolveSpendCredential,
515
- rotateAuthorityBinding,
516
- revokeAuthorityBinding,
517
- revokeSpendCredential
518
- };
1
+ "use strict";
2
+
3
+ const crypto = require("crypto");
4
+
5
+ function normalizeString(value, fallback = null) {
6
+ const trimmed = typeof value === "string" ? value.trim() : "";
7
+ return trimmed || fallback;
8
+ }
9
+
10
+ function ensureObject(value) {
11
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
12
+ }
13
+
14
+ function ensureArray(value) {
15
+ return Array.isArray(value) ? value : [];
16
+ }
17
+
18
+ function nowIso() {
19
+ return new Date().toISOString();
20
+ }
21
+
22
+ function buildCredentialPublicView(credential, includeToken = false) {
23
+ if (!credential) return null;
24
+ const view = {
25
+ credential_id: credential.credential_id,
26
+ account_id: credential.account_id,
27
+ status: credential.status,
28
+ spend_posture: credential.spend_posture,
29
+ effective_pool_binding_mode: credential.entitlement_id ? "entitlement_bound" : credential.pack_id ? "pack_bound" : "unbound",
30
+ scope: credential.scope,
31
+ agent_id: credential.agent_id,
32
+ budget_id: credential.budget_id,
33
+ pack_id: credential.pack_id || null,
34
+ entitlement_id: credential.entitlement_id || null,
35
+ expires_at_iso: credential.expires_at_iso,
36
+ created_at_iso: credential.created_at_iso,
37
+ updated_at_iso: credential.updated_at_iso,
38
+ issued_by: credential.issued_by || null,
39
+ labels: ensureArray(credential.labels)
40
+ };
41
+ if (includeToken) {
42
+ view.bearer_token = credential.bearer_token;
43
+ }
44
+ return view;
45
+ }
46
+
47
+ function buildAuthorityBindingPublicView(binding, credential, includeToken = false) {
48
+ if (!binding) return null;
49
+ const view = {
50
+ binding_id: binding.binding_id,
51
+ account_id: binding.account_id,
52
+ status: binding.status,
53
+ authority_kind: binding.authority_kind,
54
+ spend_posture: binding.spend_posture,
55
+ scope: binding.scope,
56
+ authority_scope: ensureArray(binding.authority_scope),
57
+ allowed_consequence_families: ensureArray(binding.allowed_consequence_families),
58
+ consequence_bounds: binding.consequence_bounds || {
59
+ max_commit_units: null,
60
+ max_reserve_units: null,
61
+ max_reversal_units: null
62
+ },
63
+ agent_id: binding.agent_id,
64
+ budget_id: binding.budget_id,
65
+ pack_id: binding.pack_id || null,
66
+ entitlement_id: binding.entitlement_id || null,
67
+ credential_id: binding.credential_id || null,
68
+ issued_by: binding.issued_by || null,
69
+ labels: ensureArray(binding.labels),
70
+ expires_at_iso: binding.expires_at_iso || null,
71
+ rotated_from_binding_id: binding.rotated_from_binding_id || null,
72
+ replaced_by_binding_id: binding.replaced_by_binding_id || null,
73
+ created_at_iso: binding.created_at_iso,
74
+ updated_at_iso: binding.updated_at_iso,
75
+ revoked_at_iso: binding.revoked_at_iso || null,
76
+ revoke_reason: binding.revoke_reason || null,
77
+ spend_credential: buildCredentialPublicView(credential, includeToken)
78
+ };
79
+ return view;
80
+ }
81
+
82
+ function buildAuthorityBindingContractSummary(binding, credential) {
83
+ if (!binding) return null;
84
+ const publicView = buildAuthorityBindingPublicView(binding, credential, false);
85
+ return {
86
+ summary_version: "xytara-authority-binding-contract-summary-v1",
87
+ binding_id: binding.binding_id,
88
+ account_id: binding.account_id,
89
+ authority_kind: binding.authority_kind,
90
+ spend_posture: binding.spend_posture,
91
+ authority_scope: ensureArray(binding.authority_scope),
92
+ allowed_consequence_families: ensureArray(binding.allowed_consequence_families),
93
+ consequence_bounds: publicView.consequence_bounds,
94
+ linked_credential_id: binding.credential_id || null,
95
+ contract_state: binding.status === "active" ? "active_contract" : "inactive_contract",
96
+ linked_surfaces: {
97
+ binding_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}`,
98
+ spend_credential_ref: binding.credential_id ? `/v1/account-auth/spend-credentials/${encodeURIComponent(binding.credential_id)}` : null
99
+ }
100
+ };
101
+ }
102
+
103
+ function buildAuthorityBindingRotationSummary(binding, credential) {
104
+ if (!binding) return null;
105
+ const active = binding.status === "active";
106
+ return {
107
+ summary_version: "xytara-authority-binding-rotation-summary-v1",
108
+ binding_id: binding.binding_id,
109
+ account_id: binding.account_id,
110
+ status: binding.status,
111
+ renewable_state: active ? "renewable" : "inactive",
112
+ rotatable_state: active ? "rotatable" : "inactive",
113
+ expires_at_iso: binding.expires_at_iso || null,
114
+ rotated_from_binding_id: binding.rotated_from_binding_id || null,
115
+ replaced_by_binding_id: binding.replaced_by_binding_id || null,
116
+ linked_credential_id: binding.credential_id || null,
117
+ linked_surfaces: {
118
+ binding_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}`,
119
+ contract_summary_ref: `/v1/account-auth/authority-bindings/${encodeURIComponent(binding.binding_id)}/contract-summary`,
120
+ spend_credential_ref: binding.credential_id ? `/v1/account-auth/spend-credentials/${encodeURIComponent(binding.credential_id)}` : null
121
+ }
122
+ };
123
+ }
124
+
125
+ function isCredentialExpired(credential) {
126
+ if (!credential || !credential.expires_at_iso) return false;
127
+ const expiresAt = Date.parse(credential.expires_at_iso);
128
+ return Number.isFinite(expiresAt) ? Date.now() >= expiresAt : false;
129
+ }
130
+
131
+ function createSpendCredential(state, body) {
132
+ const payload = ensureObject(body);
133
+ const credentialId = normalizeString(payload.credential_id, `spend_credential_${state.accountSpendCredentials.size + 1}`);
134
+ const accountId = normalizeString(payload.account_id, "acct_demo");
135
+ const agentId = normalizeString(payload.agent_id, null);
136
+ const budgetId = normalizeString(payload.budget_id, null);
137
+ const packId = normalizeString(payload.pack_id, null);
138
+ const entitlementId = normalizeString(payload.entitlement_id, null);
139
+ const createdAtIso = nowIso();
140
+ const expiresAtIso = normalizeString(payload.expires_at_iso, null);
141
+ const credential = {
142
+ credential_id: credentialId,
143
+ bearer_token: normalizeString(payload.bearer_token, `xytara_spend_${crypto.randomBytes(18).toString("hex")}`),
144
+ account_id: accountId,
145
+ agent_id: agentId,
146
+ budget_id: budgetId,
147
+ pack_id: packId,
148
+ entitlement_id: entitlementId,
149
+ spend_posture: agentId || budgetId ? "bounded_spend" : "open_spend",
150
+ scope: normalizeString(payload.scope, "runtime_spend"),
151
+ labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean),
152
+ status: normalizeString(payload.status, "active"),
153
+ issued_by: normalizeString(payload.issued_by, "operator"),
154
+ expires_at_iso: expiresAtIso,
155
+ created_at_iso: createdAtIso,
156
+ updated_at_iso: createdAtIso,
157
+ revoked_at_iso: null,
158
+ revoke_reason: null
159
+ };
160
+ state.accountSpendCredentials.set(credentialId, credential);
161
+ state.accountSpendCredentialsByToken.set(credential.bearer_token, credentialId);
162
+ return buildCredentialPublicView(credential, true);
163
+ }
164
+
165
+ function createAuthorityBinding(state, body) {
166
+ const payload = ensureObject(body);
167
+ const bindingId = normalizeString(payload.binding_id, `authority_binding_${state.accountAuthorityBindings.size + 1}`);
168
+ const credential = createSpendCredential(state, {
169
+ credential_id: normalizeString(payload.credential_id, `spend_for_${bindingId}`),
170
+ bearer_token: normalizeString(payload.bearer_token, null),
171
+ account_id: normalizeString(payload.account_id, "acct_demo"),
172
+ agent_id: normalizeString(payload.agent_id, null),
173
+ budget_id: normalizeString(payload.budget_id, null),
174
+ pack_id: normalizeString(payload.pack_id, null),
175
+ entitlement_id: normalizeString(payload.entitlement_id, null),
176
+ scope: normalizeString(payload.scope, "runtime_spend"),
177
+ labels: ensureArray(payload.labels),
178
+ status: normalizeString(payload.status, "active"),
179
+ issued_by: normalizeString(payload.issued_by, "operator"),
180
+ expires_at_iso: normalizeString(payload.expires_at_iso, null)
181
+ });
182
+ const createdAtIso = nowIso();
183
+ const binding = {
184
+ binding_id: bindingId,
185
+ account_id: credential.account_id,
186
+ credential_id: credential.credential_id,
187
+ authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
188
+ spend_posture: credential.spend_posture,
189
+ scope: credential.scope,
190
+ authority_scope: ensureArray(payload.authority_scope).map((value) => String(value || "").trim()).filter(Boolean),
191
+ allowed_consequence_families: ensureArray(payload.allowed_consequence_families).map((value) => String(value || "").trim()).filter(Boolean),
192
+ consequence_bounds: {
193
+ max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : null,
194
+ max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : null,
195
+ max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : null
196
+ },
197
+ agent_id: credential.agent_id,
198
+ budget_id: credential.budget_id,
199
+ pack_id: credential.pack_id || null,
200
+ entitlement_id: credential.entitlement_id || null,
201
+ status: normalizeString(payload.status, "active"),
202
+ issued_by: normalizeString(payload.issued_by, "operator"),
203
+ labels: ensureArray(payload.labels),
204
+ expires_at_iso: credential.expires_at_iso,
205
+ rotated_from_binding_id: normalizeString(payload.rotated_from_binding_id, null),
206
+ replaced_by_binding_id: normalizeString(payload.replaced_by_binding_id, null),
207
+ created_at_iso: createdAtIso,
208
+ updated_at_iso: createdAtIso,
209
+ revoked_at_iso: null,
210
+ revoke_reason: null
211
+ };
212
+ state.accountAuthorityBindings.set(bindingId, binding);
213
+ return buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(credential.credential_id), true);
214
+ }
215
+
216
+ function listSpendCredentials(state, filters) {
217
+ const payload = ensureObject(filters);
218
+ const accountId = normalizeString(payload.account_id, null);
219
+ const status = normalizeString(payload.status, null);
220
+ return Array.from(state.accountSpendCredentials.values())
221
+ .filter((credential) => {
222
+ if (accountId && credential.account_id !== accountId) return false;
223
+ if (status && credential.status !== status) return false;
224
+ return true;
225
+ })
226
+ .map((credential) => buildCredentialPublicView(credential, false));
227
+ }
228
+
229
+ function getSpendCredential(state, credentialId) {
230
+ if (!credentialId || !state.accountSpendCredentials.has(credentialId)) return null;
231
+ return buildCredentialPublicView(state.accountSpendCredentials.get(credentialId), false);
232
+ }
233
+
234
+ function listAuthorityBindings(state, filters) {
235
+ const payload = ensureObject(filters);
236
+ const accountId = normalizeString(payload.account_id, null);
237
+ const status = normalizeString(payload.status, null);
238
+ return Array.from(state.accountAuthorityBindings.values())
239
+ .filter((binding) => {
240
+ if (accountId && binding.account_id !== accountId) return false;
241
+ if (status && binding.status !== status) return false;
242
+ return true;
243
+ })
244
+ .map((binding) => buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(binding.credential_id), false));
245
+ }
246
+
247
+ function getAuthorityBinding(state, bindingId) {
248
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
249
+ const binding = state.accountAuthorityBindings.get(bindingId);
250
+ return buildAuthorityBindingPublicView(binding, state.accountSpendCredentials.get(binding.credential_id), false);
251
+ }
252
+
253
+ function getAuthorityBindingContractSummary(state, bindingId) {
254
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
255
+ const binding = state.accountAuthorityBindings.get(bindingId);
256
+ return buildAuthorityBindingContractSummary(binding, state.accountSpendCredentials.get(binding.credential_id));
257
+ }
258
+
259
+ function getAuthorityBindingRotationSummary(state, bindingId) {
260
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
261
+ const binding = state.accountAuthorityBindings.get(bindingId);
262
+ return buildAuthorityBindingRotationSummary(binding, state.accountSpendCredentials.get(binding.credential_id));
263
+ }
264
+
265
+ function evaluateAuthorityBindingAction(binding, action, units) {
266
+ const target = binding && typeof binding === "object" ? binding : null;
267
+ const numericUnits = Number.isFinite(Number(units)) ? Number(units) : 0;
268
+ const allowedScopes = target ? ensureArray(target.authority_scope) : [];
269
+ const allowedFamilies = target ? ensureArray(target.allowed_consequence_families) : [];
270
+ const bounds = target && target.consequence_bounds ? target.consequence_bounds : {};
271
+
272
+ if (!target) {
273
+ return { ok: true };
274
+ }
275
+ if (target.status !== "active") {
276
+ return { ok: false, reason: "authority_binding_inactive", binding_id: target.binding_id };
277
+ }
278
+
279
+ const scopeMap = {
280
+ delegated_credit_spend: "runtime.execute",
281
+ reserve: "economics.reserve",
282
+ release: "economics.release",
283
+ reverse: "economics.reverse"
284
+ };
285
+ const familyMap = {
286
+ delegated_credit_spend: "commit",
287
+ reserve: "reserve",
288
+ release: "release",
289
+ reverse: "reverse"
290
+ };
291
+ const boundKeyMap = {
292
+ delegated_credit_spend: "max_commit_units",
293
+ reserve: "max_reserve_units",
294
+ reverse: "max_reversal_units"
295
+ };
296
+
297
+ const requiredScope = scopeMap[action] || null;
298
+ if (requiredScope && allowedScopes.length > 0 && !allowedScopes.includes(requiredScope)) {
299
+ return {
300
+ ok: false,
301
+ reason: "authority_scope_not_allowed",
302
+ binding_id: target.binding_id,
303
+ required_scope: requiredScope,
304
+ authority_scope: allowedScopes
305
+ };
306
+ }
307
+
308
+ const requiredFamily = familyMap[action] || null;
309
+ if (requiredFamily && allowedFamilies.length > 0 && !allowedFamilies.includes(requiredFamily)) {
310
+ return {
311
+ ok: false,
312
+ reason: "authority_consequence_family_not_allowed",
313
+ binding_id: target.binding_id,
314
+ required_consequence_family: requiredFamily,
315
+ allowed_consequence_families: allowedFamilies
316
+ };
317
+ }
318
+
319
+ const boundKey = boundKeyMap[action] || null;
320
+ if (boundKey && Number.isFinite(Number(bounds[boundKey])) && numericUnits > Number(bounds[boundKey])) {
321
+ return {
322
+ ok: false,
323
+ reason: "authority_consequence_bound_exceeded",
324
+ binding_id: target.binding_id,
325
+ bound_key: boundKey,
326
+ max_units: Number(bounds[boundKey]),
327
+ attempted_units: numericUnits
328
+ };
329
+ }
330
+
331
+ return {
332
+ ok: true,
333
+ binding_id: target.binding_id,
334
+ authority_scope: allowedScopes,
335
+ allowed_consequence_families: allowedFamilies,
336
+ consequence_bounds: {
337
+ max_commit_units: Number.isFinite(Number(bounds.max_commit_units)) ? Number(bounds.max_commit_units) : null,
338
+ max_reserve_units: Number.isFinite(Number(bounds.max_reserve_units)) ? Number(bounds.max_reserve_units) : null,
339
+ max_reversal_units: Number.isFinite(Number(bounds.max_reversal_units)) ? Number(bounds.max_reversal_units) : null
340
+ }
341
+ };
342
+ }
343
+
344
+ function revokeSpendCredential(state, credentialId, body) {
345
+ if (!credentialId || !state.accountSpendCredentials.has(credentialId)) return null;
346
+ const payload = ensureObject(body);
347
+ const current = state.accountSpendCredentials.get(credentialId);
348
+ const next = {
349
+ ...current,
350
+ status: "revoked",
351
+ revoked_at_iso: nowIso(),
352
+ revoke_reason: normalizeString(payload.reason, "operator_revoked"),
353
+ updated_at_iso: nowIso()
354
+ };
355
+ state.accountSpendCredentials.set(credentialId, next);
356
+ return buildCredentialPublicView(next, false);
357
+ }
358
+
359
+ function revokeAuthorityBinding(state, bindingId, body) {
360
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
361
+ const payload = ensureObject(body);
362
+ const current = state.accountAuthorityBindings.get(bindingId);
363
+ const next = {
364
+ ...current,
365
+ status: "revoked",
366
+ revoked_at_iso: nowIso(),
367
+ revoke_reason: normalizeString(payload.reason, "operator_revoked"),
368
+ updated_at_iso: nowIso()
369
+ };
370
+ state.accountAuthorityBindings.set(bindingId, next);
371
+ if (current.credential_id) {
372
+ revokeSpendCredential(state, current.credential_id, payload);
373
+ }
374
+ return buildAuthorityBindingPublicView(next, current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false);
375
+ }
376
+
377
+ function renewAuthorityBinding(state, bindingId, body) {
378
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
379
+ const payload = ensureObject(body);
380
+ const current = state.accountAuthorityBindings.get(bindingId);
381
+ const nextExpiresAtIso = normalizeString(payload.expires_at_iso, current.expires_at_iso || null);
382
+ const updatedAtIso = nowIso();
383
+ const next = {
384
+ ...current,
385
+ expires_at_iso: nextExpiresAtIso,
386
+ updated_at_iso: updatedAtIso
387
+ };
388
+ state.accountAuthorityBindings.set(bindingId, next);
389
+ if (current.credential_id && state.accountSpendCredentials.has(current.credential_id)) {
390
+ const credential = state.accountSpendCredentials.get(current.credential_id);
391
+ state.accountSpendCredentials.set(current.credential_id, {
392
+ ...credential,
393
+ expires_at_iso: nextExpiresAtIso,
394
+ updated_at_iso: updatedAtIso
395
+ });
396
+ }
397
+ return buildAuthorityBindingPublicView(next, current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false);
398
+ }
399
+
400
+ function rotateAuthorityBinding(state, bindingId, body) {
401
+ if (!bindingId || !state.accountAuthorityBindings.has(bindingId)) return null;
402
+ const payload = ensureObject(body);
403
+ const current = state.accountAuthorityBindings.get(bindingId);
404
+ const currentCredential = current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null;
405
+ const successorBindingId = normalizeString(payload.successor_binding_id, `${bindingId}_rotated`);
406
+ const successorCredentialId = normalizeString(payload.successor_credential_id, current.credential_id ? `${current.credential_id}_rotated` : `spend_for_${successorBindingId}`);
407
+ const successor = createAuthorityBinding(state, {
408
+ binding_id: successorBindingId,
409
+ credential_id: successorCredentialId,
410
+ bearer_token: normalizeString(payload.bearer_token, null),
411
+ account_id: current.account_id,
412
+ agent_id: normalizeString(payload.agent_id, current.agent_id),
413
+ budget_id: normalizeString(payload.budget_id, current.budget_id),
414
+ pack_id: normalizeString(payload.pack_id, current.pack_id),
415
+ entitlement_id: normalizeString(payload.entitlement_id, current.entitlement_id),
416
+ scope: normalizeString(payload.scope, current.scope),
417
+ authority_kind: normalizeString(payload.authority_kind, current.authority_kind),
418
+ authority_scope: ensureArray(payload.authority_scope).length > 0 ? ensureArray(payload.authority_scope) : ensureArray(current.authority_scope),
419
+ allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0 ? ensureArray(payload.allowed_consequence_families) : ensureArray(current.allowed_consequence_families),
420
+ max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : current.consequence_bounds.max_commit_units,
421
+ max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : current.consequence_bounds.max_reserve_units,
422
+ max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : current.consequence_bounds.max_reversal_units,
423
+ labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
424
+ issued_by: normalizeString(payload.issued_by, current.issued_by || "operator"),
425
+ expires_at_iso: normalizeString(payload.expires_at_iso, current.expires_at_iso || (currentCredential ? currentCredential.expires_at_iso : null)),
426
+ rotated_from_binding_id: current.binding_id
427
+ });
428
+ const revoked = revokeAuthorityBinding(state, bindingId, {
429
+ reason: normalizeString(payload.reason, "rotated_to_successor")
430
+ });
431
+ const successorRecord = state.accountAuthorityBindings.get(successor.binding_id);
432
+ state.accountAuthorityBindings.set(successor.binding_id, {
433
+ ...successorRecord,
434
+ rotated_from_binding_id: current.binding_id
435
+ });
436
+ state.accountAuthorityBindings.set(bindingId, {
437
+ ...state.accountAuthorityBindings.get(bindingId),
438
+ replaced_by_binding_id: successor.binding_id
439
+ });
440
+ return {
441
+ rotated_binding: buildAuthorityBindingPublicView(state.accountAuthorityBindings.get(bindingId), current.credential_id ? state.accountSpendCredentials.get(current.credential_id) : null, false),
442
+ successor_authority_binding: buildAuthorityBindingPublicView(state.accountAuthorityBindings.get(successor.binding_id), state.accountSpendCredentials.get(successor.credential_id), true),
443
+ previous_view: revoked
444
+ };
445
+ }
446
+
447
+ function resolveSpendCredential(state, bearerToken) {
448
+ const token = normalizeString(bearerToken, null);
449
+ if (!token) {
450
+ return {
451
+ ok: false,
452
+ reason: "missing_spend_credential"
453
+ };
454
+ }
455
+ const credentialId = state.accountSpendCredentialsByToken.get(token);
456
+ if (!credentialId || !state.accountSpendCredentials.has(credentialId)) {
457
+ return {
458
+ ok: false,
459
+ reason: "spend_credential_not_found"
460
+ };
461
+ }
462
+ const credential = state.accountSpendCredentials.get(credentialId);
463
+ if (credential.status !== "active") {
464
+ return {
465
+ ok: false,
466
+ reason: "spend_credential_inactive",
467
+ credential: buildCredentialPublicView(credential, false)
468
+ };
469
+ }
470
+ if (isCredentialExpired(credential)) {
471
+ return {
472
+ ok: false,
473
+ reason: "spend_credential_expired",
474
+ credential: buildCredentialPublicView(credential, false)
475
+ };
476
+ }
477
+ const binding = Array.from(state.accountAuthorityBindings.values()).find((entry) => entry && entry.credential_id === credentialId && entry.status === "active") || null;
478
+ return {
479
+ ok: true,
480
+ credential,
481
+ binding,
482
+ authorization_context: {
483
+ verification_mode: "delegated_spend_credential",
484
+ wallet_id: credential.credential_id,
485
+ payment_payload: {
486
+ binding_id: binding ? binding.binding_id : null,
487
+ credential_id: credential.credential_id,
488
+ spend_posture: credential.spend_posture,
489
+ pack_id: credential.pack_id || null,
490
+ entitlement_id: credential.entitlement_id || null,
491
+ authority_scope: binding ? ensureArray(binding.authority_scope) : [],
492
+ allowed_consequence_families: binding ? ensureArray(binding.allowed_consequence_families) : [],
493
+ consequence_bounds: binding && binding.consequence_bounds ? binding.consequence_bounds : {
494
+ max_commit_units: null,
495
+ max_reserve_units: null,
496
+ max_reversal_units: null
497
+ }
498
+ }
499
+ }
500
+ };
501
+ }
502
+
503
+ module.exports = {
504
+ createAuthorityBinding,
505
+ createSpendCredential,
506
+ evaluateAuthorityBindingAction,
507
+ getAuthorityBinding,
508
+ getAuthorityBindingContractSummary,
509
+ getAuthorityBindingRotationSummary,
510
+ getSpendCredential,
511
+ listAuthorityBindings,
512
+ listSpendCredentials,
513
+ renewAuthorityBinding,
514
+ resolveSpendCredential,
515
+ rotateAuthorityBinding,
516
+ revokeAuthorityBinding,
517
+ revokeSpendCredential
518
+ };