@plasius/economy 0.7.0 → 0.9.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.cjs CHANGED
@@ -20,6 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ADMIN_TOKEN_ANOMALY_BASELINE_DAYS: () => ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
24
+ ADMIN_TOKEN_DEFAULT_WINDOW_DAYS: () => ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
25
+ ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS: () => ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
26
+ ADMIN_TOKEN_MAXIMUM_PAGE_SIZE: () => ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
27
+ ADMIN_TOKEN_MAXIMUM_TREND_POINTS: () => ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
28
+ ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS: () => ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
29
+ ADMIN_TOKEN_MINIMUM_COHORT_SIZE: () => ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
23
30
  BASELINE_GBP_CATALOG_VERSION: () => BASELINE_GBP_CATALOG_VERSION,
24
31
  BASELINE_GBP_REFERENCE_RATE: () => BASELINE_GBP_REFERENCE_RATE,
25
32
  BASELINE_GBP_TOKEN_PACKS: () => BASELINE_GBP_TOKEN_PACKS,
@@ -47,6 +54,19 @@ __export(index_exports, {
47
54
  applyWalletBalanceDelta: () => applyWalletBalanceDelta,
48
55
  applyWalletLifetimeDeltas: () => applyWalletLifetimeDeltas,
49
56
  assertActivityEntry: () => assertActivityEntry,
57
+ assertAdminTokenActivityCursorBinding: () => assertAdminTokenActivityCursorBinding,
58
+ assertAdminTokenActivityEntry: () => assertAdminTokenActivityEntry,
59
+ assertAdminTokenActivityPage: () => assertAdminTokenActivityPage,
60
+ assertAdminTokenActivityPageForRequest: () => assertAdminTokenActivityPageForRequest,
61
+ assertAdminTokenActivityPageRequest: () => assertAdminTokenActivityPageRequest,
62
+ assertAdminTokenEconomySummary: () => assertAdminTokenEconomySummary,
63
+ assertAdminTokenTrendRequest: () => assertAdminTokenTrendRequest,
64
+ assertAdminTokenTrendResult: () => assertAdminTokenTrendResult,
65
+ assertAdminTokenTrendResultForRequest: () => assertAdminTokenTrendResultForRequest,
66
+ assertAdminTokenWalletBalanceCursorBinding: () => assertAdminTokenWalletBalanceCursorBinding,
67
+ assertAdminTokenWalletBalancePage: () => assertAdminTokenWalletBalancePage,
68
+ assertAdminTokenWalletBalancePageForRequest: () => assertAdminTokenWalletBalancePageForRequest,
69
+ assertAdminTokenWalletBalancePageRequest: () => assertAdminTokenWalletBalancePageRequest,
50
70
  assertAuditedEconomyCommandEnvelope: () => assertAuditedEconomyCommandEnvelope,
51
71
  assertBalancedTransaction: () => assertBalancedTransaction,
52
72
  assertDeterministicWalletBalanceSummary: () => assertDeterministicWalletBalanceSummary,
@@ -176,6 +196,9 @@ __export(index_exports, {
176
196
  canonicalTransactionPayload: () => canonicalTransactionPayload,
177
197
  closeModuleAllowance: () => closeModuleAllowance,
178
198
  convertRewardPayout: () => convertRewardPayout,
199
+ createAdminTokenAnomalyIndicator: () => createAdminTokenAnomalyIndicator,
200
+ createAdminTokenAnomalyUnavailable: () => createAdminTokenAnomalyUnavailable,
201
+ createDefaultAdminTokenReportingWindow: () => createDefaultAdminTokenReportingWindow,
179
202
  createEarlyBackerRetentionFromPaidLot: () => createEarlyBackerRetentionFromPaidLot,
180
203
  createEconomyPortableCustomerReceipt: () => createEconomyPortableCustomerReceipt,
181
204
  createEconomyRecoveryAcceptanceEnvelope: () => createEconomyRecoveryAcceptanceEnvelope,
@@ -736,6 +759,1155 @@ function mapBitLabsConversionState(state) {
736
759
  return transition;
737
760
  }
738
761
 
762
+ // src/admin-reporting.ts
763
+ var ADMIN_TOKEN_DEFAULT_WINDOW_DAYS = 30;
764
+ var ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS = 365;
765
+ var ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS = 31;
766
+ var ADMIN_TOKEN_MAXIMUM_PAGE_SIZE = 100;
767
+ var ADMIN_TOKEN_MAXIMUM_TREND_POINTS = ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS * 24 * 5;
768
+ var ADMIN_TOKEN_MINIMUM_COHORT_SIZE = 5;
769
+ var ADMIN_TOKEN_ANOMALY_BASELINE_DAYS = 28;
770
+ var DAY_MILLISECONDS = 864e5;
771
+ var HOUR_MILLISECONDS = 36e5;
772
+ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
773
+ "acquisition",
774
+ "spend",
775
+ "reversal",
776
+ "hold",
777
+ "failure"
778
+ ]);
779
+ var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
780
+ "pending",
781
+ "held",
782
+ "settled",
783
+ "reversed",
784
+ "failed"
785
+ ]);
786
+ var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
787
+ "paid-purchase",
788
+ "subscription",
789
+ "rewarded-activity",
790
+ "gameplay",
791
+ "system-adjustment",
792
+ "unknown"
793
+ ]);
794
+ var SAFE_LABELS = /* @__PURE__ */ new Set([
795
+ "token-acquisition",
796
+ "token-spend",
797
+ "token-reversal",
798
+ "token-hold",
799
+ "token-activity-failed",
800
+ "token-system-adjustment",
801
+ "token-activity-unclassified"
802
+ ]);
803
+ var SAFE_LABELS_BY_ACTIVITY_TYPE = {
804
+ acquisition: /* @__PURE__ */ new Set([
805
+ "token-acquisition",
806
+ "token-system-adjustment",
807
+ "token-activity-unclassified"
808
+ ]),
809
+ spend: /* @__PURE__ */ new Set([
810
+ "token-spend",
811
+ "token-system-adjustment",
812
+ "token-activity-unclassified"
813
+ ]),
814
+ reversal: /* @__PURE__ */ new Set([
815
+ "token-reversal",
816
+ "token-system-adjustment",
817
+ "token-activity-unclassified"
818
+ ]),
819
+ hold: /* @__PURE__ */ new Set([
820
+ "token-hold",
821
+ "token-system-adjustment",
822
+ "token-activity-unclassified"
823
+ ]),
824
+ failure: /* @__PURE__ */ new Set([
825
+ "token-activity-failed",
826
+ "token-activity-unclassified"
827
+ ])
828
+ };
829
+ var ACTIVITY_SORTS = /* @__PURE__ */ new Set([
830
+ "occurred-at-desc",
831
+ "amount-absolute-desc"
832
+ ]);
833
+ var PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
834
+ "admin-token-activity",
835
+ "mcp-token-activity"
836
+ ]);
837
+ var BALANCE_PSEUDONYM_AUDIENCES = /* @__PURE__ */ new Set([
838
+ "admin-token-balances",
839
+ "mcp-token-balances"
840
+ ]);
841
+ var WALLET_COMPONENTS = /* @__PURE__ */ new Set([
842
+ "household",
843
+ "personal",
844
+ "gameplay-allocation"
845
+ ]);
846
+ var WALLET_STATUSES = /* @__PURE__ */ new Set([
847
+ "active",
848
+ "closed"
849
+ ]);
850
+ var WALLET_BALANCE_SORTS = /* @__PURE__ */ new Set([
851
+ "available-desc",
852
+ "updated-at-desc"
853
+ ]);
854
+ var TREND_GRANULARITIES = /* @__PURE__ */ new Set([
855
+ "hour",
856
+ "day"
857
+ ]);
858
+ var ALIAS = /^[A-Za-z0-9_-]{16,96}$/u;
859
+ var OPAQUE_CURSOR = /^c1\.[A-Za-z0-9_-]{32,480}$/u;
860
+ var PSEUDONYM_VERSION = /^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$/u;
861
+ var EXACT_STATISTIC_INTEGER = /^(?:0|-?[1-9][0-9]*)$/u;
862
+ var POSITIVE_UNSIGNED_INTEGER = /^[1-9][0-9]*$/u;
863
+ var MAXIMUM_STATISTIC_HALF_SUBUNITS = (TOKEN_SUBUNITS_MAX - TOKEN_SUBUNITS_MIN) * 2n;
864
+ var ANOMALY_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
865
+ "insufficient-history",
866
+ "privacy-suppressed-baseline"
867
+ ]);
868
+ function assertPlainObject(value, label) {
869
+ economyAssert(
870
+ typeof value === "object" && value !== null && !Array.isArray(value),
871
+ "INVALID_CONTRACT",
872
+ `${label} must be an object`
873
+ );
874
+ const prototype = Object.getPrototypeOf(value);
875
+ economyAssert(
876
+ (prototype === Object.prototype || prototype === null) && !Reflect.has(value, "toJSON"),
877
+ "INVALID_CONTRACT",
878
+ `${label} must be a plain data object without serialization hooks`
879
+ );
880
+ }
881
+ function assertExactKeys(value, allowedKeys, label) {
882
+ assertPlainObject(value, label);
883
+ const allowed = new Set(allowedKeys);
884
+ const keys = Reflect.ownKeys(value);
885
+ economyAssert(
886
+ allowedKeys.every(
887
+ (key) => !Reflect.has(value, key) || Object.hasOwn(value, key)
888
+ ) && keys.every((key) => {
889
+ if (typeof key !== "string" || !allowed.has(key)) {
890
+ return false;
891
+ }
892
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
893
+ return descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
894
+ }),
895
+ "INVALID_CONTRACT",
896
+ `${label} contains an unsupported, identifying, or non-data property`
897
+ );
898
+ }
899
+ function assertAlias(value, label) {
900
+ economyAssert(
901
+ typeof value === "string" && ALIAS.test(value),
902
+ "INVALID_CONTRACT",
903
+ `${label} must be an opaque pseudonymous alias`
904
+ );
905
+ }
906
+ function assertOpaqueCursor(value) {
907
+ economyAssert(
908
+ typeof value === "string" && OPAQUE_CURSOR.test(value),
909
+ "INVALID_CONTRACT",
910
+ "Admin Token cursor must be a bounded confidentiality-protected opaque value"
911
+ );
912
+ }
913
+ function assertUniqueValues(values, allowed, label) {
914
+ economyAssert(
915
+ Array.isArray(values),
916
+ "INVALID_CONTRACT",
917
+ `${label} must be a list`
918
+ );
919
+ const unique = new Set(values);
920
+ economyAssert(
921
+ values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
922
+ "INVALID_CONTRACT",
923
+ `${label} must contain unique supported values`
924
+ );
925
+ }
926
+ function absolute(value) {
927
+ return value < 0n ? -value : value;
928
+ }
929
+ function compareTextDescending(left, right) {
930
+ if (left === right) {
931
+ return 0;
932
+ }
933
+ return left > right ? -1 : 1;
934
+ }
935
+ function assertReportingWindow(window, maximumDays = ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS) {
936
+ assertExactKeys(
937
+ window,
938
+ ["fromInclusive", "toExclusive"],
939
+ "Admin Token reporting window"
940
+ );
941
+ const from = parseIsoTimestamp(window.fromInclusive);
942
+ const to = parseIsoTimestamp(window.toExclusive);
943
+ economyAssert(
944
+ from < to && to - from <= maximumDays * DAY_MILLISECONDS,
945
+ "INVALID_TIME_WINDOW",
946
+ `Admin Token reporting window must be positive and no longer than ${maximumDays} days`
947
+ );
948
+ return { from, to };
949
+ }
950
+ function createDefaultAdminTokenReportingWindow(asOf) {
951
+ const to = parseIsoTimestamp(asOf);
952
+ return {
953
+ fromInclusive: new Date(
954
+ to - ADMIN_TOKEN_DEFAULT_WINDOW_DAYS * DAY_MILLISECONDS
955
+ ).toISOString(),
956
+ toExclusive: new Date(to).toISOString()
957
+ };
958
+ }
959
+ function assertNonNegativeTokenAmounts(amounts, label) {
960
+ economyAssert(
961
+ amounts.every((amount) => parseTokenSubunits(amount) >= 0n),
962
+ "INVALID_AMOUNT",
963
+ `${label} cannot contain a negative amount`
964
+ );
965
+ }
966
+ function assertPositiveAuthoritySequence(sequence, label) {
967
+ economyAssert(
968
+ typeof sequence === "string" && POSITIVE_UNSIGNED_INTEGER.test(sequence),
969
+ "INVALID_CONTRACT",
970
+ `${label} must be a canonical positive integer`
971
+ );
972
+ }
973
+ function assertAdminTokenEconomySummary(summary) {
974
+ assertExactKeys(
975
+ summary,
976
+ [
977
+ "schemaVersion",
978
+ "generatedAt",
979
+ "projectionAsOf",
980
+ "authoritySequence",
981
+ "walletCount",
982
+ "activeWalletCount",
983
+ "balances",
984
+ "lifetime",
985
+ "rawIdentifiersIncluded"
986
+ ],
987
+ "Admin Token economy summary"
988
+ );
989
+ assertExactKeys(
990
+ summary.balances,
991
+ ["schemaVersion", "available", "reserved", "held", "rewardProgress"],
992
+ "Admin Token aggregate balances"
993
+ );
994
+ assertExactKeys(
995
+ summary.lifetime,
996
+ [
997
+ "schemaVersion",
998
+ "bought",
999
+ "earned",
1000
+ "allocated",
1001
+ "reclaimed",
1002
+ "spent",
1003
+ "reversed"
1004
+ ],
1005
+ "Admin Token aggregate lifetime"
1006
+ );
1007
+ economyAssert(
1008
+ 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,
1009
+ "INVALID_CONTRACT",
1010
+ "Admin Token economy summary metadata is invalid"
1011
+ );
1012
+ const generatedAt = parseIsoTimestamp(summary.generatedAt);
1013
+ const projectionAsOf = parseIsoTimestamp(summary.projectionAsOf);
1014
+ economyAssert(
1015
+ projectionAsOf <= generatedAt,
1016
+ "INVALID_TIME_WINDOW",
1017
+ "Admin Token projection cannot be newer than its generated result"
1018
+ );
1019
+ assertPositiveAuthoritySequence(
1020
+ summary.authoritySequence,
1021
+ "Admin Token summary authority sequence"
1022
+ );
1023
+ assertNonNegativeTokenAmounts(
1024
+ [
1025
+ summary.balances.available,
1026
+ summary.balances.reserved,
1027
+ summary.balances.held,
1028
+ summary.balances.rewardProgress,
1029
+ summary.lifetime.bought,
1030
+ summary.lifetime.earned,
1031
+ summary.lifetime.allocated,
1032
+ summary.lifetime.reclaimed,
1033
+ summary.lifetime.spent,
1034
+ summary.lifetime.reversed
1035
+ ],
1036
+ "Admin Token economy summary"
1037
+ );
1038
+ }
1039
+ function assertAdminTokenWalletBalanceFilter(filter) {
1040
+ assertExactKeys(
1041
+ filter,
1042
+ ["components", "statuses", "subjectAlias"],
1043
+ "Admin Token wallet balance filter"
1044
+ );
1045
+ if (filter.components !== void 0) {
1046
+ assertUniqueValues(
1047
+ filter.components,
1048
+ WALLET_COMPONENTS,
1049
+ "Admin Token wallet components"
1050
+ );
1051
+ }
1052
+ if (filter.statuses !== void 0) {
1053
+ assertUniqueValues(
1054
+ filter.statuses,
1055
+ WALLET_STATUSES,
1056
+ "Admin Token wallet statuses"
1057
+ );
1058
+ }
1059
+ if (filter.subjectAlias !== void 0) {
1060
+ assertAlias(filter.subjectAlias, "Wallet subject alias filter");
1061
+ }
1062
+ }
1063
+ function sameWalletBalanceFilter(left, right) {
1064
+ if (left === void 0 || right === void 0) {
1065
+ return left === right;
1066
+ }
1067
+ return sameOptionalValues(left.components, right.components) && sameOptionalValues(left.statuses, right.statuses) && left.subjectAlias === right.subjectAlias;
1068
+ }
1069
+ function assertAdminTokenWalletBalanceCursorBinding(binding) {
1070
+ assertExactKeys(
1071
+ binding,
1072
+ [
1073
+ "schemaVersion",
1074
+ "sort",
1075
+ "filter",
1076
+ "audience",
1077
+ "pseudonymVersion"
1078
+ ],
1079
+ "Admin Token wallet balance cursor binding"
1080
+ );
1081
+ economyAssert(
1082
+ binding.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_BALANCE_SORTS.has(binding.sort) && BALANCE_PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
1083
+ "INVALID_CONTRACT",
1084
+ "Unsupported Admin Token wallet balance cursor binding"
1085
+ );
1086
+ if (binding.filter !== void 0) {
1087
+ assertAdminTokenWalletBalanceFilter(binding.filter);
1088
+ }
1089
+ }
1090
+ function assertAdminTokenWalletBalancePageRequest(request) {
1091
+ assertExactKeys(
1092
+ request,
1093
+ [
1094
+ "schemaVersion",
1095
+ "limit",
1096
+ "cursor",
1097
+ "cursorBinding",
1098
+ "sort",
1099
+ "filter",
1100
+ "audience",
1101
+ "pseudonymVersion"
1102
+ ],
1103
+ "Admin Token wallet balance request"
1104
+ );
1105
+ economyAssert(
1106
+ 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),
1107
+ "INVALID_CONTRACT",
1108
+ "Unsupported or unbounded Admin Token wallet balance request"
1109
+ );
1110
+ if (request.filter !== void 0) {
1111
+ assertAdminTokenWalletBalanceFilter(request.filter);
1112
+ }
1113
+ economyAssert(
1114
+ request.cursor === void 0 === (request.cursorBinding === void 0),
1115
+ "INVALID_CONTRACT",
1116
+ "Admin Token wallet balance cursor and binding must be provided together"
1117
+ );
1118
+ if (request.cursor === void 0 || request.cursorBinding === void 0) {
1119
+ return;
1120
+ }
1121
+ assertOpaqueCursor(request.cursor);
1122
+ assertAdminTokenWalletBalanceCursorBinding(request.cursorBinding);
1123
+ economyAssert(
1124
+ request.cursorBinding.sort === request.sort && request.cursorBinding.audience === request.audience && request.cursorBinding.pseudonymVersion === request.pseudonymVersion && sameWalletBalanceFilter(request.cursorBinding.filter, request.filter),
1125
+ "INVALID_CONTRACT",
1126
+ "Admin Token wallet balance cursor is not bound to the normalized query"
1127
+ );
1128
+ }
1129
+ function assertAdminTokenWalletBalanceEntry(entry) {
1130
+ assertExactKeys(
1131
+ entry,
1132
+ [
1133
+ "schemaVersion",
1134
+ "walletAlias",
1135
+ "subjectAlias",
1136
+ "component",
1137
+ "status",
1138
+ "available",
1139
+ "reserved",
1140
+ "held",
1141
+ "rewardProgress",
1142
+ "updatedAt",
1143
+ "authoritySequence"
1144
+ ],
1145
+ "Admin Token wallet balance entry"
1146
+ );
1147
+ economyAssert(
1148
+ entry.schemaVersion === ECONOMY_CONTRACT_VERSION && WALLET_COMPONENTS.has(entry.component) && WALLET_STATUSES.has(entry.status),
1149
+ "INVALID_CONTRACT",
1150
+ "Unsupported Admin Token wallet balance entry"
1151
+ );
1152
+ assertAlias(entry.walletAlias, "Wallet alias");
1153
+ assertAlias(entry.subjectAlias, "Wallet subject alias");
1154
+ economyAssert(
1155
+ entry.walletAlias !== entry.subjectAlias,
1156
+ "INVALID_CONTRACT",
1157
+ "Wallet and subject aliases must use separate pseudonym domains"
1158
+ );
1159
+ assertNonNegativeTokenAmounts(
1160
+ [entry.available, entry.reserved, entry.held, entry.rewardProgress],
1161
+ "Admin Token wallet balance entry"
1162
+ );
1163
+ parseIsoTimestamp(entry.updatedAt);
1164
+ assertPositiveAuthoritySequence(
1165
+ entry.authoritySequence,
1166
+ "Admin Token wallet balance authority sequence"
1167
+ );
1168
+ }
1169
+ function compareWalletBalanceEntries(left, right, sort) {
1170
+ if (sort === "available-desc") {
1171
+ const leftAvailable = parseTokenSubunits(left.available);
1172
+ const rightAvailable = parseTokenSubunits(right.available);
1173
+ if (leftAvailable !== rightAvailable) {
1174
+ return leftAvailable > rightAvailable ? -1 : 1;
1175
+ }
1176
+ }
1177
+ const leftUpdatedAt = parseIsoTimestamp(left.updatedAt);
1178
+ const rightUpdatedAt = parseIsoTimestamp(right.updatedAt);
1179
+ if (leftUpdatedAt !== rightUpdatedAt) {
1180
+ return leftUpdatedAt > rightUpdatedAt ? -1 : 1;
1181
+ }
1182
+ return compareTextDescending(left.walletAlias, right.walletAlias);
1183
+ }
1184
+ function assertAdminTokenWalletBalancePage(page) {
1185
+ assertExactKeys(
1186
+ page,
1187
+ ["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
1188
+ "Admin Token wallet balance page"
1189
+ );
1190
+ assertExactKeys(
1191
+ page.metadata,
1192
+ [
1193
+ "schemaVersion",
1194
+ "generatedAt",
1195
+ "sort",
1196
+ "filter",
1197
+ "pageLimit",
1198
+ "audience",
1199
+ "pseudonymVersion",
1200
+ "rawIdentifiersIncluded"
1201
+ ],
1202
+ "Admin Token wallet balance metadata"
1203
+ );
1204
+ economyAssert(
1205
+ 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),
1206
+ "INVALID_CONTRACT",
1207
+ "Unsupported or unbounded Admin Token wallet balance page"
1208
+ );
1209
+ if (page.metadata.filter !== void 0) {
1210
+ assertAdminTokenWalletBalanceFilter(page.metadata.filter);
1211
+ }
1212
+ parseIsoTimestamp(page.metadata.generatedAt);
1213
+ if (page.nextCursor !== void 0) {
1214
+ assertOpaqueCursor(page.nextCursor);
1215
+ }
1216
+ const walletAliases = /* @__PURE__ */ new Set();
1217
+ let previous;
1218
+ for (const entry of page.entries) {
1219
+ assertAdminTokenWalletBalanceEntry(entry);
1220
+ const filter = page.metadata.filter;
1221
+ economyAssert(
1222
+ 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),
1223
+ "INVALID_CONTRACT",
1224
+ "Admin Token wallet balance result contains an unrequested row"
1225
+ );
1226
+ economyAssert(
1227
+ !walletAliases.has(entry.walletAlias),
1228
+ "DUPLICATE_IDENTIFIER",
1229
+ "Admin Token wallet balance page cannot repeat a wallet alias"
1230
+ );
1231
+ walletAliases.add(entry.walletAlias);
1232
+ if (previous !== void 0) {
1233
+ economyAssert(
1234
+ compareWalletBalanceEntries(previous, entry, page.metadata.sort) < 0,
1235
+ "INVALID_CONTRACT",
1236
+ "Admin Token wallet balance page does not use its declared stable sort"
1237
+ );
1238
+ }
1239
+ previous = entry;
1240
+ }
1241
+ }
1242
+ function assertAdminTokenWalletBalancePageForRequest(page, request) {
1243
+ assertAdminTokenWalletBalancePageRequest(request);
1244
+ assertAdminTokenWalletBalancePage(page);
1245
+ economyAssert(
1246
+ 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,
1247
+ "INVALID_CONTRACT",
1248
+ "Admin Token wallet balance result does not match its normalized request"
1249
+ );
1250
+ }
1251
+ function assertAdminTokenActivityEntry(entry) {
1252
+ assertExactKeys(
1253
+ entry,
1254
+ [
1255
+ "schemaVersion",
1256
+ "occurredAt",
1257
+ "activityType",
1258
+ "status",
1259
+ "source",
1260
+ "amount",
1261
+ "safeLabel",
1262
+ "rowAlias",
1263
+ "subjectAlias"
1264
+ ],
1265
+ "Admin Token activity entry"
1266
+ );
1267
+ economyAssert(
1268
+ entry.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
1269
+ "INVALID_CONTRACT",
1270
+ "Unsupported Admin Token activity contract"
1271
+ );
1272
+ parseIsoTimestamp(entry.occurredAt);
1273
+ const amount = parseTokenSubunits(entry.amount);
1274
+ economyAssert(
1275
+ (amount !== 0n || entry.activityType === "failure") && (entry.activityType !== "acquisition" || amount > 0n) && (entry.activityType !== "spend" || amount < 0n),
1276
+ "INVALID_AMOUNT",
1277
+ "Admin Token activity amount has an invalid sign or zero value"
1278
+ );
1279
+ economyAssert(
1280
+ entry.activityType === "failure" === (entry.status === "failed"),
1281
+ "INVALID_CONTRACT",
1282
+ "Failed rows must use the failure activity type"
1283
+ );
1284
+ economyAssert(
1285
+ SAFE_LABELS.has(entry.safeLabel) && SAFE_LABELS_BY_ACTIVITY_TYPE[entry.activityType]?.has(entry.safeLabel) === true,
1286
+ "INVALID_CONTRACT",
1287
+ "Admin Token activity label must use the approved non-identifying allowlist"
1288
+ );
1289
+ assertAlias(entry.rowAlias, "Row alias");
1290
+ assertAlias(entry.subjectAlias, "Subject alias");
1291
+ economyAssert(
1292
+ entry.rowAlias !== entry.subjectAlias,
1293
+ "INVALID_CONTRACT",
1294
+ "Row and subject aliases must use separate pseudonym domains"
1295
+ );
1296
+ }
1297
+ function assertAdminTokenActivityFilter(filter) {
1298
+ assertExactKeys(
1299
+ filter,
1300
+ [
1301
+ "activityTypes",
1302
+ "statuses",
1303
+ "sources",
1304
+ "subjectAlias"
1305
+ ],
1306
+ "Admin Token activity filter"
1307
+ );
1308
+ if (filter.activityTypes !== void 0) {
1309
+ assertUniqueValues(
1310
+ filter.activityTypes,
1311
+ ACTIVITY_TYPES,
1312
+ "Admin Token activity types"
1313
+ );
1314
+ }
1315
+ if (filter.statuses !== void 0) {
1316
+ assertUniqueValues(
1317
+ filter.statuses,
1318
+ ACTIVITY_STATUSES,
1319
+ "Admin Token activity statuses"
1320
+ );
1321
+ }
1322
+ if (filter.sources !== void 0) {
1323
+ assertUniqueValues(
1324
+ filter.sources,
1325
+ ACTIVITY_SOURCES,
1326
+ "Admin Token activity sources"
1327
+ );
1328
+ }
1329
+ if (filter.subjectAlias !== void 0) {
1330
+ assertAlias(filter.subjectAlias, "Subject alias filter");
1331
+ }
1332
+ }
1333
+ function sameOptionalValues(left, right) {
1334
+ if (left === void 0 || right === void 0) {
1335
+ return left === right;
1336
+ }
1337
+ return left.length === right.length && left.every((value) => right.includes(value));
1338
+ }
1339
+ function sameActivityFilter(left, right) {
1340
+ if (left === void 0 || right === void 0) {
1341
+ return left === right;
1342
+ }
1343
+ return sameOptionalValues(left.activityTypes, right.activityTypes) && sameOptionalValues(left.statuses, right.statuses) && sameOptionalValues(left.sources, right.sources) && left.subjectAlias === right.subjectAlias;
1344
+ }
1345
+ function assertAdminTokenActivityCursorBinding(binding) {
1346
+ assertExactKeys(
1347
+ binding,
1348
+ [
1349
+ "schemaVersion",
1350
+ "sort",
1351
+ "window",
1352
+ "filter",
1353
+ "audience",
1354
+ "pseudonymVersion"
1355
+ ],
1356
+ "Admin Token activity cursor binding"
1357
+ );
1358
+ economyAssert(
1359
+ binding.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_SORTS.has(binding.sort) && PSEUDONYM_AUDIENCES.has(binding.audience) && PSEUDONYM_VERSION.test(binding.pseudonymVersion),
1360
+ "INVALID_CONTRACT",
1361
+ "Unsupported Admin Token activity cursor binding"
1362
+ );
1363
+ assertReportingWindow(binding.window);
1364
+ if (binding.filter !== void 0) {
1365
+ assertAdminTokenActivityFilter(binding.filter);
1366
+ }
1367
+ }
1368
+ function assertAdminTokenActivityPageRequest(request) {
1369
+ assertExactKeys(
1370
+ request,
1371
+ [
1372
+ "schemaVersion",
1373
+ "limit",
1374
+ "cursor",
1375
+ "cursorBinding",
1376
+ "sort",
1377
+ "window",
1378
+ "filter",
1379
+ "audience",
1380
+ "pseudonymVersion"
1381
+ ],
1382
+ "Admin Token activity request"
1383
+ );
1384
+ economyAssert(
1385
+ 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),
1386
+ "INVALID_CONTRACT",
1387
+ "Unsupported or unbounded Admin Token activity request"
1388
+ );
1389
+ assertReportingWindow(request.window);
1390
+ if (request.filter !== void 0) {
1391
+ assertAdminTokenActivityFilter(request.filter);
1392
+ }
1393
+ economyAssert(
1394
+ request.cursor === void 0 === (request.cursorBinding === void 0),
1395
+ "INVALID_CONTRACT",
1396
+ "Admin Token activity cursor and trusted binding must be provided together"
1397
+ );
1398
+ if (request.cursor === void 0 || request.cursorBinding === void 0) {
1399
+ return;
1400
+ }
1401
+ assertOpaqueCursor(request.cursor);
1402
+ assertAdminTokenActivityCursorBinding(request.cursorBinding);
1403
+ economyAssert(
1404
+ 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),
1405
+ "INVALID_CONTRACT",
1406
+ "Admin Token cursor is not bound to the normalized query"
1407
+ );
1408
+ }
1409
+ function compareActivityEntries(left, right, sort) {
1410
+ if (sort === "amount-absolute-desc") {
1411
+ const leftAmount = absolute(parseTokenSubunits(left.amount));
1412
+ const rightAmount = absolute(parseTokenSubunits(right.amount));
1413
+ if (leftAmount !== rightAmount) {
1414
+ return leftAmount > rightAmount ? -1 : 1;
1415
+ }
1416
+ }
1417
+ const leftTime = parseIsoTimestamp(left.occurredAt);
1418
+ const rightTime = parseIsoTimestamp(right.occurredAt);
1419
+ if (leftTime !== rightTime) {
1420
+ return leftTime > rightTime ? -1 : 1;
1421
+ }
1422
+ return compareTextDescending(left.rowAlias, right.rowAlias);
1423
+ }
1424
+ function assertAdminTokenActivityPage(page) {
1425
+ assertExactKeys(
1426
+ page,
1427
+ ["schemaVersion", "entries", "hasMore", "nextCursor", "metadata"],
1428
+ "Admin Token activity page"
1429
+ );
1430
+ assertExactKeys(
1431
+ page.metadata,
1432
+ [
1433
+ "schemaVersion",
1434
+ "generatedAt",
1435
+ "fromInclusive",
1436
+ "toExclusive",
1437
+ "sort",
1438
+ "filter",
1439
+ "pageLimit",
1440
+ "audience",
1441
+ "pseudonymVersion",
1442
+ "rawIdentifiersIncluded"
1443
+ ],
1444
+ "Admin Token activity metadata"
1445
+ );
1446
+ economyAssert(
1447
+ 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,
1448
+ "INVALID_CONTRACT",
1449
+ "Unsupported Admin Token activity result metadata"
1450
+ );
1451
+ const window = assertReportingWindow({
1452
+ fromInclusive: page.metadata.fromInclusive,
1453
+ toExclusive: page.metadata.toExclusive
1454
+ });
1455
+ if (page.metadata.filter !== void 0) {
1456
+ assertAdminTokenActivityFilter(page.metadata.filter);
1457
+ }
1458
+ parseIsoTimestamp(page.metadata.generatedAt);
1459
+ economyAssert(
1460
+ Array.isArray(page.entries) && page.entries.length <= page.metadata.pageLimit && page.hasMore === (page.nextCursor !== void 0) && (!page.hasMore || page.entries.length > 0),
1461
+ "INVALID_CONTRACT",
1462
+ "Admin Token activity page is unbounded or has inconsistent pagination"
1463
+ );
1464
+ if (page.nextCursor !== void 0) {
1465
+ assertOpaqueCursor(page.nextCursor);
1466
+ }
1467
+ const rowAliases = /* @__PURE__ */ new Set();
1468
+ let previous;
1469
+ for (const entry of page.entries) {
1470
+ assertAdminTokenActivityEntry(entry);
1471
+ const occurredAt = parseIsoTimestamp(entry.occurredAt);
1472
+ economyAssert(
1473
+ occurredAt >= window.from && occurredAt < window.to,
1474
+ "INVALID_TIME_WINDOW",
1475
+ "Admin Token activity falls outside the declared result window"
1476
+ );
1477
+ const filter = page.metadata.filter;
1478
+ economyAssert(
1479
+ 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),
1480
+ "INVALID_CONTRACT",
1481
+ "Admin Token activity result contains a row outside its metadata filters"
1482
+ );
1483
+ economyAssert(
1484
+ !rowAliases.has(entry.rowAlias),
1485
+ "DUPLICATE_IDENTIFIER",
1486
+ "Admin Token activity page cannot repeat a row alias"
1487
+ );
1488
+ rowAliases.add(entry.rowAlias);
1489
+ if (previous !== void 0) {
1490
+ economyAssert(
1491
+ compareActivityEntries(previous, entry, page.metadata.sort) < 0,
1492
+ "INVALID_CONTRACT",
1493
+ "Admin Token activity page does not use its declared stable sort"
1494
+ );
1495
+ }
1496
+ previous = entry;
1497
+ }
1498
+ }
1499
+ function assertAdminTokenActivityPageForRequest(page, request) {
1500
+ assertAdminTokenActivityPageRequest(request);
1501
+ assertAdminTokenActivityPage(page);
1502
+ economyAssert(
1503
+ 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,
1504
+ "INVALID_CONTRACT",
1505
+ "Admin Token activity result metadata does not match its normalized request"
1506
+ );
1507
+ }
1508
+ function assertAdminTokenTrendRequest(request) {
1509
+ assertExactKeys(
1510
+ request,
1511
+ ["schemaVersion", "window", "granularity", "activityTypes"],
1512
+ "Admin Token trend request"
1513
+ );
1514
+ economyAssert(
1515
+ request.schemaVersion === ECONOMY_CONTRACT_VERSION && TREND_GRANULARITIES.has(request.granularity),
1516
+ "INVALID_CONTRACT",
1517
+ "Unsupported Admin Token trend request"
1518
+ );
1519
+ assertReportingWindow(
1520
+ request.window,
1521
+ request.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
1522
+ );
1523
+ if (request.activityTypes !== void 0) {
1524
+ assertUniqueValues(
1525
+ request.activityTypes,
1526
+ ACTIVITY_TYPES,
1527
+ "Admin Token trend activity types"
1528
+ );
1529
+ }
1530
+ }
1531
+ function medianHalfSubunits(values) {
1532
+ const ordered = [...values].sort(
1533
+ (left, right) => left === right ? 0 : left < right ? -1 : 1
1534
+ );
1535
+ const lower = ordered[Math.floor((ordered.length - 1) / 2)];
1536
+ const upper = ordered[Math.floor(ordered.length / 2)];
1537
+ economyAssert(
1538
+ lower !== void 0 && upper !== void 0,
1539
+ "INVALID_CONTRACT",
1540
+ "Median requires at least one value"
1541
+ );
1542
+ const sum = lower + upper;
1543
+ economyAssert(
1544
+ sum % 2n === 0n,
1545
+ "INVALID_AMOUNT",
1546
+ "Median cannot be represented in exact half TokenSubunits"
1547
+ );
1548
+ return sum / 2n;
1549
+ }
1550
+ function serializeExactStatistic(halfSubunits) {
1551
+ economyAssert(
1552
+ absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
1553
+ "AMOUNT_OUT_OF_RANGE",
1554
+ "Admin Token statistic exceeds its exact bounded representation"
1555
+ );
1556
+ if (halfSubunits % 2n === 0n) {
1557
+ return {
1558
+ numerator: (halfSubunits / 2n).toString(10),
1559
+ denominator: 1
1560
+ };
1561
+ }
1562
+ return {
1563
+ numerator: halfSubunits.toString(10),
1564
+ denominator: 2
1565
+ };
1566
+ }
1567
+ function parseExactStatistic(value, label) {
1568
+ assertExactKeys(value, ["numerator", "denominator"], label);
1569
+ economyAssert(
1570
+ typeof value.numerator === "string" && value.numerator.length <= 22 && EXACT_STATISTIC_INTEGER.test(value.numerator) && (value.denominator === 1 || value.denominator === 2),
1571
+ "INVALID_AMOUNT",
1572
+ `${label} must be an exact bounded rational TokenSubunit value`
1573
+ );
1574
+ const numerator = BigInt(value.numerator);
1575
+ economyAssert(
1576
+ value.denominator === 1 || numerator % 2n !== 0n,
1577
+ "INVALID_AMOUNT",
1578
+ `${label} must use a reduced exact representation`
1579
+ );
1580
+ const halfSubunits = numerator * BigInt(2 / value.denominator);
1581
+ economyAssert(
1582
+ absolute(halfSubunits) <= MAXIMUM_STATISTIC_HALF_SUBUNITS,
1583
+ "AMOUNT_OUT_OF_RANGE",
1584
+ `${label} exceeds its exact bounded representation`
1585
+ );
1586
+ return halfSubunits;
1587
+ }
1588
+ function classifyAnomaly(options) {
1589
+ if (options.absoluteDeltaHalfSubunits < options.minimumAbsoluteDeltaHalfSubunits) {
1590
+ return {
1591
+ status: "normal",
1592
+ explanationCode: "below-absolute-minimum"
1593
+ };
1594
+ }
1595
+ if (options.medianAbsoluteDeviationHalfSubunits === 0n) {
1596
+ return options.absoluteDeltaHalfSubunits > 0n ? {
1597
+ status: "irregular-spike",
1598
+ explanationCode: "zero-mad-absolute-threshold-exceeded"
1599
+ } : {
1600
+ status: "normal",
1601
+ explanationCode: "within-baseline-variation"
1602
+ };
1603
+ }
1604
+ const exceedsBaseline = options.absoluteDeltaHalfSubunits * 1000n >= options.medianAbsoluteDeviationHalfSubunits * BigInt(options.madMultiplierMilli);
1605
+ return exceedsBaseline ? {
1606
+ status: "irregular-spike",
1607
+ explanationCode: "median-mad-and-absolute-threshold-exceeded"
1608
+ } : {
1609
+ status: "normal",
1610
+ explanationCode: "within-baseline-variation"
1611
+ };
1612
+ }
1613
+ function createAdminTokenAnomalyIndicator(input) {
1614
+ assertExactKeys(
1615
+ input,
1616
+ [
1617
+ "observedAmount",
1618
+ "baselineSamples",
1619
+ "minimumAbsoluteDelta",
1620
+ "madMultiplierMilli"
1621
+ ],
1622
+ "Admin Token anomaly input"
1623
+ );
1624
+ economyAssert(
1625
+ Array.isArray(input.baselineSamples) && input.baselineSamples.length === ADMIN_TOKEN_ANOMALY_BASELINE_DAYS && Number.isSafeInteger(input.madMultiplierMilli) && input.madMultiplierMilli >= 1 && input.madMultiplierMilli <= 1e6,
1626
+ "INVALID_CONTRACT",
1627
+ "Admin Token anomaly input requires 28 baselines and a bounded fixed-point multiplier"
1628
+ );
1629
+ const observed = parseTokenSubunits(input.observedAmount);
1630
+ const baseline = input.baselineSamples.map((sample) => {
1631
+ assertExactKeys(
1632
+ sample,
1633
+ ["amount", "distinctSubjects"],
1634
+ "Admin Token anomaly baseline sample"
1635
+ );
1636
+ economyAssert(
1637
+ Number.isSafeInteger(sample.distinctSubjects) && sample.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
1638
+ "INVALID_CONTRACT",
1639
+ "Admin Token anomaly baselines must exclude privacy-suppressed cohorts"
1640
+ );
1641
+ return parseTokenSubunits(sample.amount);
1642
+ });
1643
+ const minimum = parseTokenSubunits(input.minimumAbsoluteDelta);
1644
+ economyAssert(
1645
+ minimum > 0n,
1646
+ "INVALID_AMOUNT",
1647
+ "Admin Token anomaly absolute minimum must be positive"
1648
+ );
1649
+ const baselineHalfSubunits = baseline.map((amount) => amount * 2n);
1650
+ const medianHalf = medianHalfSubunits(baselineHalfSubunits);
1651
+ const medianAbsoluteDeviationHalf = medianHalfSubunits(
1652
+ baselineHalfSubunits.map((amount) => absolute(amount - medianHalf))
1653
+ );
1654
+ const deviationHalf = observed * 2n - medianHalf;
1655
+ const classification = classifyAnomaly({
1656
+ absoluteDeltaHalfSubunits: absolute(deviationHalf),
1657
+ medianAbsoluteDeviationHalfSubunits: medianAbsoluteDeviationHalf,
1658
+ minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
1659
+ madMultiplierMilli: input.madMultiplierMilli
1660
+ });
1661
+ return {
1662
+ method: "same-window-median-mad-v1",
1663
+ ...classification,
1664
+ baselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
1665
+ medianAmount: serializeExactStatistic(medianHalf),
1666
+ medianAbsoluteDeviation: serializeExactStatistic(medianAbsoluteDeviationHalf),
1667
+ minimumAbsoluteDelta: input.minimumAbsoluteDelta,
1668
+ deviationFromMedian: serializeExactStatistic(deviationHalf),
1669
+ madMultiplierMilli: input.madMultiplierMilli
1670
+ };
1671
+ }
1672
+ function createAdminTokenAnomalyUnavailable(input) {
1673
+ assertExactKeys(
1674
+ input,
1675
+ ["reason", "eligibleBaselineWindowCount"],
1676
+ "Unavailable Admin Token anomaly input"
1677
+ );
1678
+ economyAssert(
1679
+ ANOMALY_UNAVAILABLE_REASONS.has(input.reason) && Number.isSafeInteger(input.eligibleBaselineWindowCount) && input.eligibleBaselineWindowCount >= 0 && input.eligibleBaselineWindowCount < ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
1680
+ "INVALID_CONTRACT",
1681
+ "Unavailable Admin Token anomaly requires a bounded reason and eligible baseline count"
1682
+ );
1683
+ return {
1684
+ method: "same-window-median-mad-v1",
1685
+ status: "unavailable",
1686
+ reason: input.reason,
1687
+ eligibleBaselineWindowCount: input.eligibleBaselineWindowCount,
1688
+ requiredBaselineWindowCount: ADMIN_TOKEN_ANOMALY_BASELINE_DAYS
1689
+ };
1690
+ }
1691
+ function assertAdminTokenAnomalyIndicator(anomaly, observedAmount) {
1692
+ assertExactKeys(
1693
+ anomaly,
1694
+ [
1695
+ "method",
1696
+ "status",
1697
+ "baselineWindowCount",
1698
+ "medianAmount",
1699
+ "medianAbsoluteDeviation",
1700
+ "minimumAbsoluteDelta",
1701
+ "deviationFromMedian",
1702
+ "madMultiplierMilli",
1703
+ "explanationCode"
1704
+ ],
1705
+ "Admin Token anomaly indicator"
1706
+ );
1707
+ const observed = parseTokenSubunits(observedAmount);
1708
+ const medianHalf = parseExactStatistic(
1709
+ anomaly.medianAmount,
1710
+ "Admin Token anomaly median"
1711
+ );
1712
+ const madHalf = parseExactStatistic(
1713
+ anomaly.medianAbsoluteDeviation,
1714
+ "Admin Token anomaly median absolute deviation"
1715
+ );
1716
+ const minimum = parseTokenSubunits(anomaly.minimumAbsoluteDelta);
1717
+ const deviationHalf = parseExactStatistic(
1718
+ anomaly.deviationFromMedian,
1719
+ "Admin Token anomaly deviation"
1720
+ );
1721
+ economyAssert(
1722
+ 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,
1723
+ "INVALID_CONTRACT",
1724
+ "Admin Token anomaly arithmetic or method is invalid"
1725
+ );
1726
+ const expected = classifyAnomaly({
1727
+ absoluteDeltaHalfSubunits: absolute(deviationHalf),
1728
+ medianAbsoluteDeviationHalfSubunits: madHalf,
1729
+ minimumAbsoluteDeltaHalfSubunits: minimum * 2n,
1730
+ madMultiplierMilli: anomaly.madMultiplierMilli
1731
+ });
1732
+ economyAssert(
1733
+ anomaly.status === expected.status && anomaly.explanationCode === expected.explanationCode,
1734
+ "INVALID_CONTRACT",
1735
+ "Admin Token anomaly classification is inconsistent with its explanation"
1736
+ );
1737
+ }
1738
+ function assertAdminTokenAnomalyUnavailable(anomaly) {
1739
+ assertExactKeys(
1740
+ anomaly,
1741
+ [
1742
+ "method",
1743
+ "status",
1744
+ "reason",
1745
+ "eligibleBaselineWindowCount",
1746
+ "requiredBaselineWindowCount"
1747
+ ],
1748
+ "Unavailable Admin Token anomaly"
1749
+ );
1750
+ economyAssert(
1751
+ 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,
1752
+ "INVALID_CONTRACT",
1753
+ "Unavailable Admin Token anomaly metadata is invalid"
1754
+ );
1755
+ }
1756
+ function assertTrendBucketAlignment(start, end, granularity) {
1757
+ const expectedDuration = granularity === "hour" ? HOUR_MILLISECONDS : DAY_MILLISECONDS;
1758
+ const date = new Date(start);
1759
+ const aligned = date.getUTCMinutes() === 0 && date.getUTCSeconds() === 0 && date.getUTCMilliseconds() === 0 && (granularity === "hour" || date.getUTCHours() === 0);
1760
+ economyAssert(
1761
+ aligned && end - start === expectedDuration,
1762
+ "INVALID_TIME_WINDOW",
1763
+ "Admin Token trend bucket is not aligned to its declared granularity"
1764
+ );
1765
+ }
1766
+ function assertTrendAggregate(aggregate) {
1767
+ assertPlainObject(aggregate, "Admin Token trend aggregate");
1768
+ if (aggregate.visibility === "suppressed") {
1769
+ assertExactKeys(
1770
+ aggregate,
1771
+ ["visibility", "reason", "threshold"],
1772
+ "Suppressed Admin Token trend aggregate"
1773
+ );
1774
+ economyAssert(
1775
+ aggregate.reason === "cohort-below-minimum" && aggregate.threshold === ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
1776
+ "INVALID_CONTRACT",
1777
+ "Suppressed Admin Token trend aggregate has invalid privacy metadata"
1778
+ );
1779
+ return;
1780
+ }
1781
+ assertExactKeys(
1782
+ aggregate,
1783
+ [
1784
+ "visibility",
1785
+ "distinctSubjects",
1786
+ "activityCount",
1787
+ "signedAmount"
1788
+ ],
1789
+ "Reported Admin Token trend aggregate"
1790
+ );
1791
+ parseTokenSubunits(aggregate.signedAmount);
1792
+ economyAssert(
1793
+ aggregate.visibility === "reported" && Number.isSafeInteger(aggregate.distinctSubjects) && aggregate.distinctSubjects >= ADMIN_TOKEN_MINIMUM_COHORT_SIZE && Number.isSafeInteger(aggregate.activityCount) && aggregate.activityCount >= aggregate.distinctSubjects,
1794
+ "INVALID_CONTRACT",
1795
+ "Reported Admin Token trend aggregate is invalid or below the privacy threshold"
1796
+ );
1797
+ }
1798
+ function assertAdminTokenTrendResult(result) {
1799
+ assertExactKeys(
1800
+ result,
1801
+ ["schemaVersion", "series", "metadata"],
1802
+ "Admin Token trend result"
1803
+ );
1804
+ assertExactKeys(
1805
+ result.metadata,
1806
+ [
1807
+ "schemaVersion",
1808
+ "generatedAt",
1809
+ "fromInclusive",
1810
+ "toExclusive",
1811
+ "granularity",
1812
+ "activityTypes",
1813
+ "minimumCohortSize",
1814
+ "anomalyBaselineDays",
1815
+ "rawIdentifiersIncluded"
1816
+ ],
1817
+ "Admin Token trend metadata"
1818
+ );
1819
+ economyAssert(
1820
+ 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,
1821
+ "INVALID_CONTRACT",
1822
+ "Unsupported or unbounded Admin Token trend result"
1823
+ );
1824
+ assertUniqueValues(
1825
+ result.metadata.activityTypes,
1826
+ ACTIVITY_TYPES,
1827
+ "Admin Token trend result activity types"
1828
+ );
1829
+ const window = assertReportingWindow(
1830
+ {
1831
+ fromInclusive: result.metadata.fromInclusive,
1832
+ toExclusive: result.metadata.toExclusive
1833
+ },
1834
+ result.metadata.granularity === "hour" ? ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS : ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS
1835
+ );
1836
+ parseIsoTimestamp(result.metadata.generatedAt);
1837
+ const pointKeys = /* @__PURE__ */ new Set();
1838
+ let previousKey;
1839
+ for (const point of result.series) {
1840
+ assertExactKeys(
1841
+ point,
1842
+ [
1843
+ "schemaVersion",
1844
+ "bucketStart",
1845
+ "bucketEnd",
1846
+ "activityType",
1847
+ "aggregate",
1848
+ "anomaly"
1849
+ ],
1850
+ "Admin Token trend point"
1851
+ );
1852
+ economyAssert(
1853
+ point.schemaVersion === ECONOMY_CONTRACT_VERSION && ACTIVITY_TYPES.has(point.activityType) && result.metadata.activityTypes.includes(point.activityType),
1854
+ "INVALID_CONTRACT",
1855
+ "Unsupported Admin Token trend point"
1856
+ );
1857
+ const start = parseIsoTimestamp(point.bucketStart);
1858
+ const end = parseIsoTimestamp(point.bucketEnd);
1859
+ economyAssert(
1860
+ start >= window.from && end <= window.to,
1861
+ "INVALID_TIME_WINDOW",
1862
+ "Admin Token trend bucket falls outside the declared result window"
1863
+ );
1864
+ assertTrendBucketAlignment(start, end, result.metadata.granularity);
1865
+ assertTrendAggregate(point.aggregate);
1866
+ if (point.aggregate.visibility === "suppressed") {
1867
+ economyAssert(
1868
+ point.anomaly === void 0,
1869
+ "INVALID_CONTRACT",
1870
+ "Suppressed Admin Token cohorts cannot include anomaly details"
1871
+ );
1872
+ } else {
1873
+ economyAssert(
1874
+ point.anomaly !== void 0,
1875
+ "INVALID_CONTRACT",
1876
+ "Reported Admin Token cohorts require an anomaly result"
1877
+ );
1878
+ if (point.anomaly.status === "unavailable") {
1879
+ assertAdminTokenAnomalyUnavailable(point.anomaly);
1880
+ } else {
1881
+ assertAdminTokenAnomalyIndicator(
1882
+ point.anomaly,
1883
+ point.aggregate.signedAmount
1884
+ );
1885
+ }
1886
+ }
1887
+ const key = `${point.bucketStart}\0${point.activityType}`;
1888
+ economyAssert(
1889
+ !pointKeys.has(key) && (previousKey === void 0 || previousKey < key),
1890
+ "DUPLICATE_IDENTIFIER",
1891
+ "Admin Token trend points must be unique and stably ordered"
1892
+ );
1893
+ pointKeys.add(key);
1894
+ previousKey = key;
1895
+ }
1896
+ }
1897
+ function assertAdminTokenTrendResultForRequest(result, request) {
1898
+ assertAdminTokenTrendRequest(request);
1899
+ assertAdminTokenTrendResult(result);
1900
+ const requestedActivityTypes = request.activityTypes ?? [...ACTIVITY_TYPES];
1901
+ economyAssert(
1902
+ result.metadata.fromInclusive === request.window.fromInclusive && result.metadata.toExclusive === request.window.toExclusive && result.metadata.granularity === request.granularity && sameOptionalValues(
1903
+ result.metadata.activityTypes,
1904
+ requestedActivityTypes
1905
+ ),
1906
+ "INVALID_CONTRACT",
1907
+ "Admin Token trend result metadata does not match its normalized request"
1908
+ );
1909
+ }
1910
+
739
1911
  // src/allocations.ts
740
1912
  function assertWholePositive(amount, label) {
741
1913
  const parsed = parseTokenSubunits(amount);
@@ -981,7 +2153,8 @@ var COMMAND_TYPES = /* @__PURE__ */ new Set([
981
2153
  "chargeback",
982
2154
  "reverse",
983
2155
  "adjust",
984
- "initialize-wallet"
2156
+ "initialize-wallet",
2157
+ "initialize-admin-reporting"
985
2158
  ]);
986
2159
  var COMMAND_SOURCES = /* @__PURE__ */ new Set([
987
2160
  "browser",
@@ -1045,6 +2218,7 @@ var SOURCE_COMMAND_TYPES = {
1045
2218
  system: /* @__PURE__ */ new Set([
1046
2219
  "credit-event",
1047
2220
  "credit-competition",
2221
+ "initialize-admin-reporting",
1048
2222
  "hold",
1049
2223
  "release-hold",
1050
2224
  "reverse"
@@ -1072,7 +2246,7 @@ var COMMAND_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
1072
2246
  "acceptedRegion",
1073
2247
  "writerFencingToken"
1074
2248
  ]);
1075
- function assertExactKeys(value, allowedKeys, label) {
2249
+ function assertExactKeys2(value, allowedKeys, label) {
1076
2250
  economyAssert(
1077
2251
  value !== null && typeof value === "object" && !Array.isArray(value),
1078
2252
  "INVALID_CONTRACT",
@@ -1116,7 +2290,7 @@ function assertRelationshipContext(relationshipId, authorizationVersion) {
1116
2290
  );
1117
2291
  }
1118
2292
  function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
1119
- assertExactKeys(
2293
+ assertExactKeys2(
1120
2294
  fingerprint,
1121
2295
  /* @__PURE__ */ new Set([
1122
2296
  "schemaVersion",
@@ -1141,7 +2315,7 @@ function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
1141
2315
  );
1142
2316
  }
1143
2317
  function assertEconomyAuthorizationEvidence(evidence) {
1144
- assertExactKeys(
2318
+ assertExactKeys2(
1145
2319
  evidence,
1146
2320
  /* @__PURE__ */ new Set([
1147
2321
  "schemaVersion",
@@ -1178,7 +2352,7 @@ function assertEconomyAuthorizationEvidence(evidence) {
1178
2352
  );
1179
2353
  }
1180
2354
  function assertCausationReference(causation) {
1181
- assertExactKeys(
2355
+ assertExactKeys2(
1182
2356
  causation,
1183
2357
  /* @__PURE__ */ new Set(["schemaVersion", "kind", "causationId"]),
1184
2358
  "Economy causation reference"
@@ -1233,7 +2407,7 @@ function assertCommandSourcePrincipal(envelope) {
1233
2407
  }
1234
2408
  }
1235
2409
  function assertAuditedEconomyCommandEnvelope(envelope) {
1236
- assertExactKeys(
2410
+ assertExactKeys2(
1237
2411
  envelope,
1238
2412
  COMMAND_ENVELOPE_KEYS,
1239
2413
  "Audited economy command envelope"
@@ -1299,7 +2473,7 @@ function assertAuditedEconomyCommandEnvelope(envelope) {
1299
2473
  );
1300
2474
  }
1301
2475
  function assertEconomyProviderEvidenceHash(evidence) {
1302
- assertExactKeys(
2476
+ assertExactKeys2(
1303
2477
  evidence,
1304
2478
  /* @__PURE__ */ new Set([
1305
2479
  "schemaVersion",
@@ -1370,7 +2544,7 @@ function assertEconomyProviderEvidenceHash(evidence) {
1370
2544
  }
1371
2545
  }
1372
2546
  function assertEconomyEncryptedOperationalHandleBinding(binding) {
1373
- assertExactKeys(
2547
+ assertExactKeys2(
1374
2548
  binding,
1375
2549
  /* @__PURE__ */ new Set([
1376
2550
  "schemaVersion",
@@ -1405,7 +2579,7 @@ function assertEconomyEncryptedOperationalHandleBinding(binding) {
1405
2579
  parseIsoTimestamp(binding.createdAt);
1406
2580
  }
1407
2581
  function assertEvidenceRecordReference(reference) {
1408
- assertExactKeys(
2582
+ assertExactKeys2(
1409
2583
  reference,
1410
2584
  /* @__PURE__ */ new Set(["schemaVersion", "recordId", "contentHash"]),
1411
2585
  "Evidence record reference"
@@ -1436,7 +2610,7 @@ function assertUniqueSortedReferences(references, label) {
1436
2610
  }
1437
2611
  }
1438
2612
  function assertEconomyProviderEvidenceManifest(manifest) {
1439
- assertExactKeys(
2613
+ assertExactKeys2(
1440
2614
  manifest,
1441
2615
  /* @__PURE__ */ new Set([
1442
2616
  "schemaVersion",
@@ -1478,7 +2652,7 @@ function assertEconomyProviderEvidenceManifest(manifest) {
1478
2652
  parseIsoTimestamp(manifest.createdAt);
1479
2653
  }
1480
2654
  function assertEconomyAcceptedCommandReceipt(receipt) {
1481
- assertExactKeys(
2655
+ assertExactKeys2(
1482
2656
  receipt,
1483
2657
  /* @__PURE__ */ new Set([
1484
2658
  "schemaVersion",
@@ -1502,7 +2676,7 @@ function assertEconomyAcceptedCommandReceipt(receipt) {
1502
2676
  parseIsoTimestamp(receipt.acceptedAt);
1503
2677
  }
1504
2678
  function assertEconomyCommandResultReceipt(receipt) {
1505
- assertExactKeys(
2679
+ assertExactKeys2(
1506
2680
  receipt,
1507
2681
  /* @__PURE__ */ new Set([
1508
2682
  "schemaVersion",
@@ -1559,7 +2733,7 @@ function assertEconomyCommandResultReceipt(receipt) {
1559
2733
  }
1560
2734
  }
1561
2735
  function assertEconomyAuditedIdempotencyScope(scope) {
1562
- assertExactKeys(
2736
+ assertExactKeys2(
1563
2737
  scope,
1564
2738
  /* @__PURE__ */ new Set([
1565
2739
  "schemaVersion",
@@ -1590,7 +2764,7 @@ function assertEconomyAuditedIdempotencyScope(scope) {
1590
2764
  );
1591
2765
  }
1592
2766
  function assertEconomyAuditedIdempotencyResult(result) {
1593
- assertExactKeys(
2767
+ assertExactKeys2(
1594
2768
  result,
1595
2769
  /* @__PURE__ */ new Set([
1596
2770
  "schemaVersion",
@@ -1881,7 +3055,7 @@ var MANIFEST_KEYS = /* @__PURE__ */ new Set([
1881
3055
  "recordReferences",
1882
3056
  "committedAt"
1883
3057
  ]);
1884
- function assertExactKeys2(value, allowedKeys, label) {
3058
+ function assertExactKeys3(value, allowedKeys, label) {
1885
3059
  economyAssert(
1886
3060
  value !== null && typeof value === "object" && !Array.isArray(value),
1887
3061
  "INVALID_CONTRACT",
@@ -1919,7 +3093,7 @@ function referenceOrder(left, right) {
1919
3093
  return byKind === 0 ? compareUnicodeCodeUnits(left.recordId, right.recordId) : byKind;
1920
3094
  }
1921
3095
  function assertEconomyAuthorityRecordReference(reference) {
1922
- assertExactKeys2(
3096
+ assertExactKeys3(
1923
3097
  reference,
1924
3098
  /* @__PURE__ */ new Set([
1925
3099
  "schemaVersion",
@@ -2083,7 +3257,7 @@ function assertCommitAllowedInState(manifest) {
2083
3257
  }
2084
3258
  }
2085
3259
  function assertEconomyAuthorityCommitManifest(manifest) {
2086
- assertExactKeys2(manifest, MANIFEST_KEYS, "Authority commit manifest");
3260
+ assertExactKeys3(manifest, MANIFEST_KEYS, "Authority commit manifest");
2087
3261
  economyAssert(
2088
3262
  manifest.schemaVersion === ECONOMY_CONTRACT_VERSION && COMMIT_KINDS.has(manifest.commitKind) && AUTHORITY_STATES.has(manifest.authorityStateBefore) && AUTHORITY_STATES.has(manifest.authorityStateAfter),
2089
3263
  "INVALID_CONTRACT",
@@ -2130,7 +3304,7 @@ function assertEconomyAuthorityCommitManifest(manifest) {
2130
3304
  parseIsoTimestamp(manifest.committedAt);
2131
3305
  }
2132
3306
  function assertEconomyAuthorityHead(head) {
2133
- assertExactKeys2(head, HEAD_KEYS, "Economy authority head");
3307
+ assertExactKeys3(head, HEAD_KEYS, "Economy authority head");
2134
3308
  economyAssert(
2135
3309
  head.schemaVersion === ECONOMY_CONTRACT_VERSION && AUTHORITY_STATES.has(head.state),
2136
3310
  "INVALID_CONTRACT",
@@ -2189,7 +3363,7 @@ function advanceEconomyAuthorityHead(head, manifest, manifestCanonicalHash) {
2189
3363
  };
2190
3364
  }
2191
3365
  function assertEconomyIntegrityVerificationReceipt(receipt) {
2192
- assertExactKeys2(
3366
+ assertExactKeys3(
2193
3367
  receipt,
2194
3368
  /* @__PURE__ */ new Set([
2195
3369
  "schemaVersion",
@@ -2335,7 +3509,7 @@ function assertEconomyIntegrityVerificationReceipt(receipt) {
2335
3509
  parseIsoTimestamp(receipt.verifiedAt);
2336
3510
  }
2337
3511
  function assertEconomyIntegrityAnchorManifest(manifest) {
2338
- assertExactKeys2(
3512
+ assertExactKeys3(
2339
3513
  manifest,
2340
3514
  /* @__PURE__ */ new Set([
2341
3515
  "schemaVersion",
@@ -2497,7 +3671,7 @@ function sortEconomyAuthorityRecordReferences(references) {
2497
3671
  }
2498
3672
 
2499
3673
  // src/ledger.ts
2500
- var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
3674
+ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
2501
3675
  "purchase",
2502
3676
  "subscription",
2503
3677
  "rewarded-ad",
@@ -2514,14 +3688,14 @@ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
2514
3688
  "event",
2515
3689
  "competition"
2516
3690
  ]);
2517
- var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
3691
+ var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
2518
3692
  "pending",
2519
3693
  "held",
2520
3694
  "settled",
2521
3695
  "reversed",
2522
3696
  "failed"
2523
3697
  ]);
2524
- var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
3698
+ var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
2525
3699
  "shopify",
2526
3700
  "ayet",
2527
3701
  "bitlabs",
@@ -2551,7 +3725,7 @@ function assertActivityEntry(entry) {
2551
3725
  );
2552
3726
  assertEconomyIdentifier(entry.transactionId, "transactionId");
2553
3727
  economyAssert(
2554
- ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
3728
+ ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
2555
3729
  "INVALID_CONTRACT",
2556
3730
  "Activity type, status, or source is unsupported"
2557
3731
  );
@@ -2589,7 +3763,7 @@ function assertBalancedTransaction(transaction) {
2589
3763
  assertEconomyIdentifier(transaction.transactionId, "transactionId");
2590
3764
  assertEconomyIdentifier(transaction.idempotencyKey, "idempotencyKey");
2591
3765
  economyAssert(
2592
- ACTIVITY_TYPES.has(transaction.activityType) && ACTIVITY_STATUSES.has(transaction.status),
3766
+ ACTIVITY_TYPES2.has(transaction.activityType) && ACTIVITY_STATUSES2.has(transaction.status),
2593
3767
  "INVALID_CONTRACT",
2594
3768
  "Transaction activity type or status is unsupported"
2595
3769
  );
@@ -4628,7 +5802,7 @@ var DECISIONS = /* @__PURE__ */ new Set([
4628
5802
  "approve",
4629
5803
  "reject"
4630
5804
  ]);
4631
- function assertExactKeys3(value, allowed, label) {
5805
+ function assertExactKeys4(value, allowed, label) {
4632
5806
  economyAssert(
4633
5807
  value !== null && typeof value === "object" && !Array.isArray(value),
4634
5808
  "INVALID_CONTRACT",
@@ -4655,7 +5829,7 @@ function assertReasonCode(reasonCode) {
4655
5829
  );
4656
5830
  }
4657
5831
  function assertOperatorAdjustmentPreview(preview) {
4658
- assertExactKeys3(preview, PREVIEW_KEYS, "Operator adjustment preview");
5832
+ assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
4659
5833
  economyAssert(
4660
5834
  preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
4661
5835
  "INVALID_CONTRACT",
@@ -4734,7 +5908,7 @@ function canonicalOperatorAdjustmentPreviewPayload(preview) {
4734
5908
  function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
4735
5909
  assertOperatorAdjustmentPreview(preview);
4736
5910
  assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
4737
- assertExactKeys3(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5911
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
4738
5912
  economyAssert(
4739
5913
  proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
4740
5914
  "INVALID_CONTRACT",
@@ -4761,7 +5935,7 @@ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash
4761
5935
  );
4762
5936
  }
4763
5937
  function canonicalOperatorAdjustmentProposalPayload(proposal) {
4764
- assertExactKeys3(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5938
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
4765
5939
  return JSON.stringify({
4766
5940
  schemaVersion: proposal.schemaVersion,
4767
5941
  proposalId: proposal.proposalId,
@@ -4776,7 +5950,7 @@ function canonicalOperatorAdjustmentProposalPayload(proposal) {
4776
5950
  function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
4777
5951
  assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
4778
5952
  assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
4779
- assertExactKeys3(decision, DECISION_KEYS, "Operator adjustment decision");
5953
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
4780
5954
  economyAssert(
4781
5955
  decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
4782
5956
  "INVALID_CONTRACT",
@@ -4819,7 +5993,7 @@ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedP
4819
5993
  );
4820
5994
  }
4821
5995
  function canonicalOperatorAdjustmentDecisionPayload(decision) {
4822
- assertExactKeys3(decision, DECISION_KEYS, "Operator adjustment decision");
5996
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
4823
5997
  return JSON.stringify({
4824
5998
  schemaVersion: decision.schemaVersion,
4825
5999
  decisionId: decision.decisionId,
@@ -4843,7 +6017,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
4843
6017
  expectedProposalHash
4844
6018
  );
4845
6019
  assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
4846
- assertExactKeys3(execution, EXECUTION_KEYS, "Operator adjustment execution");
6020
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
4847
6021
  economyAssert(
4848
6022
  execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
4849
6023
  "INVALID_CONTRACT",
@@ -4874,7 +6048,7 @@ function assertOperatorAdjustmentExecution(execution, preview, proposal, decisio
4874
6048
  );
4875
6049
  }
4876
6050
  function canonicalOperatorAdjustmentExecutionPayload(execution) {
4877
- assertExactKeys3(execution, EXECUTION_KEYS, "Operator adjustment execution");
6051
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
4878
6052
  return JSON.stringify({
4879
6053
  schemaVersion: execution.schemaVersion,
4880
6054
  executionId: execution.executionId,
@@ -5919,7 +7093,7 @@ function createProjectionSnapshot(transactions, rebuiltAt) {
5919
7093
  }
5920
7094
 
5921
7095
  // src/ports/query.ts
5922
- var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
7096
+ var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
5923
7097
  "purchase",
5924
7098
  "subscription",
5925
7099
  "rewarded-ad",
@@ -5936,14 +7110,14 @@ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
5936
7110
  "event",
5937
7111
  "competition"
5938
7112
  ]);
5939
- var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
7113
+ var ACTIVITY_STATUSES3 = /* @__PURE__ */ new Set([
5940
7114
  "pending",
5941
7115
  "held",
5942
7116
  "settled",
5943
7117
  "reversed",
5944
7118
  "failed"
5945
7119
  ]);
5946
- var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
7120
+ var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
5947
7121
  "shopify",
5948
7122
  "ayet",
5949
7123
  "bitlabs",
@@ -5971,14 +7145,14 @@ function assertSafeDisplayString(value, label) {
5971
7145
  `${label} must be bounded and safe for display`
5972
7146
  );
5973
7147
  }
5974
- function assertOpaqueCursor(value) {
7148
+ function assertOpaqueCursor2(value) {
5975
7149
  economyAssert(
5976
7150
  typeof value === "string" && value.length > 0 && value.length <= 512 && !hasControlCharacters2(value),
5977
7151
  "INVALID_CONTRACT",
5978
7152
  "Activity cursor must be a bounded opaque value"
5979
7153
  );
5980
7154
  }
5981
- function assertUniqueValues(values, allowed, label) {
7155
+ function assertUniqueValues2(values, allowed, label) {
5982
7156
  const unique = new Set(values);
5983
7157
  economyAssert(
5984
7158
  values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
@@ -6241,7 +7415,7 @@ function assertWalletActivityEntry(entry) {
6241
7415
  assertEconomyIdentifier(entry.activityId, "activityId");
6242
7416
  assertEconomyIdentifier(entry.walletId, "walletId");
6243
7417
  economyAssert(
6244
- ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
7418
+ ACTIVITY_TYPES3.has(entry.activityType) && ACTIVITY_STATUSES3.has(entry.status) && ACTIVITY_SOURCES3.has(entry.source),
6245
7419
  "INVALID_CONTRACT",
6246
7420
  "Wallet activity type, status, or source is unsupported"
6247
7421
  );
@@ -6289,20 +7463,20 @@ function assertWalletActivityPageRequest(request) {
6289
7463
  "Activity page limit must be between one and 100"
6290
7464
  );
6291
7465
  if (request.cursor !== void 0) {
6292
- assertOpaqueCursor(request.cursor);
7466
+ assertOpaqueCursor2(request.cursor);
6293
7467
  }
6294
7468
  const filter = request.filter;
6295
7469
  if (filter === void 0) {
6296
7470
  return;
6297
7471
  }
6298
7472
  if (filter.activityTypes !== void 0) {
6299
- assertUniqueValues(filter.activityTypes, ACTIVITY_TYPES2, "Activity types");
7473
+ assertUniqueValues2(filter.activityTypes, ACTIVITY_TYPES3, "Activity types");
6300
7474
  }
6301
7475
  if (filter.statuses !== void 0) {
6302
- assertUniqueValues(filter.statuses, ACTIVITY_STATUSES2, "Activity statuses");
7476
+ assertUniqueValues2(filter.statuses, ACTIVITY_STATUSES3, "Activity statuses");
6303
7477
  }
6304
7478
  if (filter.sources !== void 0) {
6305
- assertUniqueValues(filter.sources, ACTIVITY_SOURCES2, "Activity sources");
7479
+ assertUniqueValues2(filter.sources, ACTIVITY_SOURCES3, "Activity sources");
6306
7480
  }
6307
7481
  if (filter.beneficiaryAccountId !== void 0) {
6308
7482
  assertEconomyIdentifier(
@@ -6335,7 +7509,7 @@ function assertWalletActivityPage(page) {
6335
7509
  "Activity pages are bounded and cannot advertise more rows from an empty page"
6336
7510
  );
6337
7511
  if (page.nextCursor !== void 0) {
6338
- assertOpaqueCursor(page.nextCursor);
7512
+ assertOpaqueCursor2(page.nextCursor);
6339
7513
  }
6340
7514
  const activityIds = /* @__PURE__ */ new Set();
6341
7515
  let previous;
@@ -7317,7 +8491,7 @@ var RESULT_OUTCOMES = /* @__PURE__ */ new Set([
7317
8491
  "failed",
7318
8492
  "no-op"
7319
8493
  ]);
7320
- var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
8494
+ var ACTIVITY_TYPES4 = /* @__PURE__ */ new Set([
7321
8495
  "purchase",
7322
8496
  "subscription",
7323
8497
  "rewarded-ad",
@@ -7429,7 +8603,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
7429
8603
  "signature",
7430
8604
  ...PORTABLE_BODY_KEYS
7431
8605
  ]);
7432
- function assertExactKeys4(value, allowedKeys, label) {
8606
+ function assertExactKeys5(value, allowedKeys, label) {
7433
8607
  economyAssert(
7434
8608
  value !== null && typeof value === "object" && !Array.isArray(value),
7435
8609
  "INVALID_CONTRACT",
@@ -7518,7 +8692,7 @@ function canonicalSignatureMetadata(signature) {
7518
8692
  };
7519
8693
  }
7520
8694
  function assertEconomySealedRecoveryPayload(payload) {
7521
- assertExactKeys4(
8695
+ assertExactKeys5(
7522
8696
  payload,
7523
8697
  /* @__PURE__ */ new Set([
7524
8698
  "schemaVersion",
@@ -7558,7 +8732,7 @@ function assertEconomySealedRecoveryPayload(payload) {
7558
8732
  );
7559
8733
  }
7560
8734
  function assertAcceptanceBody(body) {
7561
- assertExactKeys4(
8735
+ assertExactKeys5(
7562
8736
  body,
7563
8737
  "acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
7564
8738
  "Recovery acceptance body"
@@ -7627,7 +8801,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
7627
8801
  };
7628
8802
  }
7629
8803
  function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
7630
- assertExactKeys4(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
8804
+ assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
7631
8805
  assertAcceptanceBody(envelope);
7632
8806
  assertEconomyIdentifier(
7633
8807
  envelope.acceptanceEnvelopeId,
@@ -7668,7 +8842,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
7668
8842
  });
7669
8843
  }
7670
8844
  function assertCommittedResultBody(body) {
7671
- assertExactKeys4(
8845
+ assertExactKeys5(
7672
8846
  body,
7673
8847
  "committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
7674
8848
  "Recovery committed-result body"
@@ -7762,7 +8936,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
7762
8936
  };
7763
8937
  }
7764
8938
  function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
7765
- assertExactKeys4(
8939
+ assertExactKeys5(
7766
8940
  result,
7767
8941
  COMMITTED_RESULT_KEYS,
7768
8942
  "Recovery committed result"
@@ -7821,7 +8995,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
7821
8995
  );
7822
8996
  }
7823
8997
  function assertEconomyEvidenceSignatureMetadata(signature) {
7824
- assertExactKeys4(
8998
+ assertExactKeys5(
7825
8999
  signature,
7826
9000
  /* @__PURE__ */ new Set([
7827
9001
  "schemaVersion",
@@ -7841,7 +9015,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
7841
9015
  parseIsoTimestamp(signature.signedAt);
7842
9016
  }
7843
9017
  function assertEconomyEvidenceSignature(signature) {
7844
- assertExactKeys4(
9018
+ assertExactKeys5(
7845
9019
  signature,
7846
9020
  /* @__PURE__ */ new Set([
7847
9021
  "schemaVersion",
@@ -7863,7 +9037,7 @@ function assertEconomyEvidenceSignature(signature) {
7863
9037
  assertBase64url(signature.value, "Evidence signature value", 32, 2048);
7864
9038
  }
7865
9039
  function assertRegionalEvidenceBody(body) {
7866
- assertExactKeys4(
9040
+ assertExactKeys5(
7867
9041
  body,
7868
9042
  "evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
7869
9043
  "Regional evidence-receipt body"
@@ -7955,7 +9129,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
7955
9129
  };
7956
9130
  }
7957
9131
  function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
7958
- assertExactKeys4(receipt, REGIONAL_KEYS, "Regional evidence receipt");
9132
+ assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
7959
9133
  assertRegionalEvidenceBody(receipt);
7960
9134
  assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
7961
9135
  assertEconomyEvidenceSignature(receipt.signature);
@@ -8157,7 +9331,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
8157
9331
  );
8158
9332
  }
8159
9333
  function assertEconomyMerkleInclusionProof(proof) {
8160
- assertExactKeys4(
9334
+ assertExactKeys5(
8161
9335
  proof,
8162
9336
  /* @__PURE__ */ new Set([
8163
9337
  "schemaVersion",
@@ -8188,7 +9362,7 @@ function assertEconomyMerkleInclusionProof(proof) {
8188
9362
  "Merkle leaf position is outside its bounded tree"
8189
9363
  );
8190
9364
  for (const step of proof.siblings) {
8191
- assertExactKeys4(
9365
+ assertExactKeys5(
8192
9366
  step,
8193
9367
  /* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
8194
9368
  "Merkle proof step"
@@ -8277,7 +9451,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
8277
9451
  );
8278
9452
  }
8279
9453
  function assertPortableEvidenceReference(reference) {
8280
- assertExactKeys4(
9454
+ assertExactKeys5(
8281
9455
  reference,
8282
9456
  /* @__PURE__ */ new Set([
8283
9457
  "schemaVersion",
@@ -8314,7 +9488,7 @@ function canonicalPortableEvidenceReference(reference) {
8314
9488
  };
8315
9489
  }
8316
9490
  function assertPortableBody(body) {
8317
- assertExactKeys4(
9491
+ assertExactKeys5(
8318
9492
  body,
8319
9493
  "portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
8320
9494
  "Portable customer-receipt body"
@@ -8338,7 +9512,7 @@ function assertPortableBody(body) {
8338
9512
  assertEconomyIdentifier(value, label);
8339
9513
  }
8340
9514
  economyAssert(
8341
- ACTIVITY_TYPES3.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
9515
+ ACTIVITY_TYPES4.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
8342
9516
  "INVALID_CONTRACT",
8343
9517
  "Portable customer receipt has an unsupported activity or direction"
8344
9518
  );
@@ -8438,7 +9612,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
8438
9612
  };
8439
9613
  }
8440
9614
  function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
8441
- assertExactKeys4(receipt, PORTABLE_KEYS, "Portable customer receipt");
9615
+ assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
8442
9616
  assertPortableBody(receipt);
8443
9617
  assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
8444
9618
  assertEconomyEvidenceSignature(receipt.signature);
@@ -8738,7 +9912,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
8738
9912
  "lifetimeProjectionId",
8739
9913
  "outboxEventId"
8740
9914
  ]);
8741
- function assertExactKeys5(value, allowed, label) {
9915
+ function assertExactKeys6(value, allowed, label) {
8742
9916
  economyAssert(
8743
9917
  value !== null && typeof value === "object" && !Array.isArray(value),
8744
9918
  "INVALID_CONTRACT",
@@ -8778,7 +9952,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
8778
9952
  };
8779
9953
  }
8780
9954
  function assertPersonalWalletInitializationCommand(command) {
8781
- assertExactKeys5(command, COMMAND_KEYS, "Wallet initialization command");
9955
+ assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
8782
9956
  economyAssert(
8783
9957
  command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
8784
9958
  "INVALID_CONTRACT",
@@ -8802,7 +9976,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
8802
9976
  });
8803
9977
  }
8804
9978
  function assertPersonalWalletInitializationOutboxIntent(intent) {
8805
- assertExactKeys5(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
9979
+ assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
8806
9980
  economyAssert(
8807
9981
  intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
8808
9982
  "INVALID_CONTRACT",
@@ -8902,8 +10076,8 @@ function createPersonalWalletInitializationState(input, hash) {
8902
10076
  return state;
8903
10077
  }
8904
10078
  function assertPersonalWalletInitializationState(state) {
8905
- assertExactKeys5(state, STATE_KEYS, "Wallet initialization state");
8906
- assertExactKeys5(
10079
+ assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
10080
+ assertExactKeys6(
8907
10081
  state.documentIds,
8908
10082
  DOCUMENT_ID_KEYS,
8909
10083
  "Wallet initialization document IDs"
@@ -8935,6 +10109,13 @@ function assertPersonalWalletInitializationState(state) {
8935
10109
  }
8936
10110
  // Annotate the CommonJS export names for ESM import in node:
8937
10111
  0 && (module.exports = {
10112
+ ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
10113
+ ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
10114
+ ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
10115
+ ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
10116
+ ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
10117
+ ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
10118
+ ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
8938
10119
  BASELINE_GBP_CATALOG_VERSION,
8939
10120
  BASELINE_GBP_REFERENCE_RATE,
8940
10121
  BASELINE_GBP_TOKEN_PACKS,
@@ -8962,6 +10143,19 @@ function assertPersonalWalletInitializationState(state) {
8962
10143
  applyWalletBalanceDelta,
8963
10144
  applyWalletLifetimeDeltas,
8964
10145
  assertActivityEntry,
10146
+ assertAdminTokenActivityCursorBinding,
10147
+ assertAdminTokenActivityEntry,
10148
+ assertAdminTokenActivityPage,
10149
+ assertAdminTokenActivityPageForRequest,
10150
+ assertAdminTokenActivityPageRequest,
10151
+ assertAdminTokenEconomySummary,
10152
+ assertAdminTokenTrendRequest,
10153
+ assertAdminTokenTrendResult,
10154
+ assertAdminTokenTrendResultForRequest,
10155
+ assertAdminTokenWalletBalanceCursorBinding,
10156
+ assertAdminTokenWalletBalancePage,
10157
+ assertAdminTokenWalletBalancePageForRequest,
10158
+ assertAdminTokenWalletBalancePageRequest,
8965
10159
  assertAuditedEconomyCommandEnvelope,
8966
10160
  assertBalancedTransaction,
8967
10161
  assertDeterministicWalletBalanceSummary,
@@ -9091,6 +10285,9 @@ function assertPersonalWalletInitializationState(state) {
9091
10285
  canonicalTransactionPayload,
9092
10286
  closeModuleAllowance,
9093
10287
  convertRewardPayout,
10288
+ createAdminTokenAnomalyIndicator,
10289
+ createAdminTokenAnomalyUnavailable,
10290
+ createDefaultAdminTokenReportingWindow,
9094
10291
  createEarlyBackerRetentionFromPaidLot,
9095
10292
  createEconomyPortableCustomerReceipt,
9096
10293
  createEconomyRecoveryAcceptanceEnvelope,