xytara 2.2.0 → 2.4.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.
@@ -2,6 +2,26 @@
2
2
 
3
3
  const crypto = require("crypto");
4
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");
5
25
 
6
26
  function normalizeString(value, fallback) {
7
27
  const trimmed = typeof value === "string" ? value.trim() : "";
@@ -155,13 +175,21 @@ function actOnEconomicsReceipt(state, receiptId, body) {
155
175
 
156
176
  function recordAllocationEvent(state, body, direction) {
157
177
  const payload = ensureObject(body);
178
+ const allocationId = normalizeString(payload.allocation_id, `alloc_${state.economicsAllocations.length + 1}`);
158
179
  const event = {
159
- allocation_id: normalizeString(payload.allocation_id, `alloc_${state.economicsAllocations.length + 1}`),
180
+ allocation_id: allocationId,
160
181
  account_id: normalizeString(payload.account_id, "acct_demo"),
161
182
  budget_id: normalizeString(payload.budget_id, null),
162
183
  job_id: normalizeString(payload.job_id, null),
163
184
  agent_id: normalizeString(payload.agent_id, null),
164
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),
165
193
  units: typeof payload.units === "number" ? payload.units : 0,
166
194
  direction,
167
195
  reason: normalizeString(payload.reason, null),
@@ -347,6 +375,11 @@ function listCreditSpendsForAccount(state, accountId) {
347
375
  return ensureArray(state.economicsCreditSpends).filter((item) => item && item.account_id === accountId);
348
376
  }
349
377
 
378
+ function getAllocationEvent(state, allocationId) {
379
+ if (!allocationId) return null;
380
+ return ensureArray(state.economicsAllocations).find((item) => item && item.allocation_id === allocationId) || null;
381
+ }
382
+
350
383
  function getCreditSpend(state, creditSpendId) {
351
384
  if (!creditSpendId) return null;
352
385
  return ensureArray(state.economicsCreditSpends).find((item) => item && item.credit_spend_id === creditSpendId) || null;
@@ -478,6 +511,450 @@ function buildCreditBalanceSummary(state, accountId) {
478
511
  };
479
512
  }
480
513
 
514
+ function buildWalletSummary(state, accountId) {
515
+ const balance = buildCreditBalanceSummary(state, accountId);
516
+ const allocations = listAllocationEventsForAccount(state, accountId);
517
+ const usageMeters = listUsageMetersForAccount(state, accountId);
518
+ const reserveUnits = allocations
519
+ .filter((entry) => entry && entry.direction === "reserve")
520
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
521
+ const committedUnits = allocations
522
+ .filter((entry) => entry && entry.direction === "commit")
523
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
524
+ const releasedUnits = allocations
525
+ .filter((entry) => entry && entry.direction === "release")
526
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
527
+ const reversedUnits = allocations
528
+ .filter((entry) => entry && entry.direction === "reverse")
529
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
530
+ const reserveCount = allocations.filter((entry) => entry && entry.direction === "reserve").length;
531
+ const walletState = balance.available_units <= 0
532
+ ? "depleted"
533
+ : balance.entitlement_summary.low_entitlement_count > 0
534
+ ? "low_balance"
535
+ : "healthy";
536
+
537
+ return {
538
+ wallet_version: "xytara-machine-wallet-summary-v1",
539
+ wallet_id: `wallet_${accountId}`,
540
+ account_id: accountId,
541
+ canonical_unit: "usage_units",
542
+ wallet_state: walletState,
543
+ issued_units: balance.issued_units,
544
+ available_units: balance.available_units,
545
+ reserved_units: reserveUnits,
546
+ committed_units: committedUnits,
547
+ released_units: releasedUnits,
548
+ reversed_units: reversedUnits,
549
+ consumed_units: balance.consumed_units,
550
+ reserve_count: reserveCount,
551
+ entitlement_count: balance.entitlement_summary.entitlement_count,
552
+ active_entitlement_count: balance.entitlement_summary.active_entitlement_count,
553
+ usage_meter_count: usageMeters.length,
554
+ replenishment_posture: balance.replenishment_summary.depleted_count > 0
555
+ ? "replenishment_required"
556
+ : balance.replenishment_summary.low_balance_count > 0
557
+ ? "replenishment_recommended"
558
+ : "sufficient_capacity",
559
+ linked_surfaces: {
560
+ credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
561
+ entitlements_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/entitlements`,
562
+ usage_meters_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/usage-meters`,
563
+ wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
564
+ wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
565
+ wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
566
+ },
567
+ generated_at_iso: nowIso()
568
+ };
569
+ }
570
+
571
+ function buildWalletLifecycleSummary(state, accountId) {
572
+ const wallet = buildWalletSummary(state, accountId);
573
+ const allocations = listAllocationEventsForAccount(state, accountId);
574
+ const railCredits = listRailCreditsForAccount(state, accountId);
575
+ const creditSpends = listCreditSpendsForAccount(state, accountId);
576
+ const usageMeters = listUsageMetersForAccount(state, accountId);
577
+ const mintedUnits = allocations
578
+ .filter((entry) => entry && entry.direction === "mint")
579
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0)
580
+ + railCredits.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
581
+ const reservedUnits = allocations
582
+ .filter((entry) => entry && entry.direction === "reserve")
583
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
584
+ const explicitCommittedUnits = allocations
585
+ .filter((entry) => entry && entry.direction === "commit")
586
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
587
+ const explicitCommitSpendIds = new Set(
588
+ allocations
589
+ .filter((entry) => entry && entry.direction === "commit" && entry.credit_spend_id)
590
+ .map((entry) => entry.credit_spend_id)
591
+ );
592
+ const fallbackCommittedSpends = creditSpends.filter((entry) => entry && !explicitCommitSpendIds.has(entry.credit_spend_id));
593
+ const spendCommittedUnits = fallbackCommittedSpends.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
594
+ const releasedUnits = allocations
595
+ .filter((entry) => entry && entry.direction === "release")
596
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
597
+ const reversedUnits = allocations
598
+ .filter((entry) => entry && entry.direction === "reverse")
599
+ .reduce((sum, entry) => sum + Number(entry.units || 0), 0);
600
+ const committedUnits = explicitCommittedUnits + spendCommittedUnits;
601
+ const openReservedUnits = Math.max(0, reservedUnits - releasedUnits);
602
+ const correctionState = reversedUnits > 0 ? "corrective_activity_present" : "none";
603
+ const reserveState = openReservedUnits > 0 ? "open_reserves_present" : reservedUnits > 0 ? "reserves_fully_resolved" : "no_reserves_recorded";
604
+ const commitState = committedUnits > 0 ? "committed_consequence_present" : "no_committed_consequence";
605
+
606
+ return {
607
+ summary_version: "xytara-wallet-lifecycle-summary-v1",
608
+ wallet_id: wallet.wallet_id,
609
+ account_id: accountId,
610
+ canonical_unit: wallet.canonical_unit,
611
+ canonical_lifecycle_model: "mint_reserve_commit_release_reverse",
612
+ lifecycle_semantics: {
613
+ mint: "introduces usage-unit capacity into the hidden machine wallet",
614
+ reserve: "places bounded pre-execution hold against available capacity before final consequence",
615
+ commit: "records final consequence against wallet capacity, including live credit-spend consequence",
616
+ release: "returns previously reserved capacity when bounded execution does not finalize against that hold",
617
+ reverse: "records explicit corrective removal or rollback against previously issued or committed capacity"
618
+ },
619
+ lifecycle_totals: {
620
+ minted_units: mintedUnits,
621
+ reserved_units: reservedUnits,
622
+ committed_units: committedUnits,
623
+ released_units: releasedUnits,
624
+ reversed_units: reversedUnits,
625
+ consumed_units: wallet.consumed_units,
626
+ open_reserved_units: openReservedUnits,
627
+ available_units: wallet.available_units
628
+ },
629
+ lifecycle_states: {
630
+ wallet_state: wallet.wallet_state,
631
+ reserve_state: reserveState,
632
+ commit_state: commitState,
633
+ correction_state: correctionState
634
+ },
635
+ record_interpretation: {
636
+ mint_sources: {
637
+ allocation_mint_count: allocations.filter((entry) => entry && entry.direction === "mint").length,
638
+ rail_credit_count: railCredits.length
639
+ },
640
+ reserve_sources: {
641
+ allocation_reserve_count: allocations.filter((entry) => entry && entry.direction === "reserve").length
642
+ },
643
+ commit_sources: {
644
+ explicit_commit_count: allocations.filter((entry) => entry && entry.direction === "commit").length,
645
+ derived_credit_spend_commit_count: fallbackCommittedSpends.length,
646
+ usage_meter_count: usageMeters.length
647
+ },
648
+ release_sources: {
649
+ allocation_release_count: allocations.filter((entry) => entry && entry.direction === "release").length
650
+ },
651
+ reverse_sources: {
652
+ allocation_reverse_count: allocations.filter((entry) => entry && entry.direction === "reverse").length
653
+ }
654
+ },
655
+ linked_surfaces: {
656
+ wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
657
+ wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
658
+ wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`,
659
+ credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
660
+ treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
661
+ reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
662
+ },
663
+ generated_at_iso: nowIso()
664
+ };
665
+ }
666
+
667
+ function buildWalletLedgerSummary(state, accountId) {
668
+ const wallet = buildWalletSummary(state, accountId);
669
+ const lifecycle = buildWalletLifecycleSummary(state, accountId);
670
+ const allocations = listAllocationEventsForAccount(state, accountId);
671
+ const spends = listCreditSpendsForAccount(state, accountId);
672
+ const railCredits = listRailCreditsForAccount(state, accountId);
673
+ const explicitCommitSpendIds = new Set(
674
+ allocations
675
+ .filter((entry) => entry && entry.direction === "commit" && entry.credit_spend_id)
676
+ .map((entry) => entry.credit_spend_id)
677
+ );
678
+ const fallbackCommittedSpends = spends.filter((entry) => entry && !explicitCommitSpendIds.has(entry.credit_spend_id));
679
+ const consequences = {
680
+ mint_count: allocations.filter((entry) => entry && entry.direction === "mint").length + railCredits.length,
681
+ reserve_count: allocations.filter((entry) => entry && entry.direction === "reserve").length,
682
+ commit_count: allocations.filter((entry) => entry && entry.direction === "commit").length + fallbackCommittedSpends.length,
683
+ release_count: allocations.filter((entry) => entry && entry.direction === "release").length,
684
+ reverse_count: allocations.filter((entry) => entry && entry.direction === "reverse").length
685
+ };
686
+
687
+ return {
688
+ summary_version: "xytara-wallet-ledger-summary-v1",
689
+ wallet_id: wallet.wallet_id,
690
+ account_id: accountId,
691
+ canonical_truth_posture: "allocation_and_consequence_records_with_materialized_wallet_summary",
692
+ canonical_lifecycle_model: lifecycle.canonical_lifecycle_model,
693
+ canonical_unit: wallet.canonical_unit,
694
+ wallet_state: wallet.wallet_state,
695
+ wallet_summary: {
696
+ issued_units: wallet.issued_units,
697
+ available_units: wallet.available_units,
698
+ reserved_units: wallet.reserved_units,
699
+ committed_units: wallet.committed_units,
700
+ released_units: wallet.released_units,
701
+ reversed_units: wallet.reversed_units,
702
+ consumed_units: wallet.consumed_units
703
+ },
704
+ lifecycle_state_summary: lifecycle.lifecycle_states,
705
+ ledger_lifecycle_counts: consequences,
706
+ source_record_counts: {
707
+ allocation_count: allocations.length,
708
+ rail_credit_count: railCredits.length,
709
+ credit_spend_count: spends.length,
710
+ entitlement_count: wallet.entitlement_count,
711
+ usage_meter_count: wallet.usage_meter_count
712
+ },
713
+ translation_boundary: {
714
+ public_commercial_shell: "credits",
715
+ canonical_hidden_unit: "usage_units",
716
+ canonical_wallet_truth: "hidden_machine_wallet",
717
+ materialized_projection: "wallet_summary"
718
+ },
719
+ linked_surfaces: {
720
+ wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
721
+ wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
722
+ ledger_export_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/ledger-export`,
723
+ reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
724
+ },
725
+ generated_at_iso: nowIso()
726
+ };
727
+ }
728
+
729
+ function buildWalletReserveSummary(state, accountId) {
730
+ const allocations = listAllocationEventsForAccount(state, accountId);
731
+ const reserveEvents = allocations.filter((entry) => entry && entry.direction === "reserve");
732
+ const resolutionEvents = allocations.filter((entry) => entry && (entry.direction === "release" || entry.direction === "reverse"));
733
+ const reserveRows = reserveEvents.map((reserve) => {
734
+ const linkedResolutions = resolutionEvents.filter((entry) => entry && entry.resolves_allocation_id === reserve.allocation_id);
735
+ const resolvedUnits = linkedResolutions.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
736
+ const openUnits = Math.max(0, Number(reserve.units || 0) - resolvedUnits);
737
+ return {
738
+ reserve_ref: reserve.reserve_ref || `reserve.${reserve.allocation_id}`,
739
+ allocation_id: reserve.allocation_id,
740
+ account_id: reserve.account_id,
741
+ units: Number(reserve.units || 0),
742
+ open_units: openUnits,
743
+ reserve_state: openUnits > 0 ? "open" : "resolved",
744
+ reason: reserve.reason || null,
745
+ created_at_iso: reserve.created_at_iso || null,
746
+ linked_resolution_count: linkedResolutions.length,
747
+ linked_resolutions: linkedResolutions.map((entry) => ({
748
+ allocation_id: entry.allocation_id,
749
+ direction: entry.direction,
750
+ units: Number(entry.units || 0),
751
+ reason: entry.reason || null,
752
+ created_at_iso: entry.created_at_iso || null
753
+ }))
754
+ };
755
+ });
756
+
757
+ return {
758
+ summary_version: "xytara-wallet-reserve-summary-v1",
759
+ account_id: accountId,
760
+ reserve_count: reserveRows.length,
761
+ open_reserve_count: reserveRows.filter((entry) => entry.reserve_state === "open").length,
762
+ resolved_reserve_count: reserveRows.filter((entry) => entry.reserve_state === "resolved").length,
763
+ total_reserved_units: reserveRows.reduce((sum, entry) => sum + entry.units, 0),
764
+ total_open_reserved_units: reserveRows.reduce((sum, entry) => sum + entry.open_units, 0),
765
+ reserves: reserveRows,
766
+ linked_surfaces: {
767
+ wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
768
+ wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
769
+ wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
770
+ wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
771
+ },
772
+ generated_at_iso: nowIso()
773
+ };
774
+ }
775
+
776
+ function buildWalletCommitSummary(state, accountId) {
777
+ const allocations = listAllocationEventsForAccount(state, accountId);
778
+ const commitEvents = allocations.filter((entry) => entry && entry.direction === "commit");
779
+ const reverseEvents = allocations.filter((entry) => entry && entry.direction === "reverse");
780
+ const commitRows = commitEvents.map((commit) => {
781
+ const linkedReversals = reverseEvents.filter((entry) => entry && entry.resolves_allocation_id === commit.allocation_id);
782
+ const reversedUnits = linkedReversals.reduce((sum, entry) => sum + Number(entry.units || 0), 0);
783
+ const netCommittedUnits = Math.max(0, Number(commit.units || 0) - reversedUnits);
784
+ return {
785
+ commit_ref: commit.commit_ref || `commit.${commit.allocation_id}`,
786
+ allocation_id: commit.allocation_id,
787
+ account_id: commit.account_id,
788
+ credit_spend_id: commit.credit_spend_id || null,
789
+ usage_meter_id: commit.usage_meter_id || null,
790
+ transaction_id: commit.transaction_id || null,
791
+ receipt_ref: commit.receipt_ref || null,
792
+ units: Number(commit.units || 0),
793
+ net_committed_units: netCommittedUnits,
794
+ commit_state: netCommittedUnits > 0 ? "active" : "fully_reversed",
795
+ reason: commit.reason || null,
796
+ created_at_iso: commit.created_at_iso || null,
797
+ linked_reversal_count: linkedReversals.length,
798
+ linked_reversals: linkedReversals.map((entry) => ({
799
+ allocation_id: entry.allocation_id,
800
+ direction: entry.direction,
801
+ units: Number(entry.units || 0),
802
+ reason: entry.reason || null,
803
+ created_at_iso: entry.created_at_iso || null
804
+ }))
805
+ };
806
+ });
807
+
808
+ return {
809
+ summary_version: "xytara-wallet-commit-summary-v1",
810
+ account_id: accountId,
811
+ commit_count: commitRows.length,
812
+ active_commit_count: commitRows.filter((entry) => entry.commit_state === "active").length,
813
+ fully_reversed_commit_count: commitRows.filter((entry) => entry.commit_state === "fully_reversed").length,
814
+ total_committed_units: commitRows.reduce((sum, entry) => sum + entry.units, 0),
815
+ total_net_committed_units: commitRows.reduce((sum, entry) => sum + entry.net_committed_units, 0),
816
+ commits: commitRows,
817
+ linked_surfaces: {
818
+ wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
819
+ wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
820
+ wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
821
+ wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`
822
+ },
823
+ generated_at_iso: nowIso()
824
+ };
825
+ }
826
+
827
+ function buildWalletLedgerBundle(state, accountId) {
828
+ const wallet = buildWalletSummary(state, accountId);
829
+ const lifecycle = buildWalletLifecycleSummary(state, accountId);
830
+ const reserves = buildWalletReserveSummary(state, accountId);
831
+ const commits = buildWalletCommitSummary(state, accountId);
832
+ const ledger = buildWalletLedgerSummary(state, accountId);
833
+ const balance = buildCreditBalanceSummary(state, accountId);
834
+
835
+ return {
836
+ bundle_version: "xytara-wallet-ledger-bundle-v1",
837
+ account_id: accountId,
838
+ wallet_id: wallet.wallet_id,
839
+ canonical_unit: wallet.canonical_unit,
840
+ canonical_truth_posture: ledger.canonical_truth_posture,
841
+ canonical_lifecycle_model: lifecycle.canonical_lifecycle_model,
842
+ bundle_state: {
843
+ wallet_state: wallet.wallet_state,
844
+ reserve_state: lifecycle.lifecycle_states.reserve_state,
845
+ commit_state: lifecycle.lifecycle_states.commit_state,
846
+ correction_state: lifecycle.lifecycle_states.correction_state,
847
+ replenishment_posture: wallet.replenishment_posture
848
+ },
849
+ compact_totals: {
850
+ issued_units: wallet.issued_units,
851
+ available_units: wallet.available_units,
852
+ consumed_units: wallet.consumed_units,
853
+ open_reserved_units: lifecycle.lifecycle_totals.open_reserved_units,
854
+ active_commit_units: commits.total_net_committed_units,
855
+ reversed_units: lifecycle.lifecycle_totals.reversed_units
856
+ },
857
+ wallet_summary: wallet,
858
+ wallet_lifecycle_summary: lifecycle,
859
+ wallet_reserve_summary: reserves,
860
+ wallet_commit_summary: commits,
861
+ wallet_ledger_summary: ledger,
862
+ credit_balance_summary: balance,
863
+ linked_surfaces: {
864
+ wallet_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet`,
865
+ wallet_lifecycle_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-lifecycle-summary`,
866
+ wallet_reserve_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-reserve-summary`,
867
+ wallet_commit_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-commit-summary`,
868
+ wallet_ledger_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-summary`,
869
+ reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`
870
+ },
871
+ generated_at_iso: nowIso()
872
+ };
873
+ }
874
+
875
+ function applyWalletLifecycleEvent(state, body, direction) {
876
+ const payload = ensureObject(body);
877
+ const accountId = normalizeString(payload.account_id, "acct_demo");
878
+ const units = typeof payload.units === "number" ? payload.units : 0;
879
+ if (!(units > 0)) {
880
+ return { ok: false, reason: "units_must_be_positive", account_id: accountId };
881
+ }
882
+
883
+ let reserveTarget = null;
884
+ let resolvedTarget = null;
885
+ if (direction === "release") {
886
+ const resolvesAllocationId = normalizeString(payload.resolves_allocation_id, null);
887
+ if (!resolvesAllocationId) {
888
+ return { ok: false, reason: "resolves_allocation_id_required", account_id: accountId };
889
+ }
890
+ reserveTarget = getAllocationEvent(state, resolvesAllocationId);
891
+ if (!reserveTarget || reserveTarget.account_id !== accountId || reserveTarget.direction !== "reserve") {
892
+ return { ok: false, reason: "reserve_target_not_found", account_id: accountId, resolves_allocation_id: resolvesAllocationId };
893
+ }
894
+ }
895
+ if (direction === "reverse") {
896
+ const resolvesAllocationId = normalizeString(payload.resolves_allocation_id, null);
897
+ if (resolvesAllocationId) {
898
+ resolvedTarget = getAllocationEvent(state, resolvesAllocationId);
899
+ if (!resolvedTarget || resolvedTarget.account_id !== accountId) {
900
+ return { ok: false, reason: "reverse_target_not_found", account_id: accountId, resolves_allocation_id: resolvesAllocationId };
901
+ }
902
+ }
903
+ }
904
+
905
+ const lifecycle = buildWalletLifecycleSummary(state, accountId);
906
+ if (direction === "reserve" && lifecycle.lifecycle_totals.available_units < units) {
907
+ return {
908
+ ok: false,
909
+ reason: "insufficient_available_units",
910
+ account_id: accountId,
911
+ available_units: lifecycle.lifecycle_totals.available_units,
912
+ required_units: units
913
+ };
914
+ }
915
+
916
+ if (direction === "release" && lifecycle.lifecycle_totals.open_reserved_units < units) {
917
+ return {
918
+ ok: false,
919
+ reason: "insufficient_open_reserved_units",
920
+ account_id: accountId,
921
+ open_reserved_units: lifecycle.lifecycle_totals.open_reserved_units,
922
+ required_units: units
923
+ };
924
+ }
925
+
926
+ if (direction === "reverse" && lifecycle.lifecycle_totals.available_units < units) {
927
+ return {
928
+ ok: false,
929
+ reason: "insufficient_reversible_units",
930
+ account_id: accountId,
931
+ available_units: lifecycle.lifecycle_totals.available_units,
932
+ required_units: units
933
+ };
934
+ }
935
+
936
+ const event = recordAllocationEvent(state, {
937
+ ...payload,
938
+ reserve_ref: direction === "reserve"
939
+ ? normalizeString(payload.reserve_ref, null)
940
+ : reserveTarget
941
+ ? reserveTarget.reserve_ref || `reserve.${reserveTarget.allocation_id}`
942
+ : normalizeString(payload.reserve_ref, null)
943
+ ,
944
+ commit_ref: resolvedTarget && resolvedTarget.direction === "commit"
945
+ ? resolvedTarget.commit_ref || `commit.${resolvedTarget.allocation_id}`
946
+ : normalizeString(payload.commit_ref, null)
947
+ }, direction);
948
+ return {
949
+ ok: true,
950
+ lifecycle_event: event,
951
+ wallet_lifecycle_summary: buildWalletLifecycleSummary(state, accountId),
952
+ wallet_reserve_summary: buildWalletReserveSummary(state, accountId),
953
+ wallet_commit_summary: buildWalletCommitSummary(state, accountId),
954
+ balance: buildCreditBalanceSummary(state, accountId)
955
+ };
956
+ }
957
+
481
958
  function getWorkflowTaskRefs(workflowRef) {
482
959
  const workflow = findWorkflow(workflowRef);
483
960
  if (!workflow || !Array.isArray(workflow.tasks)) return [];
@@ -768,6 +1245,21 @@ function consumeAccountCredits(state, body) {
768
1245
  remaining_units: nextEntitlement.remaining_units
769
1246
  };
770
1247
  }
1248
+ recordAllocationEvent(state, {
1249
+ allocation_id: `alloc_commit_${spend.credit_spend_id}`,
1250
+ account_id: accountId,
1251
+ budget_id: spend.budget_id,
1252
+ job_id: normalizeString(payload.job_id, null),
1253
+ agent_id: spend.agent_id,
1254
+ receipt_ref: spend.receipt_id,
1255
+ transaction_id: spend.transaction_id,
1256
+ credit_spend_id: spend.credit_spend_id,
1257
+ usage_meter_id: usageMeter.usage_meter_id,
1258
+ lifecycle_ref: `commit.${spend.credit_spend_id}`,
1259
+ commit_ref: `commit.${spend.credit_spend_id}`,
1260
+ units,
1261
+ reason: spend.reason
1262
+ }, "commit");
771
1263
  state.economicsCreditSpends = [spend, ...ensureArray(state.economicsCreditSpends)].slice(0, 500);
772
1264
  return {
773
1265
  ok: true,
@@ -922,6 +1414,199 @@ function buildTreasurySummary(state, accountId) {
922
1414
  };
923
1415
  }
924
1416
 
1417
+ function selectRecommendedCreditPack(totalUnits, usageMeterCount) {
1418
+ if (totalUnits >= 1500 || usageMeterCount >= 20) return "credits.fleet";
1419
+ if (totalUnits >= 500 || usageMeterCount >= 10) return "credits.agent";
1420
+ if (totalUnits >= 100 || usageMeterCount >= 3) return "credits.builder";
1421
+ if (totalUnits > 0 || usageMeterCount > 0) return "credits.starter";
1422
+ return null;
1423
+ }
1424
+
1425
+ function buildEconomicsIntelligenceSummary(state, accountId) {
1426
+ const balanceSummary = buildCreditBalanceSummary(state, accountId);
1427
+ const meteringSummary = buildUsageMeteringSummary(state, accountId);
1428
+ const replenishmentSummary = buildEntitlementReplenishmentSummary(state, accountId);
1429
+ const treasurySummary = buildTreasurySummary(state, accountId);
1430
+
1431
+ const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1432
+ const totalUnits = Number(meteringSummary.total_units || 0);
1433
+ const availableUnits = Number(balanceSummary.available_units || 0);
1434
+ const consumedUnits = Number(balanceSummary.consumed_units || 0);
1435
+ const lowBalanceCount = Number(replenishmentSummary.low_balance_count || 0);
1436
+ const depletedCount = Number(replenishmentSummary.depleted_count || 0);
1437
+ const mintedUnits = Number(treasurySummary.treasury && treasurySummary.treasury.minted_units || 0);
1438
+ const settledAmountMinor = Number(treasurySummary.treasury && treasurySummary.treasury.settled_amount_minor || 0);
1439
+ const budgetCount = Number(treasurySummary.budgets && treasurySummary.budgets.total || 0);
1440
+
1441
+ let recommendedFundingPosture = "direct_pay_first";
1442
+ if (availableUnits > 0 || consumedUnits > 0 || usageMeterCount > 0) {
1443
+ recommendedFundingPosture = "credits_first";
1444
+ }
1445
+ if (availableUnits <= 0 && (usageMeterCount > 0 || consumedUnits > 0)) {
1446
+ recommendedFundingPosture = "pack_backed_credits_first";
1447
+ }
1448
+
1449
+ const recommendedPackId = replenishmentSummary.recommended_pack_ids[0] || selectRecommendedCreditPack(totalUnits, usageMeterCount);
1450
+
1451
+ let replenishmentRiskState = "low";
1452
+ if (lowBalanceCount > 0) replenishmentRiskState = "watch";
1453
+ if (depletedCount > 0 || (availableUnits > 0 && availableUnits <= Math.max(8, totalUnits))) {
1454
+ replenishmentRiskState = "high";
1455
+ }
1456
+
1457
+ let treasuryHealthState = "healthy";
1458
+ if (mintedUnits === 0 && settledAmountMinor === 0 && usageMeterCount === 0) {
1459
+ treasuryHealthState = "pre_funding";
1460
+ } else if (availableUnits <= 0 && (consumedUnits > 0 || usageMeterCount > 0)) {
1461
+ treasuryHealthState = "constrained";
1462
+ } else if (lowBalanceCount > 0 || budgetCount > 0) {
1463
+ treasuryHealthState = "watch";
1464
+ }
1465
+
1466
+ let nextBestAction = "continue_current_posture";
1467
+ if (recommendedFundingPosture === "direct_pay_first") {
1468
+ nextBestAction = "start_with_direct_pay";
1469
+ }
1470
+ if (recommendedFundingPosture === "credits_first" && recommendedPackId && usageMeterCount >= 3) {
1471
+ nextBestAction = "consider_pack_funding";
1472
+ }
1473
+ if (replenishmentRiskState === "watch") {
1474
+ nextBestAction = "prepare_replenishment";
1475
+ }
1476
+ if (replenishmentRiskState === "high") {
1477
+ nextBestAction = "replenish_credits";
1478
+ }
1479
+ if (treasuryHealthState === "constrained") {
1480
+ nextBestAction = "restore_runtime_balance";
1481
+ }
1482
+
1483
+ return {
1484
+ account_id: accountId,
1485
+ category: "machine-commerce-account-economics-intelligence-summary",
1486
+ recommended_funding_posture: recommendedFundingPosture,
1487
+ recommended_pack_id: recommendedPackId,
1488
+ replenishment_risk_state: replenishmentRiskState,
1489
+ treasury_health_state: treasuryHealthState,
1490
+ next_best_action: nextBestAction,
1491
+ explanation_signals: {
1492
+ available_units: availableUnits,
1493
+ consumed_units: consumedUnits,
1494
+ usage_meter_count: usageMeterCount,
1495
+ metered_units: totalUnits,
1496
+ low_balance_count: lowBalanceCount,
1497
+ depleted_count: depletedCount,
1498
+ recommended_replenishment_pack_ids: replenishmentSummary.recommended_pack_ids,
1499
+ pricing_bands: meteringSummary.pricing_bands,
1500
+ minted_units: mintedUnits,
1501
+ settled_amount_minor: settledAmountMinor,
1502
+ budget_count: budgetCount
1503
+ },
1504
+ linked_surfaces: {
1505
+ credit_balance_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/credit-balance`,
1506
+ metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`,
1507
+ entitlement_replenishment_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/entitlements/replenishment-summary`,
1508
+ treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
1509
+ operator_dashboard_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/operator-dashboard`
1510
+ },
1511
+ generated_at_iso: nowIso()
1512
+ };
1513
+ }
1514
+
1515
+ function buildTreasuryIntelligenceSummary(state, accountId) {
1516
+ const treasurySummary = buildTreasurySummary(state, accountId);
1517
+ const treasuryDrilldown = buildTreasuryDrilldown(state, accountId);
1518
+ const reconciliationPack = buildReconciliationPack(state, accountId);
1519
+ const meteringSummary = buildUsageMeteringSummary(state, accountId);
1520
+ const balanceSummary = buildCreditBalanceSummary(state, accountId);
1521
+ const railSummary = buildRailSummary(state, accountId);
1522
+
1523
+ const mintedUnits = Number(treasurySummary.treasury.minted_units || 0);
1524
+ const consumedUnits = Number(treasurySummary.treasury.consumed_units || 0);
1525
+ const availableUnits = Number(treasurySummary.treasury.available_units || 0);
1526
+ const settledAmountMinor = Number(treasurySummary.treasury.settled_amount_minor || 0);
1527
+ const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1528
+ const pendingTransactions = Number(treasuryDrilldown.unresolved_flags.pending_transactions || 0);
1529
+ const pendingReceipts = Number(treasuryDrilldown.unresolved_flags.pending_receipts || 0);
1530
+ const disputedReceipts = Number(reconciliationPack.unresolved_state.disputed_receipt_count || 0);
1531
+ const escalatedReceipts = Number(reconciliationPack.unresolved_state.escalated_receipt_count || 0);
1532
+ const paymentLedgerCount = Number(treasurySummary.payment_ledger_count || 0);
1533
+ const railCreditEventCount = Number(railSummary.credit_event_count || 0);
1534
+
1535
+ let treasuryEfficiencyState = "healthy";
1536
+ if (mintedUnits === 0 && settledAmountMinor === 0 && usageMeterCount === 0) {
1537
+ treasuryEfficiencyState = "pre_funding";
1538
+ } else if (availableUnits <= 0 && (consumedUnits > 0 || usageMeterCount > 0)) {
1539
+ treasuryEfficiencyState = "constrained";
1540
+ } else if (pendingTransactions > 0 || pendingReceipts > 0) {
1541
+ treasuryEfficiencyState = "watch";
1542
+ }
1543
+
1544
+ let valueCaptureState = "aligned";
1545
+ if (usageMeterCount === 0 && paymentLedgerCount === 0 && railCreditEventCount === 0) {
1546
+ valueCaptureState = "pre_conversion";
1547
+ } else if (usageMeterCount >= 3 && paymentLedgerCount <= 1 && consumedUnits > 0) {
1548
+ valueCaptureState = "repeat_use_ready";
1549
+ } else if (consumedUnits > mintedUnits && mintedUnits > 0) {
1550
+ valueCaptureState = "leaking";
1551
+ }
1552
+
1553
+ let reconciliationRiskState = "low";
1554
+ if (pendingTransactions > 0 || pendingReceipts > 0) reconciliationRiskState = "watch";
1555
+ if (disputedReceipts > 0 || escalatedReceipts > 0) reconciliationRiskState = "high";
1556
+
1557
+ let replenishmentFatigueState = "low";
1558
+ if (railCreditEventCount >= 2 && availableUnits <= Math.max(8, meteringSummary.total_units || 0)) {
1559
+ replenishmentFatigueState = "watch";
1560
+ }
1561
+ if (railCreditEventCount >= 3 && balanceSummary.replenishment_summary.low_balance_count > 0) {
1562
+ replenishmentFatigueState = "high";
1563
+ }
1564
+
1565
+ let nextBestAction = "continue_treasury_posture";
1566
+ if (treasuryEfficiencyState === "pre_funding") {
1567
+ nextBestAction = "establish_runtime_funding";
1568
+ } else if (treasuryEfficiencyState === "constrained") {
1569
+ nextBestAction = "restore_runtime_balance";
1570
+ } else if (reconciliationRiskState === "high") {
1571
+ nextBestAction = "review_reconciliation_pack";
1572
+ } else if (reconciliationRiskState === "watch") {
1573
+ nextBestAction = "inspect_treasury_drilldown";
1574
+ } else if (replenishmentFatigueState === "high" || valueCaptureState === "repeat_use_ready") {
1575
+ nextBestAction = "recommend_larger_pack_posture";
1576
+ }
1577
+
1578
+ return {
1579
+ account_id: accountId,
1580
+ category: "machine-commerce-account-treasury-intelligence-summary",
1581
+ treasury_efficiency_state: treasuryEfficiencyState,
1582
+ value_capture_state: valueCaptureState,
1583
+ reconciliation_risk_state: reconciliationRiskState,
1584
+ replenishment_fatigue_state: replenishmentFatigueState,
1585
+ next_best_action: nextBestAction,
1586
+ explanation_signals: {
1587
+ minted_units: mintedUnits,
1588
+ consumed_units: consumedUnits,
1589
+ available_units: availableUnits,
1590
+ settled_amount_minor: settledAmountMinor,
1591
+ usage_meter_count: usageMeterCount,
1592
+ payment_ledger_count: paymentLedgerCount,
1593
+ rail_credit_event_count: railCreditEventCount,
1594
+ pending_transaction_count: pendingTransactions,
1595
+ pending_receipt_count: pendingReceipts,
1596
+ disputed_receipt_count: disputedReceipts,
1597
+ escalated_receipt_count: escalatedReceipts
1598
+ },
1599
+ linked_surfaces: {
1600
+ treasury_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-summary`,
1601
+ treasury_drilldown_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-drilldown`,
1602
+ reconciliation_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/reconciliation-pack`,
1603
+ metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`,
1604
+ rail_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/rail-summary`
1605
+ },
1606
+ generated_at_iso: nowIso()
1607
+ };
1608
+ }
1609
+
925
1610
  function buildLedgerExport(state, accountId) {
926
1611
  return {
927
1612
  export_version: "xytara-economics-ledger-export-v1",
@@ -1184,6 +1869,1731 @@ function buildAgentCreditSpendPolicyView(state, accountId, agentId) {
1184
1869
  };
1185
1870
  }
1186
1871
 
1872
+ function buildPricingPolicySummary(state, accountId) {
1873
+ const balanceSummary = buildCreditBalanceSummary(state, accountId);
1874
+ const meteringSummary = buildUsageMeteringSummary(state, accountId);
1875
+ const policySummary = buildPolicySummary(state, accountId);
1876
+ const economicsIntelligence = buildEconomicsIntelligenceSummary(state, accountId);
1877
+ const replenishmentSummary = buildEntitlementReplenishmentSummary(state, accountId);
1878
+
1879
+ const pricingBands = ensureArray(meteringSummary.pricing_bands).filter(Boolean);
1880
+ const dominantPricingBand = pricingBands[0] || null;
1881
+ const usageMeterCount = Number(meteringSummary.usage_meter_count || 0);
1882
+ const totalUnits = Number(meteringSummary.total_units || 0);
1883
+
1884
+ let pricingPosture = "direct_pay_entry";
1885
+ if (usageMeterCount > 0 || Number(balanceSummary.consumed_units || 0) > 0) {
1886
+ pricingPosture = "credits_first_runtime";
1887
+ }
1888
+ if (economicsIntelligence.recommended_funding_posture === "pack_backed_credits_first") {
1889
+ pricingPosture = "pack_backed_runtime";
1890
+ }
1891
+
1892
+ let pricingRiskState = "low";
1893
+ if (replenishmentSummary.low_balance_count > 0 || policySummary.active_budget_count > 0) {
1894
+ pricingRiskState = "watch";
1895
+ }
1896
+ if (replenishmentSummary.depleted_count > 0 || (usageMeterCount > 0 && Number(balanceSummary.available_units || 0) <= Math.max(8, totalUnits))) {
1897
+ pricingRiskState = "high";
1898
+ }
1899
+
1900
+ return {
1901
+ summary_version: "xytara-pricing-policy-summary-v1",
1902
+ account_id: accountId,
1903
+ pricing_posture: pricingPosture,
1904
+ pricing_risk_state: pricingRiskState,
1905
+ dominant_pricing_band: dominantPricingBand,
1906
+ recommended_pack_id: economicsIntelligence.recommended_pack_id,
1907
+ bounded_spend_available: policySummary.bounded_spend_available,
1908
+ explanation_signals: {
1909
+ usage_meter_count: usageMeterCount,
1910
+ total_units: totalUnits,
1911
+ pricing_bands: pricingBands,
1912
+ available_units: balanceSummary.available_units,
1913
+ active_budget_count: policySummary.active_budget_count,
1914
+ agent_count: policySummary.agent_count,
1915
+ low_balance_count: replenishmentSummary.low_balance_count,
1916
+ depleted_count: replenishmentSummary.depleted_count
1917
+ },
1918
+ linked_surfaces: {
1919
+ policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-summary`,
1920
+ policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`,
1921
+ economics_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/intelligence-summary`,
1922
+ metering_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/metering-summary`
1923
+ },
1924
+ generated_at_iso: nowIso()
1925
+ };
1926
+ }
1927
+
1928
+ function buildPricingPolicyOperatorBundle(state, accountId) {
1929
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
1930
+ const policySummary = buildPolicySummary(state, accountId);
1931
+ const policyPack = buildAccountCreditSpendPolicyPack(state, accountId);
1932
+ const economicsIntelligence = buildEconomicsIntelligenceSummary(state, accountId);
1933
+ const treasuryIntelligence = buildTreasuryIntelligenceSummary(state, accountId);
1934
+
1935
+ let recommendedOperatorMotion = "maintain_current_pricing_posture";
1936
+ if (pricingPolicySummary.pricing_risk_state === "high") {
1937
+ recommendedOperatorMotion = "restore_pricing_headroom";
1938
+ } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
1939
+ recommendedOperatorMotion = "stabilize_pack_backed_runtime";
1940
+ } else if (policySummary.bounded_spend_available) {
1941
+ recommendedOperatorMotion = "tighten_bounded_spend_pricing_controls";
1942
+ } else if (economicsIntelligence.recommended_funding_posture === "direct_pay_first") {
1943
+ recommendedOperatorMotion = "keep_direct_pay_entry_clear";
1944
+ }
1945
+
1946
+ return {
1947
+ bundle_version: "xytara-pricing-policy-operator-bundle-v1",
1948
+ account_id: accountId,
1949
+ operator_posture: {
1950
+ pricing_posture: pricingPolicySummary.pricing_posture,
1951
+ pricing_risk_state: pricingPolicySummary.pricing_risk_state,
1952
+ treasury_health_state: economicsIntelligence.treasury_health_state,
1953
+ value_capture_state: treasuryIntelligence.value_capture_state,
1954
+ recommended_operator_motion: recommendedOperatorMotion
1955
+ },
1956
+ pricing_policy_summary: pricingPolicySummary,
1957
+ policy_summary: policySummary,
1958
+ policy_pack: policyPack,
1959
+ economics_intelligence_summary: economicsIntelligence,
1960
+ treasury_intelligence_summary: treasuryIntelligence,
1961
+ linked_surfaces: {
1962
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
1963
+ policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`,
1964
+ economics_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/intelligence-summary`,
1965
+ treasury_intelligence_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/treasury-intelligence-summary`
1966
+ },
1967
+ generated_at_iso: nowIso()
1968
+ };
1969
+ }
1970
+
1971
+ function buildPricingPolicyPack(state, accountId) {
1972
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
1973
+ const operatorBundle = buildPricingPolicyOperatorBundle(state, accountId);
1974
+ const pricingBandProfiles = Object.entries(PRICING_BAND_UNITS).map(([pricing_band, usage_units]) => ({
1975
+ pricing_band,
1976
+ usage_units,
1977
+ recommended_for: usage_units >= 8
1978
+ ? "high consequence or multi-step runtime work"
1979
+ : usage_units >= 3
1980
+ ? "moderate runtime execution"
1981
+ : "entry and lightweight runtime paths"
1982
+ }));
1983
+ const policyTemplates = [
1984
+ {
1985
+ template_id: "direct_pay_entry_clear",
1986
+ recommended_for: "keeping first-contact spend simple",
1987
+ target_motion: "keep_direct_pay_entry_clear",
1988
+ pricing_posture: "direct_pay_entry"
1989
+ },
1990
+ {
1991
+ template_id: "credits_first_runtime_default",
1992
+ recommended_for: "normal repeat runtime execution",
1993
+ target_motion: "maintain_current_pricing_posture",
1994
+ pricing_posture: "credits_first_runtime"
1995
+ },
1996
+ {
1997
+ template_id: "pack_backed_runtime_scale",
1998
+ recommended_for: "repeat usage with replenishment pressure",
1999
+ target_motion: "stabilize_pack_backed_runtime",
2000
+ pricing_posture: "pack_backed_runtime"
2001
+ },
2002
+ {
2003
+ template_id: "bounded_spend_guardrails",
2004
+ recommended_for: "agent and budget-constrained runtime usage",
2005
+ target_motion: "tighten_bounded_spend_pricing_controls",
2006
+ pricing_posture: "credits_first_runtime"
2007
+ }
2008
+ ];
2009
+
2010
+ return {
2011
+ pack_version: "xytara-pricing-policy-pack-v1",
2012
+ account_id: accountId,
2013
+ pricing_policy_summary: pricingPolicySummary,
2014
+ operator_bundle: operatorBundle,
2015
+ pricing_band_profiles: pricingBandProfiles,
2016
+ policy_templates: policyTemplates,
2017
+ recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
2018
+ linked_surfaces: {
2019
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2020
+ pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2021
+ pricing_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-application-summary`
2022
+ },
2023
+ generated_at_iso: nowIso()
2024
+ };
2025
+ }
2026
+
2027
+ function buildPricingPolicyApplicationSummary(state, accountId, templateId) {
2028
+ const pack = buildPricingPolicyPack(state, accountId);
2029
+ const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2030
+ || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2031
+ || ensureArray(pack.policy_templates)[0]
2032
+ || null;
2033
+
2034
+ return {
2035
+ summary_version: "xytara-pricing-policy-application-summary-v1",
2036
+ account_id: accountId,
2037
+ recommended_policy_motion: pack.recommended_policy_motion,
2038
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2039
+ available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2040
+ selected_template: selectedTemplate,
2041
+ suggested_pricing_targets: {
2042
+ funding_posture: pack.pricing_policy_summary.pricing_posture,
2043
+ dominant_pricing_band: pack.pricing_policy_summary.dominant_pricing_band,
2044
+ recommended_pack_id: pack.pricing_policy_summary.recommended_pack_id,
2045
+ bounded_spend_available: pack.pricing_policy_summary.bounded_spend_available
2046
+ },
2047
+ linked_surfaces: {
2048
+ pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2049
+ pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2050
+ policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-pack`
2051
+ },
2052
+ generated_at_iso: nowIso()
2053
+ };
2054
+ }
2055
+
2056
+ function buildPricingPolicyPackage(state, accountId) {
2057
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2058
+ const operatorBundle = buildPricingPolicyOperatorBundle(state, accountId);
2059
+ const pack = buildPricingPolicyPack(state, accountId);
2060
+ const applicationSummary = buildPricingPolicyApplicationSummary(state, accountId, null);
2061
+ return {
2062
+ package_version: "xytara-pricing-policy-package-v1",
2063
+ account_id: accountId,
2064
+ package_posture: {
2065
+ pricing_posture: pricingPolicySummary.pricing_posture,
2066
+ pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2067
+ recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2068
+ recommended_policy_motion: pack.recommended_policy_motion
2069
+ },
2070
+ pricing_policy_summary: pricingPolicySummary,
2071
+ pricing_policy_operator_bundle: operatorBundle,
2072
+ pricing_policy_pack: pack,
2073
+ pricing_policy_application_summary: applicationSummary,
2074
+ linked_surfaces: {
2075
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2076
+ pricing_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-operator-bundle`,
2077
+ pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2078
+ pricing_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-application-summary`
2079
+ },
2080
+ generated_at_iso: nowIso()
2081
+ };
2082
+ }
2083
+
2084
+ function buildQuotePolicyDecisionSummary(state, body) {
2085
+ const payload = ensureObject(body);
2086
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2087
+ const usagePreview = buildUsageMeterPreview(state, payload);
2088
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2089
+ const policyDecision = buildCreditSpendPolicyDecision(state, payload);
2090
+ const quotedUnits = resolveUsageMeterUnits(payload, buildUsageMeterBase(payload));
2091
+ const amountMinor = quotedUnits * 100;
2092
+
2093
+ let quotePolicyState = "direct_pay_quote";
2094
+ if (pricingPolicySummary.pricing_posture !== "direct_pay_entry") {
2095
+ quotePolicyState = "credits_first_quote";
2096
+ }
2097
+ if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2098
+ quotePolicyState = "pack_backed_quote";
2099
+ }
2100
+
2101
+ let recommendedQuoteMotion = "issue_standard_quote";
2102
+ if (!policyDecision.ok) {
2103
+ recommendedQuoteMotion = "require_bounded_policy_repair";
2104
+ } else if (pricingPolicySummary.pricing_risk_state === "high") {
2105
+ recommendedQuoteMotion = "issue_replenishment_aware_quote";
2106
+ } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2107
+ recommendedQuoteMotion = "issue_pack_aligned_quote";
2108
+ }
2109
+
2110
+ return {
2111
+ summary_version: "xytara-quote-policy-decision-summary-v1",
2112
+ account_id: accountId,
2113
+ quote_policy_state: quotePolicyState,
2114
+ recommended_quote_motion: recommendedQuoteMotion,
2115
+ quoted_units: quotedUnits,
2116
+ quoted_amount_minor: amountMinor,
2117
+ pricing_band: usagePreview.pricing_band,
2118
+ task_domain: usagePreview.task_domain,
2119
+ policy_guard: {
2120
+ ok: Boolean(policyDecision.ok),
2121
+ reason: policyDecision.reason || null,
2122
+ budget_id: policyDecision.budget_id || null,
2123
+ agent_id: policyDecision.agent_id || null,
2124
+ max_reserve_units: policyDecision.max_reserve_units || null
2125
+ },
2126
+ linked_surfaces: {
2127
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2128
+ pricing_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-package`,
2129
+ policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/policy-summary`
2130
+ },
2131
+ generated_at_iso: nowIso()
2132
+ };
2133
+ }
2134
+
2135
+ function buildPricingBandDecisionSummary(state, body) {
2136
+ const payload = ensureObject(body);
2137
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2138
+ const usagePreview = buildUsageMeterPreview(state, payload);
2139
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2140
+ const bandUnits = PRICING_BAND_UNITS[usagePreview.pricing_band] || usagePreview.usage_units || 1;
2141
+
2142
+ let bandDecisionState = "standard_band";
2143
+ if (usagePreview.pricing_band === "utility") {
2144
+ bandDecisionState = "entry_band";
2145
+ } else if (usagePreview.pricing_band === "premium" || usagePreview.pricing_band === "heavy") {
2146
+ bandDecisionState = "high_consequence_band";
2147
+ }
2148
+
2149
+ let recommendedBandMotion = "accept_detected_band";
2150
+ if (pricingPolicySummary.pricing_risk_state === "high" && bandUnits >= 8) {
2151
+ recommendedBandMotion = "review_high_unit_band";
2152
+ } else if (pricingPolicySummary.pricing_posture === "direct_pay_entry" && bandUnits > 3) {
2153
+ recommendedBandMotion = "check_entry_path_alignment";
2154
+ }
2155
+
2156
+ return {
2157
+ summary_version: "xytara-pricing-band-decision-summary-v1",
2158
+ account_id: accountId,
2159
+ pricing_band: usagePreview.pricing_band,
2160
+ usage_units: usagePreview.usage_units,
2161
+ band_units: bandUnits,
2162
+ band_decision_state: bandDecisionState,
2163
+ recommended_band_motion: recommendedBandMotion,
2164
+ task_ref: usagePreview.task_ref,
2165
+ workflow_ref: usagePreview.workflow_ref,
2166
+ task_domain: usagePreview.task_domain,
2167
+ linked_surfaces: {
2168
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2169
+ pricing_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-pack`,
2170
+ metering_preview_ref: "/v1/economics/metering/preview"
2171
+ },
2172
+ generated_at_iso: nowIso()
2173
+ };
2174
+ }
2175
+
2176
+ function buildQuotePolicyOperatorBundle(state, body) {
2177
+ const payload = ensureObject(body);
2178
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2179
+ const quoteDecision = buildQuotePolicyDecisionSummary(state, payload);
2180
+ const bandDecision = buildPricingBandDecisionSummary(state, payload);
2181
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2182
+
2183
+ let recommendedOperatorMotion = "maintain_quote_policy_posture";
2184
+ if (quoteDecision.policy_guard.ok === false) {
2185
+ recommendedOperatorMotion = "repair_bounded_quote_controls";
2186
+ } else if (quoteDecision.recommended_quote_motion === "issue_replenishment_aware_quote") {
2187
+ recommendedOperatorMotion = "prepare_replenishment_aligned_quote";
2188
+ } else if (bandDecision.recommended_band_motion === "review_high_unit_band") {
2189
+ recommendedOperatorMotion = "review_high_unit_quote_band";
2190
+ }
2191
+
2192
+ return {
2193
+ bundle_version: "xytara-quote-policy-operator-bundle-v1",
2194
+ account_id: accountId,
2195
+ operator_posture: {
2196
+ quote_policy_state: quoteDecision.quote_policy_state,
2197
+ pricing_band: bandDecision.pricing_band,
2198
+ pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2199
+ recommended_quote_motion: quoteDecision.recommended_quote_motion,
2200
+ recommended_band_motion: bandDecision.recommended_band_motion,
2201
+ recommended_operator_motion: recommendedOperatorMotion
2202
+ },
2203
+ quote_policy_decision_summary: quoteDecision,
2204
+ pricing_band_decision_summary: bandDecision,
2205
+ pricing_policy_summary: pricingPolicySummary,
2206
+ linked_surfaces: {
2207
+ quote_policy_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-decision-summary`,
2208
+ pricing_band_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-band-decision-summary`,
2209
+ quote_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-package`
2210
+ },
2211
+ generated_at_iso: nowIso()
2212
+ };
2213
+ }
2214
+
2215
+ function summarizeQuotePolicyOperatorBundle(state, body) {
2216
+ const bundle = buildQuotePolicyOperatorBundle(state, body);
2217
+ return {
2218
+ bundle_version: bundle.bundle_version,
2219
+ account_id: bundle.account_id,
2220
+ quote_policy_state: bundle.operator_posture.quote_policy_state,
2221
+ pricing_band: bundle.operator_posture.pricing_band,
2222
+ recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
2223
+ };
2224
+ }
2225
+
2226
+ function buildQuotePolicyPack(state, body) {
2227
+ const payload = ensureObject(body);
2228
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2229
+ const operatorBundle = buildQuotePolicyOperatorBundle(state, payload);
2230
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2231
+ const templates = [
2232
+ {
2233
+ template_id: "direct_pay_quote_entry",
2234
+ recommended_for: "first-contact quotes and low-friction runtime entry",
2235
+ target_motion: "issue_standard_quote",
2236
+ quote_policy_state: "direct_pay_quote"
2237
+ },
2238
+ {
2239
+ template_id: "credits_first_quote_default",
2240
+ recommended_for: "normal repeat runtime quoting",
2241
+ target_motion: "issue_standard_quote",
2242
+ quote_policy_state: "credits_first_quote"
2243
+ },
2244
+ {
2245
+ template_id: "pack_aligned_quote_flow",
2246
+ recommended_for: "repeat use with pack-backed credits posture",
2247
+ target_motion: "issue_pack_aligned_quote",
2248
+ quote_policy_state: "pack_backed_quote"
2249
+ },
2250
+ {
2251
+ template_id: "replenishment_aware_quote",
2252
+ recommended_for: "high pricing-risk or low-headroom quote posture",
2253
+ target_motion: "issue_replenishment_aware_quote",
2254
+ quote_policy_state: "credits_first_quote"
2255
+ },
2256
+ {
2257
+ template_id: "bounded_quote_guardrails",
2258
+ recommended_for: "agent or budget-constrained quoting",
2259
+ target_motion: "require_bounded_policy_repair",
2260
+ quote_policy_state: "credits_first_quote"
2261
+ }
2262
+ ];
2263
+
2264
+ return {
2265
+ pack_version: "xytara-quote-policy-pack-v1",
2266
+ account_id: accountId,
2267
+ quote_policy_operator_bundle: operatorBundle,
2268
+ pricing_policy_summary: pricingPolicySummary,
2269
+ recommended_policy_motion: operatorBundle.operator_posture.recommended_quote_motion,
2270
+ policy_templates: templates,
2271
+ linked_surfaces: {
2272
+ quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2273
+ quote_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-application-summary`,
2274
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`
2275
+ },
2276
+ generated_at_iso: nowIso()
2277
+ };
2278
+ }
2279
+
2280
+ function summarizeQuotePolicyPack(state, body) {
2281
+ const pack = buildQuotePolicyPack(state, body);
2282
+ return {
2283
+ pack_version: pack.pack_version,
2284
+ account_id: pack.account_id,
2285
+ recommended_policy_motion: pack.recommended_policy_motion,
2286
+ template_count: ensureArray(pack.policy_templates).length
2287
+ };
2288
+ }
2289
+
2290
+ function buildQuotePolicyApplicationSummary(state, body) {
2291
+ const payload = ensureObject(body);
2292
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2293
+ const templateId = normalizeString(payload.template_id, null);
2294
+ const pack = buildQuotePolicyPack(state, payload);
2295
+ const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2296
+ || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2297
+ || ensureArray(pack.policy_templates)[0]
2298
+ || null;
2299
+
2300
+ return {
2301
+ summary_version: "xytara-quote-policy-application-summary-v1",
2302
+ account_id: accountId,
2303
+ recommended_policy_motion: pack.recommended_policy_motion,
2304
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2305
+ available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2306
+ selected_template: selectedTemplate,
2307
+ suggested_quote_targets: {
2308
+ quote_policy_state: pack.quote_policy_operator_bundle.operator_posture.quote_policy_state,
2309
+ pricing_band: pack.quote_policy_operator_bundle.operator_posture.pricing_band,
2310
+ recommended_quote_motion: pack.quote_policy_operator_bundle.operator_posture.recommended_quote_motion,
2311
+ pricing_risk_state: pack.pricing_policy_summary.pricing_risk_state
2312
+ },
2313
+ linked_surfaces: {
2314
+ quote_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-pack`,
2315
+ quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2316
+ quote_policy_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-package`
2317
+ },
2318
+ generated_at_iso: nowIso()
2319
+ };
2320
+ }
2321
+
2322
+ function buildQuotePolicyPackage(state, body) {
2323
+ const payload = ensureObject(body);
2324
+ const accountId = normalizeString(payload.account_id, "acct_demo");
2325
+ const quoteDecision = buildQuotePolicyDecisionSummary(state, payload);
2326
+ const bandDecision = buildPricingBandDecisionSummary(state, payload);
2327
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2328
+ const operatorBundle = buildQuotePolicyOperatorBundle(state, payload);
2329
+ const policyPack = buildQuotePolicyPack(state, payload);
2330
+ const applicationSummary = buildQuotePolicyApplicationSummary(state, payload);
2331
+
2332
+ return {
2333
+ package_version: "xytara-quote-policy-package-v1",
2334
+ account_id: accountId,
2335
+ package_posture: {
2336
+ quote_policy_state: quoteDecision.quote_policy_state,
2337
+ recommended_quote_motion: quoteDecision.recommended_quote_motion,
2338
+ pricing_band: bandDecision.pricing_band,
2339
+ recommended_band_motion: bandDecision.recommended_band_motion,
2340
+ pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2341
+ recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2342
+ recommended_policy_motion: policyPack.recommended_policy_motion
2343
+ },
2344
+ quote_policy_decision_summary: quoteDecision,
2345
+ pricing_band_decision_summary: bandDecision,
2346
+ quote_policy_operator_bundle: operatorBundle,
2347
+ quote_policy_pack: policyPack,
2348
+ quote_policy_application_summary: applicationSummary,
2349
+ pricing_policy_summary: pricingPolicySummary,
2350
+ linked_surfaces: {
2351
+ quote_policy_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-decision-summary`,
2352
+ pricing_band_decision_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-band-decision-summary`,
2353
+ quote_policy_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-operator-bundle`,
2354
+ quote_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-pack`,
2355
+ quote_policy_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/quote-policy-application-summary`,
2356
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`
2357
+ },
2358
+ generated_at_iso: nowIso()
2359
+ };
2360
+ }
2361
+
2362
+ function summarizeQuotePolicyPackage(state, body) {
2363
+ const pack = buildQuotePolicyPackage(state, body);
2364
+ return {
2365
+ package_version: pack.package_version,
2366
+ account_id: pack.account_id,
2367
+ quote_policy_state: pack.package_posture.quote_policy_state,
2368
+ pricing_band: pack.package_posture.pricing_band,
2369
+ recommended_operator_motion: pack.package_posture.recommended_operator_motion,
2370
+ recommended_policy_motion: pack.package_posture.recommended_policy_motion
2371
+ };
2372
+ }
2373
+
2374
+ function buildTrustInputSummary(state, accountId) {
2375
+ const paymentCount = listPaymentLedgerForAccount(state, accountId).length;
2376
+ const creditSpendCount = ensureArray(state.economicsCreditSpends).filter((entry) => entry && entry.account_id === accountId).length;
2377
+ const allocationCount = ensureArray(state.economicsAllocations).filter((entry) => entry && entry.account_id === accountId).length;
2378
+ const disputeCount = listMapValuesByAccount(state.disputes, accountId).length;
2379
+ const refundCount = listMapValuesByAccount(state.refunds, accountId).length;
2380
+ const remediationCount = listMapValuesByAccount(state.remediationTickets, accountId).length;
2381
+ const activeParticipantCount = listOperatorParticipantsForAccount(state, accountId).filter((entry) => entry && entry.status === "active").length;
2382
+ const revokedParticipantCount = listOperatorParticipantsForAccount(state, accountId).filter((entry) => entry && entry.status === "revoked").length;
2383
+
2384
+ let runtimeHistoryState = "thin";
2385
+ if (paymentCount > 0 || creditSpendCount > 0 || allocationCount > 0) {
2386
+ runtimeHistoryState = "working";
2387
+ }
2388
+ if (
2389
+ paymentCount > 0
2390
+ && creditSpendCount > 0
2391
+ && allocationCount > 0
2392
+ && disputeCount === 0
2393
+ && refundCount === 0
2394
+ && remediationCount === 0
2395
+ ) {
2396
+ runtimeHistoryState = "strong";
2397
+ }
2398
+
2399
+ let reputationRiskState = "low";
2400
+ if (disputeCount > 0 || refundCount > 0 || remediationCount > 0) {
2401
+ reputationRiskState = "high";
2402
+ } else if (paymentCount === 0 || creditSpendCount === 0 || revokedParticipantCount > 0) {
2403
+ reputationRiskState = "watch";
2404
+ }
2405
+
2406
+ let recommendedInputMotion = "maintain_runtime_reputation_inputs";
2407
+ if (runtimeHistoryState === "thin") {
2408
+ recommendedInputMotion = "establish_runtime_history_inputs";
2409
+ } else if (reputationRiskState === "high") {
2410
+ recommendedInputMotion = "repair_reputation_risk_inputs";
2411
+ } else if (reputationRiskState === "watch") {
2412
+ recommendedInputMotion = "deepen_runtime_history_inputs";
2413
+ }
2414
+
2415
+ return {
2416
+ summary_version: "xytara-trust-input-summary-v1",
2417
+ account_id: accountId,
2418
+ runtime_history_state: runtimeHistoryState,
2419
+ reputation_risk_state: reputationRiskState,
2420
+ recommended_input_motion: recommendedInputMotion,
2421
+ explanation_signals: {
2422
+ payment_count: paymentCount,
2423
+ credit_spend_count: creditSpendCount,
2424
+ allocation_count: allocationCount,
2425
+ dispute_count: disputeCount,
2426
+ refund_count: refundCount,
2427
+ remediation_count: remediationCount,
2428
+ active_participant_count: activeParticipantCount,
2429
+ revoked_participant_count: revokedParticipantCount
2430
+ },
2431
+ linked_surfaces: {
2432
+ trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
2433
+ payment_ledger_ref: "/v1/payment-ledger",
2434
+ multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`
2435
+ },
2436
+ generated_at_iso: nowIso()
2437
+ };
2438
+ }
2439
+
2440
+ function buildTrustLayerSummary(state, accountId) {
2441
+ const authoritySummary = buildAuthoritySummary(state, accountId);
2442
+ const authorityAttention = buildAuthorityAttentionSummary(state, accountId);
2443
+ const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
2444
+ const machineIdentityAttention = buildMachineIdentityAttentionSummary(state, accountId);
2445
+ const walletSummary = buildWalletSummary(state, accountId);
2446
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2447
+ const trustInputSummary = buildTrustInputSummary(state, accountId);
2448
+
2449
+ const activeAuthorityBindings = Number(authoritySummary.authority_binding_count || 0);
2450
+ const activeIdentityBindings = Number(machineIdentitySummary.identity_binding_count || 0);
2451
+ const availableUnits = Number(walletSummary.available_units || 0);
2452
+
2453
+ let trustState = "early";
2454
+ if (
2455
+ activeAuthorityBindings > 0
2456
+ && activeIdentityBindings > 0
2457
+ && authorityAttention.overall_attention_state === "healthy"
2458
+ && machineIdentityAttention.overall_attention_state === "healthy"
2459
+ && trustInputSummary.runtime_history_state !== "thin"
2460
+ ) {
2461
+ trustState = "strong";
2462
+ } else if (
2463
+ activeAuthorityBindings > 0
2464
+ || activeIdentityBindings > 0
2465
+ || trustInputSummary.runtime_history_state !== "thin"
2466
+ ) {
2467
+ trustState = "working";
2468
+ }
2469
+
2470
+ let trustRiskState = "low";
2471
+ if (
2472
+ authorityAttention.overall_attention_state === "attention_required"
2473
+ || machineIdentityAttention.overall_attention_state === "attention_required"
2474
+ || pricingPolicySummary.pricing_risk_state === "high"
2475
+ || trustInputSummary.reputation_risk_state === "high"
2476
+ ) {
2477
+ trustRiskState = "high";
2478
+ } else if (
2479
+ pricingPolicySummary.pricing_risk_state === "watch"
2480
+ || availableUnits <= 0
2481
+ || trustInputSummary.reputation_risk_state === "watch"
2482
+ ) {
2483
+ trustRiskState = "watch";
2484
+ }
2485
+
2486
+ let recommendedTrustMotion = "maintain_runtime_trust_posture";
2487
+ if (trustState === "early") {
2488
+ recommendedTrustMotion = "establish_authority_and_identity_trust";
2489
+ } else if (trustRiskState === "high") {
2490
+ recommendedTrustMotion = "repair_runtime_trust_attention";
2491
+ } else if (trustInputSummary.runtime_history_state === "thin") {
2492
+ recommendedTrustMotion = "deepen_runtime_reputation_inputs";
2493
+ } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2494
+ recommendedTrustMotion = "stabilize_pack_backed_trust_posture";
2495
+ }
2496
+
2497
+ return {
2498
+ summary_version: "xytara-trust-layer-summary-v1",
2499
+ account_id: accountId,
2500
+ trust_state: trustState,
2501
+ trust_risk_state: trustRiskState,
2502
+ recommended_trust_motion: recommendedTrustMotion,
2503
+ explanation_signals: {
2504
+ authority_state: authoritySummary.authority_state,
2505
+ authority_binding_count: activeAuthorityBindings,
2506
+ authority_attention_state: authorityAttention.overall_attention_state,
2507
+ machine_identity_state: machineIdentitySummary.machine_identity_state,
2508
+ identity_binding_count: activeIdentityBindings,
2509
+ machine_identity_attention_state: machineIdentityAttention.overall_attention_state,
2510
+ pricing_posture: pricingPolicySummary.pricing_posture,
2511
+ pricing_risk_state: pricingPolicySummary.pricing_risk_state,
2512
+ available_units: availableUnits,
2513
+ runtime_history_state: trustInputSummary.runtime_history_state,
2514
+ reputation_risk_state: trustInputSummary.reputation_risk_state,
2515
+ active_participant_count: trustInputSummary.explanation_signals.active_participant_count,
2516
+ dispute_count: trustInputSummary.explanation_signals.dispute_count
2517
+ },
2518
+ linked_surfaces: {
2519
+ authority_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-summary`,
2520
+ authority_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-attention-summary`,
2521
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
2522
+ machine_identity_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attention-summary`,
2523
+ pricing_policy_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/pricing-policy-summary`,
2524
+ trust_input_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-input-summary`
2525
+ },
2526
+ generated_at_iso: nowIso()
2527
+ };
2528
+ }
2529
+
2530
+ function buildTrustLayerOperatorBundle(state, accountId) {
2531
+ const trustSummary = buildTrustLayerSummary(state, accountId);
2532
+ const authoritySummary = buildAuthoritySummary(state, accountId);
2533
+ const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
2534
+ const pricingPolicySummary = buildPricingPolicySummary(state, accountId);
2535
+ const trustInputSummary = buildTrustInputSummary(state, accountId);
2536
+
2537
+ let recommendedOperatorMotion = "maintain_runtime_trust_posture";
2538
+ if (trustSummary.trust_state === "early") {
2539
+ recommendedOperatorMotion = "establish_runtime_trust_foundations";
2540
+ } else if (trustSummary.trust_risk_state === "high") {
2541
+ recommendedOperatorMotion = "repair_runtime_trust_attention";
2542
+ } else if (trustInputSummary.runtime_history_state === "thin") {
2543
+ recommendedOperatorMotion = "deepen_runtime_reputation_inputs";
2544
+ } else if (pricingPolicySummary.pricing_posture === "pack_backed_runtime") {
2545
+ recommendedOperatorMotion = "stabilize_pack_backed_trust_posture";
2546
+ }
2547
+
2548
+ return {
2549
+ bundle_version: "xytara-trust-layer-operator-bundle-v1",
2550
+ account_id: accountId,
2551
+ operator_posture: {
2552
+ trust_state: trustSummary.trust_state,
2553
+ trust_risk_state: trustSummary.trust_risk_state,
2554
+ authority_state: authoritySummary.authority_state,
2555
+ machine_identity_state: machineIdentitySummary.machine_identity_state,
2556
+ runtime_history_state: trustInputSummary.runtime_history_state,
2557
+ reputation_risk_state: trustInputSummary.reputation_risk_state,
2558
+ pricing_posture: pricingPolicySummary.pricing_posture,
2559
+ recommended_operator_motion: recommendedOperatorMotion
2560
+ },
2561
+ trust_layer_summary: trustSummary,
2562
+ trust_input_summary: trustInputSummary,
2563
+ authority_summary: authoritySummary,
2564
+ machine_identity_summary: machineIdentitySummary,
2565
+ pricing_policy_summary: pricingPolicySummary,
2566
+ linked_surfaces: trustSummary.linked_surfaces,
2567
+ generated_at_iso: nowIso()
2568
+ };
2569
+ }
2570
+
2571
+ function summarizeTrustLayerOperatorBundle(state, accountId) {
2572
+ const bundle = buildTrustLayerOperatorBundle(state, accountId);
2573
+ return {
2574
+ bundle_version: bundle.bundle_version,
2575
+ account_id: bundle.account_id,
2576
+ trust_state: bundle.operator_posture.trust_state,
2577
+ trust_risk_state: bundle.operator_posture.trust_risk_state,
2578
+ recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
2579
+ };
2580
+ }
2581
+
2582
+ function buildTrustLayerPolicyPack(state, accountId) {
2583
+ const operatorBundle = buildTrustLayerOperatorBundle(state, accountId);
2584
+ const templates = [
2585
+ {
2586
+ template_id: "runtime_trust_foundation",
2587
+ recommended_for: "establishing initial authority and identity trust",
2588
+ target_motion: "establish_runtime_trust_foundations",
2589
+ trust_state: "early"
2590
+ },
2591
+ {
2592
+ template_id: "runtime_trust_maintenance",
2593
+ recommended_for: "healthy continuing runtime trust posture",
2594
+ target_motion: "maintain_runtime_trust_posture",
2595
+ trust_state: "working"
2596
+ },
2597
+ {
2598
+ template_id: "trust_attention_repair",
2599
+ recommended_for: "repairing active authority, identity, or pricing risk",
2600
+ target_motion: "repair_runtime_trust_attention",
2601
+ trust_state: "working"
2602
+ },
2603
+ {
2604
+ template_id: "pack_backed_trust_stabilization",
2605
+ recommended_for: "repeat-use runtime trust with pack-backed credits",
2606
+ target_motion: "stabilize_pack_backed_trust_posture",
2607
+ trust_state: "strong"
2608
+ }
2609
+ ];
2610
+
2611
+ return {
2612
+ pack_version: "xytara-trust-layer-policy-pack-v1",
2613
+ account_id: accountId,
2614
+ trust_layer_operator_bundle: operatorBundle,
2615
+ recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
2616
+ policy_templates: templates,
2617
+ linked_surfaces: {
2618
+ trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2619
+ trust_layer_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-application-summary`,
2620
+ trust_layer_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-package`
2621
+ },
2622
+ generated_at_iso: nowIso()
2623
+ };
2624
+ }
2625
+
2626
+ function summarizeTrustLayerPolicyPack(state, accountId) {
2627
+ const pack = buildTrustLayerPolicyPack(state, accountId);
2628
+ return {
2629
+ pack_version: pack.pack_version,
2630
+ account_id: pack.account_id,
2631
+ recommended_policy_motion: pack.recommended_policy_motion,
2632
+ template_count: ensureArray(pack.policy_templates).length
2633
+ };
2634
+ }
2635
+
2636
+ function buildTrustLayerApplicationSummary(state, accountId, templateId) {
2637
+ const pack = buildTrustLayerPolicyPack(state, accountId);
2638
+ const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
2639
+ || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
2640
+ || ensureArray(pack.policy_templates)[0]
2641
+ || null;
2642
+
2643
+ return {
2644
+ summary_version: "xytara-trust-layer-application-summary-v1",
2645
+ account_id: accountId,
2646
+ recommended_policy_motion: pack.recommended_policy_motion,
2647
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2648
+ available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
2649
+ selected_template: selectedTemplate,
2650
+ suggested_trust_targets: {
2651
+ trust_state: pack.trust_layer_operator_bundle.operator_posture.trust_state,
2652
+ trust_risk_state: pack.trust_layer_operator_bundle.operator_posture.trust_risk_state,
2653
+ authority_state: pack.trust_layer_operator_bundle.operator_posture.authority_state,
2654
+ machine_identity_state: pack.trust_layer_operator_bundle.operator_posture.machine_identity_state
2655
+ },
2656
+ linked_surfaces: {
2657
+ trust_layer_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-policy-pack`,
2658
+ trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2659
+ trust_layer_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-package`
2660
+ },
2661
+ generated_at_iso: nowIso()
2662
+ };
2663
+ }
2664
+
2665
+ function buildTrustLayerPackage(state, accountId) {
2666
+ const summary = buildTrustLayerSummary(state, accountId);
2667
+ const operatorBundle = buildTrustLayerOperatorBundle(state, accountId);
2668
+ const policyPack = buildTrustLayerPolicyPack(state, accountId);
2669
+ const applicationSummary = buildTrustLayerApplicationSummary(state, accountId, null);
2670
+
2671
+ return {
2672
+ package_version: "xytara-trust-layer-package-v1",
2673
+ account_id: accountId,
2674
+ package_posture: {
2675
+ trust_state: summary.trust_state,
2676
+ trust_risk_state: summary.trust_risk_state,
2677
+ recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
2678
+ recommended_policy_motion: policyPack.recommended_policy_motion
2679
+ },
2680
+ trust_layer_summary: summary,
2681
+ trust_layer_operator_bundle: operatorBundle,
2682
+ trust_input_summary: operatorBundle.trust_input_summary,
2683
+ trust_layer_policy_pack: policyPack,
2684
+ trust_layer_application_summary: applicationSummary,
2685
+ linked_surfaces: {
2686
+ trust_input_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-input-summary`,
2687
+ trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
2688
+ trust_layer_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-operator-bundle`,
2689
+ trust_layer_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-policy-pack`,
2690
+ trust_layer_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-application-summary`
2691
+ },
2692
+ generated_at_iso: nowIso()
2693
+ };
2694
+ }
2695
+
2696
+ function summarizeTrustLayerPackage(state, accountId) {
2697
+ const pack = buildTrustLayerPackage(state, accountId);
2698
+ return {
2699
+ package_version: pack.package_version,
2700
+ account_id: pack.account_id,
2701
+ trust_state: pack.package_posture.trust_state,
2702
+ trust_risk_state: pack.package_posture.trust_risk_state,
2703
+ recommended_operator_motion: pack.package_posture.recommended_operator_motion,
2704
+ recommended_policy_motion: pack.package_posture.recommended_policy_motion
2705
+ };
2706
+ }
2707
+
2708
+ function listOperatorParticipantsForAccount(state, accountId) {
2709
+ return Array.from(state.operatorParticipants.values())
2710
+ .filter((entry) => entry && entry.account_id === accountId);
2711
+ }
2712
+
2713
+ function listLegacyAgentAccountsForParticipation(state, accountId) {
2714
+ return Array.from(state.agentAccounts.values())
2715
+ .map((entry) => entry && entry.account ? entry.account : null)
2716
+ .filter(Boolean)
2717
+ .filter((entry) => entry.account_id === accountId);
2718
+ }
2719
+
2720
+ function buildMultiOperatorParticipantPublicView(entry) {
2721
+ if (!entry) return null;
2722
+ return {
2723
+ participant_id: entry.participant_id,
2724
+ account_id: entry.account_id,
2725
+ label: entry.label,
2726
+ operator_kind: entry.operator_kind,
2727
+ status: entry.status,
2728
+ participant_scope: ensureArray(entry.participant_scope),
2729
+ authority_binding_id: entry.authority_binding_id || null,
2730
+ identity_binding_id: entry.identity_binding_id || null,
2731
+ rotated_from_participant_id: entry.rotated_from_participant_id || null,
2732
+ replaced_by_participant_id: entry.replaced_by_participant_id || null,
2733
+ created_at_iso: entry.created_at_iso,
2734
+ updated_at_iso: entry.updated_at_iso,
2735
+ revoked_at_iso: entry.revoked_at_iso || null,
2736
+ revoke_reason: entry.revoke_reason || null,
2737
+ issued_by: entry.issued_by || null,
2738
+ labels: ensureArray(entry.labels)
2739
+ };
2740
+ }
2741
+
2742
+ function listMultiOperatorParticipants(state, accountId) {
2743
+ return listOperatorParticipantsForAccount(state, accountId).map((entry) => buildMultiOperatorParticipantPublicView(entry));
2744
+ }
2745
+
2746
+ function getMultiOperatorParticipant(state, accountId, participantId) {
2747
+ if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2748
+ const entry = state.operatorParticipants.get(participantId);
2749
+ if (!entry || entry.account_id !== accountId) return null;
2750
+ return buildMultiOperatorParticipantPublicView(entry);
2751
+ }
2752
+
2753
+ function buildMultiOperatorAdmissionPreview(state, accountId, body) {
2754
+ const payload = ensureObject(body);
2755
+ const policyPack = buildMultiOperatorParticipationPolicyPack(state, accountId);
2756
+ const selectedTemplate = ensureArray(policyPack.policy_templates).find((entry) => entry.template_id === normalizeString(payload.template_id, null))
2757
+ || ensureArray(policyPack.policy_templates).find((entry) => entry.target_motion === policyPack.recommended_policy_motion)
2758
+ || ensureArray(policyPack.policy_templates)[0]
2759
+ || null;
2760
+ const participantLabel = normalizeString(payload.label, `operator-participant-${listOperatorParticipantsForAccount(state, accountId).length + 1}`);
2761
+ return {
2762
+ preview_version: "xytara-multi-operator-admission-preview-v1",
2763
+ account_id: accountId,
2764
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
2765
+ selected_template: selectedTemplate,
2766
+ proposed_participant: {
2767
+ label: participantLabel,
2768
+ operator_kind: normalizeString(payload.operator_kind, "coordinator_operator"),
2769
+ participant_scope: ensureArray(payload.participant_scope).length > 0
2770
+ ? ensureArray(payload.participant_scope)
2771
+ : ["runtime.execute", "economics.reserve"]
2772
+ },
2773
+ planned_bindings: {
2774
+ authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
2775
+ identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity")
2776
+ },
2777
+ linked_surfaces: {
2778
+ multi_operator_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
2779
+ multi_operator_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`
2780
+ },
2781
+ generated_at_iso: nowIso()
2782
+ };
2783
+ }
2784
+
2785
+ function createMultiOperatorParticipant(state, accountId, body) {
2786
+ const payload = ensureObject(body);
2787
+ const createdAtIso = nowIso();
2788
+ const nextIndex = state.operatorParticipants.size + 1;
2789
+ const participantId = normalizeString(payload.participant_id, `operator_participant_${nextIndex}`);
2790
+ const participantScope = ensureArray(payload.participant_scope).length > 0
2791
+ ? ensureArray(payload.participant_scope).map((value) => String(value || "").trim()).filter(Boolean)
2792
+ : ["runtime.execute", "economics.reserve"];
2793
+ const authorityBinding = createAuthorityBinding(state, {
2794
+ binding_id: normalizeString(payload.authority_binding_id, `${participantId}_authority`),
2795
+ credential_id: normalizeString(payload.credential_id, `${participantId}_credential`),
2796
+ account_id: accountId,
2797
+ authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
2798
+ authority_scope: participantScope,
2799
+ allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0
2800
+ ? ensureArray(payload.allowed_consequence_families)
2801
+ : ["commit", "reserve"],
2802
+ max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : 5,
2803
+ max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : 5,
2804
+ max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : 1,
2805
+ labels: ensureArray(payload.labels),
2806
+ issued_by: normalizeString(payload.issued_by, "operator")
2807
+ });
2808
+ const identityBinding = createIdentityBinding(state, {
2809
+ binding_id: normalizeString(payload.identity_binding_id, `${participantId}_identity`),
2810
+ account_id: accountId,
2811
+ identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity"),
2812
+ identity_ref: normalizeString(payload.identity_ref, `${participantId}.identity`),
2813
+ attached_agent_account_id: participantId,
2814
+ labels: ensureArray(payload.labels),
2815
+ issued_by: normalizeString(payload.issued_by, "operator")
2816
+ });
2817
+ const participant = {
2818
+ participant_id: participantId,
2819
+ account_id: accountId,
2820
+ label: normalizeString(payload.label, participantId),
2821
+ operator_kind: normalizeString(payload.operator_kind, "coordinator_operator"),
2822
+ status: normalizeString(payload.status, "active"),
2823
+ participant_scope: participantScope,
2824
+ authority_binding_id: authorityBinding.binding_id,
2825
+ identity_binding_id: identityBinding.binding_id,
2826
+ created_at_iso: createdAtIso,
2827
+ updated_at_iso: createdAtIso,
2828
+ issued_by: normalizeString(payload.issued_by, "operator"),
2829
+ labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean)
2830
+ };
2831
+ state.operatorParticipants.set(participantId, participant);
2832
+ return {
2833
+ participant: buildMultiOperatorParticipantPublicView(participant),
2834
+ authority_binding: authorityBinding,
2835
+ identity_binding: identityBinding
2836
+ };
2837
+ }
2838
+
2839
+ function renewMultiOperatorParticipant(state, accountId, participantId, body) {
2840
+ const payload = ensureObject(body);
2841
+ if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2842
+ const current = state.operatorParticipants.get(participantId);
2843
+ if (!current || current.account_id !== accountId) return null;
2844
+ const renewedAuthorityBinding = current.authority_binding_id
2845
+ ? renewAuthorityBinding(state, current.authority_binding_id, { expires_at_iso: normalizeString(payload.expires_at_iso, null) })
2846
+ : null;
2847
+ const renewedIdentityBinding = current.identity_binding_id
2848
+ ? renewIdentityBinding(state, current.identity_binding_id, { expires_at_iso: normalizeString(payload.expires_at_iso, null) })
2849
+ : null;
2850
+ const next = {
2851
+ ...current,
2852
+ updated_at_iso: nowIso()
2853
+ };
2854
+ state.operatorParticipants.set(participantId, next);
2855
+ return {
2856
+ participant: buildMultiOperatorParticipantPublicView(next),
2857
+ authority_binding: renewedAuthorityBinding,
2858
+ identity_binding: renewedIdentityBinding
2859
+ };
2860
+ }
2861
+
2862
+ function revokeMultiOperatorParticipant(state, accountId, participantId, body) {
2863
+ const payload = ensureObject(body);
2864
+ if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2865
+ const current = state.operatorParticipants.get(participantId);
2866
+ if (!current || current.account_id !== accountId) return null;
2867
+ const revokedAuthorityBinding = current.authority_binding_id
2868
+ ? revokeAuthorityBinding(state, current.authority_binding_id, { reason: normalizeString(payload.reason, "participant_revoked") })
2869
+ : null;
2870
+ const revokedIdentityBinding = current.identity_binding_id
2871
+ ? revokeIdentityBinding(state, current.identity_binding_id, { reason: normalizeString(payload.reason, "participant_revoked") })
2872
+ : null;
2873
+ const next = {
2874
+ ...current,
2875
+ status: "revoked",
2876
+ updated_at_iso: nowIso(),
2877
+ revoked_at_iso: nowIso(),
2878
+ revoke_reason: normalizeString(payload.reason, "participant_revoked")
2879
+ };
2880
+ state.operatorParticipants.set(participantId, next);
2881
+ return {
2882
+ participant: buildMultiOperatorParticipantPublicView(next),
2883
+ authority_binding: revokedAuthorityBinding,
2884
+ identity_binding: revokedIdentityBinding
2885
+ };
2886
+ }
2887
+
2888
+ function rotateMultiOperatorParticipant(state, accountId, participantId, body) {
2889
+ const payload = ensureObject(body);
2890
+ if (!participantId || !state.operatorParticipants.has(participantId)) return null;
2891
+ const current = state.operatorParticipants.get(participantId);
2892
+ if (!current || current.account_id !== accountId) return null;
2893
+ const successorParticipantId = normalizeString(payload.successor_participant_id, `${participantId}_rotated`);
2894
+ const authorityRotation = current.authority_binding_id
2895
+ ? rotateAuthorityBinding(state, current.authority_binding_id, {
2896
+ successor_binding_id: normalizeString(payload.successor_authority_binding_id, `${successorParticipantId}_authority`),
2897
+ successor_credential_id: normalizeString(payload.successor_credential_id, `${successorParticipantId}_credential`),
2898
+ authority_scope: ensureArray(payload.participant_scope).length > 0 ? ensureArray(payload.participant_scope) : ensureArray(current.participant_scope),
2899
+ labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
2900
+ reason: normalizeString(payload.reason, "participant_rotated")
2901
+ })
2902
+ : null;
2903
+ const identityRotation = current.identity_binding_id
2904
+ ? rotateIdentityBinding(state, current.identity_binding_id, {
2905
+ successor_binding_id: normalizeString(payload.successor_identity_binding_id, `${successorParticipantId}_identity`),
2906
+ attached_agent_account_id: successorParticipantId,
2907
+ labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
2908
+ reason: normalizeString(payload.reason, "participant_rotated")
2909
+ })
2910
+ : null;
2911
+ const successor = {
2912
+ participant_id: successorParticipantId,
2913
+ account_id: accountId,
2914
+ label: normalizeString(payload.label, current.label),
2915
+ operator_kind: normalizeString(payload.operator_kind, current.operator_kind),
2916
+ status: normalizeString(payload.status, "active"),
2917
+ participant_scope: ensureArray(payload.participant_scope).length > 0
2918
+ ? ensureArray(payload.participant_scope).map((value) => String(value || "").trim()).filter(Boolean)
2919
+ : ensureArray(current.participant_scope),
2920
+ authority_binding_id: authorityRotation && authorityRotation.successor_authority_binding
2921
+ ? authorityRotation.successor_authority_binding.binding_id
2922
+ : null,
2923
+ identity_binding_id: identityRotation && identityRotation.successor_identity_binding
2924
+ ? identityRotation.successor_identity_binding.binding_id
2925
+ : null,
2926
+ rotated_from_participant_id: current.participant_id,
2927
+ replaced_by_participant_id: null,
2928
+ created_at_iso: nowIso(),
2929
+ updated_at_iso: nowIso(),
2930
+ issued_by: normalizeString(payload.issued_by, current.issued_by || "operator"),
2931
+ labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean) : ensureArray(current.labels)
2932
+ };
2933
+ const rotated = {
2934
+ ...current,
2935
+ status: "revoked",
2936
+ replaced_by_participant_id: successorParticipantId,
2937
+ updated_at_iso: nowIso(),
2938
+ revoked_at_iso: nowIso(),
2939
+ revoke_reason: normalizeString(payload.reason, "participant_rotated")
2940
+ };
2941
+ state.operatorParticipants.set(participantId, rotated);
2942
+ state.operatorParticipants.set(successorParticipantId, successor);
2943
+ return {
2944
+ rotated_participant: buildMultiOperatorParticipantPublicView(rotated),
2945
+ successor_participant: buildMultiOperatorParticipantPublicView(successor),
2946
+ authority_rotation: authorityRotation,
2947
+ identity_rotation: identityRotation
2948
+ };
2949
+ }
2950
+
2951
+ function buildMultiOperatorParticipantRotationSummary(state, accountId, participantId) {
2952
+ const participant = getMultiOperatorParticipant(state, accountId, participantId);
2953
+ if (!participant) return null;
2954
+ return {
2955
+ summary_version: "xytara-multi-operator-participant-rotation-summary-v1",
2956
+ account_id: accountId,
2957
+ participant_id: participant.participant_id,
2958
+ status: participant.status,
2959
+ predecessor_participant_id: participant.rotated_from_participant_id || null,
2960
+ successor_participant_id: participant.replaced_by_participant_id || null,
2961
+ rotation_state: participant.rotated_from_participant_id || participant.replaced_by_participant_id ? "lineage_present" : "standalone",
2962
+ linked_surfaces: {
2963
+ participant_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants/${encodeURIComponent(participantId)}`
2964
+ },
2965
+ generated_at_iso: nowIso()
2966
+ };
2967
+ }
2968
+
2969
+ function buildMultiOperatorReviewBundle(state, accountId) {
2970
+ const participants = listOperatorParticipantsForAccount(state, accountId);
2971
+ const reviewRows = participants.map((entry) => {
2972
+ let review_state = "healthy";
2973
+ if (entry.status === "revoked") review_state = "revoked";
2974
+ else if (!entry.authority_binding_id || !entry.identity_binding_id) review_state = "repair_required";
2975
+ else if (ensureArray(entry.participant_scope).length === 0) review_state = "attention_required";
2976
+ return {
2977
+ participant_id: entry.participant_id,
2978
+ label: entry.label,
2979
+ status: entry.status,
2980
+ operator_kind: entry.operator_kind,
2981
+ review_state,
2982
+ authority_binding_id: entry.authority_binding_id || null,
2983
+ identity_binding_id: entry.identity_binding_id || null
2984
+ };
2985
+ });
2986
+ return {
2987
+ bundle_version: "xytara-multi-operator-review-bundle-v1",
2988
+ account_id: accountId,
2989
+ review_rows: reviewRows,
2990
+ review_counts: {
2991
+ healthy_count: reviewRows.filter((entry) => entry.review_state === "healthy").length,
2992
+ attention_required_count: reviewRows.filter((entry) => entry.review_state === "attention_required").length,
2993
+ repair_required_count: reviewRows.filter((entry) => entry.review_state === "repair_required").length,
2994
+ revoked_count: reviewRows.filter((entry) => entry.review_state === "revoked").length
2995
+ },
2996
+ linked_surfaces: {
2997
+ participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`,
2998
+ package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
2999
+ },
3000
+ generated_at_iso: nowIso()
3001
+ };
3002
+ }
3003
+
3004
+ function buildMultiOperatorAttentionSummary(state, accountId) {
3005
+ const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3006
+ const attentionRows = ensureArray(reviewBundle.review_rows).filter((entry) => entry.review_state !== "healthy");
3007
+ return {
3008
+ summary_version: "xytara-multi-operator-attention-summary-v1",
3009
+ account_id: accountId,
3010
+ overall_attention_state: attentionRows.length > 0 ? "attention_required" : "healthy",
3011
+ attention_rows: attentionRows,
3012
+ linked_surfaces: {
3013
+ multi_operator_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-review-bundle`,
3014
+ multi_operator_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3015
+ },
3016
+ generated_at_iso: nowIso()
3017
+ };
3018
+ }
3019
+
3020
+ function buildMultiOperatorParticipationSummary(state, accountId) {
3021
+ const authoritySummary = buildAuthoritySummary(state, accountId);
3022
+ const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
3023
+ const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3024
+ const operatorParticipants = listOperatorParticipantsForAccount(state, accountId);
3025
+ const agentAccounts = listLegacyAgentAccountsForParticipation(state, accountId);
3026
+ const coordinationHandoffCount = ensureArray(state.coordinationHandoffs).length;
3027
+ const admissionCaseCount = ensureArray(state.zoneAdmissionCases).length;
3028
+ const activeAuthorityBindings = Number(authoritySummary.authority_binding_count || 0);
3029
+ const activeIdentityBindings = Number(machineIdentitySummary.identity_binding_count || 0);
3030
+ const activeParticipantCount = operatorParticipants.filter((entry) => entry.status === "active").length;
3031
+ const activeAgentCount = agentAccounts.filter((entry) => entry.status === "active").length;
3032
+ const activeOperatorCount = activeParticipantCount > 0 ? activeParticipantCount : activeAgentCount;
3033
+
3034
+ let participationState = "single_operator_only";
3035
+ if (activeOperatorCount >= 2 && activeAuthorityBindings > 0 && activeIdentityBindings > 0) {
3036
+ participationState = "multi_operator_ready";
3037
+ } else if (activeOperatorCount >= 1 || activeAuthorityBindings > 0 || activeIdentityBindings > 0) {
3038
+ participationState = "emerging_multi_operator";
3039
+ }
3040
+
3041
+ let coordinationReadinessState = "limited";
3042
+ if (coordinationHandoffCount > 0 && admissionCaseCount > 0) {
3043
+ coordinationReadinessState = "active";
3044
+ } else if (coordinationHandoffCount > 0 || admissionCaseCount > 0) {
3045
+ coordinationReadinessState = "preview_ready";
3046
+ }
3047
+
3048
+ let participationRiskState = "low";
3049
+ if (trustLayerSummary.trust_risk_state === "high" || activeOperatorCount === 0) {
3050
+ participationRiskState = "high";
3051
+ } else if (coordinationReadinessState !== "active" || participationState !== "multi_operator_ready") {
3052
+ participationRiskState = "watch";
3053
+ }
3054
+
3055
+ let recommendedParticipationMotion = "maintain_multi_operator_posture";
3056
+ if (participationState === "single_operator_only") {
3057
+ recommendedParticipationMotion = "establish_second_operator_and_bindings";
3058
+ } else if (participationRiskState === "high") {
3059
+ recommendedParticipationMotion = "repair_trust_before_multi_operator_expansion";
3060
+ } else if (coordinationReadinessState !== "active") {
3061
+ recommendedParticipationMotion = "activate_coordination_followthrough";
3062
+ } else if (participationState === "emerging_multi_operator") {
3063
+ recommendedParticipationMotion = "tighten_multi_operator_contracts";
3064
+ }
3065
+
3066
+ return {
3067
+ summary_version: "xytara-multi-operator-participation-summary-v1",
3068
+ account_id: accountId,
3069
+ multi_operator_participation_state: participationState,
3070
+ coordination_readiness_state: coordinationReadinessState,
3071
+ participation_risk_state: participationRiskState,
3072
+ recommended_participation_motion: recommendedParticipationMotion,
3073
+ explanation_signals: {
3074
+ active_operator_participant_count: activeParticipantCount,
3075
+ active_legacy_agent_account_count: activeAgentCount,
3076
+ authority_binding_count: activeAuthorityBindings,
3077
+ identity_binding_count: activeIdentityBindings,
3078
+ trust_state: trustLayerSummary.trust_state,
3079
+ trust_risk_state: trustLayerSummary.trust_risk_state,
3080
+ coordination_handoff_count: coordinationHandoffCount,
3081
+ admission_case_count: admissionCaseCount
3082
+ },
3083
+ linked_surfaces: {
3084
+ multi_operator_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participants`,
3085
+ agent_accounts_ref: "/v1/agent-accounts",
3086
+ authority_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-summary`,
3087
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
3088
+ trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
3089
+ coordination_center_ref: "/v1/coordination-center/summary",
3090
+ zones_dashboard_ref: "/v1/coordination-center/zones-dashboard"
3091
+ },
3092
+ generated_at_iso: nowIso()
3093
+ };
3094
+ }
3095
+
3096
+ function buildMultiOperatorParticipationOperatorBundle(state, accountId) {
3097
+ const summary = buildMultiOperatorParticipationSummary(state, accountId);
3098
+ const authoritySummary = buildAuthoritySummary(state, accountId);
3099
+ const machineIdentitySummary = buildMachineIdentitySummary(state, accountId);
3100
+ const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3101
+ const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3102
+ const attentionSummary = buildMultiOperatorAttentionSummary(state, accountId);
3103
+ const operatorParticipants = listMultiOperatorParticipants(state, accountId);
3104
+ const agentAccounts = listLegacyAgentAccountsForParticipation(state, accountId);
3105
+ const activeOperatorCount = operatorParticipants.filter((entry) => entry.status === "active").length;
3106
+
3107
+ let recommendedOperatorMotion = "maintain_multi_operator_posture";
3108
+ if (summary.multi_operator_participation_state === "single_operator_only") {
3109
+ recommendedOperatorMotion = "issue_additional_operator_account";
3110
+ } else if (summary.participation_risk_state === "high") {
3111
+ recommendedOperatorMotion = "repair_multi_operator_trust";
3112
+ } else if (summary.coordination_readiness_state !== "active") {
3113
+ recommendedOperatorMotion = "open_coordination_followthrough";
3114
+ } else if (summary.multi_operator_participation_state === "emerging_multi_operator") {
3115
+ recommendedOperatorMotion = "tighten_multi_operator_contracts";
3116
+ }
3117
+
3118
+ return {
3119
+ bundle_version: "xytara-multi-operator-participation-operator-bundle-v1",
3120
+ account_id: accountId,
3121
+ operator_posture: {
3122
+ multi_operator_participation_state: summary.multi_operator_participation_state,
3123
+ coordination_readiness_state: summary.coordination_readiness_state,
3124
+ participation_risk_state: summary.participation_risk_state,
3125
+ active_operator_participant_count: activeOperatorCount,
3126
+ active_legacy_agent_account_count: agentAccounts.filter((entry) => entry.status === "active").length,
3127
+ authority_state: authoritySummary.authority_state,
3128
+ machine_identity_state: machineIdentitySummary.machine_identity_state,
3129
+ trust_state: trustLayerSummary.trust_state,
3130
+ overall_attention_state: attentionSummary.overall_attention_state,
3131
+ recommended_operator_motion: recommendedOperatorMotion
3132
+ },
3133
+ multi_operator_participation_summary: summary,
3134
+ multi_operator_review_bundle: reviewBundle,
3135
+ multi_operator_attention_summary: attentionSummary,
3136
+ authority_summary: authoritySummary,
3137
+ machine_identity_summary: machineIdentitySummary,
3138
+ trust_layer_summary: trustLayerSummary,
3139
+ operator_participants: operatorParticipants,
3140
+ legacy_agent_accounts: agentAccounts,
3141
+ linked_surfaces: summary.linked_surfaces,
3142
+ generated_at_iso: nowIso()
3143
+ };
3144
+ }
3145
+
3146
+ function summarizeMultiOperatorParticipationOperatorBundle(state, accountId) {
3147
+ const bundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3148
+ return {
3149
+ bundle_version: bundle.bundle_version,
3150
+ account_id: bundle.account_id,
3151
+ multi_operator_participation_state: bundle.operator_posture.multi_operator_participation_state,
3152
+ coordination_readiness_state: bundle.operator_posture.coordination_readiness_state,
3153
+ participation_risk_state: bundle.operator_posture.participation_risk_state,
3154
+ recommended_operator_motion: bundle.operator_posture.recommended_operator_motion
3155
+ };
3156
+ }
3157
+
3158
+ function buildMultiOperatorParticipationPolicyPack(state, accountId) {
3159
+ const operatorBundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3160
+ const templates = [
3161
+ {
3162
+ template_id: "second_operator_foundation",
3163
+ recommended_for: "opening a second operator track on top of a single-operator account",
3164
+ target_motion: "issue_additional_operator_account",
3165
+ target_state: "emerging_multi_operator"
3166
+ },
3167
+ {
3168
+ template_id: "coordination_activation",
3169
+ recommended_for: "activating cross-zone and coordination followthrough",
3170
+ target_motion: "open_coordination_followthrough",
3171
+ target_state: "emerging_multi_operator"
3172
+ },
3173
+ {
3174
+ template_id: "contract_tightening",
3175
+ recommended_for: "tightening authority and identity contracts for multiple operators",
3176
+ target_motion: "tighten_multi_operator_contracts",
3177
+ target_state: "multi_operator_ready"
3178
+ },
3179
+ {
3180
+ template_id: "multi_operator_trust_repair",
3181
+ recommended_for: "repairing trust before widening operator participation",
3182
+ target_motion: "repair_multi_operator_trust",
3183
+ target_state: "emerging_multi_operator"
3184
+ },
3185
+ {
3186
+ template_id: "steady_multi_operator_maintenance",
3187
+ recommended_for: "maintaining a healthy multi-operator runtime posture",
3188
+ target_motion: "maintain_multi_operator_posture",
3189
+ target_state: "multi_operator_ready"
3190
+ }
3191
+ ];
3192
+
3193
+ return {
3194
+ pack_version: "xytara-multi-operator-participation-policy-pack-v1",
3195
+ account_id: accountId,
3196
+ multi_operator_participation_operator_bundle: operatorBundle,
3197
+ recommended_policy_motion: operatorBundle.operator_posture.recommended_operator_motion,
3198
+ policy_templates: templates,
3199
+ linked_surfaces: {
3200
+ multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3201
+ multi_operator_participation_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-application-summary`,
3202
+ multi_operator_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3203
+ },
3204
+ generated_at_iso: nowIso()
3205
+ };
3206
+ }
3207
+
3208
+ function summarizeMultiOperatorParticipationPolicyPack(state, accountId) {
3209
+ const pack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3210
+ return {
3211
+ pack_version: pack.pack_version,
3212
+ account_id: pack.account_id,
3213
+ recommended_policy_motion: pack.recommended_policy_motion,
3214
+ template_count: ensureArray(pack.policy_templates).length
3215
+ };
3216
+ }
3217
+
3218
+ function buildMultiOperatorParticipationApplicationSummary(state, accountId, templateId) {
3219
+ const pack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3220
+ const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
3221
+ || ensureArray(pack.policy_templates).find((entry) => entry.target_motion === pack.recommended_policy_motion)
3222
+ || ensureArray(pack.policy_templates)[0]
3223
+ || null;
3224
+
3225
+ return {
3226
+ summary_version: "xytara-multi-operator-participation-application-summary-v1",
3227
+ account_id: accountId,
3228
+ recommended_policy_motion: pack.recommended_policy_motion,
3229
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
3230
+ available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
3231
+ selected_template: selectedTemplate,
3232
+ suggested_participation_targets: {
3233
+ multi_operator_participation_state: pack.multi_operator_participation_operator_bundle.operator_posture.multi_operator_participation_state,
3234
+ coordination_readiness_state: pack.multi_operator_participation_operator_bundle.operator_posture.coordination_readiness_state,
3235
+ participation_risk_state: pack.multi_operator_participation_operator_bundle.operator_posture.participation_risk_state,
3236
+ trust_state: pack.multi_operator_participation_operator_bundle.operator_posture.trust_state
3237
+ },
3238
+ linked_surfaces: {
3239
+ multi_operator_participation_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
3240
+ multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3241
+ multi_operator_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-package`
3242
+ },
3243
+ generated_at_iso: nowIso()
3244
+ };
3245
+ }
3246
+
3247
+ function buildMultiOperatorParticipationPackage(state, accountId) {
3248
+ const summary = buildMultiOperatorParticipationSummary(state, accountId);
3249
+ const operatorBundle = buildMultiOperatorParticipationOperatorBundle(state, accountId);
3250
+ const policyPack = buildMultiOperatorParticipationPolicyPack(state, accountId);
3251
+ const applicationSummary = buildMultiOperatorParticipationApplicationSummary(state, accountId, null);
3252
+ const reviewBundle = buildMultiOperatorReviewBundle(state, accountId);
3253
+ const attentionSummary = buildMultiOperatorAttentionSummary(state, accountId);
3254
+
3255
+ return {
3256
+ package_version: "xytara-multi-operator-participation-package-v1",
3257
+ account_id: accountId,
3258
+ package_posture: {
3259
+ multi_operator_participation_state: summary.multi_operator_participation_state,
3260
+ coordination_readiness_state: summary.coordination_readiness_state,
3261
+ participation_risk_state: summary.participation_risk_state,
3262
+ overall_attention_state: attentionSummary.overall_attention_state,
3263
+ recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion,
3264
+ recommended_policy_motion: policyPack.recommended_policy_motion
3265
+ },
3266
+ multi_operator_participation_summary: summary,
3267
+ multi_operator_participation_operator_bundle: operatorBundle,
3268
+ multi_operator_participation_policy_pack: policyPack,
3269
+ multi_operator_participation_application_summary: applicationSummary,
3270
+ multi_operator_review_bundle: reviewBundle,
3271
+ multi_operator_attention_summary: attentionSummary,
3272
+ linked_surfaces: {
3273
+ multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`,
3274
+ multi_operator_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-operator-bundle`,
3275
+ multi_operator_participation_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-policy-pack`,
3276
+ multi_operator_participation_application_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-application-summary`,
3277
+ multi_operator_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-review-bundle`,
3278
+ multi_operator_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-attention-summary`
3279
+ },
3280
+ generated_at_iso: nowIso()
3281
+ };
3282
+ }
3283
+
3284
+ function summarizeMultiOperatorParticipationPackage(state, accountId) {
3285
+ const pack = buildMultiOperatorParticipationPackage(state, accountId);
3286
+ return {
3287
+ package_version: pack.package_version,
3288
+ account_id: pack.account_id,
3289
+ multi_operator_participation_state: pack.package_posture.multi_operator_participation_state,
3290
+ coordination_readiness_state: pack.package_posture.coordination_readiness_state,
3291
+ participation_risk_state: pack.package_posture.participation_risk_state,
3292
+ recommended_operator_motion: pack.package_posture.recommended_operator_motion,
3293
+ recommended_policy_motion: pack.package_posture.recommended_policy_motion
3294
+ };
3295
+ }
3296
+
3297
+ function listNetworkParticipantsForAccount(state, accountId) {
3298
+ return Array.from(state.networkParticipants.values())
3299
+ .filter((entry) => entry && entry.account_id === accountId);
3300
+ }
3301
+
3302
+ function buildNetworkParticipantPublicView(entry) {
3303
+ if (!entry) return null;
3304
+ return {
3305
+ network_participant_id: entry.network_participant_id,
3306
+ account_id: entry.account_id,
3307
+ label: entry.label,
3308
+ network_kind: entry.network_kind,
3309
+ partner_ref: entry.partner_ref || null,
3310
+ status: entry.status,
3311
+ participation_scope: ensureArray(entry.participation_scope),
3312
+ authority_binding_id: entry.authority_binding_id || null,
3313
+ identity_binding_id: entry.identity_binding_id || null,
3314
+ created_at_iso: entry.created_at_iso,
3315
+ updated_at_iso: entry.updated_at_iso,
3316
+ issued_by: entry.issued_by || null,
3317
+ labels: ensureArray(entry.labels)
3318
+ };
3319
+ }
3320
+
3321
+ function listNetworkParticipants(state, accountId) {
3322
+ return listNetworkParticipantsForAccount(state, accountId).map((entry) => buildNetworkParticipantPublicView(entry));
3323
+ }
3324
+
3325
+ function getNetworkParticipant(state, accountId, participantId) {
3326
+ if (!participantId || !state.networkParticipants.has(participantId)) return null;
3327
+ const entry = state.networkParticipants.get(participantId);
3328
+ if (!entry || entry.account_id !== accountId) return null;
3329
+ return buildNetworkParticipantPublicView(entry);
3330
+ }
3331
+
3332
+ function buildNetworkParticipationAdmissionPreview(state, accountId, body) {
3333
+ const payload = ensureObject(body);
3334
+ const nextIndex = listNetworkParticipantsForAccount(state, accountId).length + 1;
3335
+ return {
3336
+ preview_version: "xytara-network-participation-admission-preview-v1",
3337
+ account_id: accountId,
3338
+ proposed_participant: {
3339
+ label: normalizeString(payload.label, `network-participant-${nextIndex}`),
3340
+ network_kind: normalizeString(payload.network_kind, "external_operator"),
3341
+ partner_ref: normalizeString(payload.partner_ref, `partner_${nextIndex}`),
3342
+ participation_scope: ensureArray(payload.participation_scope).length > 0
3343
+ ? ensureArray(payload.participation_scope)
3344
+ : ["network.coordinate", "runtime.execute"]
3345
+ },
3346
+ planned_bindings: {
3347
+ authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
3348
+ identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity")
3349
+ },
3350
+ linked_surfaces: {
3351
+ network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3352
+ network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3353
+ },
3354
+ generated_at_iso: nowIso()
3355
+ };
3356
+ }
3357
+
3358
+ function createNetworkParticipant(state, accountId, body) {
3359
+ const payload = ensureObject(body);
3360
+ const createdAtIso = nowIso();
3361
+ const nextIndex = state.networkParticipants.size + 1;
3362
+ const networkParticipantId = normalizeString(payload.network_participant_id, `network_participant_${nextIndex}`);
3363
+ const participationScope = ensureArray(payload.participation_scope).length > 0
3364
+ ? ensureArray(payload.participation_scope).map((value) => String(value || "").trim()).filter(Boolean)
3365
+ : ["network.coordinate", "runtime.execute"];
3366
+ const authorityBinding = createAuthorityBinding(state, {
3367
+ binding_id: normalizeString(payload.authority_binding_id, `${networkParticipantId}_authority`),
3368
+ credential_id: normalizeString(payload.credential_id, `${networkParticipantId}_credential`),
3369
+ account_id: accountId,
3370
+ authority_kind: normalizeString(payload.authority_kind, "delegated_runtime_spend"),
3371
+ authority_scope: participationScope,
3372
+ allowed_consequence_families: ensureArray(payload.allowed_consequence_families).length > 0
3373
+ ? ensureArray(payload.allowed_consequence_families)
3374
+ : ["commit", "reserve"],
3375
+ max_commit_units: Number.isFinite(Number(payload.max_commit_units)) ? Number(payload.max_commit_units) : 5,
3376
+ max_reserve_units: Number.isFinite(Number(payload.max_reserve_units)) ? Number(payload.max_reserve_units) : 5,
3377
+ max_reversal_units: Number.isFinite(Number(payload.max_reversal_units)) ? Number(payload.max_reversal_units) : 1,
3378
+ labels: ensureArray(payload.labels),
3379
+ issued_by: normalizeString(payload.issued_by, "operator")
3380
+ });
3381
+ const identityBinding = createIdentityBinding(state, {
3382
+ binding_id: normalizeString(payload.identity_binding_id, `${networkParticipantId}_identity`),
3383
+ account_id: accountId,
3384
+ identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity"),
3385
+ identity_ref: normalizeString(payload.identity_ref, `${networkParticipantId}.identity`),
3386
+ attached_agent_account_id: networkParticipantId,
3387
+ labels: ensureArray(payload.labels),
3388
+ issued_by: normalizeString(payload.issued_by, "operator")
3389
+ });
3390
+ const participant = {
3391
+ network_participant_id: networkParticipantId,
3392
+ account_id: accountId,
3393
+ label: normalizeString(payload.label, networkParticipantId),
3394
+ network_kind: normalizeString(payload.network_kind, "external_operator"),
3395
+ partner_ref: normalizeString(payload.partner_ref, null),
3396
+ status: normalizeString(payload.status, "active"),
3397
+ participation_scope: participationScope,
3398
+ authority_binding_id: authorityBinding.binding_id,
3399
+ identity_binding_id: identityBinding.binding_id,
3400
+ created_at_iso: createdAtIso,
3401
+ updated_at_iso: createdAtIso,
3402
+ issued_by: normalizeString(payload.issued_by, "operator"),
3403
+ labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean)
3404
+ };
3405
+ state.networkParticipants.set(networkParticipantId, participant);
3406
+ return {
3407
+ network_participant: buildNetworkParticipantPublicView(participant),
3408
+ authority_binding: authorityBinding,
3409
+ identity_binding: identityBinding
3410
+ };
3411
+ }
3412
+
3413
+ function buildNetworkParticipationReviewBundle(state, accountId) {
3414
+ const participants = listNetworkParticipantsForAccount(state, accountId);
3415
+ const reviewRows = participants.map((entry) => {
3416
+ let review_state = "healthy";
3417
+ if (entry.status !== "active") review_state = "revoked";
3418
+ else if (!entry.authority_binding_id || !entry.identity_binding_id) review_state = "repair_required";
3419
+ else if (!entry.partner_ref) review_state = "attention_required";
3420
+ return {
3421
+ network_participant_id: entry.network_participant_id,
3422
+ label: entry.label,
3423
+ network_kind: entry.network_kind,
3424
+ status: entry.status,
3425
+ partner_ref: entry.partner_ref || null,
3426
+ review_state
3427
+ };
3428
+ });
3429
+ return {
3430
+ bundle_version: "xytara-network-participation-review-bundle-v1",
3431
+ account_id: accountId,
3432
+ review_rows: reviewRows,
3433
+ review_counts: {
3434
+ healthy_count: reviewRows.filter((entry) => entry.review_state === "healthy").length,
3435
+ attention_required_count: reviewRows.filter((entry) => entry.review_state === "attention_required").length,
3436
+ repair_required_count: reviewRows.filter((entry) => entry.review_state === "repair_required").length,
3437
+ revoked_count: reviewRows.filter((entry) => entry.review_state === "revoked").length
3438
+ },
3439
+ linked_surfaces: {
3440
+ network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3441
+ network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3442
+ },
3443
+ generated_at_iso: nowIso()
3444
+ };
3445
+ }
3446
+
3447
+ function buildNetworkParticipationAttentionSummary(state, accountId) {
3448
+ const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3449
+ const attentionRows = ensureArray(reviewBundle.review_rows).filter((entry) => entry.review_state !== "healthy");
3450
+ return {
3451
+ summary_version: "xytara-network-participation-attention-summary-v1",
3452
+ account_id: accountId,
3453
+ overall_attention_state: attentionRows.length > 0 ? "attention_required" : "healthy",
3454
+ attention_rows: attentionRows,
3455
+ linked_surfaces: {
3456
+ network_participation_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-review-bundle`,
3457
+ network_participation_package_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-package`
3458
+ },
3459
+ generated_at_iso: nowIso()
3460
+ };
3461
+ }
3462
+
3463
+ function buildNetworkParticipationSummary(state, accountId) {
3464
+ const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3465
+ const multiOperatorSummary = buildMultiOperatorParticipationSummary(state, accountId);
3466
+ const participants = listNetworkParticipantsForAccount(state, accountId);
3467
+ const activeParticipantCount = participants.filter((entry) => entry.status === "active").length;
3468
+ const coordinationHandoffCount = ensureArray(state.coordinationHandoffs).length;
3469
+ const admissionCaseCount = ensureArray(state.zoneAdmissionCases).length;
3470
+
3471
+ let participationState = "local_only";
3472
+ if (activeParticipantCount > 0 && multiOperatorSummary.multi_operator_participation_state !== "single_operator_only") {
3473
+ participationState = "external_network_present";
3474
+ } else if (activeParticipantCount > 0) {
3475
+ participationState = "network_edge_present";
3476
+ }
3477
+
3478
+ let networkReadinessState = "limited";
3479
+ if (activeParticipantCount > 0 && coordinationHandoffCount > 0 && admissionCaseCount > 0) {
3480
+ networkReadinessState = "active";
3481
+ } else if (activeParticipantCount > 0 || coordinationHandoffCount > 0 || admissionCaseCount > 0) {
3482
+ networkReadinessState = "preview_ready";
3483
+ }
3484
+
3485
+ let participationRiskState = "low";
3486
+ if (trustLayerSummary.trust_risk_state === "high" || activeParticipantCount === 0) {
3487
+ participationRiskState = "high";
3488
+ } else if (networkReadinessState !== "active") {
3489
+ participationRiskState = "watch";
3490
+ }
3491
+
3492
+ let recommendedParticipationMotion = "maintain_external_network_posture";
3493
+ if (activeParticipantCount === 0) {
3494
+ recommendedParticipationMotion = "admit_first_external_network_participant";
3495
+ } else if (participationRiskState === "high") {
3496
+ recommendedParticipationMotion = "repair_trust_before_external_network_expansion";
3497
+ } else if (networkReadinessState !== "active") {
3498
+ recommendedParticipationMotion = "activate_external_coordination_followthrough";
3499
+ }
3500
+
3501
+ return {
3502
+ summary_version: "xytara-network-participation-summary-v1",
3503
+ account_id: accountId,
3504
+ network_participation_state: participationState,
3505
+ network_readiness_state: networkReadinessState,
3506
+ participation_risk_state: participationRiskState,
3507
+ recommended_participation_motion: recommendedParticipationMotion,
3508
+ explanation_signals: {
3509
+ active_network_participant_count: activeParticipantCount,
3510
+ coordination_handoff_count: coordinationHandoffCount,
3511
+ admission_case_count: admissionCaseCount,
3512
+ trust_state: trustLayerSummary.trust_state,
3513
+ trust_risk_state: trustLayerSummary.trust_risk_state,
3514
+ multi_operator_participation_state: multiOperatorSummary.multi_operator_participation_state
3515
+ },
3516
+ linked_surfaces: {
3517
+ network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`,
3518
+ multi_operator_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/multi-operator-participation-summary`,
3519
+ trust_layer_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/trust-layer-summary`,
3520
+ coordination_center_ref: "/v1/coordination-center/summary"
3521
+ },
3522
+ generated_at_iso: nowIso()
3523
+ };
3524
+ }
3525
+
3526
+ function buildNetworkParticipationOperatorBundle(state, accountId) {
3527
+ const summary = buildNetworkParticipationSummary(state, accountId);
3528
+ const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3529
+ const attentionSummary = buildNetworkParticipationAttentionSummary(state, accountId);
3530
+ const trustLayerSummary = buildTrustLayerSummary(state, accountId);
3531
+ const multiOperatorSummary = buildMultiOperatorParticipationSummary(state, accountId);
3532
+ const participants = listNetworkParticipants(state, accountId);
3533
+
3534
+ let recommendedOperatorMotion = "maintain_external_network_posture";
3535
+ if (summary.network_participation_state === "local_only") {
3536
+ recommendedOperatorMotion = "admit_first_external_network_participant";
3537
+ } else if (summary.participation_risk_state === "high") {
3538
+ recommendedOperatorMotion = "repair_trust_before_external_network_expansion";
3539
+ } else if (summary.network_readiness_state !== "active") {
3540
+ recommendedOperatorMotion = "activate_external_coordination_followthrough";
3541
+ }
3542
+
3543
+ return {
3544
+ bundle_version: "xytara-network-participation-operator-bundle-v1",
3545
+ account_id: accountId,
3546
+ operator_posture: {
3547
+ network_participation_state: summary.network_participation_state,
3548
+ network_readiness_state: summary.network_readiness_state,
3549
+ participation_risk_state: summary.participation_risk_state,
3550
+ active_network_participant_count: participants.filter((entry) => entry.status === "active").length,
3551
+ trust_state: trustLayerSummary.trust_state,
3552
+ multi_operator_participation_state: multiOperatorSummary.multi_operator_participation_state,
3553
+ overall_attention_state: attentionSummary.overall_attention_state,
3554
+ recommended_operator_motion: recommendedOperatorMotion
3555
+ },
3556
+ network_participation_summary: summary,
3557
+ network_participation_review_bundle: reviewBundle,
3558
+ network_participation_attention_summary: attentionSummary,
3559
+ trust_layer_summary: trustLayerSummary,
3560
+ multi_operator_participation_summary: multiOperatorSummary,
3561
+ network_participants: participants,
3562
+ linked_surfaces: summary.linked_surfaces,
3563
+ generated_at_iso: nowIso()
3564
+ };
3565
+ }
3566
+
3567
+ function buildNetworkParticipationPackage(state, accountId) {
3568
+ const summary = buildNetworkParticipationSummary(state, accountId);
3569
+ const operatorBundle = buildNetworkParticipationOperatorBundle(state, accountId);
3570
+ const reviewBundle = buildNetworkParticipationReviewBundle(state, accountId);
3571
+ const attentionSummary = buildNetworkParticipationAttentionSummary(state, accountId);
3572
+ return {
3573
+ package_version: "xytara-network-participation-package-v1",
3574
+ account_id: accountId,
3575
+ package_posture: {
3576
+ network_participation_state: summary.network_participation_state,
3577
+ network_readiness_state: summary.network_readiness_state,
3578
+ participation_risk_state: summary.participation_risk_state,
3579
+ overall_attention_state: attentionSummary.overall_attention_state,
3580
+ recommended_operator_motion: operatorBundle.operator_posture.recommended_operator_motion
3581
+ },
3582
+ network_participation_summary: summary,
3583
+ network_participation_operator_bundle: operatorBundle,
3584
+ network_participation_review_bundle: reviewBundle,
3585
+ network_participation_attention_summary: attentionSummary,
3586
+ linked_surfaces: {
3587
+ network_participation_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-summary`,
3588
+ network_participation_operator_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-operator-bundle`,
3589
+ network_participation_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-review-bundle`,
3590
+ network_participation_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participation-attention-summary`,
3591
+ network_participants_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/network-participants`
3592
+ },
3593
+ generated_at_iso: nowIso()
3594
+ };
3595
+ }
3596
+
1187
3597
  function buildRailSummary(state, accountId) {
1188
3598
  const credits = listRailCreditsForAccount(state, accountId);
1189
3599
  const paymentLedger = listPaymentLedgerForAccount(state, accountId);
@@ -1402,6 +3812,15 @@ module.exports = {
1402
3812
  previewRailCredits,
1403
3813
  applyRailCredits,
1404
3814
  buildCreditBalanceSummary,
3815
+ buildWalletSummary,
3816
+ buildWalletLifecycleSummary,
3817
+ buildWalletReserveSummary,
3818
+ buildWalletCommitSummary,
3819
+ buildWalletLedgerBundle,
3820
+ buildWalletLedgerSummary,
3821
+ applyWalletLifecycleEvent,
3822
+ buildEconomicsIntelligenceSummary,
3823
+ buildTreasuryIntelligenceSummary,
1405
3824
  buildTreasurySummary,
1406
3825
  buildLedgerExport,
1407
3826
  buildTreasuryDrilldown,
@@ -1412,6 +3831,56 @@ module.exports = {
1412
3831
  buildPolicySummary,
1413
3832
  buildAccountCreditSpendPolicyPack,
1414
3833
  buildAgentCreditSpendPolicyView,
3834
+ buildPricingPolicySummary,
3835
+ buildPricingPolicyOperatorBundle,
3836
+ buildPricingPolicyPack,
3837
+ buildPricingPolicyApplicationSummary,
3838
+ buildPricingPolicyPackage,
3839
+ buildQuotePolicyDecisionSummary,
3840
+ buildPricingBandDecisionSummary,
3841
+ buildQuotePolicyOperatorBundle,
3842
+ summarizeQuotePolicyOperatorBundle,
3843
+ buildQuotePolicyPack,
3844
+ summarizeQuotePolicyPack,
3845
+ buildQuotePolicyApplicationSummary,
3846
+ buildQuotePolicyPackage,
3847
+ summarizeQuotePolicyPackage,
3848
+ buildTrustInputSummary,
3849
+ buildTrustLayerSummary,
3850
+ buildTrustLayerOperatorBundle,
3851
+ summarizeTrustLayerOperatorBundle,
3852
+ buildTrustLayerPolicyPack,
3853
+ summarizeTrustLayerPolicyPack,
3854
+ buildTrustLayerApplicationSummary,
3855
+ buildTrustLayerPackage,
3856
+ summarizeTrustLayerPackage,
3857
+ listNetworkParticipants,
3858
+ getNetworkParticipant,
3859
+ buildNetworkParticipationAdmissionPreview,
3860
+ createNetworkParticipant,
3861
+ buildNetworkParticipationReviewBundle,
3862
+ buildNetworkParticipationAttentionSummary,
3863
+ buildNetworkParticipationSummary,
3864
+ buildNetworkParticipationOperatorBundle,
3865
+ buildNetworkParticipationPackage,
3866
+ listMultiOperatorParticipants,
3867
+ getMultiOperatorParticipant,
3868
+ buildMultiOperatorAdmissionPreview,
3869
+ createMultiOperatorParticipant,
3870
+ renewMultiOperatorParticipant,
3871
+ revokeMultiOperatorParticipant,
3872
+ rotateMultiOperatorParticipant,
3873
+ buildMultiOperatorParticipantRotationSummary,
3874
+ buildMultiOperatorReviewBundle,
3875
+ buildMultiOperatorAttentionSummary,
3876
+ buildMultiOperatorParticipationSummary,
3877
+ buildMultiOperatorParticipationOperatorBundle,
3878
+ summarizeMultiOperatorParticipationOperatorBundle,
3879
+ buildMultiOperatorParticipationPolicyPack,
3880
+ summarizeMultiOperatorParticipationPolicyPack,
3881
+ buildMultiOperatorParticipationApplicationSummary,
3882
+ buildMultiOperatorParticipationPackage,
3883
+ summarizeMultiOperatorParticipationPackage,
1415
3884
  buildRailSummary,
1416
3885
  buildTreasuryWorkflowPack,
1417
3886
  buildTreasurySignoffPack,
@@ -1438,6 +3907,7 @@ module.exports = {
1438
3907
  listMapValuesByAccount,
1439
3908
  listEntitlementsForAccount,
1440
3909
  getEntitlement,
3910
+ getAllocationEvent,
1441
3911
  getCreditSpend,
1442
3912
  listUsageMetersForAccount,
1443
3913
  getUsageMeter,