xytara 3.1.16 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/README.md +120 -92
  2. package/RELEASE_NOTES.md +7 -3
  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
@@ -1,4017 +0,0 @@
1
- "use strict";
2
-
3
- const crypto = require("crypto");
4
- const { findTask, findWorkflow } = require("../fixtures/catalog");
5
- const {
6
- buildAuthoritySummary,
7
- buildAuthorityAttentionSummary
8
- } = require("./commerce_authority");
9
- const {
10
- buildMachineIdentitySummary,
11
- buildMachineIdentityAttentionSummary
12
- } = require("./commerce_identity");
13
- const {
14
- createAuthorityBinding,
15
- renewAuthorityBinding,
16
- revokeAuthorityBinding,
17
- rotateAuthorityBinding
18
- } = require("./account_auth");
19
- const {
20
- createIdentityBinding,
21
- renewIdentityBinding,
22
- revokeIdentityBinding,
23
- rotateIdentityBinding
24
- } = require("./identity_auth");
25
-
26
- function normalizeString(value, fallback) {
27
- const trimmed = typeof value === "string" ? value.trim() : "";
28
- return trimmed || fallback || null;
29
- }
30
-
31
- function nowIso() {
32
- return new Date().toISOString();
33
- }
34
-
35
- function ensureArray(value) {
36
- return Array.isArray(value) ? value : [];
37
- }
38
-
39
- function ensureObject(value) {
40
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
41
- }
42
-
43
- const PRICING_BAND_UNITS = {
44
- utility: 1,
45
- transactional: 2,
46
- decision_support: 3,
47
- governed_high_consequence: 5,
48
- trust_critical: 8
49
- };
50
-
51
- function createEconomicsBudget(state, body) {
52
- const payload = ensureObject(body);
53
- const accountId = normalizeString(payload.account_id, "acct_demo");
54
- const budgetId = normalizeString(payload.budget_id, `budget_${state.economicsBudgets.size + 1}`);
55
- const createdAt = nowIso();
56
- const budget = {
57
- budget_id: budgetId,
58
- account_id: accountId,
59
- label: normalizeString(payload.label, budgetId),
60
- status: normalizeString(payload.status, "active"),
61
- max_reserve_units: typeof payload.max_reserve_units === "number" ? payload.max_reserve_units : 1000,
62
- allowed_job_domains: ensureArray(payload.allowed_job_domains),
63
- policy_ref: normalizeString(payload.policy_ref, "policy.default"),
64
- created_at_iso: createdAt,
65
- updated_at_iso: createdAt
66
- };
67
- state.economicsBudgets.set(budgetId, budget);
68
- return budget;
69
- }
70
-
71
- function setEconomicsBudgetStatus(state, budgetId, body) {
72
- if (!state.economicsBudgets.has(budgetId)) return null;
73
- const payload = ensureObject(body);
74
- const current = state.economicsBudgets.get(budgetId);
75
- const next = {
76
- ...current,
77
- status: normalizeString(payload.status, current.status),
78
- status_reason: normalizeString(payload.reason, current.status_reason || null),
79
- updated_at_iso: nowIso()
80
- };
81
- state.economicsBudgets.set(budgetId, next);
82
- return next;
83
- }
84
-
85
- function createEconomicsAgent(state, body) {
86
- const payload = ensureObject(body);
87
- const accountId = normalizeString(payload.account_id, "acct_demo");
88
- const agentId = normalizeString(payload.agent_id, `agent_${state.economicsAgents.size + 1}`);
89
- const createdAt = nowIso();
90
- const agent = {
91
- agent_id: agentId,
92
- account_id: accountId,
93
- label: normalizeString(payload.label, agentId),
94
- status: normalizeString(payload.status, "active"),
95
- default_budget_id: normalizeString(payload.default_budget_id, null),
96
- allowed_job_domains: ensureArray(payload.allowed_job_domains),
97
- created_at_iso: createdAt,
98
- updated_at_iso: createdAt
99
- };
100
- state.economicsAgents.set(agentId, agent);
101
- return agent;
102
- }
103
-
104
- function setEconomicsAgentStatus(state, agentId, body) {
105
- if (!state.economicsAgents.has(agentId)) return null;
106
- const payload = ensureObject(body);
107
- const current = state.economicsAgents.get(agentId);
108
- const next = {
109
- ...current,
110
- status: normalizeString(payload.status, current.status),
111
- status_reason: normalizeString(payload.reason, current.status_reason || null),
112
- updated_at_iso: nowIso()
113
- };
114
- state.economicsAgents.set(agentId, next);
115
- return next;
116
- }
117
-
118
- function createEconomicsReceipt(state, body) {
119
- const payload = ensureObject(body);
120
- const accountId = normalizeString(payload.account_id, "acct_demo");
121
- const receiptId = normalizeString(payload.receipt_id, `econ_receipt_${state.economicsReceipts.size + 1}`);
122
- const createdAt = nowIso();
123
- const receipt = {
124
- receipt_id: receiptId,
125
- account_id: accountId,
126
- job_id: normalizeString(payload.job_id, null),
127
- agent_id: normalizeString(payload.agent_id, null),
128
- type: normalizeString(payload.type, "execution_result"),
129
- lifecycle_status: normalizeString(payload.lifecycle_status, "recorded"),
130
- operator_status: normalizeString(payload.operator_status, "pending_review"),
131
- evidence: {
132
- hash: normalizeString(payload.hash, null),
133
- uri: normalizeString(payload.uri, null)
134
- },
135
- created_at_iso: createdAt,
136
- updated_at_iso: createdAt
137
- };
138
- state.economicsReceipts.set(receiptId, receipt);
139
- return receipt;
140
- }
141
-
142
- function updateEconomicsReceiptLifecycle(state, receiptId, body) {
143
- if (!state.economicsReceipts.has(receiptId)) return null;
144
- const payload = ensureObject(body);
145
- const current = state.economicsReceipts.get(receiptId);
146
- const next = {
147
- ...current,
148
- lifecycle_status: normalizeString(payload.lifecycle_status, current.lifecycle_status),
149
- lifecycle_reason: normalizeString(payload.reason, current.lifecycle_reason || null),
150
- updated_at_iso: nowIso()
151
- };
152
- state.economicsReceipts.set(receiptId, next);
153
- return next;
154
- }
155
-
156
- function actOnEconomicsReceipt(state, receiptId, body) {
157
- if (!state.economicsReceipts.has(receiptId)) return null;
158
- const payload = ensureObject(body);
159
- const current = state.economicsReceipts.get(receiptId);
160
- const historyEntry = {
161
- action: normalizeString(payload.action, "reviewed"),
162
- actor: normalizeString(payload.actor, "operator"),
163
- reason: normalizeString(payload.reason, null),
164
- at_iso: nowIso()
165
- };
166
- const next = {
167
- ...current,
168
- operator_status: historyEntry.action,
169
- operator_history: [...ensureArray(current.operator_history), historyEntry],
170
- updated_at_iso: historyEntry.at_iso
171
- };
172
- state.economicsReceipts.set(receiptId, next);
173
- return next;
174
- }
175
-
176
- function recordAllocationEvent(state, body, direction) {
177
- const payload = ensureObject(body);
178
- const allocationId = normalizeString(payload.allocation_id, `alloc_${state.economicsAllocations.length + 1}`);
179
- const event = {
180
- allocation_id: allocationId,
181
- account_id: normalizeString(payload.account_id, "acct_demo"),
182
- budget_id: normalizeString(payload.budget_id, null),
183
- job_id: normalizeString(payload.job_id, null),
184
- agent_id: normalizeString(payload.agent_id, null),
185
- receipt_ref: normalizeString(payload.receipt_ref, null),
186
- transaction_id: normalizeString(payload.transaction_id, null),
187
- credit_spend_id: normalizeString(payload.credit_spend_id, null),
188
- usage_meter_id: normalizeString(payload.usage_meter_id, null),
189
- lifecycle_ref: normalizeString(payload.lifecycle_ref, null),
190
- reserve_ref: normalizeString(payload.reserve_ref, direction === "reserve" ? `reserve.${allocationId}` : null),
191
- commit_ref: normalizeString(payload.commit_ref, direction === "commit" ? `commit.${allocationId}` : null),
192
- resolves_allocation_id: normalizeString(payload.resolves_allocation_id, null),
193
- units: typeof payload.units === "number" ? payload.units : 0,
194
- direction,
195
- reason: normalizeString(payload.reason, null),
196
- created_at_iso: nowIso()
197
- };
198
- // Allocation events are the source of truth for credit balances; they must never be truncated.
199
- state.economicsAllocations = [event, ...ensureArray(state.economicsAllocations)];
200
- return event;
201
- }
202
-
203
- function previewRailCredits(body) {
204
- const payload = ensureObject(body);
205
- const units = typeof payload.units === "number" ? payload.units : typeof payload.amount_units === "number" ? payload.amount_units : 0;
206
- return {
207
- account_id: normalizeString(payload.account_id, "acct_demo"),
208
- rail_kind: normalizeString(payload.rail_kind, "payment_credit"),
209
- units,
210
- preview_status: "admissible",
211
- normalized_event_kind: "mint",
212
- bounded_operator_artifacts: [
213
- "rail_summary",
214
- "treasury_summary",
215
- "reconciliation_pack"
216
- ]
217
- };
218
- }
219
-
220
- function applyRailCredits(state, body) {
221
- const payload = ensureObject(body);
222
- const preview = previewRailCredits(payload);
223
- const event = {
224
- credit_event_id: normalizeString(payload.credit_event_id, `credit_${state.economicsRailCredits.length + 1}`),
225
- ...preview,
226
- amount_minor: typeof payload.amount_minor === "number" ? payload.amount_minor : null,
227
- currency: normalizeString(payload.currency, null),
228
- purchase_intent_id: normalizeString(payload.purchase_intent_id, null),
229
- provider_reference: normalizeString(payload.provider_reference, null),
230
- normalized_event_kind: "mint",
231
- reverses_credit_event_id: null,
232
- created_at_iso: nowIso(),
233
- applied_status: "recorded"
234
- };
235
- state.economicsRailCredits = [event, ...ensureArray(state.economicsRailCredits)].slice(0, 200);
236
- return event;
237
- }
238
-
239
- function reverseRailCredits(state, body) {
240
- const payload = ensureObject(body);
241
- const accountId = normalizeString(payload.account_id, "acct_demo");
242
- const originalCreditEventId = normalizeString(payload.credit_event_id, null);
243
- const purchaseIntentId = normalizeString(payload.purchase_intent_id, null);
244
- const providerReference = normalizeString(payload.provider_reference, null);
245
- const credits = ensureArray(state.economicsRailCredits);
246
- const original = credits.find((entry) => {
247
- if (!entry || entry.account_id !== accountId || entry.normalized_event_kind === "reverse") return false;
248
- if (originalCreditEventId && entry.credit_event_id === originalCreditEventId) return true;
249
- if (purchaseIntentId && entry.purchase_intent_id === purchaseIntentId) return true;
250
- if (providerReference && entry.provider_reference === providerReference) return true;
251
- return false;
252
- });
253
-
254
- if (!original) {
255
- return {
256
- ok: false,
257
- reason: "credit_event_not_found",
258
- account_id: accountId,
259
- credit_event_id: originalCreditEventId,
260
- purchase_intent_id: purchaseIntentId
261
- };
262
- }
263
-
264
- const existingReversal = credits.find((entry) =>
265
- entry
266
- && entry.account_id === accountId
267
- && entry.normalized_event_kind === "reverse"
268
- && entry.reverses_credit_event_id === original.credit_event_id
269
- );
270
- if (existingReversal) {
271
- return {
272
- ok: true,
273
- reversal: existingReversal,
274
- original,
275
- already_reversed: true
276
- };
277
- }
278
-
279
- const reversalUnits = Number.isFinite(Number(payload.units))
280
- ? Math.max(0, Number(payload.units))
281
- : Math.max(0, Number(original.units || 0));
282
- const reversal = {
283
- credit_event_id: normalizeString(payload.reversal_credit_event_id, `credit_reverse_${state.economicsRailCredits.length + 1}`),
284
- account_id: accountId,
285
- rail_kind: normalizeString(payload.rail_kind, original.rail_kind || "payment_credit"),
286
- units: reversalUnits,
287
- preview_status: "admissible",
288
- normalized_event_kind: "reverse",
289
- reverses_credit_event_id: original.credit_event_id,
290
- amount_minor: Number.isFinite(Number(payload.amount_minor))
291
- ? Number(payload.amount_minor)
292
- : Number.isFinite(Number(original.amount_minor))
293
- ? Number(original.amount_minor)
294
- : null,
295
- currency: normalizeString(payload.currency, original.currency || null),
296
- purchase_intent_id: purchaseIntentId || original.purchase_intent_id || null,
297
- provider_reference: providerReference || original.provider_reference || null,
298
- reason: normalizeString(payload.reason, "hosted_checkout_refund_compensation"),
299
- created_at_iso: nowIso(),
300
- applied_status: "recorded"
301
- };
302
- state.economicsRailCredits = [reversal, ...credits].slice(0, 200);
303
- return {
304
- ok: true,
305
- reversal,
306
- original,
307
- already_reversed: false
308
- };
309
- }
310
-
311
- function summarizeRailCreditLifecycle(credits) {
312
- const allCredits = Array.isArray(credits) ? credits : [];
313
- return {
314
- mint_count: allCredits.filter((entry) => entry && entry.normalized_event_kind !== "reverse").length,
315
- reverse_count: allCredits.filter((entry) => entry && entry.normalized_event_kind === "reverse").length,
316
- minted_units: allCredits
317
- .filter((entry) => entry && entry.normalized_event_kind !== "reverse")
318
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0),
319
- reversed_units: allCredits
320
- .filter((entry) => entry && entry.normalized_event_kind === "reverse")
321
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0)
322
- };
323
- }
324
-
325
- function listEntitlementsForAccount(state, accountId) {
326
- return Array.from(state.economicsEntitlements.values()).filter((item) => item && item.account_id === accountId);
327
- }
328
-
329
- function getEntitlement(state, entitlementId) {
330
- if (!entitlementId) return null;
331
- return state.economicsEntitlements.get(entitlementId) || null;
332
- }
333
-
334
- function buildEntitlementReplenishmentView(entitlement) {
335
- if (!entitlement) return null;
336
- const remainingUnits = Number(entitlement.remaining_units || 0);
337
- const thresholdUnits = Number(entitlement.low_balance_threshold_units || 25);
338
- const lowBalanceState = remainingUnits <= 0 ? "depleted" : remainingUnits <= thresholdUnits ? "low" : "healthy";
339
- return {
340
- entitlement_id: entitlement.entitlement_id,
341
- account_id: entitlement.account_id,
342
- pack_id: entitlement.pack_id || null,
343
- low_balance_threshold_units: thresholdUnits,
344
- low_balance_state: lowBalanceState,
345
- recommended_replenishment_pack_id: entitlement.preferred_replacement_pack_id || entitlement.pack_id || null,
346
- preferred_external_topup_ref: entitlement.preferred_external_topup_ref || null,
347
- remaining_units: remainingUnits,
348
- generated_at_iso: nowIso()
349
- };
350
- }
351
-
352
- function upsertEntitlementPool(state, body) {
353
- const payload = ensureObject(body);
354
- const accountId = normalizeString(payload.account_id, "acct_demo");
355
- const entitlementId = normalizeString(payload.entitlement_id, `entitlement_${state.economicsEntitlements.size + 1}`);
356
- const now = nowIso();
357
- const current = state.economicsEntitlements.get(entitlementId) || null;
358
- const issuedUnitsDelta = typeof payload.issued_units === "number" ? payload.issued_units : 0;
359
- const next = current ? {
360
- ...current,
361
- issued_units: (current.issued_units || 0) + issuedUnitsDelta,
362
- remaining_units: Math.max(0, ((current.issued_units || 0) + issuedUnitsDelta) - (current.consumed_units || 0)),
363
- low_balance_threshold_units: typeof payload.low_balance_threshold_units === "number"
364
- ? payload.low_balance_threshold_units
365
- : current.low_balance_threshold_units,
366
- preferred_replacement_pack_id: normalizeString(payload.preferred_replacement_pack_id, current.preferred_replacement_pack_id || null),
367
- preferred_external_topup_ref: normalizeString(payload.preferred_external_topup_ref, current.preferred_external_topup_ref || null),
368
- updated_at_iso: now
369
- } : {
370
- entitlement_id: entitlementId,
371
- account_id: accountId,
372
- pack_id: normalizeString(payload.pack_id, null),
373
- pool_kind: normalizeString(payload.pool_kind, "pack_credit_pool"),
374
- source_ref: normalizeString(payload.source_ref, null),
375
- issued_units: issuedUnitsDelta,
376
- consumed_units: 0,
377
- remaining_units: issuedUnitsDelta,
378
- low_balance_threshold_units: typeof payload.low_balance_threshold_units === "number" ? payload.low_balance_threshold_units : 25,
379
- preferred_replacement_pack_id: normalizeString(payload.preferred_replacement_pack_id, normalizeString(payload.pack_id, null)),
380
- preferred_external_topup_ref: normalizeString(payload.preferred_external_topup_ref, null),
381
- status: normalizeString(payload.status, "active"),
382
- created_at_iso: now,
383
- updated_at_iso: now
384
- };
385
- state.economicsEntitlements.set(entitlementId, next);
386
- return next;
387
- }
388
-
389
- function updateEntitlementReplenishmentPreference(state, entitlementId, body) {
390
- const current = getEntitlement(state, entitlementId);
391
- if (!current) return null;
392
- const payload = ensureObject(body);
393
- const next = {
394
- ...current,
395
- low_balance_threshold_units: typeof payload.low_balance_threshold_units === "number"
396
- ? payload.low_balance_threshold_units
397
- : current.low_balance_threshold_units,
398
- preferred_replacement_pack_id: normalizeString(payload.preferred_replacement_pack_id, current.preferred_replacement_pack_id || null),
399
- preferred_external_topup_ref: normalizeString(payload.preferred_external_topup_ref, current.preferred_external_topup_ref || null),
400
- updated_at_iso: nowIso()
401
- };
402
- state.economicsEntitlements.set(entitlementId, next);
403
- return next;
404
- }
405
-
406
- function buildEntitlementSummary(state, accountId) {
407
- const entitlements = listEntitlementsForAccount(state, accountId);
408
- const replenishmentViews = entitlements.map((entry) => buildEntitlementReplenishmentView(entry));
409
- return {
410
- account_id: accountId,
411
- entitlement_count: entitlements.length,
412
- active_entitlement_count: entitlements.filter((entry) => entry.status === "active" && entry.remaining_units > 0).length,
413
- low_entitlement_count: replenishmentViews.filter((entry) => entry && entry.low_balance_state === "low").length,
414
- depleted_entitlement_count: replenishmentViews.filter((entry) => entry && entry.low_balance_state === "depleted").length,
415
- issued_units: entitlements.reduce((sum, entry) => sum + (entry.issued_units || 0), 0),
416
- consumed_units: entitlements.reduce((sum, entry) => sum + (entry.consumed_units || 0), 0),
417
- remaining_units: entitlements.reduce((sum, entry) => sum + (entry.remaining_units || 0), 0),
418
- pack_ids: Array.from(new Set(entitlements.map((entry) => entry.pack_id).filter(Boolean))),
419
- generated_at_iso: nowIso()
420
- };
421
- }
422
-
423
- function buildEntitlementReplenishmentSummary(state, accountId) {
424
- const entitlements = listEntitlementsForAccount(state, accountId);
425
- const replenishment = entitlements.map((entry) => buildEntitlementReplenishmentView(entry));
426
- return {
427
- account_id: accountId,
428
- entitlement_count: replenishment.length,
429
- low_balance_count: replenishment.filter((entry) => entry && entry.low_balance_state === "low").length,
430
- depleted_count: replenishment.filter((entry) => entry && entry.low_balance_state === "depleted").length,
431
- recommended_pack_ids: Array.from(new Set(replenishment.map((entry) => entry && entry.recommended_replenishment_pack_id).filter(Boolean))),
432
- entitlements: replenishment,
433
- generated_at_iso: nowIso()
434
- };
435
- }
436
-
437
- function selectEntitlementPool(state, payload) {
438
- const accountId = normalizeString(payload.account_id, "acct_demo");
439
- const requestedEntitlementId = normalizeString(payload.entitlement_id, null);
440
- const requestedPackId = normalizeString(payload.pack_id, null);
441
- if (requestedEntitlementId) {
442
- const entitlement = getEntitlement(state, requestedEntitlementId);
443
- if (!entitlement || entitlement.account_id !== accountId) {
444
- return { ok: false, reason: "entitlement_not_found", entitlement_id: requestedEntitlementId };
445
- }
446
- if (entitlement.status !== "active" || entitlement.remaining_units <= 0) {
447
- return { ok: false, reason: "entitlement_inactive", entitlement_id: requestedEntitlementId };
448
- }
449
- return { ok: true, entitlement };
450
- }
451
- const candidates = listEntitlementsForAccount(state, accountId)
452
- .filter((entry) => entry.status === "active" && entry.remaining_units > 0)
453
- .filter((entry) => !requestedPackId || entry.pack_id === requestedPackId)
454
- .sort((left, right) => String(left.created_at_iso).localeCompare(String(right.created_at_iso)) || String(left.entitlement_id).localeCompare(String(right.entitlement_id)));
455
- if (candidates.length === 0) {
456
- return requestedPackId
457
- ? { ok: false, reason: "entitlement_pack_not_found", pack_id: requestedPackId }
458
- : { ok: true, entitlement: null };
459
- }
460
- return { ok: true, entitlement: candidates[0] };
461
- }
462
-
463
- function listCreditSpendsForAccount(state, accountId) {
464
- return ensureArray(state.economicsCreditSpends).filter((item) => item && item.account_id === accountId);
465
- }
466
-
467
- function getAllocationEvent(state, allocationId) {
468
- if (!allocationId) return null;
469
- return ensureArray(state.economicsAllocations).find((item) => item && item.allocation_id === allocationId) || null;
470
- }
471
-
472
- function getCreditSpend(state, creditSpendId) {
473
- if (!creditSpendId) return null;
474
- return ensureArray(state.economicsCreditSpends).find((item) => item && item.credit_spend_id === creditSpendId) || null;
475
- }
476
-
477
- function getTaskDomain(taskRef) {
478
- const task = findTask(taskRef);
479
- return task && task.public_category ? task.public_category : null;
480
- }
481
-
482
- function buildCreditSpendPolicyDecision(state, payload) {
483
- const accountId = normalizeString(payload.account_id, "acct_demo");
484
- const taskRef = normalizeString(payload.task_ref, null);
485
- const taskDomain = getTaskDomain(taskRef);
486
- const agentId = normalizeString(payload.agent_id, null);
487
- const budgetIdFromPayload = normalizeString(payload.budget_id, null);
488
- const agent = agentId ? state.economicsAgents.get(agentId) || null : null;
489
-
490
- if (agentId && !agent) {
491
- return {
492
- ok: false,
493
- reason: "agent_not_found",
494
- account_id: accountId,
495
- agent_id: agentId
496
- };
497
- }
498
-
499
- if (agent && agent.account_id !== accountId) {
500
- return {
501
- ok: false,
502
- reason: "agent_account_mismatch",
503
- account_id: accountId,
504
- agent_id: agentId
505
- };
506
- }
507
-
508
- if (agent && agent.status !== "active") {
509
- return {
510
- ok: false,
511
- reason: "agent_inactive",
512
- account_id: accountId,
513
- agent_id: agentId,
514
- agent_status: agent.status
515
- };
516
- }
517
-
518
- if (agent && ensureArray(agent.allowed_job_domains).length > 0 && taskDomain && !ensureArray(agent.allowed_job_domains).includes(taskDomain)) {
519
- return {
520
- ok: false,
521
- reason: "agent_domain_not_allowed",
522
- account_id: accountId,
523
- agent_id: agentId,
524
- task_domain: taskDomain,
525
- allowed_job_domains: ensureArray(agent.allowed_job_domains)
526
- };
527
- }
528
-
529
- const resolvedBudgetId = budgetIdFromPayload || (agent && agent.default_budget_id ? agent.default_budget_id : null);
530
- const budget = resolvedBudgetId ? state.economicsBudgets.get(resolvedBudgetId) || null : null;
531
-
532
- if (resolvedBudgetId && !budget) {
533
- return {
534
- ok: false,
535
- reason: "budget_not_found",
536
- account_id: accountId,
537
- budget_id: resolvedBudgetId
538
- };
539
- }
540
-
541
- if (budget && budget.account_id !== accountId) {
542
- return {
543
- ok: false,
544
- reason: "budget_account_mismatch",
545
- account_id: accountId,
546
- budget_id: resolvedBudgetId
547
- };
548
- }
549
-
550
- if (budget && budget.status !== "active") {
551
- return {
552
- ok: false,
553
- reason: "budget_inactive",
554
- account_id: accountId,
555
- budget_id: resolvedBudgetId,
556
- budget_status: budget.status
557
- };
558
- }
559
-
560
- if (budget && ensureArray(budget.allowed_job_domains).length > 0 && taskDomain && !ensureArray(budget.allowed_job_domains).includes(taskDomain)) {
561
- return {
562
- ok: false,
563
- reason: "budget_domain_not_allowed",
564
- account_id: accountId,
565
- budget_id: resolvedBudgetId,
566
- task_domain: taskDomain,
567
- allowed_job_domains: ensureArray(budget.allowed_job_domains)
568
- };
569
- }
570
-
571
- return {
572
- ok: true,
573
- task_domain: taskDomain,
574
- agent_id: agent ? agent.agent_id : null,
575
- budget_id: budget ? budget.budget_id : null,
576
- policy_ref: budget ? budget.policy_ref || null : null,
577
- max_reserve_units: budget && typeof budget.max_reserve_units === "number" ? budget.max_reserve_units : null
578
- };
579
- }
580
-
581
- function buildCreditBalanceSummary(state, accountId) {
582
- const credits = listRailCreditsForAccount(state, accountId);
583
- const allocations = listAllocationEventsForAccount(state, accountId);
584
- const spends = listCreditSpendsForAccount(state, accountId);
585
- const railCreditLifecycle = summarizeRailCreditLifecycle(credits);
586
- const issuedUnits = allocations.filter((entry) => entry.direction === "mint").reduce((sum, entry) => sum + (entry.units || 0), 0)
587
- + railCreditLifecycle.minted_units;
588
- const reversedUnits = allocations.filter((entry) => entry.direction === "reverse").reduce((sum, entry) => sum + (entry.units || 0), 0)
589
- + railCreditLifecycle.reversed_units;
590
- const consumedUnits = spends.reduce((sum, entry) => sum + (entry.units || 0), 0);
591
- return {
592
- account_id: accountId,
593
- issued_units: issuedUnits,
594
- consumed_units: consumedUnits,
595
- reversed_units: reversedUnits,
596
- available_units: Math.max(0, issuedUnits - consumedUnits - reversedUnits),
597
- spend_count: spends.length,
598
- entitlement_summary: buildEntitlementSummary(state, accountId),
599
- metering_summary: buildUsageMeteringSummary(state, accountId),
600
- replenishment_summary: buildEntitlementReplenishmentSummary(state, accountId),
601
- generated_at_iso: nowIso()
602
- };
603
- }
604
-
605
- function buildWalletSummary(state, accountId) {
606
- const balance = buildCreditBalanceSummary(state, accountId);
607
- const allocations = listAllocationEventsForAccount(state, accountId);
608
- const usageMeters = listUsageMetersForAccount(state, accountId);
609
- const reserveUnits = allocations
610
- .filter((entry) => entry && entry.direction === "reserve")
611
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
612
- const committedUnits = allocations
613
- .filter((entry) => entry && entry.direction === "commit")
614
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
615
- const releasedUnits = allocations
616
- .filter((entry) => entry && entry.direction === "release")
617
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
618
- const reversedUnits = allocations
619
- .filter((entry) => entry && entry.direction === "reverse")
620
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
621
- const reserveCount = allocations.filter((entry) => entry && entry.direction === "reserve").length;
622
- const walletState = balance.available_units <= 0
623
- ? "depleted"
624
- : balance.entitlement_summary.low_entitlement_count > 0
625
- ? "low_balance"
626
- : "healthy";
627
-
628
- return {
629
- wallet_version: "xytara-machine-wallet-summary-v1",
630
- wallet_id: `wallet_${accountId}`,
631
- account_id: accountId,
632
- canonical_unit: "usage_units",
633
- wallet_state: walletState,
634
- issued_units: balance.issued_units,
635
- available_units: balance.available_units,
636
- reserved_units: reserveUnits,
637
- committed_units: committedUnits,
638
- released_units: releasedUnits,
639
- reversed_units: reversedUnits,
640
- consumed_units: balance.consumed_units,
641
- reserve_count: reserveCount,
642
- entitlement_count: balance.entitlement_summary.entitlement_count,
643
- active_entitlement_count: balance.entitlement_summary.active_entitlement_count,
644
- usage_meter_count: usageMeters.length,
645
- replenishment_posture: balance.replenishment_summary.depleted_count > 0
646
- ? "replenishment_required"
647
- : balance.replenishment_summary.low_balance_count > 0
648
- ? "replenishment_recommended"
649
- : "sufficient_capacity",
650
- linked_surfaces: {
651
- credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
652
- entitlements_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/entitlements`,
653
- usage_meters_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/usage-meters`,
654
- wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
655
- wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
656
- wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
657
- },
658
- generated_at_iso: nowIso()
659
- };
660
- }
661
-
662
- function buildWalletLifecycleSummary(state, accountId) {
663
- const wallet = buildWalletSummary(state, accountId);
664
- const allocations = listAllocationEventsForAccount(state, accountId);
665
- const railCredits = listRailCreditsForAccount(state, accountId);
666
- const creditSpends = listCreditSpendsForAccount(state, accountId);
667
- const usageMeters = listUsageMetersForAccount(state, accountId);
668
- const railCreditLifecycle = summarizeRailCreditLifecycle(railCredits);
669
- const mintedUnits = allocations
670
- .filter((entry) => entry && entry.direction === "mint")
671
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0)
672
- + railCreditLifecycle.minted_units;
673
- const reservedUnits = allocations
674
- .filter((entry) => entry && entry.direction === "reserve")
675
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
676
- const explicitCommittedUnits = allocations
677
- .filter((entry) => entry && entry.direction === "commit")
678
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
679
- const explicitCommitSpendIds = new Set(
680
- allocations
681
- .filter((entry) => entry && entry.direction === "commit" && entry.credit_spend_id)
682
- .map((entry) => entry.credit_spend_id)
683
- );
684
- const fallbackCommittedSpends = creditSpends.filter((entry) => entry && !explicitCommitSpendIds.has(entry.credit_spend_id));
685
- const spendCommittedUnits = fallbackCommittedSpends.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
686
- const releasedUnits = allocations
687
- .filter((entry) => entry && entry.direction === "release")
688
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
689
- const reversedUnits = allocations
690
- .filter((entry) => entry && entry.direction === "reverse")
691
- .reduce((sum, entry) => sum + Number(entry.units || 0), 0)
692
- + railCreditLifecycle.reversed_units;
693
- const committedUnits = explicitCommittedUnits + spendCommittedUnits;
694
- const openReservedUnits = Math.max(0, reservedUnits - releasedUnits);
695
- const correctionState = reversedUnits > 0 ? "corrective_activity_present" : "none";
696
- const reserveState = openReservedUnits > 0 ? "open_reserves_present" : reservedUnits > 0 ? "reserves_fully_resolved" : "no_reserves_recorded";
697
- const commitState = committedUnits > 0 ? "committed_consequence_present" : "no_committed_consequence";
698
-
699
- return {
700
- summary_version: "xytara-wallet-lifecycle-summary-v1",
701
- wallet_id: wallet.wallet_id,
702
- account_id: accountId,
703
- canonical_unit: wallet.canonical_unit,
704
- canonical_lifecycle_model: "mint_reserve_commit_release_reverse",
705
- lifecycle_semantics: {
706
- mint: "introduces usage-unit capacity into the hidden machine wallet",
707
- reserve: "places bounded pre-execution hold against available capacity before final consequence",
708
- commit: "records final consequence against wallet capacity, including live credit-spend consequence",
709
- release: "returns previously reserved capacity when bounded execution does not finalize against that hold",
710
- reverse: "records explicit corrective removal or rollback against previously issued or committed capacity"
711
- },
712
- lifecycle_totals: {
713
- minted_units: mintedUnits,
714
- reserved_units: reservedUnits,
715
- committed_units: committedUnits,
716
- released_units: releasedUnits,
717
- reversed_units: reversedUnits,
718
- consumed_units: wallet.consumed_units,
719
- open_reserved_units: openReservedUnits,
720
- available_units: wallet.available_units
721
- },
722
- lifecycle_states: {
723
- wallet_state: wallet.wallet_state,
724
- reserve_state: reserveState,
725
- commit_state: commitState,
726
- correction_state: correctionState
727
- },
728
- record_interpretation: {
729
- mint_sources: {
730
- allocation_mint_count: allocations.filter((entry) => entry && entry.direction === "mint").length,
731
- rail_credit_count: railCreditLifecycle.mint_count
732
- },
733
- reserve_sources: {
734
- allocation_reserve_count: allocations.filter((entry) => entry && entry.direction === "reserve").length
735
- },
736
- commit_sources: {
737
- explicit_commit_count: allocations.filter((entry) => entry && entry.direction === "commit").length,
738
- derived_credit_spend_commit_count: fallbackCommittedSpends.length,
739
- usage_meter_count: usageMeters.length
740
- },
741
- release_sources: {
742
- allocation_release_count: allocations.filter((entry) => entry && entry.direction === "release").length
743
- },
744
- reverse_sources: {
745
- allocation_reverse_count: allocations.filter((entry) => entry && entry.direction === "reverse").length,
746
- rail_credit_reverse_count: railCreditLifecycle.reverse_count
747
- }
748
- },
749
- linked_surfaces: {
750
- wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
751
- wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
752
- wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`,
753
- credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
754
- treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
755
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
756
- },
757
- generated_at_iso: nowIso()
758
- };
759
- }
760
-
761
- function buildWalletLedgerSummary(state, accountId) {
762
- const wallet = buildWalletSummary(state, accountId);
763
- const lifecycle = buildWalletLifecycleSummary(state, accountId);
764
- const allocations = listAllocationEventsForAccount(state, accountId);
765
- const spends = listCreditSpendsForAccount(state, accountId);
766
- const railCredits = listRailCreditsForAccount(state, accountId);
767
- const explicitCommitSpendIds = new Set(
768
- allocations
769
- .filter((entry) => entry && entry.direction === "commit" && entry.credit_spend_id)
770
- .map((entry) => entry.credit_spend_id)
771
- );
772
- const fallbackCommittedSpends = spends.filter((entry) => entry && !explicitCommitSpendIds.has(entry.credit_spend_id));
773
- const consequences = {
774
- mint_count: allocations.filter((entry) => entry && entry.direction === "mint").length + railCredits.length,
775
- reserve_count: allocations.filter((entry) => entry && entry.direction === "reserve").length,
776
- commit_count: allocations.filter((entry) => entry && entry.direction === "commit").length + fallbackCommittedSpends.length,
777
- release_count: allocations.filter((entry) => entry && entry.direction === "release").length,
778
- reverse_count: allocations.filter((entry) => entry && entry.direction === "reverse").length
779
- };
780
-
781
- return {
782
- summary_version: "xytara-wallet-ledger-summary-v1",
783
- wallet_id: wallet.wallet_id,
784
- account_id: accountId,
785
- canonical_truth_posture: "allocation_and_consequence_records_with_materialized_wallet_summary",
786
- canonical_lifecycle_model: lifecycle.canonical_lifecycle_model,
787
- canonical_unit: wallet.canonical_unit,
788
- wallet_state: wallet.wallet_state,
789
- wallet_summary: {
790
- issued_units: wallet.issued_units,
791
- available_units: wallet.available_units,
792
- reserved_units: wallet.reserved_units,
793
- committed_units: wallet.committed_units,
794
- released_units: wallet.released_units,
795
- reversed_units: wallet.reversed_units,
796
- consumed_units: wallet.consumed_units
797
- },
798
- lifecycle_state_summary: lifecycle.lifecycle_states,
799
- ledger_lifecycle_counts: consequences,
800
- source_record_counts: {
801
- allocation_count: allocations.length,
802
- rail_credit_count: railCredits.length,
803
- credit_spend_count: spends.length,
804
- entitlement_count: wallet.entitlement_count,
805
- usage_meter_count: wallet.usage_meter_count
806
- },
807
- translation_boundary: {
808
- public_commercial_shell: "credits",
809
- canonical_hidden_unit: "usage_units",
810
- canonical_wallet_truth: "hidden_machine_wallet",
811
- materialized_projection: "wallet_summary"
812
- },
813
- linked_surfaces: {
814
- wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
815
- wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
816
- ledger_export_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/ledger-export`,
817
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
818
- },
819
- generated_at_iso: nowIso()
820
- };
821
- }
822
-
823
- function buildWalletReserveSummary(state, accountId) {
824
- const allocations = listAllocationEventsForAccount(state, accountId);
825
- const reserveEvents = allocations.filter((entry) => entry && entry.direction === "reserve");
826
- const resolutionEvents = allocations.filter((entry) => entry && (entry.direction === "release" || entry.direction === "reverse"));
827
- const reserveRows = reserveEvents.map((reserve) => {
828
- const linkedResolutions = resolutionEvents.filter((entry) => entry && entry.resolves_allocation_id === reserve.allocation_id);
829
- const resolvedUnits = linkedResolutions.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
830
- const openUnits = Math.max(0, Number(reserve.units || 0) - resolvedUnits);
831
- return {
832
- reserve_ref: reserve.reserve_ref || `reserve.${reserve.allocation_id}`,
833
- allocation_id: reserve.allocation_id,
834
- account_id: reserve.account_id,
835
- units: Number(reserve.units || 0),
836
- open_units: openUnits,
837
- reserve_state: openUnits > 0 ? "open" : "resolved",
838
- reason: reserve.reason || null,
839
- created_at_iso: reserve.created_at_iso || null,
840
- linked_resolution_count: linkedResolutions.length,
841
- linked_resolutions: linkedResolutions.map((entry) => ({
842
- allocation_id: entry.allocation_id,
843
- direction: entry.direction,
844
- units: Number(entry.units || 0),
845
- reason: entry.reason || null,
846
- created_at_iso: entry.created_at_iso || null
847
- }))
848
- };
849
- });
850
-
851
- return {
852
- summary_version: "xytara-wallet-reserve-summary-v1",
853
- account_id: accountId,
854
- reserve_count: reserveRows.length,
855
- open_reserve_count: reserveRows.filter((entry) => entry.reserve_state === "open").length,
856
- resolved_reserve_count: reserveRows.filter((entry) => entry.reserve_state === "resolved").length,
857
- total_reserved_units: reserveRows.reduce((sum, entry) => sum + entry.units, 0),
858
- total_open_reserved_units: reserveRows.reduce((sum, entry) => sum + entry.open_units, 0),
859
- reserves: reserveRows,
860
- linked_surfaces: {
861
- wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
862
- wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
863
- wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
864
- wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
865
- },
866
- generated_at_iso: nowIso()
867
- };
868
- }
869
-
870
- function buildWalletCommitSummary(state, accountId) {
871
- const allocations = listAllocationEventsForAccount(state, accountId);
872
- const commitEvents = allocations.filter((entry) => entry && entry.direction === "commit");
873
- const reverseEvents = allocations.filter((entry) => entry && entry.direction === "reverse");
874
- const commitRows = commitEvents.map((commit) => {
875
- const linkedReversals = reverseEvents.filter((entry) => entry && entry.resolves_allocation_id === commit.allocation_id);
876
- const reversedUnits = linkedReversals.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
877
- const netCommittedUnits = Math.max(0, Number(commit.units || 0) - reversedUnits);
878
- return {
879
- commit_ref: commit.commit_ref || `commit.${commit.allocation_id}`,
880
- allocation_id: commit.allocation_id,
881
- account_id: commit.account_id,
882
- credit_spend_id: commit.credit_spend_id || null,
883
- usage_meter_id: commit.usage_meter_id || null,
884
- transaction_id: commit.transaction_id || null,
885
- receipt_ref: commit.receipt_ref || null,
886
- units: Number(commit.units || 0),
887
- net_committed_units: netCommittedUnits,
888
- commit_state: netCommittedUnits > 0 ? "active" : "fully_reversed",
889
- reason: commit.reason || null,
890
- created_at_iso: commit.created_at_iso || null,
891
- linked_reversal_count: linkedReversals.length,
892
- linked_reversals: linkedReversals.map((entry) => ({
893
- allocation_id: entry.allocation_id,
894
- direction: entry.direction,
895
- units: Number(entry.units || 0),
896
- reason: entry.reason || null,
897
- created_at_iso: entry.created_at_iso || null
898
- }))
899
- };
900
- });
901
-
902
- return {
903
- summary_version: "xytara-wallet-commit-summary-v1",
904
- account_id: accountId,
905
- commit_count: commitRows.length,
906
- active_commit_count: commitRows.filter((entry) => entry.commit_state === "active").length,
907
- fully_reversed_commit_count: commitRows.filter((entry) => entry.commit_state === "fully_reversed").length,
908
- total_committed_units: commitRows.reduce((sum, entry) => sum + entry.units, 0),
909
- total_net_committed_units: commitRows.reduce((sum, entry) => sum + entry.net_committed_units, 0),
910
- commits: commitRows,
911
- linked_surfaces: {
912
- wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
913
- wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
914
- wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
915
- wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
916
- },
917
- generated_at_iso: nowIso()
918
- };
919
- }
920
-
921
- function buildWalletLedgerBundle(state, accountId) {
922
- const wallet = buildWalletSummary(state, accountId);
923
- const lifecycle = buildWalletLifecycleSummary(state, accountId);
924
- const reserves = buildWalletReserveSummary(state, accountId);
925
- const commits = buildWalletCommitSummary(state, accountId);
926
- const ledger = buildWalletLedgerSummary(state, accountId);
927
- const balance = buildCreditBalanceSummary(state, accountId);
928
-
929
- return {
930
- bundle_version: "xytara-wallet-ledger-bundle-v1",
931
- account_id: accountId,
932
- wallet_id: wallet.wallet_id,
933
- canonical_unit: wallet.canonical_unit,
934
- canonical_truth_posture: ledger.canonical_truth_posture,
935
- canonical_lifecycle_model: lifecycle.canonical_lifecycle_model,
936
- bundle_state: {
937
- wallet_state: wallet.wallet_state,
938
- reserve_state: lifecycle.lifecycle_states.reserve_state,
939
- commit_state: lifecycle.lifecycle_states.commit_state,
940
- correction_state: lifecycle.lifecycle_states.correction_state,
941
- replenishment_posture: wallet.replenishment_posture
942
- },
943
- compact_totals: {
944
- issued_units: wallet.issued_units,
945
- available_units: wallet.available_units,
946
- consumed_units: wallet.consumed_units,
947
- open_reserved_units: lifecycle.lifecycle_totals.open_reserved_units,
948
- active_commit_units: commits.total_net_committed_units,
949
- reversed_units: lifecycle.lifecycle_totals.reversed_units
950
- },
951
- wallet_summary: wallet,
952
- wallet_lifecycle_summary: lifecycle,
953
- wallet_reserve_summary: reserves,
954
- wallet_commit_summary: commits,
955
- wallet_ledger_summary: ledger,
956
- credit_balance_summary: balance,
957
- linked_surfaces: {
958
- wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
959
- wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
960
- wallet_reserve_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-reserve-summary`,
961
- wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
962
- wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`,
963
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
964
- },
965
- generated_at_iso: nowIso()
966
- };
967
- }
968
-
969
- function applyWalletLifecycleEvent(state, body, direction) {
970
- const payload = ensureObject(body);
971
- const accountId = normalizeString(payload.account_id, "acct_demo");
972
- const units = typeof payload.units === "number" ? payload.units : 0;
973
- if (!(units > 0)) {
974
- return { ok: false, reason: "units_must_be_positive", account_id: accountId };
975
- }
976
-
977
- let reserveTarget = null;
978
- let resolvedTarget = null;
979
- if (direction === "release") {
980
- const resolvesAllocationId = normalizeString(payload.resolves_allocation_id, null);
981
- if (!resolvesAllocationId) {
982
- return { ok: false, reason: "resolves_allocation_id_required", account_id: accountId };
983
- }
984
- reserveTarget = getAllocationEvent(state, resolvesAllocationId);
985
- if (!reserveTarget || reserveTarget.account_id !== accountId || reserveTarget.direction !== "reserve") {
986
- return { ok: false, reason: "reserve_target_not_found", account_id: accountId, resolves_allocation_id: resolvesAllocationId };
987
- }
988
- }
989
- if (direction === "reverse") {
990
- const resolvesAllocationId = normalizeString(payload.resolves_allocation_id, null);
991
- if (resolvesAllocationId) {
992
- resolvedTarget = getAllocationEvent(state, resolvesAllocationId);
993
- if (!resolvedTarget || resolvedTarget.account_id !== accountId) {
994
- return { ok: false, reason: "reverse_target_not_found", account_id: accountId, resolves_allocation_id: resolvesAllocationId };
995
- }
996
- }
997
- }
998
-
999
- const lifecycle = buildWalletLifecycleSummary(state, accountId);
1000
- if (direction === "reserve" && lifecycle.lifecycle_totals.available_units < units) {
1001
- return {
1002
- ok: false,
1003
- reason: "insufficient_available_units",
1004
- account_id: accountId,
1005
- available_units: lifecycle.lifecycle_totals.available_units,
1006
- required_units: units
1007
- };
1008
- }
1009
-
1010
- if (direction === "release" && lifecycle.lifecycle_totals.open_reserved_units < units) {
1011
- return {
1012
- ok: false,
1013
- reason: "insufficient_open_reserved_units",
1014
- account_id: accountId,
1015
- open_reserved_units: lifecycle.lifecycle_totals.open_reserved_units,
1016
- required_units: units
1017
- };
1018
- }
1019
-
1020
- if (direction === "reverse" && lifecycle.lifecycle_totals.available_units < units) {
1021
- return {
1022
- ok: false,
1023
- reason: "insufficient_reversible_units",
1024
- account_id: accountId,
1025
- available_units: lifecycle.lifecycle_totals.available_units,
1026
- required_units: units
1027
- };
1028
- }
1029
-
1030
- const event = recordAllocationEvent(state, {
1031
- ...payload,
1032
- reserve_ref: direction === "reserve"
1033
- ? normalizeString(payload.reserve_ref, null)
1034
- : reserveTarget
1035
- ? reserveTarget.reserve_ref || `reserve.${reserveTarget.allocation_id}`
1036
- : normalizeString(payload.reserve_ref, null)
1037
- ,
1038
- commit_ref: resolvedTarget && resolvedTarget.direction === "commit"
1039
- ? resolvedTarget.commit_ref || `commit.${resolvedTarget.allocation_id}`
1040
- : normalizeString(payload.commit_ref, null)
1041
- }, direction);
1042
- return {
1043
- ok: true,
1044
- lifecycle_event: event,
1045
- wallet_lifecycle_summary: buildWalletLifecycleSummary(state, accountId),
1046
- wallet_reserve_summary: buildWalletReserveSummary(state, accountId),
1047
- wallet_commit_summary: buildWalletCommitSummary(state, accountId),
1048
- balance: buildCreditBalanceSummary(state, accountId)
1049
- };
1050
- }
1051
-
1052
- function getWorkflowTaskRefs(workflowRef) {
1053
- const workflow = findWorkflow(workflowRef);
1054
- if (!workflow || !Array.isArray(workflow.tasks)) return [];
1055
- return workflow.tasks
1056
- .map((entry) => entry && (entry.task_ref || entry.public_task_ref || entry.task_id))
1057
- .filter(Boolean);
1058
- }
1059
-
1060
- function buildUsageMeterBase(payload) {
1061
- const taskRef = normalizeString(payload.task_ref, null);
1062
- const workflowRef = normalizeString(payload.workflow_ref, null);
1063
- const task = taskRef ? findTask(taskRef) : null;
1064
- const workflowTaskRefs = workflowRef ? getWorkflowTaskRefs(workflowRef) : [];
1065
- const workflowTasks = workflowTaskRefs.map((ref) => findTask(ref)).filter(Boolean);
1066
- const pricingBand = task
1067
- ? task.pricing_band
1068
- : workflowTasks.length > 0
1069
- ? workflowTasks.reduce((selected, entry) => {
1070
- const currentUnits = PRICING_BAND_UNITS[entry.pricing_band] || 1;
1071
- const selectedUnits = PRICING_BAND_UNITS[selected] || 1;
1072
- return currentUnits > selectedUnits ? entry.pricing_band : selected;
1073
- }, workflowTasks[0].pricing_band || "utility")
1074
- : "utility";
1075
- const taskDomain = task
1076
- ? task.public_category || null
1077
- : workflowTasks.length > 0
1078
- ? Array.from(new Set(workflowTasks.map((entry) => entry.public_category).filter(Boolean))).join(",")
1079
- : null;
1080
- const suggestedUnits = task
1081
- ? (PRICING_BAND_UNITS[task.pricing_band] || 1)
1082
- : workflowTasks.length > 0
1083
- ? workflowTasks.reduce((sum, entry) => sum + (PRICING_BAND_UNITS[entry.pricing_band] || 1), 0)
1084
- : 1;
1085
- return {
1086
- task_ref: taskRef,
1087
- workflow_ref: workflowRef,
1088
- pricing_band: pricingBand,
1089
- task_domain: taskDomain,
1090
- workflow_task_refs: workflowTaskRefs,
1091
- suggested_units: suggestedUnits
1092
- };
1093
- }
1094
-
1095
- function resolveUsageMeterUnits(payload, base) {
1096
- if (typeof payload.units === "number" && Number.isFinite(payload.units) && payload.units > 0) return payload.units;
1097
- if (typeof payload.quoted_units === "number" && Number.isFinite(payload.quoted_units) && payload.quoted_units > 0) return payload.quoted_units;
1098
- return base.suggested_units;
1099
- }
1100
-
1101
- function createUsageMeterRecord(state, body) {
1102
- const payload = ensureObject(body);
1103
- const accountId = normalizeString(payload.account_id, "acct_demo");
1104
- const base = buildUsageMeterBase(payload);
1105
- const units = resolveUsageMeterUnits(payload, base);
1106
- const meterInput = {
1107
- account_id: accountId,
1108
- task_ref: base.task_ref,
1109
- workflow_ref: base.workflow_ref,
1110
- pricing_band: base.pricing_band,
1111
- task_domain: base.task_domain,
1112
- units,
1113
- quote_id: normalizeString(payload.quote_id, null),
1114
- credit_spend_id: normalizeString(payload.credit_spend_id, null),
1115
- transaction_id: normalizeString(payload.transaction_id, null),
1116
- meter_kind: normalizeString(payload.meter_kind, "credit_spend"),
1117
- pack_id: normalizeString(payload.pack_id, null),
1118
- entitlement_id: normalizeString(payload.entitlement_id, null)
1119
- };
1120
- const fingerprint = crypto.createHash("sha256").update(JSON.stringify(meterInput)).digest("hex").slice(0, 16);
1121
- const usageMeterId = normalizeString(payload.usage_meter_id, `usage_meter_${fingerprint}`);
1122
- const createdAt = nowIso();
1123
- const record = {
1124
- usage_meter_id: usageMeterId,
1125
- ...meterInput,
1126
- workflow_task_refs: base.workflow_task_refs,
1127
- deterministic_profile: {
1128
- pricing_band: base.pricing_band,
1129
- suggested_units: base.suggested_units,
1130
- explicit_units: typeof payload.units === "number" || typeof payload.quoted_units === "number"
1131
- },
1132
- created_at_iso: createdAt
1133
- };
1134
- state.economicsUsageMeters.set(usageMeterId, record);
1135
- return record;
1136
- }
1137
-
1138
- function listUsageMetersForAccount(state, accountId) {
1139
- return Array.from(state.economicsUsageMeters.values())
1140
- .filter((item) => item && item.account_id === accountId)
1141
- .sort((left, right) => String(right.created_at_iso || "").localeCompare(String(left.created_at_iso || "")) || String(right.usage_meter_id || "").localeCompare(String(left.usage_meter_id || "")));
1142
- }
1143
-
1144
- function getUsageMeter(state, usageMeterId) {
1145
- if (!usageMeterId) return null;
1146
- return state.economicsUsageMeters.get(usageMeterId) || null;
1147
- }
1148
-
1149
- function buildUsageMeterPreview(state, body) {
1150
- const payload = ensureObject(body);
1151
- const accountId = normalizeString(payload.account_id, "acct_demo");
1152
- const base = buildUsageMeterBase(payload);
1153
- const units = resolveUsageMeterUnits(payload, base);
1154
- return {
1155
- ok: true,
1156
- account_id: accountId,
1157
- task_ref: base.task_ref,
1158
- workflow_ref: base.workflow_ref,
1159
- pricing_band: base.pricing_band,
1160
- task_domain: base.task_domain,
1161
- workflow_task_refs: base.workflow_task_refs,
1162
- usage_units: units,
1163
- deterministic_profile: {
1164
- pricing_band: base.pricing_band,
1165
- suggested_units: base.suggested_units,
1166
- explicit_units: typeof payload.units === "number" || typeof payload.quoted_units === "number"
1167
- },
1168
- generated_at_iso: nowIso()
1169
- };
1170
- }
1171
-
1172
- function buildUsageMeteringSummary(state, accountId) {
1173
- const usageMeters = listUsageMetersForAccount(state, accountId);
1174
- return {
1175
- account_id: accountId,
1176
- usage_meter_count: usageMeters.length,
1177
- total_units: usageMeters.reduce((sum, entry) => sum + Number(entry.units || 0), 0),
1178
- pricing_bands: Array.from(new Set(usageMeters.map((entry) => entry.pricing_band).filter(Boolean))),
1179
- latest_usage_meter_id: usageMeters.length > 0 ? usageMeters[0].usage_meter_id : null,
1180
- generated_at_iso: nowIso()
1181
- };
1182
- }
1183
-
1184
- function buildEconomicConsequenceHandoffBundle(state, body) {
1185
- const payload = ensureObject(body);
1186
- const accountId = normalizeString(payload.account_id, "acct_demo");
1187
- const usageMeterId = normalizeString(payload.usage_meter_id, null);
1188
- const creditSpendId = normalizeString(payload.credit_spend_id, null);
1189
- if (!usageMeterId) {
1190
- return { ok: false, reason: "usage_meter_id_required" };
1191
- }
1192
- if (!creditSpendId) {
1193
- return { ok: false, reason: "credit_spend_id_required" };
1194
- }
1195
- const usageMeter = getUsageMeter(state, usageMeterId);
1196
- if (!usageMeter || usageMeter.account_id !== accountId) {
1197
- return { ok: false, reason: "usage_meter_not_found", usage_meter_id: usageMeterId };
1198
- }
1199
- const creditSpend = getCreditSpend(state, creditSpendId);
1200
- if (!creditSpend || creditSpend.account_id !== accountId) {
1201
- return { ok: false, reason: "credit_spend_not_found", credit_spend_id: creditSpendId };
1202
- }
1203
- if (normalizeString(usageMeter.credit_spend_id, null) !== creditSpend.credit_spend_id) {
1204
- return {
1205
- ok: false,
1206
- reason: "usage_meter_credit_spend_mismatch",
1207
- usage_meter_id: usageMeterId,
1208
- credit_spend_id: creditSpendId
1209
- };
1210
- }
1211
- const meterProfileRef = normalizeString(payload.meter_profile_ref, `meter-profile.${usageMeter.pricing_band || "utility"}.v1`);
1212
- const paymentRef = normalizeString(payload.payment_ref, null);
1213
- const settlementRef = normalizeString(payload.settlement_ref, null);
1214
- const settlementTxid = normalizeString(payload.settlement_txid, null);
1215
- const settlementStatus = normalizeString(payload.settlement_status, null);
1216
- const settlementFinalityStatus = normalizeString(payload.settlement_finality_status, null);
1217
- const treasuryReceiptRef = normalizeString(payload.treasury_receipt_ref, null);
1218
- const proofRef = normalizeString(payload.proof_ref, null);
1219
- const handoffBundle = {
1220
- contract_version: "naxytra-economic-consequence-handoff-v1",
1221
- source_system: "xytara",
1222
- account_ref: accountId,
1223
- usage_meter_ref: usageMeter.usage_meter_id,
1224
- meter_profile_ref: meterProfileRef,
1225
- credit_spend_ref: creditSpend.credit_spend_id,
1226
- usage_meter: usageMeter,
1227
- credit_spend: creditSpend,
1228
- payment_ref: paymentRef,
1229
- settlement_ref: settlementRef,
1230
- settlement_txid: settlementTxid,
1231
- settlement_status: settlementStatus,
1232
- settlement_finality_status: settlementFinalityStatus,
1233
- treasury_receipt_ref: treasuryReceiptRef,
1234
- proof_ref: proofRef,
1235
- handoff_surfaces: {
1236
- proof_bridge_surface: "/v1/proof-center/bridge/economic-handoff",
1237
- proof_conformance_surface: "/v1/proof-center/bridge/economic-conformance-pack"
1238
- },
1239
- generated_at_iso: nowIso()
1240
- };
1241
- return {
1242
- ok: true,
1243
- handoff_bundle: handoffBundle
1244
- };
1245
- }
1246
-
1247
- function consumeAccountCredits(state, body) {
1248
- const payload = ensureObject(body);
1249
- const accountId = normalizeString(payload.account_id, "acct_demo");
1250
- const usageMeterPreview = buildUsageMeterPreview(state, payload);
1251
- const units = usageMeterPreview.usage_units;
1252
- const balance = buildCreditBalanceSummary(state, accountId);
1253
- const policyDecision = buildCreditSpendPolicyDecision(state, payload);
1254
- const entitlementDecision = selectEntitlementPool(state, payload);
1255
- if (!policyDecision.ok) {
1256
- return {
1257
- ok: false,
1258
- ...policyDecision
1259
- };
1260
- }
1261
- if (!entitlementDecision.ok) {
1262
- return {
1263
- ok: false,
1264
- ...entitlementDecision
1265
- };
1266
- }
1267
- if (balance.available_units < units) {
1268
- return {
1269
- ok: false,
1270
- reason: "insufficient_credits",
1271
- required_units: units,
1272
- available_units: balance.available_units
1273
- };
1274
- }
1275
- if (policyDecision.budget_id) {
1276
- const alreadySpentUnderBudget = listCreditSpendsForAccount(state, accountId)
1277
- .filter((entry) => entry && entry.budget_id === policyDecision.budget_id)
1278
- .reduce((sum, entry) => sum + (entry.units || 0), 0);
1279
- const nextSpentUnderBudget = alreadySpentUnderBudget + units;
1280
- if (policyDecision.max_reserve_units != null && nextSpentUnderBudget > policyDecision.max_reserve_units) {
1281
- return {
1282
- ok: false,
1283
- reason: "budget_limit_exceeded",
1284
- budget_id: policyDecision.budget_id,
1285
- max_reserve_units: policyDecision.max_reserve_units,
1286
- attempted_units: units,
1287
- spent_units: alreadySpentUnderBudget,
1288
- next_spent_units: nextSpentUnderBudget
1289
- };
1290
- }
1291
- }
1292
- const spend = {
1293
- credit_spend_id: normalizeString(payload.credit_spend_id, `credit_spend_${ensureArray(state.economicsCreditSpends).length + 1}`),
1294
- account_id: accountId,
1295
- transaction_id: normalizeString(payload.transaction_id, null),
1296
- receipt_id: normalizeString(payload.receipt_id, null),
1297
- quote_id: normalizeString(payload.quote_id, null),
1298
- task_ref: normalizeString(payload.task_ref, null),
1299
- task_domain: policyDecision.task_domain,
1300
- agent_id: policyDecision.agent_id,
1301
- budget_id: policyDecision.budget_id,
1302
- policy_ref: policyDecision.policy_ref,
1303
- entitlement_id: entitlementDecision.entitlement ? entitlementDecision.entitlement.entitlement_id : null,
1304
- pack_id: entitlementDecision.entitlement ? entitlementDecision.entitlement.pack_id || null : normalizeString(payload.pack_id, null),
1305
- units,
1306
- reason: normalizeString(payload.reason, "execution_credit_spend"),
1307
- created_at_iso: nowIso()
1308
- };
1309
- const usageMeter = createUsageMeterRecord(state, {
1310
- account_id: accountId,
1311
- task_ref: spend.task_ref,
1312
- workflow_ref: normalizeString(payload.workflow_ref, null),
1313
- task_domain: spend.task_domain,
1314
- units,
1315
- quote_id: spend.quote_id,
1316
- credit_spend_id: spend.credit_spend_id,
1317
- transaction_id: spend.transaction_id,
1318
- pack_id: spend.pack_id,
1319
- entitlement_id: spend.entitlement_id,
1320
- meter_kind: "credit_spend"
1321
- });
1322
- spend.usage_meter_id = usageMeter.usage_meter_id;
1323
- spend.usage_meter = {
1324
- usage_meter_id: usageMeter.usage_meter_id,
1325
- pricing_band: usageMeter.pricing_band,
1326
- units: usageMeter.units
1327
- };
1328
- if (entitlementDecision.entitlement) {
1329
- const nextEntitlement = {
1330
- ...entitlementDecision.entitlement,
1331
- consumed_units: (entitlementDecision.entitlement.consumed_units || 0) + units,
1332
- remaining_units: Math.max(0, (entitlementDecision.entitlement.remaining_units || 0) - units),
1333
- updated_at_iso: spend.created_at_iso
1334
- };
1335
- state.economicsEntitlements.set(nextEntitlement.entitlement_id, nextEntitlement);
1336
- spend.entitlement = {
1337
- entitlement_id: nextEntitlement.entitlement_id,
1338
- pack_id: nextEntitlement.pack_id || null,
1339
- remaining_units: nextEntitlement.remaining_units
1340
- };
1341
- }
1342
- recordAllocationEvent(state, {
1343
- allocation_id: `alloc_commit_${spend.credit_spend_id}`,
1344
- account_id: accountId,
1345
- budget_id: spend.budget_id,
1346
- job_id: normalizeString(payload.job_id, null),
1347
- agent_id: spend.agent_id,
1348
- receipt_ref: spend.receipt_id,
1349
- transaction_id: spend.transaction_id,
1350
- credit_spend_id: spend.credit_spend_id,
1351
- usage_meter_id: usageMeter.usage_meter_id,
1352
- lifecycle_ref: `commit.${spend.credit_spend_id}`,
1353
- commit_ref: `commit.${spend.credit_spend_id}`,
1354
- units,
1355
- reason: spend.reason
1356
- }, "commit");
1357
- state.economicsCreditSpends = [spend, ...ensureArray(state.economicsCreditSpends)].slice(0, 500);
1358
- return {
1359
- ok: true,
1360
- credit_spend: spend,
1361
- balance: buildCreditBalanceSummary(state, accountId)
1362
- };
1363
- }
1364
-
1365
- function previewCreditSpend(state, body) {
1366
- const payload = ensureObject(body);
1367
- const accountId = normalizeString(payload.account_id, "acct_demo");
1368
- const usageMeterPreview = buildUsageMeterPreview(state, payload);
1369
- const units = usageMeterPreview.usage_units;
1370
- const balance = buildCreditBalanceSummary(state, accountId);
1371
- const policyDecision = buildCreditSpendPolicyDecision(state, payload);
1372
- const entitlementDecision = selectEntitlementPool(state, payload);
1373
- const preview = {
1374
- ok: Boolean(policyDecision.ok),
1375
- account_id: accountId,
1376
- task_ref: normalizeString(payload.task_ref, null),
1377
- units,
1378
- balance,
1379
- spend_posture: policyDecision.budget_id || policyDecision.agent_id ? "bounded_spend" : "open_spend",
1380
- entitlement_guard: {
1381
- reason: entitlementDecision.reason || null,
1382
- entitlement_id: entitlementDecision.entitlement ? entitlementDecision.entitlement.entitlement_id : normalizeString(payload.entitlement_id, null),
1383
- pack_id: entitlementDecision.entitlement ? entitlementDecision.entitlement.pack_id || null : normalizeString(payload.pack_id, null)
1384
- },
1385
- policy_guard: {
1386
- reason: policyDecision.reason || null,
1387
- task_domain: policyDecision.task_domain || null,
1388
- agent_id: policyDecision.agent_id || normalizeString(payload.agent_id, null),
1389
- budget_id: policyDecision.budget_id || normalizeString(payload.budget_id, null),
1390
- policy_ref: policyDecision.policy_ref || null,
1391
- max_reserve_units: policyDecision.max_reserve_units || null,
1392
- allowed_job_domains: policyDecision.allowed_job_domains || null,
1393
- budget_status: policyDecision.budget_status || null,
1394
- agent_status: policyDecision.agent_status || null
1395
- },
1396
- credit_spend_preview: {
1397
- available_units: balance.available_units,
1398
- required_units: units,
1399
- executable_now: false,
1400
- next_balance_units: balance.available_units,
1401
- failure_reason: null
1402
- },
1403
- usage_meter_preview: usageMeterPreview,
1404
- generated_at_iso: nowIso()
1405
- };
1406
-
1407
- if (!policyDecision.ok) {
1408
- preview.credit_spend_preview.failure_reason = policyDecision.reason;
1409
- return preview;
1410
- }
1411
-
1412
- if (!entitlementDecision.ok) {
1413
- preview.ok = false;
1414
- preview.credit_spend_preview.failure_reason = entitlementDecision.reason;
1415
- return preview;
1416
- }
1417
-
1418
- if (balance.available_units < units) {
1419
- preview.ok = false;
1420
- preview.credit_spend_preview.failure_reason = "insufficient_credits";
1421
- return preview;
1422
- }
1423
-
1424
- if (policyDecision.budget_id) {
1425
- const alreadySpentUnderBudget = listCreditSpendsForAccount(state, accountId)
1426
- .filter((entry) => entry && entry.budget_id === policyDecision.budget_id)
1427
- .reduce((sum, entry) => sum + (entry.units || 0), 0);
1428
- const nextSpentUnderBudget = alreadySpentUnderBudget + units;
1429
- preview.credit_spend_preview.budget_spent_units = alreadySpentUnderBudget;
1430
- preview.credit_spend_preview.next_budget_spent_units = nextSpentUnderBudget;
1431
- if (policyDecision.max_reserve_units != null && nextSpentUnderBudget > policyDecision.max_reserve_units) {
1432
- preview.ok = false;
1433
- preview.credit_spend_preview.failure_reason = "budget_limit_exceeded";
1434
- return preview;
1435
- }
1436
- }
1437
-
1438
- preview.credit_spend_preview.executable_now = true;
1439
- preview.credit_spend_preview.next_balance_units = Math.max(0, balance.available_units - units);
1440
- preview.credit_spend_preview.entitlement_id = entitlementDecision.entitlement ? entitlementDecision.entitlement.entitlement_id : null;
1441
- preview.credit_spend_preview.pack_id = entitlementDecision.entitlement ? entitlementDecision.entitlement.pack_id || null : normalizeString(payload.pack_id, null);
1442
- preview.credit_spend_preview.usage_meter_units = preview.usage_meter_preview.usage_units;
1443
- preview.credit_spend_preview.pricing_band = preview.usage_meter_preview.pricing_band;
1444
- return preview;
1445
- }
1446
-
1447
- function listMapValuesByAccount(map, accountId) {
1448
- return Array.from(map.values()).filter((item) => item && item.account_id === accountId);
1449
- }
1450
-
1451
- function listAllocationEventsForAccount(state, accountId) {
1452
- return ensureArray(state.economicsAllocations).filter((item) => item && item.account_id === accountId);
1453
- }
1454
-
1455
- function listRailCreditsForAccount(state, accountId) {
1456
- return ensureArray(state.economicsRailCredits).filter((item) => item && item.account_id === accountId);
1457
- }
1458
-
1459
- function listPaymentLedgerForAccount(state, accountId) {
1460
- return ensureArray(state.paymentLedger).filter((item) => item && item.account_id === accountId);
1461
- }
1462
-
1463
- function listTransactionsForAccount(state, accountId) {
1464
- return Array.from(state.transactions.values())
1465
- .map((entry) => entry && entry.transaction)
1466
- .filter((item) => item && item.account_id === accountId);
1467
- }
1468
-
1469
- function listReceiptsForAccount(state, accountId) {
1470
- return Array.from(state.receipts.values())
1471
- .map((entry) => entry && entry.receipt)
1472
- .filter((item) => item && item.account_id === accountId);
1473
- }
1474
-
1475
- function listEconomicsJobActionsForAccount(state, accountId) {
1476
- return ensureArray(state.economicsJobActions).filter((item) => item && item.account_id === accountId);
1477
- }
1478
-
1479
- function buildTreasurySummary(state, accountId) {
1480
- const allocations = listAllocationEventsForAccount(state, accountId);
1481
- const credits = listRailCreditsForAccount(state, accountId);
1482
- const spends = listCreditSpendsForAccount(state, accountId);
1483
- const paymentLedger = listPaymentLedgerForAccount(state, accountId);
1484
- const budgets = listMapValuesByAccount(state.economicsBudgets, accountId);
1485
- const railCreditLifecycle = summarizeRailCreditLifecycle(credits);
1486
- const mintedUnits = allocations.filter((entry) => entry.direction === "mint").reduce((sum, entry) => sum + (entry.units || 0), 0)
1487
- + railCreditLifecycle.minted_units;
1488
- const reversedUnits = allocations.filter((entry) => entry.direction === "reverse").reduce((sum, entry) => sum + (entry.units || 0), 0)
1489
- + railCreditLifecycle.reversed_units;
1490
- const consumedUnits = spends.reduce((sum, entry) => sum + (entry.units || 0), 0);
1491
- const settledMinor = paymentLedger.reduce((sum, entry) => sum + (entry.amount_minor || 0), 0);
1492
- const committedUnits = listTransactionsForAccount(state, accountId).length;
1493
- return {
1494
- account_id: accountId,
1495
- treasury: {
1496
- minted_units: mintedUnits,
1497
- consumed_units: consumedUnits,
1498
- available_units: Math.max(0, mintedUnits - consumedUnits - reversedUnits),
1499
- committed_units: committedUnits,
1500
- reversed_units: reversedUnits,
1501
- settled_amount_minor: settledMinor
1502
- },
1503
- budgets: {
1504
- total: budgets.length,
1505
- active: budgets.filter((entry) => entry.status === "active").length,
1506
- total_committed_units: committedUnits
1507
- },
1508
- payment_ledger_count: paymentLedger.length,
1509
- generated_at_iso: nowIso()
1510
- };
1511
- }
1512
-
1513
- function selectRecommendedCreditPack(totalUnits, usageMeterCount) {
1514
- if (totalUnits >= 1500 || usageMeterCount >= 20) return "credits.fleet";
1515
- if (totalUnits >= 500 || usageMeterCount >= 10) return "credits.agent";
1516
- if (totalUnits >= 100 || usageMeterCount >= 3) return "credits.builder";
1517
- if (totalUnits > 0 || usageMeterCount > 0) return "credits.starter";
1518
- return null;
1519
- }
1520
-
1521
- function buildEconomicsIntelligenceSummary(state, accountId) {
1522
- const balanceSummary = buildCreditBalanceSummary(state, accountId);
1523
- const meteringSummary = buildUsageMeteringSummary(state, accountId);
1524
- const replenishmentSummary = buildEntitlementReplenishmentSummary(state, accountId);
1525
- const treasurySummary = buildTreasurySummary(state, accountId);
1526
-
1527
- const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1528
- const totalUnits = Number(meteringSummary.total_units || 0);
1529
- const availableUnits = Number(balanceSummary.available_units || 0);
1530
- const consumedUnits = Number(balanceSummary.consumed_units || 0);
1531
- const lowBalanceCount = Number(replenishmentSummary.low_balance_count || 0);
1532
- const depletedCount = Number(replenishmentSummary.depleted_count || 0);
1533
- const mintedUnits = Number(treasurySummary.treasury && treasurySummary.treasury.minted_units || 0);
1534
- const settledAmountMinor = Number(treasurySummary.treasury && treasurySummary.treasury.settled_amount_minor || 0);
1535
- const budgetCount = Number(treasurySummary.budgets && treasurySummary.budgets.total || 0);
1536
-
1537
- let recommendedFundingPosture = "direct_pay_first";
1538
- if (availableUnits > 0 || consumedUnits > 0 || usageMeterCount > 0) {
1539
- recommendedFundingPosture = "credits_first";
1540
- }
1541
- if (availableUnits <= 0 && (usageMeterCount > 0 || consumedUnits > 0)) {
1542
- recommendedFundingPosture = "pack_backed_credits_first";
1543
- }
1544
-
1545
- const recommendedPackId = replenishmentSummary.recommended_pack_ids[0] || selectRecommendedCreditPack(totalUnits, usageMeterCount);
1546
-
1547
- let replenishmentRiskState = "low";
1548
- if (lowBalanceCount > 0) replenishmentRiskState = "watch";
1549
- if (depletedCount > 0 || (availableUnits > 0 && availableUnits <= Math.max(8, totalUnits))) {
1550
- replenishmentRiskState = "high";
1551
- }
1552
-
1553
- let treasuryHealthState = "healthy";
1554
- if (mintedUnits === 0 && settledAmountMinor === 0 && usageMeterCount === 0) {
1555
- treasuryHealthState = "pre_funding";
1556
- } else if (availableUnits <= 0 && (consumedUnits > 0 || usageMeterCount > 0)) {
1557
- treasuryHealthState = "constrained";
1558
- } else if (lowBalanceCount > 0 || budgetCount > 0) {
1559
- treasuryHealthState = "watch";
1560
- }
1561
-
1562
- let nextBestAction = "continue_current_posture";
1563
- if (recommendedFundingPosture === "direct_pay_first") {
1564
- nextBestAction = "start_with_direct_pay";
1565
- }
1566
- if (recommendedFundingPosture === "credits_first" && recommendedPackId && usageMeterCount >= 3) {
1567
- nextBestAction = "consider_pack_funding";
1568
- }
1569
- if (replenishmentRiskState === "watch") {
1570
- nextBestAction = "prepare_replenishment";
1571
- }
1572
- if (replenishmentRiskState === "high") {
1573
- nextBestAction = "replenish_credits";
1574
- }
1575
- if (treasuryHealthState === "constrained") {
1576
- nextBestAction = "restore_runtime_balance";
1577
- }
1578
-
1579
- return {
1580
- account_id: accountId,
1581
- category: "machine-commerce-account-economics-intelligence-summary",
1582
- recommended_funding_posture: recommendedFundingPosture,
1583
- recommended_pack_id: recommendedPackId,
1584
- replenishment_risk_state: replenishmentRiskState,
1585
- treasury_health_state: treasuryHealthState,
1586
- next_best_action: nextBestAction,
1587
- explanation_signals: {
1588
- available_units: availableUnits,
1589
- consumed_units: consumedUnits,
1590
- usage_meter_count: usageMeterCount,
1591
- metered_units: totalUnits,
1592
- low_balance_count: lowBalanceCount,
1593
- depleted_count: depletedCount,
1594
- recommended_replenishment_pack_ids: replenishmentSummary.recommended_pack_ids,
1595
- pricing_bands: meteringSummary.pricing_bands,
1596
- minted_units: mintedUnits,
1597
- settled_amount_minor: settledAmountMinor,
1598
- budget_count: budgetCount
1599
- },
1600
- linked_surfaces: {
1601
- credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
1602
- metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`,
1603
- entitlement_replenishment_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/entitlements/replenishment-summary`,
1604
- treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
1605
- operator_dashboard_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/operator-dashboard`
1606
- },
1607
- generated_at_iso: nowIso()
1608
- };
1609
- }
1610
-
1611
- function buildTreasuryIntelligenceSummary(state, accountId) {
1612
- const treasurySummary = buildTreasurySummary(state, accountId);
1613
- const treasuryDrilldown = buildTreasuryDrilldown(state, accountId);
1614
- const reconciliationPack = buildReconciliationPack(state, accountId);
1615
- const meteringSummary = buildUsageMeteringSummary(state, accountId);
1616
- const balanceSummary = buildCreditBalanceSummary(state, accountId);
1617
- const railSummary = buildRailSummary(state, accountId);
1618
-
1619
- const mintedUnits = Number(treasurySummary.treasury.minted_units || 0);
1620
- const consumedUnits = Number(treasurySummary.treasury.consumed_units || 0);
1621
- const availableUnits = Number(treasurySummary.treasury.available_units || 0);
1622
- const settledAmountMinor = Number(treasurySummary.treasury.settled_amount_minor || 0);
1623
- const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1624
- const pendingTransactions = Number(treasuryDrilldown.unresolved_flags.pending_transactions || 0);
1625
- const pendingReceipts = Number(treasuryDrilldown.unresolved_flags.pending_receipts || 0);
1626
- const disputedReceipts = Number(reconciliationPack.unresolved_state.disputed_receipt_count || 0);
1627
- const escalatedReceipts = Number(reconciliationPack.unresolved_state.escalated_receipt_count || 0);
1628
- const paymentLedgerCount = Number(treasurySummary.payment_ledger_count || 0);
1629
- const railCreditEventCount = Number(railSummary.credit_event_count || 0);
1630
-
1631
- let treasuryEfficiencyState = "healthy";
1632
- if (mintedUnits === 0 && settledAmountMinor === 0 && usageMeterCount === 0) {
1633
- treasuryEfficiencyState = "pre_funding";
1634
- } else if (availableUnits <= 0 && (consumedUnits > 0 || usageMeterCount > 0)) {
1635
- treasuryEfficiencyState = "constrained";
1636
- } else if (pendingTransactions > 0 || pendingReceipts > 0) {
1637
- treasuryEfficiencyState = "watch";
1638
- }
1639
-
1640
- let valueCaptureState = "aligned";
1641
- if (usageMeterCount === 0 && paymentLedgerCount === 0 && railCreditEventCount === 0) {
1642
- valueCaptureState = "pre_conversion";
1643
- } else if (usageMeterCount >= 3 && paymentLedgerCount <= 1 && consumedUnits > 0) {
1644
- valueCaptureState = "repeat_use_ready";
1645
- } else if (consumedUnits > mintedUnits && mintedUnits > 0) {
1646
- valueCaptureState = "leaking";
1647
- }
1648
-
1649
- let reconciliationRiskState = "low";
1650
- if (pendingTransactions > 0 || pendingReceipts > 0) reconciliationRiskState = "watch";
1651
- if (disputedReceipts > 0 || escalatedReceipts > 0) reconciliationRiskState = "high";
1652
-
1653
- let replenishmentFatigueState = "low";
1654
- if (railCreditEventCount >= 2 && availableUnits <= Math.max(8, meteringSummary.total_units || 0)) {
1655
- replenishmentFatigueState = "watch";
1656
- }
1657
- if (railCreditEventCount >= 3 && balanceSummary.replenishment_summary.low_balance_count > 0) {
1658
- replenishmentFatigueState = "high";
1659
- }
1660
-
1661
- let nextBestAction = "continue_treasury_posture";
1662
- if (treasuryEfficiencyState === "pre_funding") {
1663
- nextBestAction = "establish_runtime_funding";
1664
- } else if (treasuryEfficiencyState === "constrained") {
1665
- nextBestAction = "restore_runtime_balance";
1666
- } else if (reconciliationRiskState === "high") {
1667
- nextBestAction = "review_reconciliation_pack";
1668
- } else if (reconciliationRiskState === "watch") {
1669
- nextBestAction = "inspect_treasury_drilldown";
1670
- } else if (replenishmentFatigueState === "high" || valueCaptureState === "repeat_use_ready") {
1671
- nextBestAction = "recommend_larger_pack_posture";
1672
- }
1673
-
1674
- return {
1675
- account_id: accountId,
1676
- category: "machine-commerce-account-treasury-intelligence-summary",
1677
- treasury_efficiency_state: treasuryEfficiencyState,
1678
- value_capture_state: valueCaptureState,
1679
- reconciliation_risk_state: reconciliationRiskState,
1680
- replenishment_fatigue_state: replenishmentFatigueState,
1681
- next_best_action: nextBestAction,
1682
- explanation_signals: {
1683
- minted_units: mintedUnits,
1684
- consumed_units: consumedUnits,
1685
- available_units: availableUnits,
1686
- settled_amount_minor: settledAmountMinor,
1687
- usage_meter_count: usageMeterCount,
1688
- payment_ledger_count: paymentLedgerCount,
1689
- rail_credit_event_count: railCreditEventCount,
1690
- pending_transaction_count: pendingTransactions,
1691
- pending_receipt_count: pendingReceipts,
1692
- disputed_receipt_count: disputedReceipts,
1693
- escalated_receipt_count: escalatedReceipts
1694
- },
1695
- linked_surfaces: {
1696
- treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
1697
- treasury_drilldown_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-drilldown`,
1698
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`,
1699
- metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`,
1700
- rail_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/rail-summary`
1701
- },
1702
- generated_at_iso: nowIso()
1703
- };
1704
- }
1705
-
1706
- function buildLedgerExport(state, accountId) {
1707
- return {
1708
- export_version: "xytara-economics-ledger-export-v1",
1709
- account: {
1710
- account_id: accountId
1711
- },
1712
- budgets: listMapValuesByAccount(state.economicsBudgets, accountId),
1713
- agents: listMapValuesByAccount(state.economicsAgents, accountId),
1714
- economics_receipts: listMapValuesByAccount(state.economicsReceipts, accountId),
1715
- entitlements: listEntitlementsForAccount(state, accountId),
1716
- allocations: listAllocationEventsForAccount(state, accountId),
1717
- rail_credits: listRailCreditsForAccount(state, accountId),
1718
- credit_spends: listCreditSpendsForAccount(state, accountId),
1719
- payment_ledger: listPaymentLedgerForAccount(state, accountId),
1720
- governed_transactions: listTransactionsForAccount(state, accountId),
1721
- generated_at_iso: nowIso()
1722
- };
1723
- }
1724
-
1725
- function buildTreasuryDrilldown(state, accountId) {
1726
- const summary = buildTreasurySummary(state, accountId);
1727
- const paymentLedger = listPaymentLedgerForAccount(state, accountId);
1728
- return {
1729
- account_id: accountId,
1730
- summary,
1731
- latest_payment_entries: paymentLedger.slice(0, 10),
1732
- latest_allocation_entries: listAllocationEventsForAccount(state, accountId).slice(0, 10),
1733
- latest_credit_entries: listRailCreditsForAccount(state, accountId).slice(0, 10),
1734
- latest_entitlement_entries: listEntitlementsForAccount(state, accountId).slice(0, 10),
1735
- latest_credit_spend_entries: listCreditSpendsForAccount(state, accountId).slice(0, 10),
1736
- unresolved_flags: {
1737
- pending_transactions: listTransactionsForAccount(state, accountId).filter((entry) => entry.status !== "completed").length,
1738
- pending_receipts: listMapValuesByAccount(state.economicsReceipts, accountId).filter((entry) => entry.lifecycle_status !== "validated").length
1739
- },
1740
- generated_at_iso: nowIso()
1741
- };
1742
- }
1743
-
1744
- function buildReconciliationPack(state, accountId) {
1745
- const treasury = buildTreasurySummary(state, accountId);
1746
- const paymentLedger = listPaymentLedgerForAccount(state, accountId);
1747
- return {
1748
- pack_version: "xytara-economics-reconciliation-pack-v1",
1749
- account_id: accountId,
1750
- treasury_summary: treasury,
1751
- payment_ledger_count: paymentLedger.length,
1752
- transaction_count: listTransactionsForAccount(state, accountId).length,
1753
- canonical_state: {
1754
- budgets: listMapValuesByAccount(state.economicsBudgets, accountId).length,
1755
- agents: listMapValuesByAccount(state.economicsAgents, accountId).length,
1756
- economics_receipts: listMapValuesByAccount(state.economicsReceipts, accountId).length,
1757
- entitlements: listEntitlementsForAccount(state, accountId).length
1758
- },
1759
- unresolved_state: {
1760
- disputed_receipt_count: listMapValuesByAccount(state.economicsReceipts, accountId).filter((entry) => entry.operator_status === "disputed").length,
1761
- escalated_receipt_count: listMapValuesByAccount(state.economicsReceipts, accountId).filter((entry) => entry.operator_status === "escalated").length
1762
- },
1763
- replenishment_summary: buildEntitlementReplenishmentSummary(state, accountId),
1764
- generated_at_iso: nowIso()
1765
- };
1766
- }
1767
-
1768
- function buildAccountSummary(state, accountId) {
1769
- const budgets = listMapValuesByAccount(state.economicsBudgets, accountId);
1770
- const agents = listMapValuesByAccount(state.economicsAgents, accountId);
1771
- const economicsReceipts = listMapValuesByAccount(state.economicsReceipts, accountId);
1772
- const governedTransactions = listTransactionsForAccount(state, accountId);
1773
- return {
1774
- account_id: accountId,
1775
- advisory_state: {
1776
- budget_count: budgets.length,
1777
- active_budget_count: budgets.filter((entry) => entry.status === "active").length,
1778
- agent_count: agents.length,
1779
- active_agent_count: agents.filter((entry) => entry.status === "active").length,
1780
- economics_receipt_count: economicsReceipts.length,
1781
- governed_transaction_count: governedTransactions.length
1782
- },
1783
- integrity_signals: {
1784
- missing_default_budget_agent_count: agents.filter((entry) => !entry.default_budget_id).length,
1785
- unvalidated_receipt_count: economicsReceipts.filter((entry) => entry.lifecycle_status !== "validated").length,
1786
- pending_transaction_count: governedTransactions.filter((entry) => entry.status !== "completed").length
1787
- },
1788
- evidence_entries: economicsReceipts.slice(0, 10).map((entry) => ({
1789
- receipt_id: entry.receipt_id,
1790
- hash: entry.evidence && entry.evidence.hash ? entry.evidence.hash : null,
1791
- uri: entry.evidence && entry.evidence.uri ? entry.evidence.uri : null,
1792
- lifecycle_status: entry.lifecycle_status
1793
- })),
1794
- generated_at_iso: nowIso()
1795
- };
1796
- }
1797
-
1798
- function buildOperatorView(state, accountId) {
1799
- const receipts = listMapValuesByAccount(state.economicsReceipts, accountId);
1800
- const budgets = listMapValuesByAccount(state.economicsBudgets, accountId);
1801
- const agents = listMapValuesByAccount(state.economicsAgents, accountId);
1802
- const jobActions = listEconomicsJobActionsForAccount(state, accountId);
1803
- return {
1804
- account_id: accountId,
1805
- lifecycle_buckets: {
1806
- recorded: receipts.filter((entry) => entry.lifecycle_status === "recorded").length,
1807
- validated: receipts.filter((entry) => entry.lifecycle_status === "validated").length,
1808
- reversed: receipts.filter((entry) => entry.lifecycle_status === "reversed").length
1809
- },
1810
- receipt_linkability_state: {
1811
- with_job_id: receipts.filter((entry) => entry.job_id).length,
1812
- without_job_id: receipts.filter((entry) => !entry.job_id).length
1813
- },
1814
- integrity_alerts: {
1815
- paused_budget_count: budgets.filter((entry) => entry.status === "paused").length,
1816
- suspended_agent_count: agents.filter((entry) => entry.status === "suspended").length
1817
- },
1818
- receipt_anomalies: {
1819
- missing_evidence_locator_count: receipts.filter((entry) => !(entry.evidence && (entry.evidence.hash || entry.evidence.uri))).length
1820
- },
1821
- per_job_evidence_summaries: Object.values(
1822
- receipts.reduce((acc, entry) => {
1823
- if (!entry || !entry.job_id) return acc;
1824
- if (!acc[entry.job_id]) acc[entry.job_id] = { job_id: entry.job_id, receipt_count: 0, validated_count: 0 };
1825
- acc[entry.job_id].receipt_count += 1;
1826
- if (entry.lifecycle_status === "validated") acc[entry.job_id].validated_count += 1;
1827
- return acc;
1828
- }, {})
1829
- ),
1830
- trust_linked_economic_summary: {
1831
- disputed_receipt_count: receipts.filter((entry) => entry.operator_status === "disputed").length,
1832
- escalated_receipt_count: receipts.filter((entry) => entry.operator_status === "escalated").length
1833
- },
1834
- budget_usage_read_model: budgets.map((entry) => ({
1835
- budget_id: entry.budget_id,
1836
- status: entry.status,
1837
- max_reserve_units: entry.max_reserve_units
1838
- })),
1839
- agent_usage_read_model: agents.map((entry) => ({
1840
- agent_id: entry.agent_id,
1841
- status: entry.status,
1842
- default_budget_id: entry.default_budget_id || null
1843
- })),
1844
- job_operator_actions: jobActions,
1845
- generated_at_iso: nowIso()
1846
- };
1847
- }
1848
-
1849
- function buildOperatorDashboard(state, accountId) {
1850
- const treasurySummary = buildTreasurySummary(state, accountId);
1851
- const operatorView = buildOperatorView(state, accountId);
1852
- const recentReceipts = listMapValuesByAccount(state.economicsReceipts, accountId).slice(0, 10);
1853
- return {
1854
- account_id: accountId,
1855
- overview: {
1856
- minted_units: treasurySummary.treasury.minted_units,
1857
- committed_units: treasurySummary.treasury.committed_units,
1858
- settled_amount_minor: treasurySummary.treasury.settled_amount_minor
1859
- },
1860
- trust: operatorView.trust_linked_economic_summary,
1861
- workflow: {
1862
- treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
1863
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
1864
- },
1865
- recent_activity: recentReceipts.map((entry) => ({
1866
- receipt_id: entry.receipt_id,
1867
- lifecycle_status: entry.lifecycle_status,
1868
- operator_status: entry.operator_status,
1869
- updated_at_iso: entry.updated_at_iso
1870
- })),
1871
- case_summaries: {
1872
- disputed_jobs: Array.from(new Set(recentReceipts.filter((entry) => entry.operator_status === "disputed").map((entry) => entry.job_id).filter(Boolean))),
1873
- escalated_jobs: Array.from(new Set(recentReceipts.filter((entry) => entry.operator_status === "escalated").map((entry) => entry.job_id).filter(Boolean)))
1874
- },
1875
- generated_at_iso: nowIso()
1876
- };
1877
- }
1878
-
1879
- function buildPolicySummary(state, accountId) {
1880
- const budgets = listMapValuesByAccount(state.economicsBudgets, accountId);
1881
- const agents = listMapValuesByAccount(state.economicsAgents, accountId);
1882
- const activeBudgets = budgets.filter((entry) => entry.status === "active");
1883
- return {
1884
- account_id: accountId,
1885
- default_spend_posture: "open_spend",
1886
- bounded_spend_available: activeBudgets.length > 0 || agents.length > 0,
1887
- budget_policy_count: budgets.length,
1888
- active_budget_count: activeBudgets.length,
1889
- agent_count: agents.length,
1890
- agents_with_default_budget: agents.filter((entry) => entry.default_budget_id).length,
1891
- allowed_job_domains: Array.from(new Set(budgets.flatMap((entry) => ensureArray(entry.allowed_job_domains)))),
1892
- generated_at_iso: nowIso()
1893
- };
1894
- }
1895
-
1896
- function buildAccountCreditSpendPolicyPack(state, accountId) {
1897
- const budgets = listMapValuesByAccount(state.economicsBudgets, accountId);
1898
- const agents = listMapValuesByAccount(state.economicsAgents, accountId);
1899
- const activeBudgets = budgets.filter((entry) => entry && entry.status === "active");
1900
- const allowedJobDomains = Array.from(new Set(
1901
- activeBudgets.flatMap((entry) => ensureArray(entry.allowed_job_domains)).filter(Boolean)
1902
- ));
1903
- return {
1904
- pack_version: "xytara-account-credit-spend-policy-pack-v1",
1905
- account_id: accountId,
1906
- default_spend_posture: "open_spend",
1907
- bounded_spend_posture_available: activeBudgets.length > 0 || agents.length > 0,
1908
- policy_summary: buildPolicySummary(state, accountId),
1909
- balance_summary: buildCreditBalanceSummary(state, accountId),
1910
- active_budget_count: activeBudgets.length,
1911
- active_budget_refs: activeBudgets.map((entry) => ({
1912
- budget_id: entry.budget_id,
1913
- label: entry.label,
1914
- max_reserve_units: entry.max_reserve_units,
1915
- allowed_job_domains: ensureArray(entry.allowed_job_domains),
1916
- policy_ref: entry.policy_ref || null
1917
- })),
1918
- agent_refs: agents.map((entry) => ({
1919
- agent_id: entry.agent_id,
1920
- status: entry.status,
1921
- default_budget_id: entry.default_budget_id || null,
1922
- allowed_job_domains: ensureArray(entry.allowed_job_domains)
1923
- })),
1924
- effective_allowed_job_domains: allowedJobDomains,
1925
- guidance: {
1926
- default_path: "spend_existing_credits_and_execute",
1927
- bounded_controls_note: "bounded spend only applies when the caller intentionally uses an agent or budget posture",
1928
- credit_first_execution_surface: "/v1/commands/execute",
1929
- balance_surface: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
1930
- policy_summary_surface: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-summary`
1931
- },
1932
- generated_at_iso: nowIso()
1933
- };
1934
- }
1935
-
1936
- function buildAgentCreditSpendPolicyView(state, accountId, agentId) {
1937
- const agent = state.economicsAgents.get(agentId) || null;
1938
- if (!agent || agent.account_id !== accountId) {
1939
- return null;
1940
- }
1941
- const budget = agent.default_budget_id ? state.economicsBudgets.get(agent.default_budget_id) || null : null;
1942
- const spends = listCreditSpendsForAccount(state, accountId).filter((entry) => entry && entry.agent_id === agentId);
1943
- const spentUnits = spends.reduce((sum, entry) => sum + (entry.units || 0), 0);
1944
- return {
1945
- account_id: accountId,
1946
- agent_id: agent.agent_id,
1947
- status: agent.status,
1948
- allowed_job_domains: ensureArray(agent.allowed_job_domains),
1949
- default_budget: budget ? {
1950
- budget_id: budget.budget_id,
1951
- status: budget.status,
1952
- max_reserve_units: budget.max_reserve_units,
1953
- allowed_job_domains: ensureArray(budget.allowed_job_domains),
1954
- policy_ref: budget.policy_ref || null
1955
- } : null,
1956
- spend_posture: {
1957
- mode: budget ? "bounded_spend" : "open_spend",
1958
- spent_units: spentUnits,
1959
- spend_count: spends.length,
1960
- remaining_budget_units: budget && typeof budget.max_reserve_units === "number"
1961
- ? Math.max(0, budget.max_reserve_units - spentUnits)
1962
- : null
1963
- },
1964
- generated_at_iso: nowIso()
1965
- };
1966
- }
1967
-
1968
- function buildPricingPolicySummary(state, accountId) {
1969
- const balanceSummary = buildCreditBalanceSummary(state, accountId);
1970
- const meteringSummary = buildUsageMeteringSummary(state, accountId);
1971
- const policySummary = buildPolicySummary(state, accountId);
1972
- const economicsIntelligence = buildEconomicsIntelligenceSummary(state, accountId);
1973
- const replenishmentSummary = buildEntitlementReplenishmentSummary(state, accountId);
1974
-
1975
- const pricingBands = ensureArray(meteringSummary.pricing_bands).filter(Boolean);
1976
- const dominantPricingBand = pricingBands[0] || null;
1977
- const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1978
- const totalUnits = Number(meteringSummary.total_units || 0);
1979
-
1980
- let pricingPosture = "direct_pay_entry";
1981
- if (usageMeterCount > 0 || Number(balanceSummary.consumed_units || 0) > 0) {
1982
- pricingPosture = "credits_first_runtime";
1983
- }
1984
- if (economicsIntelligence.recommended_funding_posture === "pack_backed_credits_first") {
1985
- pricingPosture = "pack_backed_runtime";
1986
- }
1987
-
1988
- let pricingRiskState = "low";
1989
- if (replenishmentSummary.low_balance_count > 0 || policySummary.active_budget_count > 0) {
1990
- pricingRiskState = "watch";
1991
- }
1992
- if (replenishmentSummary.depleted_count > 0 || (usageMeterCount > 0 && Number(balanceSummary.available_units || 0) <= Math.max(8, totalUnits))) {
1993
- pricingRiskState = "high";
1994
- }
1995
-
1996
- return {
1997
- summary_version: "xytara-pricing-policy-summary-v1",
1998
- account_id: accountId,
1999
- pricing_posture: pricingPosture,
2000
- pricing_risk_state: pricingRiskState,
2001
- dominant_pricing_band: dominantPricingBand,
2002
- recommended_pack_id: economicsIntelligence.recommended_pack_id,
2003
- bounded_spend_available: policySummary.bounded_spend_available,
2004
- explanation_signals: {
2005
- usage_meter_count: usageMeterCount,
2006
- total_units: totalUnits,
2007
- pricing_bands: pricingBands,
2008
- available_units: balanceSummary.available_units,
2009
- active_budget_count: policySummary.active_budget_count,
2010
- agent_count: policySummary.agent_count,
2011
- low_balance_count: replenishmentSummary.low_balance_count,
2012
- depleted_count: replenishmentSummary.depleted_count
2013
- },
2014
- linked_surfaces: {
2015
- policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-summary`,
2016
- policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`,
2017
- economics_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/intelligence-summary`,
2018
- metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`
2019
- },
2020
- generated_at_iso: nowIso()
2021
- };
2022
- }
2023
-
2024
- function buildPricingPolicyOperatorBundle(state, accountId) {
2025
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2026
- const policySummary = buildPolicySummary(state, accountId);
2027
- const policyPack = buildAccountCreditSpendPolicyPack(state, accountId);
2028
- const economicsIntelligence = buildEconomicsIntelligenceSummary(state, accountId);
2029
- const treasuryIntelligence = buildTreasuryIntelligenceSummary(state, accountId);
2030
-
2031
- let recommendedOperatorMotion = "maintain_current_pricing_posture";
2032
- if (pricingPolicySummary.pricing_risk_state === "high") {
2033
- recommendedOperatorMotion = "restore_pricing_headroom";
2034
- } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2035
- recommendedOperatorMotion = "stabilize_pack_backed_runtime";
2036
- } else if (policySummary.bounded_spend_available) {
2037
- recommendedOperatorMotion = "tighten_bounded_spend_pricing_controls";
2038
- } else if (economicsIntelligence.recommended_funding_posture === "direct_pay_first") {
2039
- recommendedOperatorMotion = "keep_direct_pay_entry_clear";
2040
- }
2041
-
2042
- return {
2043
- bundle_version: "xytara-pricing-policy-operator-bundle-v1",
2044
- account_id: accountId,
2045
- operator_posture: {
2046
- pricing_posture: pricingPolicySummary.pricing_posture,
2047
- pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2048
- treasury_health_state: economicsIntelligence.treasury_health_state,
2049
- value_capture_state: treasuryIntelligence.value_capture_state,
2050
- recommended_operator_motion: recommendedOperatorMotion
2051
- },
2052
- pricing_policy_summary: pricingPolicySummary,
2053
- policy_summary: policySummary,
2054
- policy_pack: policyPack,
2055
- economics_intelligence_summary: economicsIntelligence,
2056
- treasury_intelligence_summary: treasuryIntelligence,
2057
- linked_surfaces: {
2058
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2059
- policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`,
2060
- economics_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/intelligence-summary`,
2061
- treasury_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-intelligence-summary`
2062
- },
2063
- generated_at_iso: nowIso()
2064
- };
2065
- }
2066
-
2067
- function buildPricingPolicyPack(state, accountId) {
2068
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2069
- const operatorBundle = buildPricingPolicyOperatorBundle(state, accountId);
2070
- const pricingBandProfiles = Object.entries(PRICING_BAND_UNITS).map(([pricing_band, usage_units]) => ({
2071
- pricing_band,
2072
- usage_units,
2073
- recommended_for: usage_units >= 8
2074
- ? "high consequence or multi-step runtime work"
2075
- : usage_units >= 3
2076
- ? "moderate runtime execution"
2077
- : "entry and lightweight runtime paths"
2078
- }));
2079
- const policyTemplates = [
2080
- {
2081
- template_id: "direct_pay_entry_clear",
2082
- recommended_for: "keeping first-contact spend simple",
2083
- target_motion: "keep_direct_pay_entry_clear",
2084
- pricing_posture: "direct_pay_entry"
2085
- },
2086
- {
2087
- template_id: "credits_first_runtime_default",
2088
- recommended_for: "normal repeat runtime execution",
2089
- target_motion: "maintain_current_pricing_posture",
2090
- pricing_posture: "credits_first_runtime"
2091
- },
2092
- {
2093
- template_id: "pack_backed_runtime_scale",
2094
- recommended_for: "repeat usage with replenishment pressure",
2095
- target_motion: "stabilize_pack_backed_runtime",
2096
- pricing_posture: "pack_backed_runtime"
2097
- },
2098
- {
2099
- template_id: "bounded_spend_guardrails",
2100
- recommended_for: "agent and budget-constrained runtime usage",
2101
- target_motion: "tighten_bounded_spend_pricing_controls",
2102
- pricing_posture: "credits_first_runtime"
2103
- }
2104
- ];
2105
-
2106
- return {
2107
- pack_version: "xytara-pricing-policy-pack-v1",
2108
- account_id: accountId,
2109
- pricing_policy_summary: pricingPolicySummary,
2110
- operator_bundle: operatorBundle,
2111
- pricing_band_profiles: pricingBandProfiles,
2112
- policy_templates: policyTemplates,
2113
- recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
2114
- linked_surfaces: {
2115
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2116
- pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2117
- pricing_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-application-summary`
2118
- },
2119
- generated_at_iso: nowIso()
2120
- };
2121
- }
2122
-
2123
- function buildPricingPolicyApplicationSummary(state, accountId, templateId) {
2124
- const pack = buildPricingPolicyPack(state, accountId);
2125
- const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2126
- || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2127
- || ensureArray(pack.policy_templates)[0]
2128
- || null;
2129
-
2130
- return {
2131
- summary_version: "xytara-pricing-policy-application-summary-v1",
2132
- account_id: accountId,
2133
- recommended_policy_motion: pack.recommended_policy_motion,
2134
- selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2135
- available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2136
- selected_template: selectedTemplate,
2137
- suggested_pricing_targets: {
2138
- funding_posture: pack.pricing_policy_summary.pricing_posture,
2139
- dominant_pricing_band: pack.pricing_policy_summary.dominant_pricing_band,
2140
- recommended_pack_id: pack.pricing_policy_summary.recommended_pack_id,
2141
- bounded_spend_available: pack.pricing_policy_summary.bounded_spend_available
2142
- },
2143
- linked_surfaces: {
2144
- pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2145
- pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2146
- policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`
2147
- },
2148
- generated_at_iso: nowIso()
2149
- };
2150
- }
2151
-
2152
- function buildPricingPolicyPackage(state, accountId) {
2153
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2154
- const operatorBundle = buildPricingPolicyOperatorBundle(state, accountId);
2155
- const pack = buildPricingPolicyPack(state, accountId);
2156
- const applicationSummary = buildPricingPolicyApplicationSummary(state, accountId, null);
2157
- return {
2158
- package_version: "xytara-pricing-policy-package-v1",
2159
- account_id: accountId,
2160
- package_posture: {
2161
- pricing_posture: pricingPolicySummary.pricing_posture,
2162
- pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2163
- recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2164
- recommended_policy_motion: pack.recommended_policy_motion
2165
- },
2166
- pricing_policy_summary: pricingPolicySummary,
2167
- pricing_policy_operator_bundle: operatorBundle,
2168
- pricing_policy_pack: pack,
2169
- pricing_policy_application_summary: applicationSummary,
2170
- linked_surfaces: {
2171
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2172
- pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2173
- pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2174
- pricing_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-application-summary`
2175
- },
2176
- generated_at_iso: nowIso()
2177
- };
2178
- }
2179
-
2180
- function buildQuotePolicyDecisionSummary(state, body) {
2181
- const payload = ensureObject(body);
2182
- const accountId = normalizeString(payload.account_id, "acct_demo");
2183
- const usagePreview = buildUsageMeterPreview(state, payload);
2184
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2185
- const policyDecision = buildCreditSpendPolicyDecision(state, payload);
2186
- const quotedUnits = resolveUsageMeterUnits(payload, buildUsageMeterBase(payload));
2187
- const amountMinor = quotedUnits * 100;
2188
-
2189
- let quotePolicyState = "direct_pay_quote";
2190
- if (pricingPolicySummary.pricing_posture !== "direct_pay_entry") {
2191
- quotePolicyState = "credits_first_quote";
2192
- }
2193
- if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2194
- quotePolicyState = "pack_backed_quote";
2195
- }
2196
-
2197
- let recommendedQuoteMotion = "issue_standard_quote";
2198
- if (!policyDecision.ok) {
2199
- recommendedQuoteMotion = "require_bounded_policy_repair";
2200
- } else if (pricingPolicySummary.pricing_risk_state === "high") {
2201
- recommendedQuoteMotion = "issue_replenishment_aware_quote";
2202
- } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2203
- recommendedQuoteMotion = "issue_pack_aligned_quote";
2204
- }
2205
-
2206
- return {
2207
- summary_version: "xytara-quote-policy-decision-summary-v1",
2208
- account_id: accountId,
2209
- quote_policy_state: quotePolicyState,
2210
- recommended_quote_motion: recommendedQuoteMotion,
2211
- quoted_units: quotedUnits,
2212
- quoted_amount_minor: amountMinor,
2213
- pricing_band: usagePreview.pricing_band,
2214
- task_domain: usagePreview.task_domain,
2215
- policy_guard: {
2216
- ok: Boolean(policyDecision.ok),
2217
- reason: policyDecision.reason || null,
2218
- budget_id: policyDecision.budget_id || null,
2219
- agent_id: policyDecision.agent_id || null,
2220
- max_reserve_units: policyDecision.max_reserve_units || null
2221
- },
2222
- linked_surfaces: {
2223
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2224
- pricing_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-package`,
2225
- policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-summary`
2226
- },
2227
- generated_at_iso: nowIso()
2228
- };
2229
- }
2230
-
2231
- function buildPricingBandDecisionSummary(state, body) {
2232
- const payload = ensureObject(body);
2233
- const accountId = normalizeString(payload.account_id, "acct_demo");
2234
- const usagePreview = buildUsageMeterPreview(state, payload);
2235
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2236
- const bandUnits = PRICING_BAND_UNITS[usagePreview.pricing_band] || usagePreview.usage_units || 1;
2237
-
2238
- let bandDecisionState = "standard_band";
2239
- if (usagePreview.pricing_band === "utility") {
2240
- bandDecisionState = "entry_band";
2241
- } else if (usagePreview.pricing_band === "premium" || usagePreview.pricing_band === "heavy") {
2242
- bandDecisionState = "high_consequence_band";
2243
- }
2244
-
2245
- let recommendedBandMotion = "accept_detected_band";
2246
- if (pricingPolicySummary.pricing_risk_state === "high" && bandUnits >= 8) {
2247
- recommendedBandMotion = "review_high_unit_band";
2248
- } else if (pricingPolicySummary.pricing_posture === "direct_pay_entry" && bandUnits > 3) {
2249
- recommendedBandMotion = "check_entry_path_alignment";
2250
- }
2251
-
2252
- return {
2253
- summary_version: "xytara-pricing-band-decision-summary-v1",
2254
- account_id: accountId,
2255
- pricing_band: usagePreview.pricing_band,
2256
- usage_units: usagePreview.usage_units,
2257
- band_units: bandUnits,
2258
- band_decision_state: bandDecisionState,
2259
- recommended_band_motion: recommendedBandMotion,
2260
- task_ref: usagePreview.task_ref,
2261
- workflow_ref: usagePreview.workflow_ref,
2262
- task_domain: usagePreview.task_domain,
2263
- linked_surfaces: {
2264
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2265
- pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2266
- metering_preview_ref: "/v1/economics/metering/preview"
2267
- },
2268
- generated_at_iso: nowIso()
2269
- };
2270
- }
2271
-
2272
- function buildQuotePolicyOperatorBundle(state, body) {
2273
- const payload = ensureObject(body);
2274
- const accountId = normalizeString(payload.account_id, "acct_demo");
2275
- const quoteDecision = buildQuotePolicyDecisionSummary(state, payload);
2276
- const bandDecision = buildPricingBandDecisionSummary(state, payload);
2277
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2278
-
2279
- let recommendedOperatorMotion = "maintain_quote_policy_posture";
2280
- if (quoteDecision.policy_guard.ok === false) {
2281
- recommendedOperatorMotion = "repair_bounded_quote_controls";
2282
- } else if (quoteDecision.recommended_quote_motion === "issue_replenishment_aware_quote") {
2283
- recommendedOperatorMotion = "prepare_replenishment_aligned_quote";
2284
- } else if (bandDecision.recommended_band_motion === "review_high_unit_band") {
2285
- recommendedOperatorMotion = "review_high_unit_quote_band";
2286
- }
2287
-
2288
- return {
2289
- bundle_version: "xytara-quote-policy-operator-bundle-v1",
2290
- account_id: accountId,
2291
- operator_posture: {
2292
- quote_policy_state: quoteDecision.quote_policy_state,
2293
- pricing_band: bandDecision.pricing_band,
2294
- pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2295
- recommended_quote_motion: quoteDecision.recommended_quote_motion,
2296
- recommended_band_motion: bandDecision.recommended_band_motion,
2297
- recommended_operator_motion: recommendedOperatorMotion
2298
- },
2299
- quote_policy_decision_summary: quoteDecision,
2300
- pricing_band_decision_summary: bandDecision,
2301
- pricing_policy_summary: pricingPolicySummary,
2302
- linked_surfaces: {
2303
- quote_policy_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-decision-summary`,
2304
- pricing_band_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-band-decision-summary`,
2305
- quote_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-package`
2306
- },
2307
- generated_at_iso: nowIso()
2308
- };
2309
- }
2310
-
2311
- function summarizeQuotePolicyOperatorBundle(state, body) {
2312
- const bundle = buildQuotePolicyOperatorBundle(state, body);
2313
- return {
2314
- bundle_version: bundle.bundle_version,
2315
- account_id: bundle.account_id,
2316
- quote_policy_state: bundle.operator_posture.quote_policy_state,
2317
- pricing_band: bundle.operator_posture.pricing_band,
2318
- recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
2319
- };
2320
- }
2321
-
2322
- function buildQuotePolicyPack(state, body) {
2323
- const payload = ensureObject(body);
2324
- const accountId = normalizeString(payload.account_id, "acct_demo");
2325
- const operatorBundle = buildQuotePolicyOperatorBundle(state, payload);
2326
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2327
- const templates = [
2328
- {
2329
- template_id: "direct_pay_quote_entry",
2330
- recommended_for: "first-contact quotes and low-friction runtime entry",
2331
- target_motion: "issue_standard_quote",
2332
- quote_policy_state: "direct_pay_quote"
2333
- },
2334
- {
2335
- template_id: "credits_first_quote_default",
2336
- recommended_for: "normal repeat runtime quoting",
2337
- target_motion: "issue_standard_quote",
2338
- quote_policy_state: "credits_first_quote"
2339
- },
2340
- {
2341
- template_id: "pack_aligned_quote_flow",
2342
- recommended_for: "repeat use with pack-backed credits posture",
2343
- target_motion: "issue_pack_aligned_quote",
2344
- quote_policy_state: "pack_backed_quote"
2345
- },
2346
- {
2347
- template_id: "replenishment_aware_quote",
2348
- recommended_for: "high pricing-risk or low-headroom quote posture",
2349
- target_motion: "issue_replenishment_aware_quote",
2350
- quote_policy_state: "credits_first_quote"
2351
- },
2352
- {
2353
- template_id: "bounded_quote_guardrails",
2354
- recommended_for: "agent or budget-constrained quoting",
2355
- target_motion: "require_bounded_policy_repair",
2356
- quote_policy_state: "credits_first_quote"
2357
- }
2358
- ];
2359
-
2360
- return {
2361
- pack_version: "xytara-quote-policy-pack-v1",
2362
- account_id: accountId,
2363
- quote_policy_operator_bundle: operatorBundle,
2364
- pricing_policy_summary: pricingPolicySummary,
2365
- recommended_policy_motion: operatorBundle.operator_posture.recommended_quote_motion,
2366
- policy_templates: templates,
2367
- linked_surfaces: {
2368
- quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2369
- quote_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-application-summary`,
2370
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`
2371
- },
2372
- generated_at_iso: nowIso()
2373
- };
2374
- }
2375
-
2376
- function summarizeQuotePolicyPack(state, body) {
2377
- const pack = buildQuotePolicyPack(state, body);
2378
- return {
2379
- pack_version: pack.pack_version,
2380
- account_id: pack.account_id,
2381
- recommended_policy_motion: pack.recommended_policy_motion,
2382
- template_count: ensureArray(pack.policy_templates).length
2383
- };
2384
- }
2385
-
2386
- function buildQuotePolicyApplicationSummary(state, body) {
2387
- const payload = ensureObject(body);
2388
- const accountId = normalizeString(payload.account_id, "acct_demo");
2389
- const templateId = normalizeString(payload.template_id, null);
2390
- const pack = buildQuotePolicyPack(state, payload);
2391
- const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2392
- || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2393
- || ensureArray(pack.policy_templates)[0]
2394
- || null;
2395
-
2396
- return {
2397
- summary_version: "xytara-quote-policy-application-summary-v1",
2398
- account_id: accountId,
2399
- recommended_policy_motion: pack.recommended_policy_motion,
2400
- selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2401
- available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2402
- selected_template: selectedTemplate,
2403
- suggested_quote_targets: {
2404
- quote_policy_state: pack.quote_policy_operator_bundle.operator_posture.quote_policy_state,
2405
- pricing_band: pack.quote_policy_operator_bundle.operator_posture.pricing_band,
2406
- recommended_quote_motion: pack.quote_policy_operator_bundle.operator_posture.recommended_quote_motion,
2407
- pricing_risk_state: pack.pricing_policy_summary.pricing_risk_state
2408
- },
2409
- linked_surfaces: {
2410
- quote_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-pack`,
2411
- quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2412
- quote_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-package`
2413
- },
2414
- generated_at_iso: nowIso()
2415
- };
2416
- }
2417
-
2418
- function buildQuotePolicyPackage(state, body) {
2419
- const payload = ensureObject(body);
2420
- const accountId = normalizeString(payload.account_id, "acct_demo");
2421
- const quoteDecision = buildQuotePolicyDecisionSummary(state, payload);
2422
- const bandDecision = buildPricingBandDecisionSummary(state, payload);
2423
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2424
- const operatorBundle = buildQuotePolicyOperatorBundle(state, payload);
2425
- const policyPack = buildQuotePolicyPack(state, payload);
2426
- const applicationSummary = buildQuotePolicyApplicationSummary(state, payload);
2427
-
2428
- return {
2429
- package_version: "xytara-quote-policy-package-v1",
2430
- account_id: accountId,
2431
- package_posture: {
2432
- quote_policy_state: quoteDecision.quote_policy_state,
2433
- recommended_quote_motion: quoteDecision.recommended_quote_motion,
2434
- pricing_band: bandDecision.pricing_band,
2435
- recommended_band_motion: bandDecision.recommended_band_motion,
2436
- pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2437
- recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2438
- recommended_policy_motion: policyPack.recommended_policy_motion
2439
- },
2440
- quote_policy_decision_summary: quoteDecision,
2441
- pricing_band_decision_summary: bandDecision,
2442
- quote_policy_operator_bundle: operatorBundle,
2443
- quote_policy_pack: policyPack,
2444
- quote_policy_application_summary: applicationSummary,
2445
- pricing_policy_summary: pricingPolicySummary,
2446
- linked_surfaces: {
2447
- quote_policy_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-decision-summary`,
2448
- pricing_band_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-band-decision-summary`,
2449
- quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2450
- quote_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-pack`,
2451
- quote_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-application-summary`,
2452
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`
2453
- },
2454
- generated_at_iso: nowIso()
2455
- };
2456
- }
2457
-
2458
- function summarizeQuotePolicyPackage(state, body) {
2459
- const pack = buildQuotePolicyPackage(state, body);
2460
- return {
2461
- package_version: pack.package_version,
2462
- account_id: pack.account_id,
2463
- quote_policy_state: pack.package_posture.quote_policy_state,
2464
- pricing_band: pack.package_posture.pricing_band,
2465
- recommended_operator_motion: pack.package_posture.recommended_operator_motion,
2466
- recommended_policy_motion: pack.package_posture.recommended_policy_motion
2467
- };
2468
- }
2469
-
2470
- function buildTrustInputSummary(state, accountId) {
2471
- const paymentCount = listPaymentLedgerForAccount(state, accountId).length;
2472
- const creditSpendCount = ensureArray(state.economicsCreditSpends).filter((entry) => entry && entry.account_id === accountId).length;
2473
- const allocationCount = ensureArray(state.economicsAllocations).filter((entry) => entry && entry.account_id === accountId).length;
2474
- const disputeCount = listMapValuesByAccount(state.disputes, accountId).length;
2475
- const refundCount = listMapValuesByAccount(state.refunds, accountId).length;
2476
- const remediationCount = listMapValuesByAccount(state.remediationTickets, accountId).length;
2477
- const activeParticipantCount = listOperatorParticipantsForAccount(state, accountId).filter((entry) => entry && entry.status === "active").length;
2478
- const revokedParticipantCount = listOperatorParticipantsForAccount(state, accountId).filter((entry) => entry && entry.status === "revoked").length;
2479
-
2480
- let runtimeHistoryState = "thin";
2481
- if (paymentCount > 0 || creditSpendCount > 0 || allocationCount > 0) {
2482
- runtimeHistoryState = "working";
2483
- }
2484
- if (
2485
- paymentCount > 0
2486
- && creditSpendCount > 0
2487
- && allocationCount > 0
2488
- && disputeCount === 0
2489
- && refundCount === 0
2490
- && remediationCount === 0
2491
- ) {
2492
- runtimeHistoryState = "strong";
2493
- }
2494
-
2495
- let reputationRiskState = "low";
2496
- if (disputeCount > 0 || refundCount > 0 || remediationCount > 0) {
2497
- reputationRiskState = "high";
2498
- } else if (paymentCount === 0 || creditSpendCount === 0 || revokedParticipantCount > 0) {
2499
- reputationRiskState = "watch";
2500
- }
2501
-
2502
- let recommendedInputMotion = "maintain_runtime_reputation_inputs";
2503
- if (runtimeHistoryState === "thin") {
2504
- recommendedInputMotion = "establish_runtime_history_inputs";
2505
- } else if (reputationRiskState === "high") {
2506
- recommendedInputMotion = "repair_reputation_risk_inputs";
2507
- } else if (reputationRiskState === "watch") {
2508
- recommendedInputMotion = "deepen_runtime_history_inputs";
2509
- }
2510
-
2511
- return {
2512
- summary_version: "xytara-trust-input-summary-v1",
2513
- account_id: accountId,
2514
- runtime_history_state: runtimeHistoryState,
2515
- reputation_risk_state: reputationRiskState,
2516
- recommended_input_motion: recommendedInputMotion,
2517
- explanation_signals: {
2518
- payment_count: paymentCount,
2519
- credit_spend_count: creditSpendCount,
2520
- allocation_count: allocationCount,
2521
- dispute_count: disputeCount,
2522
- refund_count: refundCount,
2523
- remediation_count: remediationCount,
2524
- active_participant_count: activeParticipantCount,
2525
- revoked_participant_count: revokedParticipantCount
2526
- },
2527
- linked_surfaces: {
2528
- trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
2529
- payment_ledger_ref: "/v1/payment-ledger",
2530
- multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`
2531
- },
2532
- generated_at_iso: nowIso()
2533
- };
2534
- }
2535
-
2536
- function buildTrustLayerSummary(state, accountId) {
2537
- const authoritySummary = buildAuthoritySummary(state, accountId);
2538
- const authorityAttention = buildAuthorityAttentionSummary(state, accountId);
2539
- const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
2540
- const machineIdentityAttention = buildMachineIdentityAttentionSummary(state, accountId);
2541
- const walletSummary = buildWalletSummary(state, accountId);
2542
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2543
- const trustInputSummary = buildTrustInputSummary(state, accountId);
2544
-
2545
- const activeAuthorityBindings = Number(authoritySummary.authority_binding_count || 0);
2546
- const activeIdentityBindings = Number(machineIdentitySummary.identity_binding_count || 0);
2547
- const availableUnits = Number(walletSummary.available_units || 0);
2548
-
2549
- let trustState = "early";
2550
- if (
2551
- activeAuthorityBindings > 0
2552
- && activeIdentityBindings > 0
2553
- && authorityAttention.overall_attention_state === "healthy"
2554
- && machineIdentityAttention.overall_attention_state === "healthy"
2555
- && trustInputSummary.runtime_history_state !== "thin"
2556
- ) {
2557
- trustState = "strong";
2558
- } else if (
2559
- activeAuthorityBindings > 0
2560
- || activeIdentityBindings > 0
2561
- || trustInputSummary.runtime_history_state !== "thin"
2562
- ) {
2563
- trustState = "working";
2564
- }
2565
-
2566
- let trustRiskState = "low";
2567
- if (
2568
- authorityAttention.overall_attention_state === "attention_required"
2569
- || machineIdentityAttention.overall_attention_state === "attention_required"
2570
- || pricingPolicySummary.pricing_risk_state === "high"
2571
- || trustInputSummary.reputation_risk_state === "high"
2572
- ) {
2573
- trustRiskState = "high";
2574
- } else if (
2575
- pricingPolicySummary.pricing_risk_state === "watch"
2576
- || availableUnits <= 0
2577
- || trustInputSummary.reputation_risk_state === "watch"
2578
- ) {
2579
- trustRiskState = "watch";
2580
- }
2581
-
2582
- let recommendedTrustMotion = "maintain_runtime_trust_posture";
2583
- if (trustState === "early") {
2584
- recommendedTrustMotion = "establish_authority_and_identity_trust";
2585
- } else if (trustRiskState === "high") {
2586
- recommendedTrustMotion = "repair_runtime_trust_attention";
2587
- } else if (trustInputSummary.runtime_history_state === "thin") {
2588
- recommendedTrustMotion = "deepen_runtime_reputation_inputs";
2589
- } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2590
- recommendedTrustMotion = "stabilize_pack_backed_trust_posture";
2591
- }
2592
-
2593
- return {
2594
- summary_version: "xytara-trust-layer-summary-v1",
2595
- account_id: accountId,
2596
- trust_state: trustState,
2597
- trust_risk_state: trustRiskState,
2598
- recommended_trust_motion: recommendedTrustMotion,
2599
- explanation_signals: {
2600
- authority_state: authoritySummary.authority_state,
2601
- authority_binding_count: activeAuthorityBindings,
2602
- authority_attention_state: authorityAttention.overall_attention_state,
2603
- machine_identity_state: machineIdentitySummary.machine_identity_state,
2604
- identity_binding_count: activeIdentityBindings,
2605
- machine_identity_attention_state: machineIdentityAttention.overall_attention_state,
2606
- pricing_posture: pricingPolicySummary.pricing_posture,
2607
- pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2608
- available_units: availableUnits,
2609
- runtime_history_state: trustInputSummary.runtime_history_state,
2610
- reputation_risk_state: trustInputSummary.reputation_risk_state,
2611
- active_participant_count: trustInputSummary.explanation_signals.active_participant_count,
2612
- dispute_count: trustInputSummary.explanation_signals.dispute_count
2613
- },
2614
- linked_surfaces: {
2615
- authority_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-summary`,
2616
- authority_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-attention-summary`,
2617
- machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
2618
- machine_identity_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attention-summary`,
2619
- pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2620
- trust_input_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-input-summary`
2621
- },
2622
- generated_at_iso: nowIso()
2623
- };
2624
- }
2625
-
2626
- function buildTrustLayerOperatorBundle(state, accountId) {
2627
- const trustSummary = buildTrustLayerSummary(state, accountId);
2628
- const authoritySummary = buildAuthoritySummary(state, accountId);
2629
- const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
2630
- const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2631
- const trustInputSummary = buildTrustInputSummary(state, accountId);
2632
-
2633
- let recommendedOperatorMotion = "maintain_runtime_trust_posture";
2634
- if (trustSummary.trust_state === "early") {
2635
- recommendedOperatorMotion = "establish_runtime_trust_foundations";
2636
- } else if (trustSummary.trust_risk_state === "high") {
2637
- recommendedOperatorMotion = "repair_runtime_trust_attention";
2638
- } else if (trustInputSummary.runtime_history_state === "thin") {
2639
- recommendedOperatorMotion = "deepen_runtime_reputation_inputs";
2640
- } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2641
- recommendedOperatorMotion = "stabilize_pack_backed_trust_posture";
2642
- }
2643
-
2644
- return {
2645
- bundle_version: "xytara-trust-layer-operator-bundle-v1",
2646
- account_id: accountId,
2647
- operator_posture: {
2648
- trust_state: trustSummary.trust_state,
2649
- trust_risk_state: trustSummary.trust_risk_state,
2650
- authority_state: authoritySummary.authority_state,
2651
- machine_identity_state: machineIdentitySummary.machine_identity_state,
2652
- runtime_history_state: trustInputSummary.runtime_history_state,
2653
- reputation_risk_state: trustInputSummary.reputation_risk_state,
2654
- pricing_posture: pricingPolicySummary.pricing_posture,
2655
- recommended_operator_motion: recommendedOperatorMotion
2656
- },
2657
- trust_layer_summary: trustSummary,
2658
- trust_input_summary: trustInputSummary,
2659
- authority_summary: authoritySummary,
2660
- machine_identity_summary: machineIdentitySummary,
2661
- pricing_policy_summary: pricingPolicySummary,
2662
- linked_surfaces: trustSummary.linked_surfaces,
2663
- generated_at_iso: nowIso()
2664
- };
2665
- }
2666
-
2667
- function summarizeTrustLayerOperatorBundle(state, accountId) {
2668
- const bundle = buildTrustLayerOperatorBundle(state, accountId);
2669
- return {
2670
- bundle_version: bundle.bundle_version,
2671
- account_id: bundle.account_id,
2672
- trust_state: bundle.operator_posture.trust_state,
2673
- trust_risk_state: bundle.operator_posture.trust_risk_state,
2674
- recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
2675
- };
2676
- }
2677
-
2678
- function buildTrustLayerPolicyPack(state, accountId) {
2679
- const operatorBundle = buildTrustLayerOperatorBundle(state, accountId);
2680
- const templates = [
2681
- {
2682
- template_id: "runtime_trust_foundation",
2683
- recommended_for: "establishing initial authority and identity trust",
2684
- target_motion: "establish_runtime_trust_foundations",
2685
- trust_state: "early"
2686
- },
2687
- {
2688
- template_id: "runtime_trust_maintenance",
2689
- recommended_for: "healthy continuing runtime trust posture",
2690
- target_motion: "maintain_runtime_trust_posture",
2691
- trust_state: "working"
2692
- },
2693
- {
2694
- template_id: "trust_attention_repair",
2695
- recommended_for: "repairing active authority, identity, or pricing risk",
2696
- target_motion: "repair_runtime_trust_attention",
2697
- trust_state: "working"
2698
- },
2699
- {
2700
- template_id: "pack_backed_trust_stabilization",
2701
- recommended_for: "repeat-use runtime trust with pack-backed credits",
2702
- target_motion: "stabilize_pack_backed_trust_posture",
2703
- trust_state: "strong"
2704
- }
2705
- ];
2706
-
2707
- return {
2708
- pack_version: "xytara-trust-layer-policy-pack-v1",
2709
- account_id: accountId,
2710
- trust_layer_operator_bundle: operatorBundle,
2711
- recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
2712
- policy_templates: templates,
2713
- linked_surfaces: {
2714
- trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2715
- trust_layer_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-application-summary`,
2716
- trust_layer_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-package`
2717
- },
2718
- generated_at_iso: nowIso()
2719
- };
2720
- }
2721
-
2722
- function summarizeTrustLayerPolicyPack(state, accountId) {
2723
- const pack = buildTrustLayerPolicyPack(state, accountId);
2724
- return {
2725
- pack_version: pack.pack_version,
2726
- account_id: pack.account_id,
2727
- recommended_policy_motion: pack.recommended_policy_motion,
2728
- template_count: ensureArray(pack.policy_templates).length
2729
- };
2730
- }
2731
-
2732
- function buildTrustLayerApplicationSummary(state, accountId, templateId) {
2733
- const pack = buildTrustLayerPolicyPack(state, accountId);
2734
- const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2735
- || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2736
- || ensureArray(pack.policy_templates)[0]
2737
- || null;
2738
-
2739
- return {
2740
- summary_version: "xytara-trust-layer-application-summary-v1",
2741
- account_id: accountId,
2742
- recommended_policy_motion: pack.recommended_policy_motion,
2743
- selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2744
- available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2745
- selected_template: selectedTemplate,
2746
- suggested_trust_targets: {
2747
- trust_state: pack.trust_layer_operator_bundle.operator_posture.trust_state,
2748
- trust_risk_state: pack.trust_layer_operator_bundle.operator_posture.trust_risk_state,
2749
- authority_state: pack.trust_layer_operator_bundle.operator_posture.authority_state,
2750
- machine_identity_state: pack.trust_layer_operator_bundle.operator_posture.machine_identity_state
2751
- },
2752
- linked_surfaces: {
2753
- trust_layer_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-policy-pack`,
2754
- trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2755
- trust_layer_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-package`
2756
- },
2757
- generated_at_iso: nowIso()
2758
- };
2759
- }
2760
-
2761
- function buildTrustLayerPackage(state, accountId) {
2762
- const summary = buildTrustLayerSummary(state, accountId);
2763
- const operatorBundle = buildTrustLayerOperatorBundle(state, accountId);
2764
- const policyPack = buildTrustLayerPolicyPack(state, accountId);
2765
- const applicationSummary = buildTrustLayerApplicationSummary(state, accountId, null);
2766
-
2767
- return {
2768
- package_version: "xytara-trust-layer-package-v1",
2769
- account_id: accountId,
2770
- package_posture: {
2771
- trust_state: summary.trust_state,
2772
- trust_risk_state: summary.trust_risk_state,
2773
- recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2774
- recommended_policy_motion: policyPack.recommended_policy_motion
2775
- },
2776
- trust_layer_summary: summary,
2777
- trust_layer_operator_bundle: operatorBundle,
2778
- trust_input_summary: operatorBundle.trust_input_summary,
2779
- trust_layer_policy_pack: policyPack,
2780
- trust_layer_application_summary: applicationSummary,
2781
- linked_surfaces: {
2782
- trust_input_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-input-summary`,
2783
- trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
2784
- trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2785
- trust_layer_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-policy-pack`,
2786
- trust_layer_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-application-summary`
2787
- },
2788
- generated_at_iso: nowIso()
2789
- };
2790
- }
2791
-
2792
- function summarizeTrustLayerPackage(state, accountId) {
2793
- const pack = buildTrustLayerPackage(state, accountId);
2794
- return {
2795
- package_version: pack.package_version,
2796
- account_id: pack.account_id,
2797
- trust_state: pack.package_posture.trust_state,
2798
- trust_risk_state: pack.package_posture.trust_risk_state,
2799
- recommended_operator_motion: pack.package_posture.recommended_operator_motion,
2800
- recommended_policy_motion: pack.package_posture.recommended_policy_motion
2801
- };
2802
- }
2803
-
2804
- function listOperatorParticipantsForAccount(state, accountId) {
2805
- return Array.from(state.operatorParticipants.values())
2806
- .filter((entry) => entry && entry.account_id === accountId);
2807
- }
2808
-
2809
- function listLegacyAgentAccountsForParticipation(state, accountId) {
2810
- return Array.from(state.agentAccounts.values())
2811
- .map((entry) => entry && entry.account ? entry.account : null)
2812
- .filter(Boolean)
2813
- .filter((entry) => entry.account_id === accountId);
2814
- }
2815
-
2816
- function buildMultiOperatorParticipantPublicView(entry) {
2817
- if (!entry) return null;
2818
- return {
2819
- participant_id: entry.participant_id,
2820
- account_id: entry.account_id,
2821
- label: entry.label,
2822
- operator_kind: entry.operator_kind,
2823
- status: entry.status,
2824
- participant_scope: ensureArray(entry.participant_scope),
2825
- authority_binding_id: entry.authority_binding_id || null,
2826
- identity_binding_id: entry.identity_binding_id || null,
2827
- rotated_from_participant_id: entry.rotated_from_participant_id || null,
2828
- replaced_by_participant_id: entry.replaced_by_participant_id || null,
2829
- created_at_iso: entry.created_at_iso,
2830
- updated_at_iso: entry.updated_at_iso,
2831
- revoked_at_iso: entry.revoked_at_iso || null,
2832
- revoke_reason: entry.revoke_reason || null,
2833
- issued_by: entry.issued_by || null,
2834
- labels: ensureArray(entry.labels)
2835
- };
2836
- }
2837
-
2838
- function listMultiOperatorParticipants(state, accountId) {
2839
- return listOperatorParticipantsForAccount(state, accountId).map((entry) => buildMultiOperatorParticipantPublicView(entry));
2840
- }
2841
-
2842
- function getMultiOperatorParticipant(state, accountId, participantId) {
2843
- if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2844
- const entry = state.operatorParticipants.get(participantId);
2845
- if (!entry || entry.account_id !== accountId) return null;
2846
- return buildMultiOperatorParticipantPublicView(entry);
2847
- }
2848
-
2849
- function buildMultiOperatorAdmissionPreview(state, accountId, body) {
2850
- const payload = ensureObject(body);
2851
- const policyPack = buildMultiOperatorParticipationPolicyPack(state, accountId);
2852
- const selectedTemplate = ensureArray(policyPack.policy_templates).find((entry) => entry.template_id === normalizeString(payload.template_id, null))
2853
- || ensureArray(policyPack.policy_templates).find((entry) => entry.target_motion === policyPack.recommended_policy_motion)
2854
- || ensureArray(policyPack.policy_templates)[0]
2855
- || null;
2856
- const participantLabel = normalizeString(payload.label, `operator-participant-${listOperatorParticipantsForAccount(state, accountId).length + 1}`);
2857
- return {
2858
- preview_version: "xytara-multi-operator-admission-preview-v1",
2859
- account_id: accountId,
2860
- selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2861
- selected_template: selectedTemplate,
2862
- proposed_participant: {
2863
- label: participantLabel,
2864
- operator_kind: normalizeString(payload.operator_kind, "coordinator_operator"),
2865
- participant_scope: ensureArray(payload.participant_scope).length > 0
2866
- ? ensureArray(payload.participant_scope)
2867
- : ["runtime.execute", "economics.reserve"]
2868
- },
2869
- planned_bindings: {
2870
- authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
2871
- identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity")
2872
- },
2873
- linked_surfaces: {
2874
- multi_operator_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
2875
- multi_operator_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`
2876
- },
2877
- generated_at_iso: nowIso()
2878
- };
2879
- }
2880
-
2881
- function createMultiOperatorParticipant(state, accountId, body) {
2882
- const payload = ensureObject(body);
2883
- const createdAtIso = nowIso();
2884
- const nextIndex = state.operatorParticipants.size + 1;
2885
- const participantId = normalizeString(payload.participant_id, `operator_participant_${nextIndex}`);
2886
- const participantScope = ensureArray(payload.participant_scope).length > 0
2887
- ? ensureArray(payload.participant_scope).map((value) => String(value || "").trim()).filter(Boolean)
2888
- : ["runtime.execute", "economics.reserve"];
2889
- const authorityBinding = createAuthorityBinding(state, {
2890
- binding_id: normalizeString(payload.authority_binding_id, `${participantId}_authority`),
2891
- credential_id: normalizeString(payload.credential_id, `${participantId}_credential`),
2892
- account_id: accountId,
2893
- authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
2894
- authority_scope: participantScope,
2895
- allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0
2896
- ? ensureArray(payload.allowed_consequence_families)
2897
- : ["commit", "reserve"],
2898
- max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : 5,
2899
- max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : 5,
2900
- max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : 1,
2901
- labels: ensureArray(payload.labels),
2902
- issued_by: normalizeString(payload.issued_by, "operator")
2903
- });
2904
- const identityBinding = createIdentityBinding(state, {
2905
- binding_id: normalizeString(payload.identity_binding_id, `${participantId}_identity`),
2906
- account_id: accountId,
2907
- identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity"),
2908
- identity_ref: normalizeString(payload.identity_ref, `${participantId}.identity`),
2909
- attached_agent_account_id: participantId,
2910
- labels: ensureArray(payload.labels),
2911
- issued_by: normalizeString(payload.issued_by, "operator")
2912
- });
2913
- const participant = {
2914
- participant_id: participantId,
2915
- account_id: accountId,
2916
- label: normalizeString(payload.label, participantId),
2917
- operator_kind: normalizeString(payload.operator_kind, "coordinator_operator"),
2918
- status: normalizeString(payload.status, "active"),
2919
- participant_scope: participantScope,
2920
- authority_binding_id: authorityBinding.binding_id,
2921
- identity_binding_id: identityBinding.binding_id,
2922
- created_at_iso: createdAtIso,
2923
- updated_at_iso: createdAtIso,
2924
- issued_by: normalizeString(payload.issued_by, "operator"),
2925
- labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean)
2926
- };
2927
- state.operatorParticipants.set(participantId, participant);
2928
- return {
2929
- participant: buildMultiOperatorParticipantPublicView(participant),
2930
- authority_binding: authorityBinding,
2931
- identity_binding: identityBinding
2932
- };
2933
- }
2934
-
2935
- function renewMultiOperatorParticipant(state, accountId, participantId, body) {
2936
- const payload = ensureObject(body);
2937
- if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2938
- const current = state.operatorParticipants.get(participantId);
2939
- if (!current || current.account_id !== accountId) return null;
2940
- const renewedAuthorityBinding = current.authority_binding_id
2941
- ? renewAuthorityBinding(state, current.authority_binding_id, { expires_at_iso: normalizeString(payload.expires_at_iso, null) })
2942
- : null;
2943
- const renewedIdentityBinding = current.identity_binding_id
2944
- ? renewIdentityBinding(state, current.identity_binding_id, { expires_at_iso: normalizeString(payload.expires_at_iso, null) })
2945
- : null;
2946
- const next = {
2947
- ...current,
2948
- updated_at_iso: nowIso()
2949
- };
2950
- state.operatorParticipants.set(participantId, next);
2951
- return {
2952
- participant: buildMultiOperatorParticipantPublicView(next),
2953
- authority_binding: renewedAuthorityBinding,
2954
- identity_binding: renewedIdentityBinding
2955
- };
2956
- }
2957
-
2958
- function revokeMultiOperatorParticipant(state, accountId, participantId, body) {
2959
- const payload = ensureObject(body);
2960
- if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2961
- const current = state.operatorParticipants.get(participantId);
2962
- if (!current || current.account_id !== accountId) return null;
2963
- const revokedAuthorityBinding = current.authority_binding_id
2964
- ? revokeAuthorityBinding(state, current.authority_binding_id, { reason: normalizeString(payload.reason, "participant_revoked") })
2965
- : null;
2966
- const revokedIdentityBinding = current.identity_binding_id
2967
- ? revokeIdentityBinding(state, current.identity_binding_id, { reason: normalizeString(payload.reason, "participant_revoked") })
2968
- : null;
2969
- const next = {
2970
- ...current,
2971
- status: "revoked",
2972
- updated_at_iso: nowIso(),
2973
- revoked_at_iso: nowIso(),
2974
- revoke_reason: normalizeString(payload.reason, "participant_revoked")
2975
- };
2976
- state.operatorParticipants.set(participantId, next);
2977
- return {
2978
- participant: buildMultiOperatorParticipantPublicView(next),
2979
- authority_binding: revokedAuthorityBinding,
2980
- identity_binding: revokedIdentityBinding
2981
- };
2982
- }
2983
-
2984
- function rotateMultiOperatorParticipant(state, accountId, participantId, body) {
2985
- const payload = ensureObject(body);
2986
- if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2987
- const current = state.operatorParticipants.get(participantId);
2988
- if (!current || current.account_id !== accountId) return null;
2989
- const successorParticipantId = normalizeString(payload.successor_participant_id, `${participantId}_rotated`);
2990
- const authorityRotation = current.authority_binding_id
2991
- ? rotateAuthorityBinding(state, current.authority_binding_id, {
2992
- successor_binding_id: normalizeString(payload.successor_authority_binding_id, `${successorParticipantId}_authority`),
2993
- successor_credential_id: normalizeString(payload.successor_credential_id, `${successorParticipantId}_credential`),
2994
- authority_scope: ensureArray(payload.participant_scope).length > 0 ? ensureArray(payload.participant_scope) : ensureArray(current.participant_scope),
2995
- labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
2996
- reason: normalizeString(payload.reason, "participant_rotated")
2997
- })
2998
- : null;
2999
- const identityRotation = current.identity_binding_id
3000
- ? rotateIdentityBinding(state, current.identity_binding_id, {
3001
- successor_binding_id: normalizeString(payload.successor_identity_binding_id, `${successorParticipantId}_identity`),
3002
- attached_agent_account_id: successorParticipantId,
3003
- labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
3004
- reason: normalizeString(payload.reason, "participant_rotated")
3005
- })
3006
- : null;
3007
- const successor = {
3008
- participant_id: successorParticipantId,
3009
- account_id: accountId,
3010
- label: normalizeString(payload.label, current.label),
3011
- operator_kind: normalizeString(payload.operator_kind, current.operator_kind),
3012
- status: normalizeString(payload.status, "active"),
3013
- participant_scope: ensureArray(payload.participant_scope).length > 0
3014
- ? ensureArray(payload.participant_scope).map((value) => String(value || "").trim()).filter(Boolean)
3015
- : ensureArray(current.participant_scope),
3016
- authority_binding_id: authorityRotation && authorityRotation.successor_authority_binding
3017
- ? authorityRotation.successor_authority_binding.binding_id
3018
- : null,
3019
- identity_binding_id: identityRotation && identityRotation.successor_identity_binding
3020
- ? identityRotation.successor_identity_binding.binding_id
3021
- : null,
3022
- rotated_from_participant_id: current.participant_id,
3023
- replaced_by_participant_id: null,
3024
- created_at_iso: nowIso(),
3025
- updated_at_iso: nowIso(),
3026
- issued_by: normalizeString(payload.issued_by, current.issued_by || "operator"),
3027
- labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean) : ensureArray(current.labels)
3028
- };
3029
- const rotated = {
3030
- ...current,
3031
- status: "revoked",
3032
- replaced_by_participant_id: successorParticipantId,
3033
- updated_at_iso: nowIso(),
3034
- revoked_at_iso: nowIso(),
3035
- revoke_reason: normalizeString(payload.reason, "participant_rotated")
3036
- };
3037
- state.operatorParticipants.set(participantId, rotated);
3038
- state.operatorParticipants.set(successorParticipantId, successor);
3039
- return {
3040
- rotated_participant: buildMultiOperatorParticipantPublicView(rotated),
3041
- successor_participant: buildMultiOperatorParticipantPublicView(successor),
3042
- authority_rotation: authorityRotation,
3043
- identity_rotation: identityRotation
3044
- };
3045
- }
3046
-
3047
- function buildMultiOperatorParticipantRotationSummary(state, accountId, participantId) {
3048
- const participant = getMultiOperatorParticipant(state, accountId, participantId);
3049
- if (!participant) return null;
3050
- return {
3051
- summary_version: "xytara-multi-operator-participant-rotation-summary-v1",
3052
- account_id: accountId,
3053
- participant_id: participant.participant_id,
3054
- status: participant.status,
3055
- predecessor_participant_id: participant.rotated_from_participant_id || null,
3056
- successor_participant_id: participant.replaced_by_participant_id || null,
3057
- rotation_state: participant.rotated_from_participant_id || participant.replaced_by_participant_id ? "lineage_present" : "standalone",
3058
- linked_surfaces: {
3059
- participant_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants/${encodeURIComponent(participantId)}`
3060
- },
3061
- generated_at_iso: nowIso()
3062
- };
3063
- }
3064
-
3065
- function buildMultiOperatorReviewBundle(state, accountId) {
3066
- const participants = listOperatorParticipantsForAccount(state, accountId);
3067
- const reviewRows = participants.map((entry) => {
3068
- let review_state = "healthy";
3069
- if (entry.status === "revoked") review_state = "revoked";
3070
- else if (!entry.authority_binding_id || !entry.identity_binding_id) review_state = "repair_required";
3071
- else if (ensureArray(entry.participant_scope).length === 0) review_state = "attention_required";
3072
- return {
3073
- participant_id: entry.participant_id,
3074
- label: entry.label,
3075
- status: entry.status,
3076
- operator_kind: entry.operator_kind,
3077
- review_state,
3078
- authority_binding_id: entry.authority_binding_id || null,
3079
- identity_binding_id: entry.identity_binding_id || null
3080
- };
3081
- });
3082
- return {
3083
- bundle_version: "xytara-multi-operator-review-bundle-v1",
3084
- account_id: accountId,
3085
- review_rows: reviewRows,
3086
- review_counts: {
3087
- healthy_count: reviewRows.filter((entry) => entry.review_state === "healthy").length,
3088
- attention_required_count: reviewRows.filter((entry) => entry.review_state === "attention_required").length,
3089
- repair_required_count: reviewRows.filter((entry) => entry.review_state === "repair_required").length,
3090
- revoked_count: reviewRows.filter((entry) => entry.review_state === "revoked").length
3091
- },
3092
- linked_surfaces: {
3093
- participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`,
3094
- package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3095
- },
3096
- generated_at_iso: nowIso()
3097
- };
3098
- }
3099
-
3100
- function buildMultiOperatorAttentionSummary(state, accountId) {
3101
- const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3102
- const attentionRows = ensureArray(reviewBundle.review_rows).filter((entry) => entry.review_state !== "healthy");
3103
- return {
3104
- summary_version: "xytara-multi-operator-attention-summary-v1",
3105
- account_id: accountId,
3106
- overall_attention_state: attentionRows.length > 0 ? "attention_required" : "healthy",
3107
- attention_rows: attentionRows,
3108
- linked_surfaces: {
3109
- multi_operator_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-review-bundle`,
3110
- multi_operator_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3111
- },
3112
- generated_at_iso: nowIso()
3113
- };
3114
- }
3115
-
3116
- function buildMultiOperatorParticipationSummary(state, accountId) {
3117
- const authoritySummary = buildAuthoritySummary(state, accountId);
3118
- const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
3119
- const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3120
- const operatorParticipants = listOperatorParticipantsForAccount(state, accountId);
3121
- const agentAccounts = listLegacyAgentAccountsForParticipation(state, accountId);
3122
- const coordinationHandoffCount = ensureArray(state.coordinationHandoffs).length;
3123
- const admissionCaseCount = ensureArray(state.zoneAdmissionCases).length;
3124
- const activeAuthorityBindings = Number(authoritySummary.authority_binding_count || 0);
3125
- const activeIdentityBindings = Number(machineIdentitySummary.identity_binding_count || 0);
3126
- const activeParticipantCount = operatorParticipants.filter((entry) => entry.status === "active").length;
3127
- const activeAgentCount = agentAccounts.filter((entry) => entry.status === "active").length;
3128
- const activeOperatorCount = activeParticipantCount > 0 ? activeParticipantCount : activeAgentCount;
3129
-
3130
- let participationState = "single_operator_only";
3131
- if (activeOperatorCount >= 2 && activeAuthorityBindings > 0 && activeIdentityBindings > 0) {
3132
- participationState = "multi_operator_ready";
3133
- } else if (activeOperatorCount >= 1 || activeAuthorityBindings > 0 || activeIdentityBindings > 0) {
3134
- participationState = "emerging_multi_operator";
3135
- }
3136
-
3137
- let coordinationReadinessState = "limited";
3138
- if (coordinationHandoffCount > 0 && admissionCaseCount > 0) {
3139
- coordinationReadinessState = "active";
3140
- } else if (coordinationHandoffCount > 0 || admissionCaseCount > 0) {
3141
- coordinationReadinessState = "preview_ready";
3142
- }
3143
-
3144
- let participationRiskState = "low";
3145
- if (trustLayerSummary.trust_risk_state === "high" || activeOperatorCount === 0) {
3146
- participationRiskState = "high";
3147
- } else if (coordinationReadinessState !== "active" || participationState !== "multi_operator_ready") {
3148
- participationRiskState = "watch";
3149
- }
3150
-
3151
- let recommendedParticipationMotion = "maintain_multi_operator_posture";
3152
- if (participationState === "single_operator_only") {
3153
- recommendedParticipationMotion = "establish_second_operator_and_bindings";
3154
- } else if (participationRiskState === "high") {
3155
- recommendedParticipationMotion = "repair_trust_before_multi_operator_expansion";
3156
- } else if (coordinationReadinessState !== "active") {
3157
- recommendedParticipationMotion = "activate_coordination_followthrough";
3158
- } else if (participationState === "emerging_multi_operator") {
3159
- recommendedParticipationMotion = "tighten_multi_operator_contracts";
3160
- }
3161
-
3162
- return {
3163
- summary_version: "xytara-multi-operator-participation-summary-v1",
3164
- account_id: accountId,
3165
- multi_operator_participation_state: participationState,
3166
- coordination_readiness_state: coordinationReadinessState,
3167
- participation_risk_state: participationRiskState,
3168
- recommended_participation_motion: recommendedParticipationMotion,
3169
- explanation_signals: {
3170
- active_operator_participant_count: activeParticipantCount,
3171
- active_legacy_agent_account_count: activeAgentCount,
3172
- authority_binding_count: activeAuthorityBindings,
3173
- identity_binding_count: activeIdentityBindings,
3174
- trust_state: trustLayerSummary.trust_state,
3175
- trust_risk_state: trustLayerSummary.trust_risk_state,
3176
- coordination_handoff_count: coordinationHandoffCount,
3177
- admission_case_count: admissionCaseCount
3178
- },
3179
- linked_surfaces: {
3180
- multi_operator_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`,
3181
- agent_accounts_ref: "/v1/agent-accounts",
3182
- authority_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-summary`,
3183
- machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
3184
- trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
3185
- coordination_center_ref: "/v1/coordination-center/summary",
3186
- zones_dashboard_ref: "/v1/coordination-center/zones-dashboard"
3187
- },
3188
- generated_at_iso: nowIso()
3189
- };
3190
- }
3191
-
3192
- function buildMultiOperatorParticipationOperatorBundle(state, accountId) {
3193
- const summary = buildMultiOperatorParticipationSummary(state, accountId);
3194
- const authoritySummary = buildAuthoritySummary(state, accountId);
3195
- const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
3196
- const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3197
- const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3198
- const attentionSummary = buildMultiOperatorAttentionSummary(state, accountId);
3199
- const operatorParticipants = listMultiOperatorParticipants(state, accountId);
3200
- const agentAccounts = listLegacyAgentAccountsForParticipation(state, accountId);
3201
- const activeOperatorCount = operatorParticipants.filter((entry) => entry.status === "active").length;
3202
-
3203
- let recommendedOperatorMotion = "maintain_multi_operator_posture";
3204
- if (summary.multi_operator_participation_state === "single_operator_only") {
3205
- recommendedOperatorMotion = "issue_additional_operator_account";
3206
- } else if (summary.participation_risk_state === "high") {
3207
- recommendedOperatorMotion = "repair_multi_operator_trust";
3208
- } else if (summary.coordination_readiness_state !== "active") {
3209
- recommendedOperatorMotion = "open_coordination_followthrough";
3210
- } else if (summary.multi_operator_participation_state === "emerging_multi_operator") {
3211
- recommendedOperatorMotion = "tighten_multi_operator_contracts";
3212
- }
3213
-
3214
- return {
3215
- bundle_version: "xytara-multi-operator-participation-operator-bundle-v1",
3216
- account_id: accountId,
3217
- operator_posture: {
3218
- multi_operator_participation_state: summary.multi_operator_participation_state,
3219
- coordination_readiness_state: summary.coordination_readiness_state,
3220
- participation_risk_state: summary.participation_risk_state,
3221
- active_operator_participant_count: activeOperatorCount,
3222
- active_legacy_agent_account_count: agentAccounts.filter((entry) => entry.status === "active").length,
3223
- authority_state: authoritySummary.authority_state,
3224
- machine_identity_state: machineIdentitySummary.machine_identity_state,
3225
- trust_state: trustLayerSummary.trust_state,
3226
- overall_attention_state: attentionSummary.overall_attention_state,
3227
- recommended_operator_motion: recommendedOperatorMotion
3228
- },
3229
- multi_operator_participation_summary: summary,
3230
- multi_operator_review_bundle: reviewBundle,
3231
- multi_operator_attention_summary: attentionSummary,
3232
- authority_summary: authoritySummary,
3233
- machine_identity_summary: machineIdentitySummary,
3234
- trust_layer_summary: trustLayerSummary,
3235
- operator_participants: operatorParticipants,
3236
- legacy_agent_accounts: agentAccounts,
3237
- linked_surfaces: summary.linked_surfaces,
3238
- generated_at_iso: nowIso()
3239
- };
3240
- }
3241
-
3242
- function summarizeMultiOperatorParticipationOperatorBundle(state, accountId) {
3243
- const bundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3244
- return {
3245
- bundle_version: bundle.bundle_version,
3246
- account_id: bundle.account_id,
3247
- multi_operator_participation_state: bundle.operator_posture.multi_operator_participation_state,
3248
- coordination_readiness_state: bundle.operator_posture.coordination_readiness_state,
3249
- participation_risk_state: bundle.operator_posture.participation_risk_state,
3250
- recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
3251
- };
3252
- }
3253
-
3254
- function buildMultiOperatorParticipationPolicyPack(state, accountId) {
3255
- const operatorBundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3256
- const templates = [
3257
- {
3258
- template_id: "second_operator_foundation",
3259
- recommended_for: "opening a second operator track on top of a single-operator account",
3260
- target_motion: "issue_additional_operator_account",
3261
- target_state: "emerging_multi_operator"
3262
- },
3263
- {
3264
- template_id: "coordination_activation",
3265
- recommended_for: "activating cross-zone and coordination followthrough",
3266
- target_motion: "open_coordination_followthrough",
3267
- target_state: "emerging_multi_operator"
3268
- },
3269
- {
3270
- template_id: "contract_tightening",
3271
- recommended_for: "tightening authority and identity contracts for multiple operators",
3272
- target_motion: "tighten_multi_operator_contracts",
3273
- target_state: "multi_operator_ready"
3274
- },
3275
- {
3276
- template_id: "multi_operator_trust_repair",
3277
- recommended_for: "repairing trust before widening operator participation",
3278
- target_motion: "repair_multi_operator_trust",
3279
- target_state: "emerging_multi_operator"
3280
- },
3281
- {
3282
- template_id: "steady_multi_operator_maintenance",
3283
- recommended_for: "maintaining a healthy multi-operator runtime posture",
3284
- target_motion: "maintain_multi_operator_posture",
3285
- target_state: "multi_operator_ready"
3286
- }
3287
- ];
3288
-
3289
- return {
3290
- pack_version: "xytara-multi-operator-participation-policy-pack-v1",
3291
- account_id: accountId,
3292
- multi_operator_participation_operator_bundle: operatorBundle,
3293
- recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
3294
- policy_templates: templates,
3295
- linked_surfaces: {
3296
- multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3297
- multi_operator_participation_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-application-summary`,
3298
- multi_operator_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3299
- },
3300
- generated_at_iso: nowIso()
3301
- };
3302
- }
3303
-
3304
- function summarizeMultiOperatorParticipationPolicyPack(state, accountId) {
3305
- const pack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3306
- return {
3307
- pack_version: pack.pack_version,
3308
- account_id: pack.account_id,
3309
- recommended_policy_motion: pack.recommended_policy_motion,
3310
- template_count: ensureArray(pack.policy_templates).length
3311
- };
3312
- }
3313
-
3314
- function buildMultiOperatorParticipationApplicationSummary(state, accountId, templateId) {
3315
- const pack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3316
- const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
3317
- || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
3318
- || ensureArray(pack.policy_templates)[0]
3319
- || null;
3320
-
3321
- return {
3322
- summary_version: "xytara-multi-operator-participation-application-summary-v1",
3323
- account_id: accountId,
3324
- recommended_policy_motion: pack.recommended_policy_motion,
3325
- selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
3326
- available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
3327
- selected_template: selectedTemplate,
3328
- suggested_participation_targets: {
3329
- multi_operator_participation_state: pack.multi_operator_participation_operator_bundle.operator_posture.multi_operator_participation_state,
3330
- coordination_readiness_state: pack.multi_operator_participation_operator_bundle.operator_posture.coordination_readiness_state,
3331
- participation_risk_state: pack.multi_operator_participation_operator_bundle.operator_posture.participation_risk_state,
3332
- trust_state: pack.multi_operator_participation_operator_bundle.operator_posture.trust_state
3333
- },
3334
- linked_surfaces: {
3335
- multi_operator_participation_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
3336
- multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3337
- multi_operator_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3338
- },
3339
- generated_at_iso: nowIso()
3340
- };
3341
- }
3342
-
3343
- function buildMultiOperatorParticipationPackage(state, accountId) {
3344
- const summary = buildMultiOperatorParticipationSummary(state, accountId);
3345
- const operatorBundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3346
- const policyPack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3347
- const applicationSummary = buildMultiOperatorParticipationApplicationSummary(state, accountId, null);
3348
- const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3349
- const attentionSummary = buildMultiOperatorAttentionSummary(state, accountId);
3350
-
3351
- return {
3352
- package_version: "xytara-multi-operator-participation-package-v1",
3353
- account_id: accountId,
3354
- package_posture: {
3355
- multi_operator_participation_state: summary.multi_operator_participation_state,
3356
- coordination_readiness_state: summary.coordination_readiness_state,
3357
- participation_risk_state: summary.participation_risk_state,
3358
- overall_attention_state: attentionSummary.overall_attention_state,
3359
- recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
3360
- recommended_policy_motion: policyPack.recommended_policy_motion
3361
- },
3362
- multi_operator_participation_summary: summary,
3363
- multi_operator_participation_operator_bundle: operatorBundle,
3364
- multi_operator_participation_policy_pack: policyPack,
3365
- multi_operator_participation_application_summary: applicationSummary,
3366
- multi_operator_review_bundle: reviewBundle,
3367
- multi_operator_attention_summary: attentionSummary,
3368
- linked_surfaces: {
3369
- multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`,
3370
- multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3371
- multi_operator_participation_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
3372
- multi_operator_participation_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-application-summary`,
3373
- multi_operator_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-review-bundle`,
3374
- multi_operator_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-attention-summary`
3375
- },
3376
- generated_at_iso: nowIso()
3377
- };
3378
- }
3379
-
3380
- function summarizeMultiOperatorParticipationPackage(state, accountId) {
3381
- const pack = buildMultiOperatorParticipationPackage(state, accountId);
3382
- return {
3383
- package_version: pack.package_version,
3384
- account_id: pack.account_id,
3385
- multi_operator_participation_state: pack.package_posture.multi_operator_participation_state,
3386
- coordination_readiness_state: pack.package_posture.coordination_readiness_state,
3387
- participation_risk_state: pack.package_posture.participation_risk_state,
3388
- recommended_operator_motion: pack.package_posture.recommended_operator_motion,
3389
- recommended_policy_motion: pack.package_posture.recommended_policy_motion
3390
- };
3391
- }
3392
-
3393
- function listNetworkParticipantsForAccount(state, accountId) {
3394
- return Array.from(state.networkParticipants.values())
3395
- .filter((entry) => entry && entry.account_id === accountId);
3396
- }
3397
-
3398
- function buildNetworkParticipantPublicView(entry) {
3399
- if (!entry) return null;
3400
- return {
3401
- network_participant_id: entry.network_participant_id,
3402
- account_id: entry.account_id,
3403
- label: entry.label,
3404
- network_kind: entry.network_kind,
3405
- partner_ref: entry.partner_ref || null,
3406
- status: entry.status,
3407
- participation_scope: ensureArray(entry.participation_scope),
3408
- authority_binding_id: entry.authority_binding_id || null,
3409
- identity_binding_id: entry.identity_binding_id || null,
3410
- created_at_iso: entry.created_at_iso,
3411
- updated_at_iso: entry.updated_at_iso,
3412
- issued_by: entry.issued_by || null,
3413
- labels: ensureArray(entry.labels)
3414
- };
3415
- }
3416
-
3417
- function listNetworkParticipants(state, accountId) {
3418
- return listNetworkParticipantsForAccount(state, accountId).map((entry) => buildNetworkParticipantPublicView(entry));
3419
- }
3420
-
3421
- function getNetworkParticipant(state, accountId, participantId) {
3422
- if (!participantId || !state.networkParticipants.has(participantId)) return null;
3423
- const entry = state.networkParticipants.get(participantId);
3424
- if (!entry || entry.account_id !== accountId) return null;
3425
- return buildNetworkParticipantPublicView(entry);
3426
- }
3427
-
3428
- function buildNetworkParticipationAdmissionPreview(state, accountId, body) {
3429
- const payload = ensureObject(body);
3430
- const nextIndex = listNetworkParticipantsForAccount(state, accountId).length + 1;
3431
- return {
3432
- preview_version: "xytara-network-participation-admission-preview-v1",
3433
- account_id: accountId,
3434
- proposed_participant: {
3435
- label: normalizeString(payload.label, `network-participant-${nextIndex}`),
3436
- network_kind: normalizeString(payload.network_kind, "external_operator"),
3437
- partner_ref: normalizeString(payload.partner_ref, `partner_${nextIndex}`),
3438
- participation_scope: ensureArray(payload.participation_scope).length > 0
3439
- ? ensureArray(payload.participation_scope)
3440
- : ["network.coordinate", "runtime.execute"]
3441
- },
3442
- planned_bindings: {
3443
- authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
3444
- identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity")
3445
- },
3446
- linked_surfaces: {
3447
- network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3448
- network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3449
- },
3450
- generated_at_iso: nowIso()
3451
- };
3452
- }
3453
-
3454
- function createNetworkParticipant(state, accountId, body) {
3455
- const payload = ensureObject(body);
3456
- const createdAtIso = nowIso();
3457
- const nextIndex = state.networkParticipants.size + 1;
3458
- const networkParticipantId = normalizeString(payload.network_participant_id, `network_participant_${nextIndex}`);
3459
- const participationScope = ensureArray(payload.participation_scope).length > 0
3460
- ? ensureArray(payload.participation_scope).map((value) => String(value || "").trim()).filter(Boolean)
3461
- : ["network.coordinate", "runtime.execute"];
3462
- const authorityBinding = createAuthorityBinding(state, {
3463
- binding_id: normalizeString(payload.authority_binding_id, `${networkParticipantId}_authority`),
3464
- credential_id: normalizeString(payload.credential_id, `${networkParticipantId}_credential`),
3465
- account_id: accountId,
3466
- authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
3467
- authority_scope: participationScope,
3468
- allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0
3469
- ? ensureArray(payload.allowed_consequence_families)
3470
- : ["commit", "reserve"],
3471
- max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : 5,
3472
- max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : 5,
3473
- max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : 1,
3474
- labels: ensureArray(payload.labels),
3475
- issued_by: normalizeString(payload.issued_by, "operator")
3476
- });
3477
- const identityBinding = createIdentityBinding(state, {
3478
- binding_id: normalizeString(payload.identity_binding_id, `${networkParticipantId}_identity`),
3479
- account_id: accountId,
3480
- identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity"),
3481
- identity_ref: normalizeString(payload.identity_ref, `${networkParticipantId}.identity`),
3482
- attached_agent_account_id: networkParticipantId,
3483
- labels: ensureArray(payload.labels),
3484
- issued_by: normalizeString(payload.issued_by, "operator")
3485
- });
3486
- const participant = {
3487
- network_participant_id: networkParticipantId,
3488
- account_id: accountId,
3489
- label: normalizeString(payload.label, networkParticipantId),
3490
- network_kind: normalizeString(payload.network_kind, "external_operator"),
3491
- partner_ref: normalizeString(payload.partner_ref, null),
3492
- status: normalizeString(payload.status, "active"),
3493
- participation_scope: participationScope,
3494
- authority_binding_id: authorityBinding.binding_id,
3495
- identity_binding_id: identityBinding.binding_id,
3496
- created_at_iso: createdAtIso,
3497
- updated_at_iso: createdAtIso,
3498
- issued_by: normalizeString(payload.issued_by, "operator"),
3499
- labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean)
3500
- };
3501
- state.networkParticipants.set(networkParticipantId, participant);
3502
- return {
3503
- network_participant: buildNetworkParticipantPublicView(participant),
3504
- authority_binding: authorityBinding,
3505
- identity_binding: identityBinding
3506
- };
3507
- }
3508
-
3509
- function buildNetworkParticipationReviewBundle(state, accountId) {
3510
- const participants = listNetworkParticipantsForAccount(state, accountId);
3511
- const reviewRows = participants.map((entry) => {
3512
- let review_state = "healthy";
3513
- if (entry.status !== "active") review_state = "revoked";
3514
- else if (!entry.authority_binding_id || !entry.identity_binding_id) review_state = "repair_required";
3515
- else if (!entry.partner_ref) review_state = "attention_required";
3516
- return {
3517
- network_participant_id: entry.network_participant_id,
3518
- label: entry.label,
3519
- network_kind: entry.network_kind,
3520
- status: entry.status,
3521
- partner_ref: entry.partner_ref || null,
3522
- review_state
3523
- };
3524
- });
3525
- return {
3526
- bundle_version: "xytara-network-participation-review-bundle-v1",
3527
- account_id: accountId,
3528
- review_rows: reviewRows,
3529
- review_counts: {
3530
- healthy_count: reviewRows.filter((entry) => entry.review_state === "healthy").length,
3531
- attention_required_count: reviewRows.filter((entry) => entry.review_state === "attention_required").length,
3532
- repair_required_count: reviewRows.filter((entry) => entry.review_state === "repair_required").length,
3533
- revoked_count: reviewRows.filter((entry) => entry.review_state === "revoked").length
3534
- },
3535
- linked_surfaces: {
3536
- network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3537
- network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3538
- },
3539
- generated_at_iso: nowIso()
3540
- };
3541
- }
3542
-
3543
- function buildNetworkParticipationAttentionSummary(state, accountId) {
3544
- const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3545
- const attentionRows = ensureArray(reviewBundle.review_rows).filter((entry) => entry.review_state !== "healthy");
3546
- return {
3547
- summary_version: "xytara-network-participation-attention-summary-v1",
3548
- account_id: accountId,
3549
- overall_attention_state: attentionRows.length > 0 ? "attention_required" : "healthy",
3550
- attention_rows: attentionRows,
3551
- linked_surfaces: {
3552
- network_participation_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-review-bundle`,
3553
- network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3554
- },
3555
- generated_at_iso: nowIso()
3556
- };
3557
- }
3558
-
3559
- function buildNetworkParticipationSummary(state, accountId) {
3560
- const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3561
- const multiOperatorSummary = buildMultiOperatorParticipationSummary(state, accountId);
3562
- const participants = listNetworkParticipantsForAccount(state, accountId);
3563
- const activeParticipantCount = participants.filter((entry) => entry.status === "active").length;
3564
- const coordinationHandoffCount = ensureArray(state.coordinationHandoffs).length;
3565
- const admissionCaseCount = ensureArray(state.zoneAdmissionCases).length;
3566
-
3567
- let participationState = "local_only";
3568
- if (activeParticipantCount > 0 && multiOperatorSummary.multi_operator_participation_state !== "single_operator_only") {
3569
- participationState = "external_network_present";
3570
- } else if (activeParticipantCount > 0) {
3571
- participationState = "network_edge_present";
3572
- }
3573
-
3574
- let networkReadinessState = "limited";
3575
- if (activeParticipantCount > 0 && coordinationHandoffCount > 0 && admissionCaseCount > 0) {
3576
- networkReadinessState = "active";
3577
- } else if (activeParticipantCount > 0 || coordinationHandoffCount > 0 || admissionCaseCount > 0) {
3578
- networkReadinessState = "preview_ready";
3579
- }
3580
-
3581
- let participationRiskState = "low";
3582
- if (trustLayerSummary.trust_risk_state === "high" || activeParticipantCount === 0) {
3583
- participationRiskState = "high";
3584
- } else if (networkReadinessState !== "active") {
3585
- participationRiskState = "watch";
3586
- }
3587
-
3588
- let recommendedParticipationMotion = "maintain_external_network_posture";
3589
- if (activeParticipantCount === 0) {
3590
- recommendedParticipationMotion = "admit_first_external_network_participant";
3591
- } else if (participationRiskState === "high") {
3592
- recommendedParticipationMotion = "repair_trust_before_external_network_expansion";
3593
- } else if (networkReadinessState !== "active") {
3594
- recommendedParticipationMotion = "activate_external_coordination_followthrough";
3595
- }
3596
-
3597
- return {
3598
- summary_version: "xytara-network-participation-summary-v1",
3599
- account_id: accountId,
3600
- network_participation_state: participationState,
3601
- network_readiness_state: networkReadinessState,
3602
- participation_risk_state: participationRiskState,
3603
- recommended_participation_motion: recommendedParticipationMotion,
3604
- explanation_signals: {
3605
- active_network_participant_count: activeParticipantCount,
3606
- coordination_handoff_count: coordinationHandoffCount,
3607
- admission_case_count: admissionCaseCount,
3608
- trust_state: trustLayerSummary.trust_state,
3609
- trust_risk_state: trustLayerSummary.trust_risk_state,
3610
- multi_operator_participation_state: multiOperatorSummary.multi_operator_participation_state
3611
- },
3612
- linked_surfaces: {
3613
- network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3614
- multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`,
3615
- trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
3616
- coordination_center_ref: "/v1/coordination-center/summary"
3617
- },
3618
- generated_at_iso: nowIso()
3619
- };
3620
- }
3621
-
3622
- function buildNetworkParticipationOperatorBundle(state, accountId) {
3623
- const summary = buildNetworkParticipationSummary(state, accountId);
3624
- const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3625
- const attentionSummary = buildNetworkParticipationAttentionSummary(state, accountId);
3626
- const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3627
- const multiOperatorSummary = buildMultiOperatorParticipationSummary(state, accountId);
3628
- const participants = listNetworkParticipants(state, accountId);
3629
-
3630
- let recommendedOperatorMotion = "maintain_external_network_posture";
3631
- if (summary.network_participation_state === "local_only") {
3632
- recommendedOperatorMotion = "admit_first_external_network_participant";
3633
- } else if (summary.participation_risk_state === "high") {
3634
- recommendedOperatorMotion = "repair_trust_before_external_network_expansion";
3635
- } else if (summary.network_readiness_state !== "active") {
3636
- recommendedOperatorMotion = "activate_external_coordination_followthrough";
3637
- }
3638
-
3639
- return {
3640
- bundle_version: "xytara-network-participation-operator-bundle-v1",
3641
- account_id: accountId,
3642
- operator_posture: {
3643
- network_participation_state: summary.network_participation_state,
3644
- network_readiness_state: summary.network_readiness_state,
3645
- participation_risk_state: summary.participation_risk_state,
3646
- active_network_participant_count: participants.filter((entry) => entry.status === "active").length,
3647
- trust_state: trustLayerSummary.trust_state,
3648
- multi_operator_participation_state: multiOperatorSummary.multi_operator_participation_state,
3649
- overall_attention_state: attentionSummary.overall_attention_state,
3650
- recommended_operator_motion: recommendedOperatorMotion
3651
- },
3652
- network_participation_summary: summary,
3653
- network_participation_review_bundle: reviewBundle,
3654
- network_participation_attention_summary: attentionSummary,
3655
- trust_layer_summary: trustLayerSummary,
3656
- multi_operator_participation_summary: multiOperatorSummary,
3657
- network_participants: participants,
3658
- linked_surfaces: summary.linked_surfaces,
3659
- generated_at_iso: nowIso()
3660
- };
3661
- }
3662
-
3663
- function buildNetworkParticipationPackage(state, accountId) {
3664
- const summary = buildNetworkParticipationSummary(state, accountId);
3665
- const operatorBundle = buildNetworkParticipationOperatorBundle(state, accountId);
3666
- const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3667
- const attentionSummary = buildNetworkParticipationAttentionSummary(state, accountId);
3668
- return {
3669
- package_version: "xytara-network-participation-package-v1",
3670
- account_id: accountId,
3671
- package_posture: {
3672
- network_participation_state: summary.network_participation_state,
3673
- network_readiness_state: summary.network_readiness_state,
3674
- participation_risk_state: summary.participation_risk_state,
3675
- overall_attention_state: attentionSummary.overall_attention_state,
3676
- recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion
3677
- },
3678
- network_participation_summary: summary,
3679
- network_participation_operator_bundle: operatorBundle,
3680
- network_participation_review_bundle: reviewBundle,
3681
- network_participation_attention_summary: attentionSummary,
3682
- linked_surfaces: {
3683
- network_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-summary`,
3684
- network_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-operator-bundle`,
3685
- network_participation_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-review-bundle`,
3686
- network_participation_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-attention-summary`,
3687
- network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`
3688
- },
3689
- generated_at_iso: nowIso()
3690
- };
3691
- }
3692
-
3693
- function buildRailSummary(state, accountId) {
3694
- const credits = listRailCreditsForAccount(state, accountId);
3695
- const railCreditLifecycle = summarizeRailCreditLifecycle(credits);
3696
- const paymentLedger = listPaymentLedgerForAccount(state, accountId);
3697
- const spends = listCreditSpendsForAccount(state, accountId);
3698
- const entitlements = listEntitlementsForAccount(state, accountId);
3699
- const replenishment = buildEntitlementReplenishmentSummary(state, accountId);
3700
- return {
3701
- account_id: accountId,
3702
- credit_event_count: credits.length,
3703
- credit_mint_count: railCreditLifecycle.mint_count,
3704
- credit_reverse_count: railCreditLifecycle.reverse_count,
3705
- credit_units_total: railCreditLifecycle.minted_units,
3706
- reversed_credit_units_total: railCreditLifecycle.reversed_units,
3707
- credit_spend_count: spends.length,
3708
- entitlement_count: entitlements.length,
3709
- low_balance_entitlement_count: replenishment.low_balance_count,
3710
- depleted_entitlement_count: replenishment.depleted_count,
3711
- available_credit_units: buildCreditBalanceSummary(state, accountId).available_units,
3712
- settlement_adapter_counts: paymentLedger.reduce((acc, entry) => {
3713
- const key = entry && entry.settlement_adapter ? entry.settlement_adapter : "unknown";
3714
- acc[key] = (acc[key] || 0) + 1;
3715
- return acc;
3716
- }, {}),
3717
- generated_at_iso: nowIso()
3718
- };
3719
- }
3720
-
3721
- function buildTreasuryWorkflowPack(state, accountId) {
3722
- return {
3723
- pack_version: "xytara-economics-treasury-workflow-pack-v1",
3724
- account_id: accountId,
3725
- treasury_summary: buildTreasurySummary(state, accountId),
3726
- rail_summary: buildRailSummary(state, accountId),
3727
- policy_summary: buildPolicySummary(state, accountId),
3728
- reconciliation_pack: buildReconciliationPack(state, accountId),
3729
- generated_at_iso: nowIso()
3730
- };
3731
- }
3732
-
3733
- function buildTreasurySignoffPack(state, accountId) {
3734
- return {
3735
- pack_version: "xytara-economics-treasury-signoff-pack-v1",
3736
- workflow_pack: buildTreasuryWorkflowPack(state, accountId),
3737
- signoff_posture: "operator_review_required",
3738
- generated_at_iso: nowIso()
3739
- };
3740
- }
3741
-
3742
- function buildRailWorkflowPack(state, accountId) {
3743
- return {
3744
- pack_version: "xytara-economics-rail-workflow-pack-v1",
3745
- account_id: accountId,
3746
- rail_summary: buildRailSummary(state, accountId),
3747
- treasury_summary: buildTreasurySummary(state, accountId),
3748
- generated_at_iso: nowIso()
3749
- };
3750
- }
3751
-
3752
- function buildRailSignoffPack(state, accountId) {
3753
- return {
3754
- pack_version: "xytara-economics-rail-signoff-pack-v1",
3755
- workflow_pack: buildRailWorkflowPack(state, accountId),
3756
- signoff_posture: "operator_review_required",
3757
- generated_at_iso: nowIso()
3758
- };
3759
- }
3760
-
3761
- function buildMarketPreview(state, body) {
3762
- const payload = ensureObject(body);
3763
- const accountId = normalizeString(payload.account_id, "acct_demo");
3764
- const treasurySummary = buildTreasurySummary(state, accountId);
3765
- return {
3766
- account_id: accountId,
3767
- market_ref: normalizeString(payload.market_ref, "market.default"),
3768
- interaction_class: normalizeString(payload.interaction_class, "standard"),
3769
- admissible_capacity_hint: {
3770
- minted_units: treasurySummary.treasury.minted_units,
3771
- committed_units: treasurySummary.treasury.committed_units,
3772
- free_units: Math.max(0, treasurySummary.treasury.minted_units - treasurySummary.treasury.committed_units)
3773
- },
3774
- recommended_artifacts: [
3775
- "treasury_summary",
3776
- "rail_summary",
3777
- "policy_summary",
3778
- "reconciliation_pack"
3779
- ],
3780
- generated_at_iso: nowIso()
3781
- };
3782
- }
3783
-
3784
- function buildMarketWorkflowPack(state, body) {
3785
- const preview = buildMarketPreview(state, body);
3786
- return {
3787
- pack_version: "xytara-economics-market-workflow-pack-v1",
3788
- preview,
3789
- treasury_summary: buildTreasurySummary(state, preview.account_id),
3790
- rail_summary: buildRailSummary(state, preview.account_id),
3791
- policy_summary: buildPolicySummary(state, preview.account_id),
3792
- reconciliation_pack: buildReconciliationPack(state, preview.account_id),
3793
- generated_at_iso: nowIso()
3794
- };
3795
- }
3796
-
3797
- function buildMarketSignoffPack(state, body) {
3798
- const workflowPack = buildMarketWorkflowPack(state, body);
3799
- return {
3800
- pack_version: "xytara-economics-market-signoff-pack-v1",
3801
- workflow_pack: workflowPack,
3802
- signoff_posture: "operator_review_required",
3803
- generated_at_iso: nowIso()
3804
- };
3805
- }
3806
-
3807
- function buildMarketCoordinationPack(state, body) {
3808
- const signoffPack = buildMarketSignoffPack(state, body);
3809
- return {
3810
- pack_version: "xytara-economics-market-coordination-pack-v1",
3811
- signoff_pack: signoffPack,
3812
- adjacency_refs: {
3813
- coordination_surface: "/v1/economics/markets/coordination-pack",
3814
- next_public_surface: "/v1/zones"
3815
- },
3816
- generated_at_iso: nowIso()
3817
- };
3818
- }
3819
-
3820
- function actOnEconomicsJob(state, jobId, body) {
3821
- const payload = ensureObject(body);
3822
- const entry = {
3823
- job_id: normalizeString(jobId, `job_${ensureArray(state.economicsJobActions).length + 1}`),
3824
- account_id: normalizeString(payload.account_id, "acct_demo"),
3825
- action: normalizeString(payload.action, "reviewed"),
3826
- actor: normalizeString(payload.actor, "operator"),
3827
- reason: normalizeString(payload.reason, null),
3828
- created_at_iso: nowIso()
3829
- };
3830
- state.economicsJobActions = [entry, ...ensureArray(state.economicsJobActions)].slice(0, 200);
3831
- return entry;
3832
- }
3833
-
3834
- function buildEvidenceByReceipt(state, receiptRef) {
3835
- const receipt = state.economicsReceipts.get(receiptRef) || null;
3836
- if (!receipt) return null;
3837
- const ledgerConsequences = ensureArray(state.economicsAllocations).filter((entry) => entry && entry.receipt_ref === receiptRef);
3838
- return {
3839
- receipt,
3840
- ledger_consequences: ledgerConsequences,
3841
- generated_at_iso: nowIso()
3842
- };
3843
- }
3844
-
3845
- function buildEvidenceByJob(state, jobId) {
3846
- const receipts = Array.from(state.economicsReceipts.values()).filter((entry) => entry && entry.job_id === jobId);
3847
- return {
3848
- job_id: jobId,
3849
- economics_receipts: receipts,
3850
- ledger_consequences: ensureArray(state.economicsAllocations).filter((entry) => entry && entry.job_id === jobId),
3851
- operator_actions: ensureArray(state.economicsJobActions).filter((entry) => entry && entry.job_id === jobId),
3852
- generated_at_iso: nowIso()
3853
- };
3854
- }
3855
-
3856
- function buildIntegrationJobEvidence(state, jobId) {
3857
- const evidence = buildEvidenceByJob(state, jobId);
3858
- return {
3859
- integration_job_ref: jobId,
3860
- adjacent_surfaces: {
3861
- proof_side: "/v1/proof-bundles/build",
3862
- transaction_side: "/v1/payment-ledger"
3863
- },
3864
- evidence_bundle: evidence,
3865
- generated_at_iso: nowIso()
3866
- };
3867
- }
3868
-
3869
- function validateReceiptLedgerHandoff(state, body) {
3870
- const payload = ensureObject(body);
3871
- const accountId = normalizeString(payload.account_id, "acct_demo");
3872
- return {
3873
- ok: true,
3874
- account_id: accountId,
3875
- validation_status: "valid",
3876
- handoff_kind: "receipt_ledger",
3877
- payment_ledger_count: listPaymentLedgerForAccount(state, accountId).length,
3878
- receipt_count: listMapValuesByAccount(state.economicsReceipts, accountId).length,
3879
- generated_at_iso: nowIso()
3880
- };
3881
- }
3882
-
3883
- function emitInterpretationHandoff(state, body) {
3884
- const payload = ensureObject(body);
3885
- const accountId = normalizeString(payload.account_id, "acct_demo");
3886
- const treasurySummary = buildTreasurySummary(state, accountId);
3887
- const handoff = {
3888
- handoff_version: "xytara-economics-interpretation-handoff-v1",
3889
- account_id: accountId,
3890
- treasury_summary: treasurySummary,
3891
- policy_summary: buildPolicySummary(state, accountId),
3892
- rail_summary: buildRailSummary(state, accountId),
3893
- reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`,
3894
- generated_at_iso: nowIso()
3895
- };
3896
- state.economicsInterpretationHandoffs = [handoff, ...ensureArray(state.economicsInterpretationHandoffs)].slice(0, 50);
3897
- return {
3898
- ok: true,
3899
- handoff
3900
- };
3901
- }
3902
-
3903
- module.exports = {
3904
- createEconomicsBudget,
3905
- setEconomicsBudgetStatus,
3906
- createEconomicsAgent,
3907
- setEconomicsAgentStatus,
3908
- createEconomicsReceipt,
3909
- updateEconomicsReceiptLifecycle,
3910
- actOnEconomicsReceipt,
3911
- recordAllocationEvent,
3912
- previewRailCredits,
3913
- applyRailCredits,
3914
- reverseRailCredits,
3915
- buildCreditBalanceSummary,
3916
- buildWalletSummary,
3917
- buildWalletLifecycleSummary,
3918
- buildWalletReserveSummary,
3919
- buildWalletCommitSummary,
3920
- buildWalletLedgerBundle,
3921
- buildWalletLedgerSummary,
3922
- applyWalletLifecycleEvent,
3923
- buildEconomicsIntelligenceSummary,
3924
- buildTreasuryIntelligenceSummary,
3925
- buildTreasurySummary,
3926
- buildLedgerExport,
3927
- buildTreasuryDrilldown,
3928
- buildReconciliationPack,
3929
- buildAccountSummary,
3930
- buildOperatorView,
3931
- buildOperatorDashboard,
3932
- buildPolicySummary,
3933
- buildAccountCreditSpendPolicyPack,
3934
- buildAgentCreditSpendPolicyView,
3935
- buildPricingPolicySummary,
3936
- buildPricingPolicyOperatorBundle,
3937
- buildPricingPolicyPack,
3938
- buildPricingPolicyApplicationSummary,
3939
- buildPricingPolicyPackage,
3940
- buildQuotePolicyDecisionSummary,
3941
- buildPricingBandDecisionSummary,
3942
- buildQuotePolicyOperatorBundle,
3943
- summarizeQuotePolicyOperatorBundle,
3944
- buildQuotePolicyPack,
3945
- summarizeQuotePolicyPack,
3946
- buildQuotePolicyApplicationSummary,
3947
- buildQuotePolicyPackage,
3948
- summarizeQuotePolicyPackage,
3949
- buildTrustInputSummary,
3950
- buildTrustLayerSummary,
3951
- buildTrustLayerOperatorBundle,
3952
- summarizeTrustLayerOperatorBundle,
3953
- buildTrustLayerPolicyPack,
3954
- summarizeTrustLayerPolicyPack,
3955
- buildTrustLayerApplicationSummary,
3956
- buildTrustLayerPackage,
3957
- summarizeTrustLayerPackage,
3958
- listNetworkParticipants,
3959
- getNetworkParticipant,
3960
- buildNetworkParticipationAdmissionPreview,
3961
- createNetworkParticipant,
3962
- buildNetworkParticipationReviewBundle,
3963
- buildNetworkParticipationAttentionSummary,
3964
- buildNetworkParticipationSummary,
3965
- buildNetworkParticipationOperatorBundle,
3966
- buildNetworkParticipationPackage,
3967
- listMultiOperatorParticipants,
3968
- getMultiOperatorParticipant,
3969
- buildMultiOperatorAdmissionPreview,
3970
- createMultiOperatorParticipant,
3971
- renewMultiOperatorParticipant,
3972
- revokeMultiOperatorParticipant,
3973
- rotateMultiOperatorParticipant,
3974
- buildMultiOperatorParticipantRotationSummary,
3975
- buildMultiOperatorReviewBundle,
3976
- buildMultiOperatorAttentionSummary,
3977
- buildMultiOperatorParticipationSummary,
3978
- buildMultiOperatorParticipationOperatorBundle,
3979
- summarizeMultiOperatorParticipationOperatorBundle,
3980
- buildMultiOperatorParticipationPolicyPack,
3981
- summarizeMultiOperatorParticipationPolicyPack,
3982
- buildMultiOperatorParticipationApplicationSummary,
3983
- buildMultiOperatorParticipationPackage,
3984
- summarizeMultiOperatorParticipationPackage,
3985
- buildRailSummary,
3986
- buildTreasuryWorkflowPack,
3987
- buildTreasurySignoffPack,
3988
- buildRailWorkflowPack,
3989
- buildRailSignoffPack,
3990
- buildEntitlementSummary,
3991
- buildEntitlementReplenishmentSummary,
3992
- buildEntitlementReplenishmentView,
3993
- buildEconomicConsequenceHandoffBundle,
3994
- buildUsageMeterPreview,
3995
- buildUsageMeteringSummary,
3996
- buildMarketPreview,
3997
- buildMarketWorkflowPack,
3998
- buildMarketSignoffPack,
3999
- buildMarketCoordinationPack,
4000
- consumeAccountCredits,
4001
- previewCreditSpend,
4002
- actOnEconomicsJob,
4003
- buildEvidenceByReceipt,
4004
- buildEvidenceByJob,
4005
- buildIntegrationJobEvidence,
4006
- validateReceiptLedgerHandoff,
4007
- emitInterpretationHandoff,
4008
- listMapValuesByAccount,
4009
- listEntitlementsForAccount,
4010
- getEntitlement,
4011
- getAllocationEvent,
4012
- getCreditSpend,
4013
- listUsageMetersForAccount,
4014
- getUsageMeter,
4015
- upsertEntitlementPool,
4016
- updateEntitlementReplenishmentPreference
4017
- };