@plasius/economy 0.7.0 → 0.8.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.
package/dist/index.js CHANGED
@@ -501,6 +501,1155 @@ function mapBitLabsConversionState(state) {
501
501
  return transition;
502
502
  }
503
503
 
504
+ // src/admin-reporting.ts
505
+ var ADMIN_TOKEN_DEFAULT_WINDOW_DAYS = 30;
506
+ var ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS = 365;
507
+ var ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS = 31;
508
+ var ADMIN_TOKEN_MAXIMUM_PAGE_SIZE = 100;
509
+ var ADMIN_TOKEN_MAXIMUM_TREND_POINTS = ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS * 24 * 5;
510
+ var ADMIN_TOKEN_MINIMUM_COHORT_SIZE = 5;
511
+ var ADMIN_TOKEN_ANOMALY_BASELINE_DAYS = 28;
512
+ var DAY_MILLISECONDS = 864e5;
513
+ var HOUR_MILLISECONDS = 36e5;
514
+ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
515
+ "acquisition",
516
+ "spend",
517
+ "reversal",
518
+ "hold",
519
+ "failure"
520
+ ]);
521
+ var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
522
+ "pending",
523
+ "held",
524
+ "settled",
525
+ "reversed",
526
+ "failed"
527
+ ]);
528
+ var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
529
+ "paid-purchase",
530
+ "subscription",
531
+ "rewarded-activity",
532
+ "gameplay",
533
+ "system-adjustment",
534
+ "unknown"
535
+ ]);
536
+ var SAFE_LABELS = /* @__PURE__ */ new Set([
537
+ "token-acquisition",
538
+ "token-spend",
539
+ "token-reversal",
540
+ "token-hold",
541
+ "token-activity-failed",
542
+ "token-system-adjustment",
543
+ "token-activity-unclassified"
544
+ ]);
545
+ var SAFE_LABELS_BY_ACTIVITY_TYPE = {
546
+ acquisition: /* @__PURE__ */ new Set([
547
+ "token-acquisition",
548
+ "token-system-adjustment",
549
+ "token-activity-unclassified"
550
+ ]),
551
+ spend: /* @__PURE__ */ new Set([
552
+ "token-spend",
553
+ "token-system-adjustment",
554
+ "token-activity-unclassified"
555
+ ]),
556
+ reversal: /* @__PURE__ */ new Set([
557
+ "token-reversal",
558
+ "token-system-adjustment",
559
+ "token-activity-unclassified"
560
+ ]),
561
+ hold: /* @__PURE__ */ new Set([
562
+ "token-hold",
563
+ "token-system-adjustment",
564
+ "token-activity-unclassified"
565
+ ]),
566
+ failure: /* @__PURE__ */ new Set([
567
+ "token-activity-failed",
568
+ "token-activity-unclassified"
569
+ ])
570
+ };
571
+ var ACTIVITY_SORTS = /* @__PURE__ */ new Set([
572
+ "occurred-at-desc",
573
+ "amount-absolute-desc"
574
+ ]);
575
+ var PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
576
+ "admin-token-activity",
577
+ "mcp-token-activity"
578
+ ]);
579
+ var BALANCE_PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
580
+ "admin-token-balances",
581
+ "mcp-token-balances"
582
+ ]);
583
+ var WALLET_COMPONENTS = /* @__PURE__ */ new Set([
584
+ "household",
585
+ "personal",
586
+ "gameplay-allocation"
587
+ ]);
588
+ var WALLET_STATUSES = /* @__PURE__ */ new Set([
589
+ "active",
590
+ "closed"
591
+ ]);
592
+ var WALLET_BALANCE_SORTS = /* @__PURE__ */ new Set([
593
+ "available-desc",
594
+ "updated-at-desc"
595
+ ]);
596
+ var TREND_GRANULARITIES = /* @__PURE__ */ new Set([
597
+ "hour",
598
+ "day"
599
+ ]);
600
+ var ALIAS = /^[A-Za-z0-9_-]{16,96}$/u;
601
+ var OPAQUE_CURSOR = /^c1\.[A-Za-z0-9_-]{32,480}$/u;
602
+ var PSEUDONYM_VERSION = /^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$/u;
603
+ var EXACT_STATISTIC_INTEGER = /^(?:0|-?[1-9][0-9]*)$/u;
604
+ var POSITIVE_UNSIGNED_INTEGER = /^[1-9][0-9]*$/u;
605
+ var MAXIMUM_STATISTIC_HALF_SUBUNITS = (TOKEN_SUBUNITS_MAX - TOKEN_SUBUNITS_MIN) * 2n;
606
+ var ANOMALY_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
607
+ "insufficient-history",
608
+ "privacy-suppressed-baseline"
609
+ ]);
610
+ function assertPlainObject(value, label) {
611
+ economyAssert(
612
+ typeof value === "object" && value !== null && !Array.isArray(value),
613
+ "INVALID_CONTRACT",
614
+ `${label} must be an object`
615
+ );
616
+ const prototype = Object.getPrototypeOf(value);
617
+ economyAssert(
618
+ (prototype === Object.prototype || prototype === null) && !Reflect.has(value, "toJSON"),
619
+ "INVALID_CONTRACT",
620
+ `${label} must be a plain data object without serialization hooks`
621
+ );
622
+ }
623
+ function assertExactKeys(value, allowedKeys, label) {
624
+ assertPlainObject(value, label);
625
+ const allowed = new Set(allowedKeys);
626
+ const keys = Reflect.ownKeys(value);
627
+ economyAssert(
628
+ allowedKeys.every(
629
+ (key) => !Reflect.has(value, key) || Object.hasOwn(value, key)
630
+ ) && keys.every((key) => {
631
+ if (typeof key !== "string" || !allowed.has(key)) {
632
+ return false;
633
+ }
634
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
635
+ return descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
636
+ }),
637
+ "INVALID_CONTRACT",
638
+ `${label} contains an unsupported, identifying, or non-data property`
639
+ );
640
+ }
641
+ function assertAlias(value, label) {
642
+ economyAssert(
643
+ typeof value === "string" && ALIAS.test(value),
644
+ "INVALID_CONTRACT",
645
+ `${label} must be an opaque pseudonymous alias`
646
+ );
647
+ }
648
+ function assertOpaqueCursor(value) {
649
+ economyAssert(
650
+ typeof value === "string" && OPAQUE_CURSOR.test(value),
651
+ "INVALID_CONTRACT",
652
+ "Admin Token cursor must be a bounded confidentiality-protected opaque value"
653
+ );
654
+ }
655
+ function assertUniqueValues(values, allowed, label) {
656
+ economyAssert(
657
+ Array.isArray(values),
658
+ "INVALID_CONTRACT",
659
+ `${label} must be a list`
660
+ );
661
+ const unique = new Set(values);
662
+ economyAssert(
663
+ values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
664
+ "INVALID_CONTRACT",
665
+ `${label} must contain unique supported values`
666
+ );
667
+ }
668
+ function absolute(value) {
669
+ return value < 0n ? -value : value;
670
+ }
671
+ function compareTextDescending(left, right) {
672
+ if (left === right) {
673
+ return 0;
674
+ }
675
+ return left > right ? -1 : 1;
676
+ }
677
+ function assertReportingWindow(window, maximumDays = ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS) {
678
+ assertExactKeys(
679
+ window,
680
+ ["fromInclusive", "toExclusive"],
681
+ "Admin Token reporting window"
682
+ );
683
+ const from = parseIsoTimestamp(window.fromInclusive);
684
+ const to = parseIsoTimestamp(window.toExclusive);
685
+ economyAssert(
686
+ from < to && to - from <= maximumDays * DAY_MILLISECONDS,
687
+ "INVALID_TIME_WINDOW",
688
+ `Admin Token reporting window must be positive and no longer than ${maximumDays} days`
689
+ );
690
+ return { from, to };
691
+ }
692
+ function createDefaultAdminTokenReportingWindow(asOf) {
693
+ const to = parseIsoTimestamp(asOf);
694
+ return {
695
+ fromInclusive: new Date(
696
+ to - ADMIN_TOKEN_DEFAULT_WINDOW_DAYS * DAY_MILLISECONDS
697
+ ).toISOString(),
698
+ toExclusive: new Date(to).toISOString()
699
+ };
700
+ }
701
+ function assertNonNegativeTokenAmounts(amounts, label) {
702
+ economyAssert(
703
+ amounts.every((amount) => parseTokenSubunits(amount) >= 0n),
704
+ "INVALID_AMOUNT",
705
+ `${label} cannot contain a negative amount`
706
+ );
707
+ }
708
+ function assertPositiveAuthoritySequence(sequence, label) {
709
+ economyAssert(
710
+ typeof sequence === "string" && POSITIVE_UNSIGNED_INTEGER.test(sequence),
711
+ "INVALID_CONTRACT",
712
+ `${label} must be a canonical positive integer`
713
+ );
714
+ }
715
+ function assertAdminTokenEconomySummary(summary) {
716
+ assertExactKeys(
717
+ summary,
718
+ [
719
+ "schemaVersion",
720
+ "generatedAt",
721
+ "projectionAsOf",
722
+ "authoritySequence",
723
+ "walletCount",
724
+ "activeWalletCount",
725
+ "balances",
726
+ "lifetime",
727
+ "rawIdentifiersIncluded"
728
+ ],
729
+ "Admin Token economy summary"
730
+ );
731
+ assertExactKeys(
732
+ summary.balances,
733
+ ["schemaVersion", "available", "reserved", "held", "rewardProgress"],
734
+ "Admin Token aggregate balances"
735
+ );
736
+ assertExactKeys(
737
+ summary.lifetime,
738
+ [
739
+ "schemaVersion",
740
+ "bought",
741
+ "earned",
742
+ "allocated",
743
+ "reclaimed",
744
+ "spent",
745
+ "reversed"
746
+ ],
747
+ "Admin Token aggregate lifetime"
748
+ );
749
+ economyAssert(
750
+ summary.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.balances.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.lifetime.schemaVersion === ECONOMY_CONTRACT_VERSION && summary.rawIdentifiersIncluded === false && Number.isSafeInteger(summary.walletCount) && summary.walletCount >= 0 && Number.isSafeInteger(summary.activeWalletCount) && summary.activeWalletCount >= 0 && summary.activeWalletCount <= summary.walletCount,
751
+ "INVALID_CONTRACT",
752
+ "Admin Token economy summary metadata is invalid"
753
+ );
754
+ const generatedAt = parseIsoTimestamp(summary.generatedAt);
755
+ const projectionAsOf = parseIsoTimestamp(summary.projectionAsOf);
756
+ economyAssert(
757
+ projectionAsOf <= generatedAt,
758
+ "INVALID_TIME_WINDOW",
759
+ "Admin Token projection cannot be newer than its generated result"
760
+ );
761
+ assertPositiveAuthoritySequence(
762
+ summary.authoritySequence,
763
+ "Admin Token summary authority sequence"
764
+ );
765
+ assertNonNegativeTokenAmounts(
766
+ [
767
+ summary.balances.available,
768
+ summary.balances.reserved,
769
+ summary.balances.held,
770
+ summary.balances.rewardProgress,
771
+ summary.lifetime.bought,
772
+ summary.lifetime.earned,
773
+ summary.lifetime.allocated,
774
+ summary.lifetime.reclaimed,
775
+ summary.lifetime.spent,
776
+ summary.lifetime.reversed
777
+ ],
778
+ "Admin Token economy summary"
779
+ );
780
+ }
781
+ function assertAdminTokenWalletBalanceFilter(filter) {
782
+ assertExactKeys(
783
+ filter,
784
+ ["components", "statuses", "subjectAlias"],
785
+ "Admin Token wallet balance filter"
786
+ );
787
+ if (filter.components !== void 0) {
788
+ assertUniqueValues(
789
+ filter.components,
790
+ WALLET_COMPONENTS,
791
+ "Admin Token wallet components"
792
+ );
793
+ }
794
+ if (filter.statuses !== void 0) {
795
+ assertUniqueValues(
796
+ filter.statuses,
797
+ WALLET_STATUSES,
798
+ "Admin Token wallet statuses"
799
+ );
800
+ }
801
+ if (filter.subjectAlias !== void 0) {
802
+ assertAlias(filter.subjectAlias, "Wallet subject alias filter");
803
+ }
804
+ }
805
+ function sameWalletBalanceFilter(left, right) {
806
+ if (left === void 0 || right === void 0) {
807
+ return left === right;
808
+ }
809
+ return sameOptionalValues(left.components, right.components) && sameOptionalValues(left.statuses, right.statuses) && left.subjectAlias === right.subjectAlias;
810
+ }
811
+ function assertAdminTokenWalletBalanceCursorBinding(binding) {
812
+ assertExactKeys(
813
+ binding,
814
+ [
815
+ "schemaVersion",
816
+ "sort",
817
+ "filter",
818
+ "audience",
819
+ "pseudonymVersion"
820
+ ],
821
+ "Admin Token wallet balance cursor binding"
822
+ );
823
+ economyAssert(
824
+ binding.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_BALANCE_SORTS.has(binding.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
825
+ "INVALID_CONTRACT",
826
+ "Unsupported Admin Token wallet balance cursor binding"
827
+ );
828
+ if (binding.filter !== void 0) {
829
+ assertAdminTokenWalletBalanceFilter(binding.filter);
830
+ }
831
+ }
832
+ function assertAdminTokenWalletBalancePageRequest(request) {
833
+ assertExactKeys(
834
+ request,
835
+ [
836
+ "schemaVersion",
837
+ "limit",
838
+ "cursor",
839
+ "cursorBinding",
840
+ "sort",
841
+ "filter",
842
+ "audience",
843
+ "pseudonymVersion"
844
+ ],
845
+ "Admin Token wallet balance request"
846
+ );
847
+ economyAssert(
848
+ request.schemaVersion === ECONOMY_CONTRACT_VERSION && Number.isSafeInteger(request.limit) && request.limit >= 1 && request.limit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && WALLET_BALANCE_SORTS.has(request.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(request.audience) && PSEUDONYM_VERSION.test(request.pseudonymVersion),
849
+ "INVALID_CONTRACT",
850
+ "Unsupported or unbounded Admin Token wallet balance request"
851
+ );
852
+ if (request.filter !== void 0) {
853
+ assertAdminTokenWalletBalanceFilter(request.filter);
854
+ }
855
+ economyAssert(
856
+ request.cursor === void 0 === (request.cursorBinding === void 0),
857
+ "INVALID_CONTRACT",
858
+ "Admin Token wallet balance cursor and binding must be provided together"
859
+ );
860
+ if (request.cursor === void 0 || request.cursorBinding === void 0) {
861
+ return;
862
+ }
863
+ assertOpaqueCursor(request.cursor);
864
+ assertAdminTokenWalletBalanceCursorBinding(request.cursorBinding);
865
+ economyAssert(
866
+ request.cursorBinding.sort === request.sort && request.cursorBinding.audience === request.audience && request.cursorBinding.pseudonymVersion === request.pseudonymVersion && sameWalletBalanceFilter(request.cursorBinding.filter, request.filter),
867
+ "INVALID_CONTRACT",
868
+ "Admin Token wallet balance cursor is not bound to the normalized query"
869
+ );
870
+ }
871
+ function assertAdminTokenWalletBalanceEntry(entry) {
872
+ assertExactKeys(
873
+ entry,
874
+ [
875
+ "schemaVersion",
876
+ "walletAlias",
877
+ "subjectAlias",
878
+ "component",
879
+ "status",
880
+ "available",
881
+ "reserved",
882
+ "held",
883
+ "rewardProgress",
884
+ "updatedAt",
885
+ "authoritySequence"
886
+ ],
887
+ "Admin Token wallet balance entry"
888
+ );
889
+ economyAssert(
890
+ entry.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_COMPONENTS.has(entry.component) && WALLET_STATUSES.has(entry.status),
891
+ "INVALID_CONTRACT",
892
+ "Unsupported Admin Token wallet balance entry"
893
+ );
894
+ assertAlias(entry.walletAlias, "Wallet alias");
895
+ assertAlias(entry.subjectAlias, "Wallet subject alias");
896
+ economyAssert(
897
+ entry.walletAlias !== entry.subjectAlias,
898
+ "INVALID_CONTRACT",
899
+ "Wallet and subject aliases must use separate pseudonym domains"
900
+ );
901
+ assertNonNegativeTokenAmounts(
902
+ [entry.available, entry.reserved, entry.held, entry.rewardProgress],
903
+ "Admin Token wallet balance entry"
904
+ );
905
+ parseIsoTimestamp(entry.updatedAt);
906
+ assertPositiveAuthoritySequence(
907
+ entry.authoritySequence,
908
+ "Admin Token wallet balance authority sequence"
909
+ );
910
+ }
911
+ function compareWalletBalanceEntries(left, right, sort) {
912
+ if (sort === "available-desc") {
913
+ const leftAvailable = parseTokenSubunits(left.available);
914
+ const rightAvailable = parseTokenSubunits(right.available);
915
+ if (leftAvailable !== rightAvailable) {
916
+ return leftAvailable > rightAvailable ? -1 : 1;
917
+ }
918
+ }
919
+ const leftUpdatedAt = parseIsoTimestamp(left.updatedAt);
920
+ const rightUpdatedAt = parseIsoTimestamp(right.updatedAt);
921
+ if (leftUpdatedAt !== rightUpdatedAt) {
922
+ return leftUpdatedAt > rightUpdatedAt ? -1 : 1;
923
+ }
924
+ return compareTextDescending(left.walletAlias, right.walletAlias);
925
+ }
926
+ function assertAdminTokenWalletBalancePage(page) {
927
+ assertExactKeys(
928
+ page,
929
+ ["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
930
+ "Admin Token wallet balance page"
931
+ );
932
+ assertExactKeys(
933
+ page.metadata,
934
+ [
935
+ "schemaVersion",
936
+ "generatedAt",
937
+ "sort",
938
+ "filter",
939
+ "pageLimit",
940
+ "audience",
941
+ "pseudonymVersion",
942
+ "rawIdentifiersIncluded"
943
+ ],
944
+ "Admin Token wallet balance metadata"
945
+ );
946
+ economyAssert(
947
+ page.schemaVersion === ECONOMY_CONTRACT_VERSION && page.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && typeof page.hasMore === "boolean" && page.metadata.rawIdentifiersIncluded === false && WALLET_BALANCE_SORTS.has(page.metadata.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(page.metadata.audience) && PSEUDONYM_VERSION.test(page.metadata.pseudonymVersion) && Number.isSafeInteger(page.metadata.pageLimit) && page.metadata.pageLimit >= 1 && page.metadata.pageLimit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && Array.isArray(page.entries) && page.entries.length <= page.metadata.pageLimit && page.hasMore === (page.nextCursor !== void 0) && (!page.hasMore || page.entries.length > 0),
948
+ "INVALID_CONTRACT",
949
+ "Unsupported or unbounded Admin Token wallet balance page"
950
+ );
951
+ if (page.metadata.filter !== void 0) {
952
+ assertAdminTokenWalletBalanceFilter(page.metadata.filter);
953
+ }
954
+ parseIsoTimestamp(page.metadata.generatedAt);
955
+ if (page.nextCursor !== void 0) {
956
+ assertOpaqueCursor(page.nextCursor);
957
+ }
958
+ const walletAliases = /* @__PURE__ */ new Set();
959
+ let previous;
960
+ for (const entry of page.entries) {
961
+ assertAdminTokenWalletBalanceEntry(entry);
962
+ const filter = page.metadata.filter;
963
+ economyAssert(
964
+ filter === void 0 || (filter.components === void 0 || filter.components.includes(entry.component)) && (filter.statuses === void 0 || filter.statuses.includes(entry.status)) && (filter.subjectAlias === void 0 || filter.subjectAlias === entry.subjectAlias),
965
+ "INVALID_CONTRACT",
966
+ "Admin Token wallet balance result contains an unrequested row"
967
+ );
968
+ economyAssert(
969
+ !walletAliases.has(entry.walletAlias),
970
+ "DUPLICATE_IDENTIFIER",
971
+ "Admin Token wallet balance page cannot repeat a wallet alias"
972
+ );
973
+ walletAliases.add(entry.walletAlias);
974
+ if (previous !== void 0) {
975
+ economyAssert(
976
+ compareWalletBalanceEntries(previous, entry, page.metadata.sort) < 0,
977
+ "INVALID_CONTRACT",
978
+ "Admin Token wallet balance page does not use its declared stable sort"
979
+ );
980
+ }
981
+ previous = entry;
982
+ }
983
+ }
984
+ function assertAdminTokenWalletBalancePageForRequest(page, request) {
985
+ assertAdminTokenWalletBalancePageRequest(request);
986
+ assertAdminTokenWalletBalancePage(page);
987
+ economyAssert(
988
+ page.metadata.sort === request.sort && sameWalletBalanceFilter(page.metadata.filter, request.filter) && page.metadata.pageLimit === request.limit && page.metadata.audience === request.audience && page.metadata.pseudonymVersion === request.pseudonymVersion,
989
+ "INVALID_CONTRACT",
990
+ "Admin Token wallet balance result does not match its normalized request"
991
+ );
992
+ }
993
+ function assertAdminTokenActivityEntry(entry) {
994
+ assertExactKeys(
995
+ entry,
996
+ [
997
+ "schemaVersion",
998
+ "occurredAt",
999
+ "activityType",
1000
+ "status",
1001
+ "source",
1002
+ "amount",
1003
+ "safeLabel",
1004
+ "rowAlias",
1005
+ "subjectAlias"
1006
+ ],
1007
+ "Admin Token activity entry"
1008
+ );
1009
+ economyAssert(
1010
+ entry.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
1011
+ "INVALID_CONTRACT",
1012
+ "Unsupported Admin Token activity contract"
1013
+ );
1014
+ parseIsoTimestamp(entry.occurredAt);
1015
+ const amount = parseTokenSubunits(entry.amount);
1016
+ economyAssert(
1017
+ (amount !== 0n || entry.activityType === "failure") && (entry.activityType !== "acquisition" || amount > 0n) && (entry.activityType !== "spend" || amount < 0n),
1018
+ "INVALID_AMOUNT",
1019
+ "Admin Token activity amount has an invalid sign or zero value"
1020
+ );
1021
+ economyAssert(
1022
+ entry.activityType === "failure" === (entry.status === "failed"),
1023
+ "INVALID_CONTRACT",
1024
+ "Failed rows must use the failure activity type"
1025
+ );
1026
+ economyAssert(
1027
+ SAFE_LABELS.has(entry.safeLabel) && SAFE_LABELS_BY_ACTIVITY_TYPE[entry.activityType]?.has(entry.safeLabel) === true,
1028
+ "INVALID_CONTRACT",
1029
+ "Admin Token activity label must use the approved non-identifying allowlist"
1030
+ );
1031
+ assertAlias(entry.rowAlias, "Row alias");
1032
+ assertAlias(entry.subjectAlias, "Subject alias");
1033
+ economyAssert(
1034
+ entry.rowAlias !== entry.subjectAlias,
1035
+ "INVALID_CONTRACT",
1036
+ "Row and subject aliases must use separate pseudonym domains"
1037
+ );
1038
+ }
1039
+ function assertAdminTokenActivityFilter(filter) {
1040
+ assertExactKeys(
1041
+ filter,
1042
+ [
1043
+ "activityTypes",
1044
+ "statuses",
1045
+ "sources",
1046
+ "subjectAlias"
1047
+ ],
1048
+ "Admin Token activity filter"
1049
+ );
1050
+ if (filter.activityTypes !== void 0) {
1051
+ assertUniqueValues(
1052
+ filter.activityTypes,
1053
+ ACTIVITY_TYPES,
1054
+ "Admin Token activity types"
1055
+ );
1056
+ }
1057
+ if (filter.statuses !== void 0) {
1058
+ assertUniqueValues(
1059
+ filter.statuses,
1060
+ ACTIVITY_STATUSES,
1061
+ "Admin Token activity statuses"
1062
+ );
1063
+ }
1064
+ if (filter.sources !== void 0) {
1065
+ assertUniqueValues(
1066
+ filter.sources,
1067
+ ACTIVITY_SOURCES,
1068
+ "Admin Token activity sources"
1069
+ );
1070
+ }
1071
+ if (filter.subjectAlias !== void 0) {
1072
+ assertAlias(filter.subjectAlias, "Subject alias filter");
1073
+ }
1074
+ }
1075
+ function sameOptionalValues(left, right) {
1076
+ if (left === void 0 || right === void 0) {
1077
+ return left === right;
1078
+ }
1079
+ return left.length === right.length && left.every((value) => right.includes(value));
1080
+ }
1081
+ function sameActivityFilter(left, right) {
1082
+ if (left === void 0 || right === void 0) {
1083
+ return left === right;
1084
+ }
1085
+ return sameOptionalValues(left.activityTypes, right.activityTypes) && sameOptionalValues(left.statuses, right.statuses) && sameOptionalValues(left.sources, right.sources) && left.subjectAlias === right.subjectAlias;
1086
+ }
1087
+ function assertAdminTokenActivityCursorBinding(binding) {
1088
+ assertExactKeys(
1089
+ binding,
1090
+ [
1091
+ "schemaVersion",
1092
+ "sort",
1093
+ "window",
1094
+ "filter",
1095
+ "audience",
1096
+ "pseudonymVersion"
1097
+ ],
1098
+ "Admin Token activity cursor binding"
1099
+ );
1100
+ economyAssert(
1101
+ binding.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_SORTS.has(binding.sort) && PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
1102
+ "INVALID_CONTRACT",
1103
+ "Unsupported Admin Token activity cursor binding"
1104
+ );
1105
+ assertReportingWindow(binding.window);
1106
+ if (binding.filter !== void 0) {
1107
+ assertAdminTokenActivityFilter(binding.filter);
1108
+ }
1109
+ }
1110
+ function assertAdminTokenActivityPageRequest(request) {
1111
+ assertExactKeys(
1112
+ request,
1113
+ [
1114
+ "schemaVersion",
1115
+ "limit",
1116
+ "cursor",
1117
+ "cursorBinding",
1118
+ "sort",
1119
+ "window",
1120
+ "filter",
1121
+ "audience",
1122
+ "pseudonymVersion"
1123
+ ],
1124
+ "Admin Token activity request"
1125
+ );
1126
+ economyAssert(
1127
+ request.schemaVersion === ECONOMY_CONTRACT_VERSION && Number.isSafeInteger(request.limit) && request.limit >= 1 && request.limit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE && ACTIVITY_SORTS.has(request.sort) && PSEUDONYM_AUDIENCES.has(request.audience) && PSEUDONYM_VERSION.test(request.pseudonymVersion),
1128
+ "INVALID_CONTRACT",
1129
+ "Unsupported or unbounded Admin Token activity request"
1130
+ );
1131
+ assertReportingWindow(request.window);
1132
+ if (request.filter !== void 0) {
1133
+ assertAdminTokenActivityFilter(request.filter);
1134
+ }
1135
+ economyAssert(
1136
+ request.cursor === void 0 === (request.cursorBinding === void 0),
1137
+ "INVALID_CONTRACT",
1138
+ "Admin Token activity cursor and trusted binding must be provided together"
1139
+ );
1140
+ if (request.cursor === void 0 || request.cursorBinding === void 0) {
1141
+ return;
1142
+ }
1143
+ assertOpaqueCursor(request.cursor);
1144
+ assertAdminTokenActivityCursorBinding(request.cursorBinding);
1145
+ economyAssert(
1146
+ request.cursorBinding.sort === request.sort && request.cursorBinding.window.fromInclusive === request.window.fromInclusive && request.cursorBinding.window.toExclusive === request.window.toExclusive && request.cursorBinding.audience === request.audience && request.cursorBinding.pseudonymVersion === request.pseudonymVersion && sameActivityFilter(request.cursorBinding.filter, request.filter),
1147
+ "INVALID_CONTRACT",
1148
+ "Admin Token cursor is not bound to the normalized query"
1149
+ );
1150
+ }
1151
+ function compareActivityEntries(left, right, sort) {
1152
+ if (sort === "amount-absolute-desc") {
1153
+ const leftAmount = absolute(parseTokenSubunits(left.amount));
1154
+ const rightAmount = absolute(parseTokenSubunits(right.amount));
1155
+ if (leftAmount !== rightAmount) {
1156
+ return leftAmount > rightAmount ? -1 : 1;
1157
+ }
1158
+ }
1159
+ const leftTime = parseIsoTimestamp(left.occurredAt);
1160
+ const rightTime = parseIsoTimestamp(right.occurredAt);
1161
+ if (leftTime !== rightTime) {
1162
+ return leftTime > rightTime ? -1 : 1;
1163
+ }
1164
+ return compareTextDescending(left.rowAlias, right.rowAlias);
1165
+ }
1166
+ function assertAdminTokenActivityPage(page) {
1167
+ assertExactKeys(
1168
+ page,
1169
+ ["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
1170
+ "Admin Token activity page"
1171
+ );
1172
+ assertExactKeys(
1173
+ page.metadata,
1174
+ [
1175
+ "schemaVersion",
1176
+ "generatedAt",
1177
+ "fromInclusive",
1178
+ "toExclusive",
1179
+ "sort",
1180
+ "filter",
1181
+ "pageLimit",
1182
+ "audience",
1183
+ "pseudonymVersion",
1184
+ "rawIdentifiersIncluded"
1185
+ ],
1186
+ "Admin Token activity metadata"
1187
+ );
1188
+ economyAssert(
1189
+ page.schemaVersion === ECONOMY_CONTRACT_VERSION && page.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && typeof page.hasMore === "boolean" && page.metadata.rawIdentifiersIncluded === false && ACTIVITY_SORTS.has(page.metadata.sort) && PSEUDONYM_AUDIENCES.has(page.metadata.audience) && PSEUDONYM_VERSION.test(page.metadata.pseudonymVersion) && Number.isSafeInteger(page.metadata.pageLimit) && page.metadata.pageLimit >= 1 && page.metadata.pageLimit <= ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
1190
+ "INVALID_CONTRACT",
1191
+ "Unsupported Admin Token activity result metadata"
1192
+ );
1193
+ const window = assertReportingWindow({
1194
+ fromInclusive: page.metadata.fromInclusive,
1195
+ toExclusive: page.metadata.toExclusive
1196
+ });
1197
+ if (page.metadata.filter !== void 0) {
1198
+ assertAdminTokenActivityFilter(page.metadata.filter);
1199
+ }
1200
+ parseIsoTimestamp(page.metadata.generatedAt);
1201
+ economyAssert(
1202
+ Array.isArray(page.entries) && page.entries.length <= page.metadata.pageLimit && page.hasMore === (page.nextCursor !== void 0) && (!page.hasMore || page.entries.length > 0),
1203
+ "INVALID_CONTRACT",
1204
+ "Admin Token activity page is unbounded or has inconsistent pagination"
1205
+ );
1206
+ if (page.nextCursor !== void 0) {
1207
+ assertOpaqueCursor(page.nextCursor);
1208
+ }
1209
+ const rowAliases = /* @__PURE__ */ new Set();
1210
+ let previous;
1211
+ for (const entry of page.entries) {
1212
+ assertAdminTokenActivityEntry(entry);
1213
+ const occurredAt = parseIsoTimestamp(entry.occurredAt);
1214
+ economyAssert(
1215
+ occurredAt >= window.from && occurredAt < window.to,
1216
+ "INVALID_TIME_WINDOW",
1217
+ "Admin Token activity falls outside the declared result window"
1218
+ );
1219
+ const filter = page.metadata.filter;
1220
+ economyAssert(
1221
+ filter === void 0 || (filter.activityTypes === void 0 || filter.activityTypes.includes(entry.activityType)) && (filter.statuses === void 0 || filter.statuses.includes(entry.status)) && (filter.sources === void 0 || filter.sources.includes(entry.source)) && (filter.subjectAlias === void 0 || filter.subjectAlias === entry.subjectAlias),
1222
+ "INVALID_CONTRACT",
1223
+ "Admin Token activity result contains a row outside its metadata filters"
1224
+ );
1225
+ economyAssert(
1226
+ !rowAliases.has(entry.rowAlias),
1227
+ "DUPLICATE_IDENTIFIER",
1228
+ "Admin Token activity page cannot repeat a row alias"
1229
+ );
1230
+ rowAliases.add(entry.rowAlias);
1231
+ if (previous !== void 0) {
1232
+ economyAssert(
1233
+ compareActivityEntries(previous, entry, page.metadata.sort) < 0,
1234
+ "INVALID_CONTRACT",
1235
+ "Admin Token activity page does not use its declared stable sort"
1236
+ );
1237
+ }
1238
+ previous = entry;
1239
+ }
1240
+ }
1241
+ function assertAdminTokenActivityPageForRequest(page, request) {
1242
+ assertAdminTokenActivityPageRequest(request);
1243
+ assertAdminTokenActivityPage(page);
1244
+ economyAssert(
1245
+ page.metadata.fromInclusive === request.window.fromInclusive && page.metadata.toExclusive === request.window.toExclusive && page.metadata.sort === request.sort && sameActivityFilter(page.metadata.filter, request.filter) && page.metadata.pageLimit === request.limit && page.metadata.audience === request.audience && page.metadata.pseudonymVersion === request.pseudonymVersion,
1246
+ "INVALID_CONTRACT",
1247
+ "Admin Token activity result metadata does not match its normalized request"
1248
+ );
1249
+ }
1250
+ function assertAdminTokenTrendRequest(request) {
1251
+ assertExactKeys(
1252
+ request,
1253
+ ["schemaVersion", "window", "granularity", "activityTypes"],
1254
+ "Admin Token trend request"
1255
+ );
1256
+ economyAssert(
1257
+ request.schemaVersion === ECONOMY_CONTRACT_VERSION && TREND_GRANULARITIES.has(request.granularity),
1258
+ "INVALID_CONTRACT",
1259
+ "Unsupported Admin Token trend request"
1260
+ );
1261
+ assertReportingWindow(
1262
+ request.window,
1263
+ request.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
1264
+ );
1265
+ if (request.activityTypes !== void 0) {
1266
+ assertUniqueValues(
1267
+ request.activityTypes,
1268
+ ACTIVITY_TYPES,
1269
+ "Admin Token trend activity types"
1270
+ );
1271
+ }
1272
+ }
1273
+ function medianHalfSubunits(values) {
1274
+ const ordered = [...values].sort(
1275
+ (left, right) => left === right ? 0 : left < right ? -1 : 1
1276
+ );
1277
+ const lower = ordered[Math.floor((ordered.length - 1) / 2)];
1278
+ const upper = ordered[Math.floor(ordered.length / 2)];
1279
+ economyAssert(
1280
+ lower !== void 0 && upper !== void 0,
1281
+ "INVALID_CONTRACT",
1282
+ "Median requires at least one value"
1283
+ );
1284
+ const sum = lower + upper;
1285
+ economyAssert(
1286
+ sum % 2n === 0n,
1287
+ "INVALID_AMOUNT",
1288
+ "Median cannot be represented in exact half TokenSubunits"
1289
+ );
1290
+ return sum / 2n;
1291
+ }
1292
+ function serializeExactStatistic(halfSubunits) {
1293
+ economyAssert(
1294
+ absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
1295
+ "AMOUNT_OUT_OF_RANGE",
1296
+ "Admin Token statistic exceeds its exact bounded representation"
1297
+ );
1298
+ if (halfSubunits % 2n === 0n) {
1299
+ return {
1300
+ numerator: (halfSubunits / 2n).toString(10),
1301
+ denominator: 1
1302
+ };
1303
+ }
1304
+ return {
1305
+ numerator: halfSubunits.toString(10),
1306
+ denominator: 2
1307
+ };
1308
+ }
1309
+ function parseExactStatistic(value, label) {
1310
+ assertExactKeys(value, ["numerator", "denominator"], label);
1311
+ economyAssert(
1312
+ typeof value.numerator === "string" && value.numerator.length <= 22 && EXACT_STATISTIC_INTEGER.test(value.numerator) && (value.denominator === 1 || value.denominator === 2),
1313
+ "INVALID_AMOUNT",
1314
+ `${label} must be an exact bounded rational TokenSubunit value`
1315
+ );
1316
+ const numerator = BigInt(value.numerator);
1317
+ economyAssert(
1318
+ value.denominator === 1 || numerator % 2n !== 0n,
1319
+ "INVALID_AMOUNT",
1320
+ `${label} must use a reduced exact representation`
1321
+ );
1322
+ const halfSubunits = numerator * BigInt(2 / value.denominator);
1323
+ economyAssert(
1324
+ absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
1325
+ "AMOUNT_OUT_OF_RANGE",
1326
+ `${label} exceeds its exact bounded representation`
1327
+ );
1328
+ return halfSubunits;
1329
+ }
1330
+ function classifyAnomaly(options) {
1331
+ if (options.absoluteDeltaHalfSubunits < options.minimumAbsoluteDeltaHalfSubunits) {
1332
+ return {
1333
+ status: "normal",
1334
+ explanationCode: "below-absolute-minimum"
1335
+ };
1336
+ }
1337
+ if (options.medianAbsoluteDeviationHalfSubunits === 0n) {
1338
+ return options.absoluteDeltaHalfSubunits > 0n ? {
1339
+ status: "irregular-spike",
1340
+ explanationCode: "zero-mad-absolute-threshold-exceeded"
1341
+ } : {
1342
+ status: "normal",
1343
+ explanationCode: "within-baseline-variation"
1344
+ };
1345
+ }
1346
+ const exceedsBaseline = options.absoluteDeltaHalfSubunits * 1000n >= options.medianAbsoluteDeviationHalfSubunits * BigInt(options.madMultiplierMilli);
1347
+ return exceedsBaseline ? {
1348
+ status: "irregular-spike",
1349
+ explanationCode: "median-mad-and-absolute-threshold-exceeded"
1350
+ } : {
1351
+ status: "normal",
1352
+ explanationCode: "within-baseline-variation"
1353
+ };
1354
+ }
1355
+ function createAdminTokenAnomalyIndicator(input) {
1356
+ assertExactKeys(
1357
+ input,
1358
+ [
1359
+ "observedAmount",
1360
+ "baselineSamples",
1361
+ "minimumAbsoluteDelta",
1362
+ "madMultiplierMilli"
1363
+ ],
1364
+ "Admin Token anomaly input"
1365
+ );
1366
+ economyAssert(
1367
+ Array.isArray(input.baselineSamples) && input.baselineSamples.length === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && Number.isSafeInteger(input.madMultiplierMilli) && input.madMultiplierMilli >= 1 && input.madMultiplierMilli <= 1e6,
1368
+ "INVALID_CONTRACT",
1369
+ "Admin Token anomaly input requires 28 baselines and a bounded fixed-point multiplier"
1370
+ );
1371
+ const observed = parseTokenSubunits(input.observedAmount);
1372
+ const baseline = input.baselineSamples.map((sample) => {
1373
+ assertExactKeys(
1374
+ sample,
1375
+ ["amount", "distinctSubjects"],
1376
+ "Admin Token anomaly baseline sample"
1377
+ );
1378
+ economyAssert(
1379
+ Number.isSafeInteger(sample.distinctSubjects) && sample.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
1380
+ "INVALID_CONTRACT",
1381
+ "Admin Token anomaly baselines must exclude privacy-suppressed cohorts"
1382
+ );
1383
+ return parseTokenSubunits(sample.amount);
1384
+ });
1385
+ const minimum = parseTokenSubunits(input.minimumAbsoluteDelta);
1386
+ economyAssert(
1387
+ minimum > 0n,
1388
+ "INVALID_AMOUNT",
1389
+ "Admin Token anomaly absolute minimum must be positive"
1390
+ );
1391
+ const baselineHalfSubunits = baseline.map((amount) => amount * 2n);
1392
+ const medianHalf = medianHalfSubunits(baselineHalfSubunits);
1393
+ const medianAbsoluteDeviationHalf = medianHalfSubunits(
1394
+ baselineHalfSubunits.map((amount) => absolute(amount - medianHalf))
1395
+ );
1396
+ const deviationHalf = observed * 2n - medianHalf;
1397
+ const classification = classifyAnomaly({
1398
+ absoluteDeltaHalfSubunits: absolute(deviationHalf),
1399
+ medianAbsoluteDeviationHalfSubunits: medianAbsoluteDeviationHalf,
1400
+ minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
1401
+ madMultiplierMilli: input.madMultiplierMilli
1402
+ });
1403
+ return {
1404
+ method: "same-window-median-mad-v1",
1405
+ ...classification,
1406
+ baselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
1407
+ medianAmount: serializeExactStatistic(medianHalf),
1408
+ medianAbsoluteDeviation: serializeExactStatistic(medianAbsoluteDeviationHalf),
1409
+ minimumAbsoluteDelta: input.minimumAbsoluteDelta,
1410
+ deviationFromMedian: serializeExactStatistic(deviationHalf),
1411
+ madMultiplierMilli: input.madMultiplierMilli
1412
+ };
1413
+ }
1414
+ function createAdminTokenAnomalyUnavailable(input) {
1415
+ assertExactKeys(
1416
+ input,
1417
+ ["reason", "eligibleBaselineWindowCount"],
1418
+ "Unavailable Admin Token anomaly input"
1419
+ );
1420
+ economyAssert(
1421
+ ANOMALY_UNAVAILABLE_REASONS.has(input.reason) && Number.isSafeInteger(input.eligibleBaselineWindowCount) && input.eligibleBaselineWindowCount >= 0 && input.eligibleBaselineWindowCount < ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
1422
+ "INVALID_CONTRACT",
1423
+ "Unavailable Admin Token anomaly requires a bounded reason and eligible baseline count"
1424
+ );
1425
+ return {
1426
+ method: "same-window-median-mad-v1",
1427
+ status: "unavailable",
1428
+ reason: input.reason,
1429
+ eligibleBaselineWindowCount: input.eligibleBaselineWindowCount,
1430
+ requiredBaselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS
1431
+ };
1432
+ }
1433
+ function assertAdminTokenAnomalyIndicator(anomaly, observedAmount) {
1434
+ assertExactKeys(
1435
+ anomaly,
1436
+ [
1437
+ "method",
1438
+ "status",
1439
+ "baselineWindowCount",
1440
+ "medianAmount",
1441
+ "medianAbsoluteDeviation",
1442
+ "minimumAbsoluteDelta",
1443
+ "deviationFromMedian",
1444
+ "madMultiplierMilli",
1445
+ "explanationCode"
1446
+ ],
1447
+ "Admin Token anomaly indicator"
1448
+ );
1449
+ const observed = parseTokenSubunits(observedAmount);
1450
+ const medianHalf = parseExactStatistic(
1451
+ anomaly.medianAmount,
1452
+ "Admin Token anomaly median"
1453
+ );
1454
+ const madHalf = parseExactStatistic(
1455
+ anomaly.medianAbsoluteDeviation,
1456
+ "Admin Token anomaly median absolute deviation"
1457
+ );
1458
+ const minimum = parseTokenSubunits(anomaly.minimumAbsoluteDelta);
1459
+ const deviationHalf = parseExactStatistic(
1460
+ anomaly.deviationFromMedian,
1461
+ "Admin Token anomaly deviation"
1462
+ );
1463
+ economyAssert(
1464
+ anomaly.method === "same-window-median-mad-v1" && anomaly.baselineWindowCount === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && medianHalf >= TOKEN_SUBUNITS_MIN * 2n && medianHalf <= TOKEN_SUBUNITS_MAX * 2n && madHalf >= 0n && minimum > 0n && Number.isSafeInteger(anomaly.madMultiplierMilli) && anomaly.madMultiplierMilli >= 1 && anomaly.madMultiplierMilli <= 1e6 && deviationHalf === observed * 2n - medianHalf,
1465
+ "INVALID_CONTRACT",
1466
+ "Admin Token anomaly arithmetic or method is invalid"
1467
+ );
1468
+ const expected = classifyAnomaly({
1469
+ absoluteDeltaHalfSubunits: absolute(deviationHalf),
1470
+ medianAbsoluteDeviationHalfSubunits: madHalf,
1471
+ minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
1472
+ madMultiplierMilli: anomaly.madMultiplierMilli
1473
+ });
1474
+ economyAssert(
1475
+ anomaly.status === expected.status && anomaly.explanationCode === expected.explanationCode,
1476
+ "INVALID_CONTRACT",
1477
+ "Admin Token anomaly classification is inconsistent with its explanation"
1478
+ );
1479
+ }
1480
+ function assertAdminTokenAnomalyUnavailable(anomaly) {
1481
+ assertExactKeys(
1482
+ anomaly,
1483
+ [
1484
+ "method",
1485
+ "status",
1486
+ "reason",
1487
+ "eligibleBaselineWindowCount",
1488
+ "requiredBaselineWindowCount"
1489
+ ],
1490
+ "Unavailable Admin Token anomaly"
1491
+ );
1492
+ economyAssert(
1493
+ anomaly.method === "same-window-median-mad-v1" && anomaly.status === "unavailable" && ANOMALY_UNAVAILABLE_REASONS.has(anomaly.reason) && Number.isSafeInteger(anomaly.eligibleBaselineWindowCount) && anomaly.eligibleBaselineWindowCount >= 0 && anomaly.eligibleBaselineWindowCount < ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && anomaly.requiredBaselineWindowCount === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
1494
+ "INVALID_CONTRACT",
1495
+ "Unavailable Admin Token anomaly metadata is invalid"
1496
+ );
1497
+ }
1498
+ function assertTrendBucketAlignment(start, end, granularity) {
1499
+ const expectedDuration = granularity === "hour" ? HOUR_MILLISECONDS : DAY_MILLISECONDS;
1500
+ const date = new Date(start);
1501
+ const aligned = date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0 && (granularity === "hour" || date.getUTCHours() === 0);
1502
+ economyAssert(
1503
+ aligned && end - start === expectedDuration,
1504
+ "INVALID_TIME_WINDOW",
1505
+ "Admin Token trend bucket is not aligned to its declared granularity"
1506
+ );
1507
+ }
1508
+ function assertTrendAggregate(aggregate) {
1509
+ assertPlainObject(aggregate, "Admin Token trend aggregate");
1510
+ if (aggregate.visibility === "suppressed") {
1511
+ assertExactKeys(
1512
+ aggregate,
1513
+ ["visibility", "reason", "threshold"],
1514
+ "Suppressed Admin Token trend aggregate"
1515
+ );
1516
+ economyAssert(
1517
+ aggregate.reason === "cohort-below-minimum" && aggregate.threshold === ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
1518
+ "INVALID_CONTRACT",
1519
+ "Suppressed Admin Token trend aggregate has invalid privacy metadata"
1520
+ );
1521
+ return;
1522
+ }
1523
+ assertExactKeys(
1524
+ aggregate,
1525
+ [
1526
+ "visibility",
1527
+ "distinctSubjects",
1528
+ "activityCount",
1529
+ "signedAmount"
1530
+ ],
1531
+ "Reported Admin Token trend aggregate"
1532
+ );
1533
+ parseTokenSubunits(aggregate.signedAmount);
1534
+ economyAssert(
1535
+ aggregate.visibility === "reported" && Number.isSafeInteger(aggregate.distinctSubjects) && aggregate.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE && Number.isSafeInteger(aggregate.activityCount) && aggregate.activityCount >= aggregate.distinctSubjects,
1536
+ "INVALID_CONTRACT",
1537
+ "Reported Admin Token trend aggregate is invalid or below the privacy threshold"
1538
+ );
1539
+ }
1540
+ function assertAdminTokenTrendResult(result) {
1541
+ assertExactKeys(
1542
+ result,
1543
+ ["schemaVersion", "series", "metadata"],
1544
+ "Admin Token trend result"
1545
+ );
1546
+ assertExactKeys(
1547
+ result.metadata,
1548
+ [
1549
+ "schemaVersion",
1550
+ "generatedAt",
1551
+ "fromInclusive",
1552
+ "toExclusive",
1553
+ "granularity",
1554
+ "activityTypes",
1555
+ "minimumCohortSize",
1556
+ "anomalyBaselineDays",
1557
+ "rawIdentifiersIncluded"
1558
+ ],
1559
+ "Admin Token trend metadata"
1560
+ );
1561
+ economyAssert(
1562
+ result.schemaVersion === ECONOMY_CONTRACT_VERSION && result.metadata.schemaVersion === ECONOMY_CONTRACT_VERSION && TREND_GRANULARITIES.has(result.metadata.granularity) && result.metadata.minimumCohortSize === ADMIN_TOKEN_MINIMUM_COHORT_SIZE && result.metadata.anomalyBaselineDays === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && result.metadata.rawIdentifiersIncluded === false && Array.isArray(result.series) && result.series.length <= ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
1563
+ "INVALID_CONTRACT",
1564
+ "Unsupported or unbounded Admin Token trend result"
1565
+ );
1566
+ assertUniqueValues(
1567
+ result.metadata.activityTypes,
1568
+ ACTIVITY_TYPES,
1569
+ "Admin Token trend result activity types"
1570
+ );
1571
+ const window = assertReportingWindow(
1572
+ {
1573
+ fromInclusive: result.metadata.fromInclusive,
1574
+ toExclusive: result.metadata.toExclusive
1575
+ },
1576
+ result.metadata.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
1577
+ );
1578
+ parseIsoTimestamp(result.metadata.generatedAt);
1579
+ const pointKeys = /* @__PURE__ */ new Set();
1580
+ let previousKey;
1581
+ for (const point of result.series) {
1582
+ assertExactKeys(
1583
+ point,
1584
+ [
1585
+ "schemaVersion",
1586
+ "bucketStart",
1587
+ "bucketEnd",
1588
+ "activityType",
1589
+ "aggregate",
1590
+ "anomaly"
1591
+ ],
1592
+ "Admin Token trend point"
1593
+ );
1594
+ economyAssert(
1595
+ point.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(point.activityType) && result.metadata.activityTypes.includes(point.activityType),
1596
+ "INVALID_CONTRACT",
1597
+ "Unsupported Admin Token trend point"
1598
+ );
1599
+ const start = parseIsoTimestamp(point.bucketStart);
1600
+ const end = parseIsoTimestamp(point.bucketEnd);
1601
+ economyAssert(
1602
+ start >= window.from && end <= window.to,
1603
+ "INVALID_TIME_WINDOW",
1604
+ "Admin Token trend bucket falls outside the declared result window"
1605
+ );
1606
+ assertTrendBucketAlignment(start, end, result.metadata.granularity);
1607
+ assertTrendAggregate(point.aggregate);
1608
+ if (point.aggregate.visibility === "suppressed") {
1609
+ economyAssert(
1610
+ point.anomaly === void 0,
1611
+ "INVALID_CONTRACT",
1612
+ "Suppressed Admin Token cohorts cannot include anomaly details"
1613
+ );
1614
+ } else {
1615
+ economyAssert(
1616
+ point.anomaly !== void 0,
1617
+ "INVALID_CONTRACT",
1618
+ "Reported Admin Token cohorts require an anomaly result"
1619
+ );
1620
+ if (point.anomaly.status === "unavailable") {
1621
+ assertAdminTokenAnomalyUnavailable(point.anomaly);
1622
+ } else {
1623
+ assertAdminTokenAnomalyIndicator(
1624
+ point.anomaly,
1625
+ point.aggregate.signedAmount
1626
+ );
1627
+ }
1628
+ }
1629
+ const key = `${point.bucketStart}\0${point.activityType}`;
1630
+ economyAssert(
1631
+ !pointKeys.has(key) && (previousKey === void 0 || previousKey < key),
1632
+ "DUPLICATE_IDENTIFIER",
1633
+ "Admin Token trend points must be unique and stably ordered"
1634
+ );
1635
+ pointKeys.add(key);
1636
+ previousKey = key;
1637
+ }
1638
+ }
1639
+ function assertAdminTokenTrendResultForRequest(result, request) {
1640
+ assertAdminTokenTrendRequest(request);
1641
+ assertAdminTokenTrendResult(result);
1642
+ const requestedActivityTypes = request.activityTypes ?? [...ACTIVITY_TYPES];
1643
+ economyAssert(
1644
+ result.metadata.fromInclusive === request.window.fromInclusive && result.metadata.toExclusive === request.window.toExclusive && result.metadata.granularity === request.granularity && sameOptionalValues(
1645
+ result.metadata.activityTypes,
1646
+ requestedActivityTypes
1647
+ ),
1648
+ "INVALID_CONTRACT",
1649
+ "Admin Token trend result metadata does not match its normalized request"
1650
+ );
1651
+ }
1652
+
504
1653
  // src/allocations.ts
505
1654
  function assertWholePositive(amount, label) {
506
1655
  const parsed = parseTokenSubunits(amount);
@@ -837,7 +1986,7 @@ var COMMAND_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
837
1986
  "acceptedRegion",
838
1987
  "writerFencingToken"
839
1988
  ]);
840
- function assertExactKeys(value, allowedKeys, label) {
1989
+ function assertExactKeys2(value, allowedKeys, label) {
841
1990
  economyAssert(
842
1991
  value !== null && typeof value === "object" && !Array.isArray(value),
843
1992
  "INVALID_CONTRACT",
@@ -881,7 +2030,7 @@ function assertRelationshipContext(relationshipId, authorizationVersion) {
881
2030
  );
882
2031
  }
883
2032
  function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
884
- assertExactKeys(
2033
+ assertExactKeys2(
885
2034
  fingerprint,
886
2035
  /* @__PURE__ */ new Set([
887
2036
  "schemaVersion",
@@ -906,7 +2055,7 @@ function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
906
2055
  );
907
2056
  }
908
2057
  function assertEconomyAuthorizationEvidence(evidence) {
909
- assertExactKeys(
2058
+ assertExactKeys2(
910
2059
  evidence,
911
2060
  /* @__PURE__ */ new Set([
912
2061
  "schemaVersion",
@@ -943,7 +2092,7 @@ function assertEconomyAuthorizationEvidence(evidence) {
943
2092
  );
944
2093
  }
945
2094
  function assertCausationReference(causation) {
946
- assertExactKeys(
2095
+ assertExactKeys2(
947
2096
  causation,
948
2097
  /* @__PURE__ */ new Set(["schemaVersion", "kind", "causationId"]),
949
2098
  "Economy causation reference"
@@ -998,7 +2147,7 @@ function assertCommandSourcePrincipal(envelope) {
998
2147
  }
999
2148
  }
1000
2149
  function assertAuditedEconomyCommandEnvelope(envelope) {
1001
- assertExactKeys(
2150
+ assertExactKeys2(
1002
2151
  envelope,
1003
2152
  COMMAND_ENVELOPE_KEYS,
1004
2153
  "Audited economy command envelope"
@@ -1064,7 +2213,7 @@ function assertAuditedEconomyCommandEnvelope(envelope) {
1064
2213
  );
1065
2214
  }
1066
2215
  function assertEconomyProviderEvidenceHash(evidence) {
1067
- assertExactKeys(
2216
+ assertExactKeys2(
1068
2217
  evidence,
1069
2218
  /* @__PURE__ */ new Set([
1070
2219
  "schemaVersion",
@@ -1135,7 +2284,7 @@ function assertEconomyProviderEvidenceHash(evidence) {
1135
2284
  }
1136
2285
  }
1137
2286
  function assertEconomyEncryptedOperationalHandleBinding(binding) {
1138
- assertExactKeys(
2287
+ assertExactKeys2(
1139
2288
  binding,
1140
2289
  /* @__PURE__ */ new Set([
1141
2290
  "schemaVersion",
@@ -1170,7 +2319,7 @@ function assertEconomyEncryptedOperationalHandleBinding(binding) {
1170
2319
  parseIsoTimestamp(binding.createdAt);
1171
2320
  }
1172
2321
  function assertEvidenceRecordReference(reference) {
1173
- assertExactKeys(
2322
+ assertExactKeys2(
1174
2323
  reference,
1175
2324
  /* @__PURE__ */ new Set(["schemaVersion", "recordId", "contentHash"]),
1176
2325
  "Evidence record reference"
@@ -1201,7 +2350,7 @@ function assertUniqueSortedReferences(references, label) {
1201
2350
  }
1202
2351
  }
1203
2352
  function assertEconomyProviderEvidenceManifest(manifest) {
1204
- assertExactKeys(
2353
+ assertExactKeys2(
1205
2354
  manifest,
1206
2355
  /* @__PURE__ */ new Set([
1207
2356
  "schemaVersion",
@@ -1243,7 +2392,7 @@ function assertEconomyProviderEvidenceManifest(manifest) {
1243
2392
  parseIsoTimestamp(manifest.createdAt);
1244
2393
  }
1245
2394
  function assertEconomyAcceptedCommandReceipt(receipt) {
1246
- assertExactKeys(
2395
+ assertExactKeys2(
1247
2396
  receipt,
1248
2397
  /* @__PURE__ */ new Set([
1249
2398
  "schemaVersion",
@@ -1267,7 +2416,7 @@ function assertEconomyAcceptedCommandReceipt(receipt) {
1267
2416
  parseIsoTimestamp(receipt.acceptedAt);
1268
2417
  }
1269
2418
  function assertEconomyCommandResultReceipt(receipt) {
1270
- assertExactKeys(
2419
+ assertExactKeys2(
1271
2420
  receipt,
1272
2421
  /* @__PURE__ */ new Set([
1273
2422
  "schemaVersion",
@@ -1324,7 +2473,7 @@ function assertEconomyCommandResultReceipt(receipt) {
1324
2473
  }
1325
2474
  }
1326
2475
  function assertEconomyAuditedIdempotencyScope(scope) {
1327
- assertExactKeys(
2476
+ assertExactKeys2(
1328
2477
  scope,
1329
2478
  /* @__PURE__ */ new Set([
1330
2479
  "schemaVersion",
@@ -1355,7 +2504,7 @@ function assertEconomyAuditedIdempotencyScope(scope) {
1355
2504
  );
1356
2505
  }
1357
2506
  function assertEconomyAuditedIdempotencyResult(result) {
1358
- assertExactKeys(
2507
+ assertExactKeys2(
1359
2508
  result,
1360
2509
  /* @__PURE__ */ new Set([
1361
2510
  "schemaVersion",
@@ -1646,7 +2795,7 @@ var MANIFEST_KEYS = /* @__PURE__ */ new Set([
1646
2795
  "recordReferences",
1647
2796
  "committedAt"
1648
2797
  ]);
1649
- function assertExactKeys2(value, allowedKeys, label) {
2798
+ function assertExactKeys3(value, allowedKeys, label) {
1650
2799
  economyAssert(
1651
2800
  value !== null && typeof value === "object" && !Array.isArray(value),
1652
2801
  "INVALID_CONTRACT",
@@ -1684,7 +2833,7 @@ function referenceOrder(left, right) {
1684
2833
  return byKind === 0 ? compareUnicodeCodeUnits(left.recordId, right.recordId) : byKind;
1685
2834
  }
1686
2835
  function assertEconomyAuthorityRecordReference(reference) {
1687
- assertExactKeys2(
2836
+ assertExactKeys3(
1688
2837
  reference,
1689
2838
  /* @__PURE__ */ new Set([
1690
2839
  "schemaVersion",
@@ -1848,7 +2997,7 @@ function assertCommitAllowedInState(manifest) {
1848
2997
  }
1849
2998
  }
1850
2999
  function assertEconomyAuthorityCommitManifest(manifest) {
1851
- assertExactKeys2(manifest, MANIFEST_KEYS, "Authority commit manifest");
3000
+ assertExactKeys3(manifest, MANIFEST_KEYS, "Authority commit manifest");
1852
3001
  economyAssert(
1853
3002
  manifest.schemaVersion === ECONOMY_CONTRACT_VERSION && COMMIT_KINDS.has(manifest.commitKind) && AUTHORITY_STATES.has(manifest.authorityStateBefore) && AUTHORITY_STATES.has(manifest.authorityStateAfter),
1854
3003
  "INVALID_CONTRACT",
@@ -1895,7 +3044,7 @@ function assertEconomyAuthorityCommitManifest(manifest) {
1895
3044
  parseIsoTimestamp(manifest.committedAt);
1896
3045
  }
1897
3046
  function assertEconomyAuthorityHead(head) {
1898
- assertExactKeys2(head, HEAD_KEYS, "Economy authority head");
3047
+ assertExactKeys3(head, HEAD_KEYS, "Economy authority head");
1899
3048
  economyAssert(
1900
3049
  head.schemaVersion === ECONOMY_CONTRACT_VERSION && AUTHORITY_STATES.has(head.state),
1901
3050
  "INVALID_CONTRACT",
@@ -1954,7 +3103,7 @@ function advanceEconomyAuthorityHead(head, manifest, manifestCanonicalHash) {
1954
3103
  };
1955
3104
  }
1956
3105
  function assertEconomyIntegrityVerificationReceipt(receipt) {
1957
- assertExactKeys2(
3106
+ assertExactKeys3(
1958
3107
  receipt,
1959
3108
  /* @__PURE__ */ new Set([
1960
3109
  "schemaVersion",
@@ -2100,7 +3249,7 @@ function assertEconomyIntegrityVerificationReceipt(receipt) {
2100
3249
  parseIsoTimestamp(receipt.verifiedAt);
2101
3250
  }
2102
3251
  function assertEconomyIntegrityAnchorManifest(manifest) {
2103
- assertExactKeys2(
3252
+ assertExactKeys3(
2104
3253
  manifest,
2105
3254
  /* @__PURE__ */ new Set([
2106
3255
  "schemaVersion",
@@ -2262,7 +3411,7 @@ function sortEconomyAuthorityRecordReferences(references) {
2262
3411
  }
2263
3412
 
2264
3413
  // src/ledger.ts
2265
- var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
3414
+ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
2266
3415
  "purchase",
2267
3416
  "subscription",
2268
3417
  "rewarded-ad",
@@ -2279,14 +3428,14 @@ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
2279
3428
  "event",
2280
3429
  "competition"
2281
3430
  ]);
2282
- var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
3431
+ var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
2283
3432
  "pending",
2284
3433
  "held",
2285
3434
  "settled",
2286
3435
  "reversed",
2287
3436
  "failed"
2288
3437
  ]);
2289
- var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
3438
+ var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
2290
3439
  "shopify",
2291
3440
  "ayet",
2292
3441
  "bitlabs",
@@ -2316,7 +3465,7 @@ function assertActivityEntry(entry) {
2316
3465
  );
2317
3466
  assertEconomyIdentifier(entry.transactionId, "transactionId");
2318
3467
  economyAssert(
2319
- ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
3468
+ ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
2320
3469
  "INVALID_CONTRACT",
2321
3470
  "Activity type, status, or source is unsupported"
2322
3471
  );
@@ -2354,7 +3503,7 @@ function assertBalancedTransaction(transaction) {
2354
3503
  assertEconomyIdentifier(transaction.transactionId, "transactionId");
2355
3504
  assertEconomyIdentifier(transaction.idempotencyKey, "idempotencyKey");
2356
3505
  economyAssert(
2357
- ACTIVITY_TYPES.has(transaction.activityType) && ACTIVITY_STATUSES.has(transaction.status),
3506
+ ACTIVITY_TYPES2.has(transaction.activityType) && ACTIVITY_STATUSES2.has(transaction.status),
2358
3507
  "INVALID_CONTRACT",
2359
3508
  "Transaction activity type or status is unsupported"
2360
3509
  );
@@ -4393,7 +5542,7 @@ var DECISIONS = /* @__PURE__ */ new Set([
4393
5542
  "approve",
4394
5543
  "reject"
4395
5544
  ]);
4396
- function assertExactKeys3(value, allowed, label) {
5545
+ function assertExactKeys4(value, allowed, label) {
4397
5546
  economyAssert(
4398
5547
  value !== null && typeof value === "object" && !Array.isArray(value),
4399
5548
  "INVALID_CONTRACT",
@@ -4420,7 +5569,7 @@ function assertReasonCode(reasonCode) {
4420
5569
  );
4421
5570
  }
4422
5571
  function assertOperatorAdjustmentPreview(preview) {
4423
- assertExactKeys3(preview, PREVIEW_KEYS, "Operator adjustment preview");
5572
+ assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
4424
5573
  economyAssert(
4425
5574
  preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
4426
5575
  "INVALID_CONTRACT",
@@ -4499,7 +5648,7 @@ function canonicalOperatorAdjustmentPreviewPayload(preview) {
4499
5648
  function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
4500
5649
  assertOperatorAdjustmentPreview(preview);
4501
5650
  assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
4502
- assertExactKeys3(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5651
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
4503
5652
  economyAssert(
4504
5653
  proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
4505
5654
  "INVALID_CONTRACT",
@@ -4526,7 +5675,7 @@ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash
4526
5675
  );
4527
5676
  }
4528
5677
  function canonicalOperatorAdjustmentProposalPayload(proposal) {
4529
- assertExactKeys3(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5678
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
4530
5679
  return JSON.stringify({
4531
5680
  schemaVersion: proposal.schemaVersion,
4532
5681
  proposalId: proposal.proposalId,
@@ -4541,7 +5690,7 @@ function canonicalOperatorAdjustmentProposalPayload(proposal) {
4541
5690
  function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
4542
5691
  assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
4543
5692
  assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
4544
- assertExactKeys3(decision, DECISION_KEYS, "Operator adjustment decision");
5693
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
4545
5694
  economyAssert(
4546
5695
  decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
4547
5696
  "INVALID_CONTRACT",
@@ -4584,7 +5733,7 @@ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedP
4584
5733
  );
4585
5734
  }
4586
5735
  function canonicalOperatorAdjustmentDecisionPayload(decision) {
4587
- assertExactKeys3(decision, DECISION_KEYS, "Operator adjustment decision");
5736
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
4588
5737
  return JSON.stringify({
4589
5738
  schemaVersion: decision.schemaVersion,
4590
5739
  decisionId: decision.decisionId,
@@ -4608,7 +5757,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
4608
5757
  expectedProposalHash
4609
5758
  );
4610
5759
  assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
4611
- assertExactKeys3(execution, EXECUTION_KEYS, "Operator adjustment execution");
5760
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
4612
5761
  economyAssert(
4613
5762
  execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
4614
5763
  "INVALID_CONTRACT",
@@ -4639,7 +5788,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
4639
5788
  );
4640
5789
  }
4641
5790
  function canonicalOperatorAdjustmentExecutionPayload(execution) {
4642
- assertExactKeys3(execution, EXECUTION_KEYS, "Operator adjustment execution");
5791
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
4643
5792
  return JSON.stringify({
4644
5793
  schemaVersion: execution.schemaVersion,
4645
5794
  executionId: execution.executionId,
@@ -5684,7 +6833,7 @@ function createProjectionSnapshot(transactions, rebuiltAt) {
5684
6833
  }
5685
6834
 
5686
6835
  // src/ports/query.ts
5687
- var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
6836
+ var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
5688
6837
  "purchase",
5689
6838
  "subscription",
5690
6839
  "rewarded-ad",
@@ -5701,14 +6850,14 @@ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
5701
6850
  "event",
5702
6851
  "competition"
5703
6852
  ]);
5704
- var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
6853
+ var ACTIVITY_STATUSES3 = /* @__PURE__ */ new Set([
5705
6854
  "pending",
5706
6855
  "held",
5707
6856
  "settled",
5708
6857
  "reversed",
5709
6858
  "failed"
5710
6859
  ]);
5711
- var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
6860
+ var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
5712
6861
  "shopify",
5713
6862
  "ayet",
5714
6863
  "bitlabs",
@@ -5736,14 +6885,14 @@ function assertSafeDisplayString(value, label) {
5736
6885
  `${label} must be bounded and safe for display`
5737
6886
  );
5738
6887
  }
5739
- function assertOpaqueCursor(value) {
6888
+ function assertOpaqueCursor2(value) {
5740
6889
  economyAssert(
5741
6890
  typeof value === "string" && value.length > 0 && value.length <= 512 && !hasControlCharacters2(value),
5742
6891
  "INVALID_CONTRACT",
5743
6892
  "Activity cursor must be a bounded opaque value"
5744
6893
  );
5745
6894
  }
5746
- function assertUniqueValues(values, allowed, label) {
6895
+ function assertUniqueValues2(values, allowed, label) {
5747
6896
  const unique = new Set(values);
5748
6897
  economyAssert(
5749
6898
  values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
@@ -6006,7 +7155,7 @@ function assertWalletActivityEntry(entry) {
6006
7155
  assertEconomyIdentifier(entry.activityId, "activityId");
6007
7156
  assertEconomyIdentifier(entry.walletId, "walletId");
6008
7157
  economyAssert(
6009
- ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
7158
+ ACTIVITY_TYPES3.has(entry.activityType) && ACTIVITY_STATUSES3.has(entry.status) && ACTIVITY_SOURCES3.has(entry.source),
6010
7159
  "INVALID_CONTRACT",
6011
7160
  "Wallet activity type, status, or source is unsupported"
6012
7161
  );
@@ -6054,20 +7203,20 @@ function assertWalletActivityPageRequest(request) {
6054
7203
  "Activity page limit must be between one and 100"
6055
7204
  );
6056
7205
  if (request.cursor !== void 0) {
6057
- assertOpaqueCursor(request.cursor);
7206
+ assertOpaqueCursor2(request.cursor);
6058
7207
  }
6059
7208
  const filter = request.filter;
6060
7209
  if (filter === void 0) {
6061
7210
  return;
6062
7211
  }
6063
7212
  if (filter.activityTypes !== void 0) {
6064
- assertUniqueValues(filter.activityTypes, ACTIVITY_TYPES2, "Activity types");
7213
+ assertUniqueValues2(filter.activityTypes, ACTIVITY_TYPES3, "Activity types");
6065
7214
  }
6066
7215
  if (filter.statuses !== void 0) {
6067
- assertUniqueValues(filter.statuses, ACTIVITY_STATUSES2, "Activity statuses");
7216
+ assertUniqueValues2(filter.statuses, ACTIVITY_STATUSES3, "Activity statuses");
6068
7217
  }
6069
7218
  if (filter.sources !== void 0) {
6070
- assertUniqueValues(filter.sources, ACTIVITY_SOURCES2, "Activity sources");
7219
+ assertUniqueValues2(filter.sources, ACTIVITY_SOURCES3, "Activity sources");
6071
7220
  }
6072
7221
  if (filter.beneficiaryAccountId !== void 0) {
6073
7222
  assertEconomyIdentifier(
@@ -6100,7 +7249,7 @@ function assertWalletActivityPage(page) {
6100
7249
  "Activity pages are bounded and cannot advertise more rows from an empty page"
6101
7250
  );
6102
7251
  if (page.nextCursor !== void 0) {
6103
- assertOpaqueCursor(page.nextCursor);
7252
+ assertOpaqueCursor2(page.nextCursor);
6104
7253
  }
6105
7254
  const activityIds = /* @__PURE__ */ new Set();
6106
7255
  let previous;
@@ -7082,7 +8231,7 @@ var RESULT_OUTCOMES = /* @__PURE__ */ new Set([
7082
8231
  "failed",
7083
8232
  "no-op"
7084
8233
  ]);
7085
- var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
8234
+ var ACTIVITY_TYPES4 = /* @__PURE__ */ new Set([
7086
8235
  "purchase",
7087
8236
  "subscription",
7088
8237
  "rewarded-ad",
@@ -7194,7 +8343,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
7194
8343
  "signature",
7195
8344
  ...PORTABLE_BODY_KEYS
7196
8345
  ]);
7197
- function assertExactKeys4(value, allowedKeys, label) {
8346
+ function assertExactKeys5(value, allowedKeys, label) {
7198
8347
  economyAssert(
7199
8348
  value !== null && typeof value === "object" && !Array.isArray(value),
7200
8349
  "INVALID_CONTRACT",
@@ -7283,7 +8432,7 @@ function canonicalSignatureMetadata(signature) {
7283
8432
  };
7284
8433
  }
7285
8434
  function assertEconomySealedRecoveryPayload(payload) {
7286
- assertExactKeys4(
8435
+ assertExactKeys5(
7287
8436
  payload,
7288
8437
  /* @__PURE__ */ new Set([
7289
8438
  "schemaVersion",
@@ -7323,7 +8472,7 @@ function assertEconomySealedRecoveryPayload(payload) {
7323
8472
  );
7324
8473
  }
7325
8474
  function assertAcceptanceBody(body) {
7326
- assertExactKeys4(
8475
+ assertExactKeys5(
7327
8476
  body,
7328
8477
  "acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
7329
8478
  "Recovery acceptance body"
@@ -7392,7 +8541,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
7392
8541
  };
7393
8542
  }
7394
8543
  function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
7395
- assertExactKeys4(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
8544
+ assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
7396
8545
  assertAcceptanceBody(envelope);
7397
8546
  assertEconomyIdentifier(
7398
8547
  envelope.acceptanceEnvelopeId,
@@ -7433,7 +8582,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
7433
8582
  });
7434
8583
  }
7435
8584
  function assertCommittedResultBody(body) {
7436
- assertExactKeys4(
8585
+ assertExactKeys5(
7437
8586
  body,
7438
8587
  "committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
7439
8588
  "Recovery committed-result body"
@@ -7527,7 +8676,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
7527
8676
  };
7528
8677
  }
7529
8678
  function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
7530
- assertExactKeys4(
8679
+ assertExactKeys5(
7531
8680
  result,
7532
8681
  COMMITTED_RESULT_KEYS,
7533
8682
  "Recovery committed result"
@@ -7586,7 +8735,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
7586
8735
  );
7587
8736
  }
7588
8737
  function assertEconomyEvidenceSignatureMetadata(signature) {
7589
- assertExactKeys4(
8738
+ assertExactKeys5(
7590
8739
  signature,
7591
8740
  /* @__PURE__ */ new Set([
7592
8741
  "schemaVersion",
@@ -7606,7 +8755,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
7606
8755
  parseIsoTimestamp(signature.signedAt);
7607
8756
  }
7608
8757
  function assertEconomyEvidenceSignature(signature) {
7609
- assertExactKeys4(
8758
+ assertExactKeys5(
7610
8759
  signature,
7611
8760
  /* @__PURE__ */ new Set([
7612
8761
  "schemaVersion",
@@ -7628,7 +8777,7 @@ function assertEconomyEvidenceSignature(signature) {
7628
8777
  assertBase64url(signature.value, "Evidence signature value", 32, 2048);
7629
8778
  }
7630
8779
  function assertRegionalEvidenceBody(body) {
7631
- assertExactKeys4(
8780
+ assertExactKeys5(
7632
8781
  body,
7633
8782
  "evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
7634
8783
  "Regional evidence-receipt body"
@@ -7720,7 +8869,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
7720
8869
  };
7721
8870
  }
7722
8871
  function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
7723
- assertExactKeys4(receipt, REGIONAL_KEYS, "Regional evidence receipt");
8872
+ assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
7724
8873
  assertRegionalEvidenceBody(receipt);
7725
8874
  assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
7726
8875
  assertEconomyEvidenceSignature(receipt.signature);
@@ -7922,7 +9071,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
7922
9071
  );
7923
9072
  }
7924
9073
  function assertEconomyMerkleInclusionProof(proof) {
7925
- assertExactKeys4(
9074
+ assertExactKeys5(
7926
9075
  proof,
7927
9076
  /* @__PURE__ */ new Set([
7928
9077
  "schemaVersion",
@@ -7953,7 +9102,7 @@ function assertEconomyMerkleInclusionProof(proof) {
7953
9102
  "Merkle leaf position is outside its bounded tree"
7954
9103
  );
7955
9104
  for (const step of proof.siblings) {
7956
- assertExactKeys4(
9105
+ assertExactKeys5(
7957
9106
  step,
7958
9107
  /* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
7959
9108
  "Merkle proof step"
@@ -8042,7 +9191,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
8042
9191
  );
8043
9192
  }
8044
9193
  function assertPortableEvidenceReference(reference) {
8045
- assertExactKeys4(
9194
+ assertExactKeys5(
8046
9195
  reference,
8047
9196
  /* @__PURE__ */ new Set([
8048
9197
  "schemaVersion",
@@ -8079,7 +9228,7 @@ function canonicalPortableEvidenceReference(reference) {
8079
9228
  };
8080
9229
  }
8081
9230
  function assertPortableBody(body) {
8082
- assertExactKeys4(
9231
+ assertExactKeys5(
8083
9232
  body,
8084
9233
  "portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
8085
9234
  "Portable customer-receipt body"
@@ -8103,7 +9252,7 @@ function assertPortableBody(body) {
8103
9252
  assertEconomyIdentifier(value, label);
8104
9253
  }
8105
9254
  economyAssert(
8106
- ACTIVITY_TYPES3.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
9255
+ ACTIVITY_TYPES4.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
8107
9256
  "INVALID_CONTRACT",
8108
9257
  "Portable customer receipt has an unsupported activity or direction"
8109
9258
  );
@@ -8203,7 +9352,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
8203
9352
  };
8204
9353
  }
8205
9354
  function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
8206
- assertExactKeys4(receipt, PORTABLE_KEYS, "Portable customer receipt");
9355
+ assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
8207
9356
  assertPortableBody(receipt);
8208
9357
  assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
8209
9358
  assertEconomyEvidenceSignature(receipt.signature);
@@ -8503,7 +9652,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
8503
9652
  "lifetimeProjectionId",
8504
9653
  "outboxEventId"
8505
9654
  ]);
8506
- function assertExactKeys5(value, allowed, label) {
9655
+ function assertExactKeys6(value, allowed, label) {
8507
9656
  economyAssert(
8508
9657
  value !== null && typeof value === "object" && !Array.isArray(value),
8509
9658
  "INVALID_CONTRACT",
@@ -8543,7 +9692,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
8543
9692
  };
8544
9693
  }
8545
9694
  function assertPersonalWalletInitializationCommand(command) {
8546
- assertExactKeys5(command, COMMAND_KEYS, "Wallet initialization command");
9695
+ assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
8547
9696
  economyAssert(
8548
9697
  command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
8549
9698
  "INVALID_CONTRACT",
@@ -8567,7 +9716,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
8567
9716
  });
8568
9717
  }
8569
9718
  function assertPersonalWalletInitializationOutboxIntent(intent) {
8570
- assertExactKeys5(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
9719
+ assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
8571
9720
  economyAssert(
8572
9721
  intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
8573
9722
  "INVALID_CONTRACT",
@@ -8667,8 +9816,8 @@ function createPersonalWalletInitializationState(input, hash) {
8667
9816
  return state;
8668
9817
  }
8669
9818
  function assertPersonalWalletInitializationState(state) {
8670
- assertExactKeys5(state, STATE_KEYS, "Wallet initialization state");
8671
- assertExactKeys5(
9819
+ assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
9820
+ assertExactKeys6(
8672
9821
  state.documentIds,
8673
9822
  DOCUMENT_ID_KEYS,
8674
9823
  "Wallet initialization document IDs"
@@ -8699,6 +9848,13 @@ function assertPersonalWalletInitializationState(state) {
8699
9848
  );
8700
9849
  }
8701
9850
  export {
9851
+ ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
9852
+ ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
9853
+ ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
9854
+ ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
9855
+ ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
9856
+ ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
9857
+ ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
8702
9858
  BASELINE_GBP_CATALOG_VERSION,
8703
9859
  BASELINE_GBP_REFERENCE_RATE,
8704
9860
  BASELINE_GBP_TOKEN_PACKS,
@@ -8726,6 +9882,19 @@ export {
8726
9882
  applyWalletBalanceDelta,
8727
9883
  applyWalletLifetimeDeltas,
8728
9884
  assertActivityEntry,
9885
+ assertAdminTokenActivityCursorBinding,
9886
+ assertAdminTokenActivityEntry,
9887
+ assertAdminTokenActivityPage,
9888
+ assertAdminTokenActivityPageForRequest,
9889
+ assertAdminTokenActivityPageRequest,
9890
+ assertAdminTokenEconomySummary,
9891
+ assertAdminTokenTrendRequest,
9892
+ assertAdminTokenTrendResult,
9893
+ assertAdminTokenTrendResultForRequest,
9894
+ assertAdminTokenWalletBalanceCursorBinding,
9895
+ assertAdminTokenWalletBalancePage,
9896
+ assertAdminTokenWalletBalancePageForRequest,
9897
+ assertAdminTokenWalletBalancePageRequest,
8729
9898
  assertAuditedEconomyCommandEnvelope,
8730
9899
  assertBalancedTransaction,
8731
9900
  assertDeterministicWalletBalanceSummary,
@@ -8855,6 +10024,9 @@ export {
8855
10024
  canonicalTransactionPayload,
8856
10025
  closeModuleAllowance,
8857
10026
  convertRewardPayout,
10027
+ createAdminTokenAnomalyIndicator,
10028
+ createAdminTokenAnomalyUnavailable,
10029
+ createDefaultAdminTokenReportingWindow,
8858
10030
  createEarlyBackerRetentionFromPaidLot,
8859
10031
  createEconomyPortableCustomerReceipt,
8860
10032
  createEconomyRecoveryAcceptanceEnvelope,