@plasius/economy 0.6.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.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,
@@ -100,6 +120,10 @@ __export(index_exports, {
100
120
  assertModuleSpendQuote: () => assertModuleSpendQuote,
101
121
  assertNonNegativeAccounts: () => assertNonNegativeAccounts,
102
122
  assertOpenPurchaseIntent: () => assertOpenPurchaseIntent,
123
+ assertOperatorAdjustmentDecision: () => assertOperatorAdjustmentDecision,
124
+ assertOperatorAdjustmentExecution: () => assertOperatorAdjustmentExecution,
125
+ assertOperatorAdjustmentPreview: () => assertOperatorAdjustmentPreview,
126
+ assertOperatorAdjustmentProposal: () => assertOperatorAdjustmentProposal,
103
127
  assertPaidLotLifecycle: () => assertPaidLotLifecycle,
104
128
  assertPaidLotLifecycleEvent: () => assertPaidLotLifecycleEvent,
105
129
  assertPaidLotPurchaseProvenance: () => assertPaidLotPurchaseProvenance,
@@ -163,11 +187,18 @@ __export(index_exports, {
163
187
  canonicalEconomyRegionalEvidenceReceiptBodyPayload: () => canonicalEconomyRegionalEvidenceReceiptBodyPayload,
164
188
  canonicalEconomyRegionalEvidenceReceiptPayload: () => canonicalEconomyRegionalEvidenceReceiptPayload,
165
189
  canonicalEconomyRegionalEvidenceReceiptSigningPayload: () => canonicalEconomyRegionalEvidenceReceiptSigningPayload,
190
+ canonicalOperatorAdjustmentDecisionPayload: () => canonicalOperatorAdjustmentDecisionPayload,
191
+ canonicalOperatorAdjustmentExecutionPayload: () => canonicalOperatorAdjustmentExecutionPayload,
192
+ canonicalOperatorAdjustmentPreviewPayload: () => canonicalOperatorAdjustmentPreviewPayload,
193
+ canonicalOperatorAdjustmentProposalPayload: () => canonicalOperatorAdjustmentProposalPayload,
166
194
  canonicalPersonalWalletInitializationCommandPayload: () => canonicalPersonalWalletInitializationCommandPayload,
167
195
  canonicalPersonalWalletInitializationOutboxPayload: () => canonicalPersonalWalletInitializationOutboxPayload,
168
196
  canonicalTransactionPayload: () => canonicalTransactionPayload,
169
197
  closeModuleAllowance: () => closeModuleAllowance,
170
198
  convertRewardPayout: () => convertRewardPayout,
199
+ createAdminTokenAnomalyIndicator: () => createAdminTokenAnomalyIndicator,
200
+ createAdminTokenAnomalyUnavailable: () => createAdminTokenAnomalyUnavailable,
201
+ createDefaultAdminTokenReportingWindow: () => createDefaultAdminTokenReportingWindow,
171
202
  createEarlyBackerRetentionFromPaidLot: () => createEarlyBackerRetentionFromPaidLot,
172
203
  createEconomyPortableCustomerReceipt: () => createEconomyPortableCustomerReceipt,
173
204
  createEconomyRecoveryAcceptanceEnvelope: () => createEconomyRecoveryAcceptanceEnvelope,
@@ -728,6 +759,1155 @@ function mapBitLabsConversionState(state) {
728
759
  return transition;
729
760
  }
730
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
+
731
1911
  // src/allocations.ts
732
1912
  function assertWholePositive(amount, label) {
733
1913
  const parsed = parseTokenSubunits(amount);
@@ -1064,7 +2244,7 @@ var COMMAND_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
1064
2244
  "acceptedRegion",
1065
2245
  "writerFencingToken"
1066
2246
  ]);
1067
- function assertExactKeys(value, allowedKeys, label) {
2247
+ function assertExactKeys2(value, allowedKeys, label) {
1068
2248
  economyAssert(
1069
2249
  value !== null && typeof value === "object" && !Array.isArray(value),
1070
2250
  "INVALID_CONTRACT",
@@ -1108,7 +2288,7 @@ function assertRelationshipContext(relationshipId, authorizationVersion) {
1108
2288
  );
1109
2289
  }
1110
2290
  function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
1111
- assertExactKeys(
2291
+ assertExactKeys2(
1112
2292
  fingerprint,
1113
2293
  /* @__PURE__ */ new Set([
1114
2294
  "schemaVersion",
@@ -1133,7 +2313,7 @@ function assertEconomyHmacFingerprint(fingerprint, expectedDomain) {
1133
2313
  );
1134
2314
  }
1135
2315
  function assertEconomyAuthorizationEvidence(evidence) {
1136
- assertExactKeys(
2316
+ assertExactKeys2(
1137
2317
  evidence,
1138
2318
  /* @__PURE__ */ new Set([
1139
2319
  "schemaVersion",
@@ -1170,7 +2350,7 @@ function assertEconomyAuthorizationEvidence(evidence) {
1170
2350
  );
1171
2351
  }
1172
2352
  function assertCausationReference(causation) {
1173
- assertExactKeys(
2353
+ assertExactKeys2(
1174
2354
  causation,
1175
2355
  /* @__PURE__ */ new Set(["schemaVersion", "kind", "causationId"]),
1176
2356
  "Economy causation reference"
@@ -1225,7 +2405,7 @@ function assertCommandSourcePrincipal(envelope) {
1225
2405
  }
1226
2406
  }
1227
2407
  function assertAuditedEconomyCommandEnvelope(envelope) {
1228
- assertExactKeys(
2408
+ assertExactKeys2(
1229
2409
  envelope,
1230
2410
  COMMAND_ENVELOPE_KEYS,
1231
2411
  "Audited economy command envelope"
@@ -1291,7 +2471,7 @@ function assertAuditedEconomyCommandEnvelope(envelope) {
1291
2471
  );
1292
2472
  }
1293
2473
  function assertEconomyProviderEvidenceHash(evidence) {
1294
- assertExactKeys(
2474
+ assertExactKeys2(
1295
2475
  evidence,
1296
2476
  /* @__PURE__ */ new Set([
1297
2477
  "schemaVersion",
@@ -1362,7 +2542,7 @@ function assertEconomyProviderEvidenceHash(evidence) {
1362
2542
  }
1363
2543
  }
1364
2544
  function assertEconomyEncryptedOperationalHandleBinding(binding) {
1365
- assertExactKeys(
2545
+ assertExactKeys2(
1366
2546
  binding,
1367
2547
  /* @__PURE__ */ new Set([
1368
2548
  "schemaVersion",
@@ -1397,7 +2577,7 @@ function assertEconomyEncryptedOperationalHandleBinding(binding) {
1397
2577
  parseIsoTimestamp(binding.createdAt);
1398
2578
  }
1399
2579
  function assertEvidenceRecordReference(reference) {
1400
- assertExactKeys(
2580
+ assertExactKeys2(
1401
2581
  reference,
1402
2582
  /* @__PURE__ */ new Set(["schemaVersion", "recordId", "contentHash"]),
1403
2583
  "Evidence record reference"
@@ -1428,7 +2608,7 @@ function assertUniqueSortedReferences(references, label) {
1428
2608
  }
1429
2609
  }
1430
2610
  function assertEconomyProviderEvidenceManifest(manifest) {
1431
- assertExactKeys(
2611
+ assertExactKeys2(
1432
2612
  manifest,
1433
2613
  /* @__PURE__ */ new Set([
1434
2614
  "schemaVersion",
@@ -1470,7 +2650,7 @@ function assertEconomyProviderEvidenceManifest(manifest) {
1470
2650
  parseIsoTimestamp(manifest.createdAt);
1471
2651
  }
1472
2652
  function assertEconomyAcceptedCommandReceipt(receipt) {
1473
- assertExactKeys(
2653
+ assertExactKeys2(
1474
2654
  receipt,
1475
2655
  /* @__PURE__ */ new Set([
1476
2656
  "schemaVersion",
@@ -1494,7 +2674,7 @@ function assertEconomyAcceptedCommandReceipt(receipt) {
1494
2674
  parseIsoTimestamp(receipt.acceptedAt);
1495
2675
  }
1496
2676
  function assertEconomyCommandResultReceipt(receipt) {
1497
- assertExactKeys(
2677
+ assertExactKeys2(
1498
2678
  receipt,
1499
2679
  /* @__PURE__ */ new Set([
1500
2680
  "schemaVersion",
@@ -1551,7 +2731,7 @@ function assertEconomyCommandResultReceipt(receipt) {
1551
2731
  }
1552
2732
  }
1553
2733
  function assertEconomyAuditedIdempotencyScope(scope) {
1554
- assertExactKeys(
2734
+ assertExactKeys2(
1555
2735
  scope,
1556
2736
  /* @__PURE__ */ new Set([
1557
2737
  "schemaVersion",
@@ -1582,7 +2762,7 @@ function assertEconomyAuditedIdempotencyScope(scope) {
1582
2762
  );
1583
2763
  }
1584
2764
  function assertEconomyAuditedIdempotencyResult(result) {
1585
- assertExactKeys(
2765
+ assertExactKeys2(
1586
2766
  result,
1587
2767
  /* @__PURE__ */ new Set([
1588
2768
  "schemaVersion",
@@ -1873,7 +3053,7 @@ var MANIFEST_KEYS = /* @__PURE__ */ new Set([
1873
3053
  "recordReferences",
1874
3054
  "committedAt"
1875
3055
  ]);
1876
- function assertExactKeys2(value, allowedKeys, label) {
3056
+ function assertExactKeys3(value, allowedKeys, label) {
1877
3057
  economyAssert(
1878
3058
  value !== null && typeof value === "object" && !Array.isArray(value),
1879
3059
  "INVALID_CONTRACT",
@@ -1911,7 +3091,7 @@ function referenceOrder(left, right) {
1911
3091
  return byKind === 0 ? compareUnicodeCodeUnits(left.recordId, right.recordId) : byKind;
1912
3092
  }
1913
3093
  function assertEconomyAuthorityRecordReference(reference) {
1914
- assertExactKeys2(
3094
+ assertExactKeys3(
1915
3095
  reference,
1916
3096
  /* @__PURE__ */ new Set([
1917
3097
  "schemaVersion",
@@ -2075,7 +3255,7 @@ function assertCommitAllowedInState(manifest) {
2075
3255
  }
2076
3256
  }
2077
3257
  function assertEconomyAuthorityCommitManifest(manifest) {
2078
- assertExactKeys2(manifest, MANIFEST_KEYS, "Authority commit manifest");
3258
+ assertExactKeys3(manifest, MANIFEST_KEYS, "Authority commit manifest");
2079
3259
  economyAssert(
2080
3260
  manifest.schemaVersion === ECONOMY_CONTRACT_VERSION && COMMIT_KINDS.has(manifest.commitKind) && AUTHORITY_STATES.has(manifest.authorityStateBefore) && AUTHORITY_STATES.has(manifest.authorityStateAfter),
2081
3261
  "INVALID_CONTRACT",
@@ -2122,7 +3302,7 @@ function assertEconomyAuthorityCommitManifest(manifest) {
2122
3302
  parseIsoTimestamp(manifest.committedAt);
2123
3303
  }
2124
3304
  function assertEconomyAuthorityHead(head) {
2125
- assertExactKeys2(head, HEAD_KEYS, "Economy authority head");
3305
+ assertExactKeys3(head, HEAD_KEYS, "Economy authority head");
2126
3306
  economyAssert(
2127
3307
  head.schemaVersion === ECONOMY_CONTRACT_VERSION && AUTHORITY_STATES.has(head.state),
2128
3308
  "INVALID_CONTRACT",
@@ -2181,7 +3361,7 @@ function advanceEconomyAuthorityHead(head, manifest, manifestCanonicalHash) {
2181
3361
  };
2182
3362
  }
2183
3363
  function assertEconomyIntegrityVerificationReceipt(receipt) {
2184
- assertExactKeys2(
3364
+ assertExactKeys3(
2185
3365
  receipt,
2186
3366
  /* @__PURE__ */ new Set([
2187
3367
  "schemaVersion",
@@ -2327,7 +3507,7 @@ function assertEconomyIntegrityVerificationReceipt(receipt) {
2327
3507
  parseIsoTimestamp(receipt.verifiedAt);
2328
3508
  }
2329
3509
  function assertEconomyIntegrityAnchorManifest(manifest) {
2330
- assertExactKeys2(
3510
+ assertExactKeys3(
2331
3511
  manifest,
2332
3512
  /* @__PURE__ */ new Set([
2333
3513
  "schemaVersion",
@@ -2489,7 +3669,7 @@ function sortEconomyAuthorityRecordReferences(references) {
2489
3669
  }
2490
3670
 
2491
3671
  // src/ledger.ts
2492
- var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
3672
+ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
2493
3673
  "purchase",
2494
3674
  "subscription",
2495
3675
  "rewarded-ad",
@@ -2506,14 +3686,14 @@ var ACTIVITY_TYPES = /* @__PURE__ */ new Set([
2506
3686
  "event",
2507
3687
  "competition"
2508
3688
  ]);
2509
- var ACTIVITY_STATUSES = /* @__PURE__ */ new Set([
3689
+ var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
2510
3690
  "pending",
2511
3691
  "held",
2512
3692
  "settled",
2513
3693
  "reversed",
2514
3694
  "failed"
2515
3695
  ]);
2516
- var ACTIVITY_SOURCES = /* @__PURE__ */ new Set([
3696
+ var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
2517
3697
  "shopify",
2518
3698
  "ayet",
2519
3699
  "bitlabs",
@@ -2543,7 +3723,7 @@ function assertActivityEntry(entry) {
2543
3723
  );
2544
3724
  assertEconomyIdentifier(entry.transactionId, "transactionId");
2545
3725
  economyAssert(
2546
- ACTIVITY_TYPES.has(entry.activityType) && ACTIVITY_STATUSES.has(entry.status) && ACTIVITY_SOURCES.has(entry.source),
3726
+ ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
2547
3727
  "INVALID_CONTRACT",
2548
3728
  "Activity type, status, or source is unsupported"
2549
3729
  );
@@ -2581,7 +3761,7 @@ function assertBalancedTransaction(transaction) {
2581
3761
  assertEconomyIdentifier(transaction.transactionId, "transactionId");
2582
3762
  assertEconomyIdentifier(transaction.idempotencyKey, "idempotencyKey");
2583
3763
  economyAssert(
2584
- ACTIVITY_TYPES.has(transaction.activityType) && ACTIVITY_STATUSES.has(transaction.status),
3764
+ ACTIVITY_TYPES2.has(transaction.activityType) && ACTIVITY_STATUSES2.has(transaction.status),
2585
3765
  "INVALID_CONTRACT",
2586
3766
  "Transaction activity type or status is unsupported"
2587
3767
  );
@@ -4546,6 +5726,341 @@ function assertDistinctAdjustmentApproval(request) {
4546
5726
  }
4547
5727
  }
4548
5728
 
5729
+ // src/operator-adjustments.ts
5730
+ var PREVIEW_KEYS = /* @__PURE__ */ new Set([
5731
+ "schemaVersion",
5732
+ "previewId",
5733
+ "adjustmentId",
5734
+ "operation",
5735
+ "targetAccountId",
5736
+ "targetComponent",
5737
+ "targetWalletId",
5738
+ "targetLedgerAccountId",
5739
+ "offsetLedgerAccountId",
5740
+ "sourceLotId",
5741
+ "amount",
5742
+ "reasonCode",
5743
+ "ticketReferenceHash",
5744
+ "transferPolicy",
5745
+ "refundPolicy",
5746
+ "originalSourceLotId",
5747
+ "originalTransactionId",
5748
+ "preparedAt",
5749
+ "expiresAt"
5750
+ ]);
5751
+ var DECISION_KEYS = /* @__PURE__ */ new Set([
5752
+ "schemaVersion",
5753
+ "decisionId",
5754
+ "adjustmentId",
5755
+ "proposalId",
5756
+ "proposalHash",
5757
+ "previewHash",
5758
+ "decision",
5759
+ "proposedByAccountId",
5760
+ "decidedByAccountId",
5761
+ "proposedAt",
5762
+ "decidedAt"
5763
+ ]);
5764
+ var PROPOSAL_KEYS = /* @__PURE__ */ new Set([
5765
+ "schemaVersion",
5766
+ "proposalId",
5767
+ "adjustmentId",
5768
+ "previewHash",
5769
+ "status",
5770
+ "proposedByAccountId",
5771
+ "proposedAt",
5772
+ "expiresAt"
5773
+ ]);
5774
+ var EXECUTION_KEYS = /* @__PURE__ */ new Set([
5775
+ "schemaVersion",
5776
+ "executionId",
5777
+ "adjustmentId",
5778
+ "previewHash",
5779
+ "proposalHash",
5780
+ "decisionHash",
5781
+ "sourceLotId",
5782
+ "transactionId",
5783
+ "resultReceiptId",
5784
+ "executedAt"
5785
+ ]);
5786
+ var OPERATIONS = /* @__PURE__ */ new Set([
5787
+ "credit",
5788
+ "reverse-credit"
5789
+ ]);
5790
+ var TARGET_COMPONENTS = /* @__PURE__ */ new Set([
5791
+ "personal",
5792
+ "household-treasury"
5793
+ ]);
5794
+ var TRANSFER_POLICIES = /* @__PURE__ */ new Set([
5795
+ "household-allocatable",
5796
+ "same-user-only",
5797
+ "non-transferable"
5798
+ ]);
5799
+ var DECISIONS = /* @__PURE__ */ new Set([
5800
+ "approve",
5801
+ "reject"
5802
+ ]);
5803
+ function assertExactKeys4(value, allowed, label) {
5804
+ economyAssert(
5805
+ value !== null && typeof value === "object" && !Array.isArray(value),
5806
+ "INVALID_CONTRACT",
5807
+ `${label} must be an object`
5808
+ );
5809
+ economyAssert(
5810
+ Object.keys(value).every((key) => allowed.has(key)),
5811
+ "INVALID_CONTRACT",
5812
+ `${label} contains an unsupported field`
5813
+ );
5814
+ }
5815
+ function assertCanonicalHash6(value, label) {
5816
+ economyAssert(
5817
+ /^sha256:[a-f0-9]{64}$/u.test(value),
5818
+ "INVALID_CONTRACT",
5819
+ `${label} must be a canonical SHA-256 reference`
5820
+ );
5821
+ }
5822
+ function assertReasonCode(reasonCode) {
5823
+ economyAssert(
5824
+ /^[A-Z][A-Z0-9_]{2,95}$/u.test(reasonCode),
5825
+ "INVALID_CONTRACT",
5826
+ "Adjustment reasonCode must be a bounded uppercase identifier"
5827
+ );
5828
+ }
5829
+ function assertOperatorAdjustmentPreview(preview) {
5830
+ assertExactKeys4(preview, PREVIEW_KEYS, "Operator adjustment preview");
5831
+ economyAssert(
5832
+ preview.schemaVersion === ECONOMY_CONTRACT_VERSION && OPERATIONS.has(preview.operation) && TARGET_COMPONENTS.has(preview.targetComponent) && TRANSFER_POLICIES.has(preview.transferPolicy) && preview.refundPolicy === "not-refundable",
5833
+ "INVALID_CONTRACT",
5834
+ "Unsupported operator adjustment preview"
5835
+ );
5836
+ assertEconomyIdentifier(preview.previewId, "previewId");
5837
+ assertEconomyIdentifier(preview.adjustmentId, "adjustmentId");
5838
+ assertEconomyIdentifier(preview.targetAccountId, "targetAccountId");
5839
+ assertEconomyIdentifier(preview.targetWalletId, "targetWalletId");
5840
+ assertEconomyIdentifier(
5841
+ preview.targetLedgerAccountId,
5842
+ "targetLedgerAccountId"
5843
+ );
5844
+ assertEconomyIdentifier(
5845
+ preview.offsetLedgerAccountId,
5846
+ "offsetLedgerAccountId"
5847
+ );
5848
+ assertEconomyIdentifier(preview.sourceLotId, "sourceLotId");
5849
+ economyAssert(
5850
+ parseTokenSubunits(preview.amount) > 0n,
5851
+ "INVALID_AMOUNT",
5852
+ "Operator adjustment amount must be positive"
5853
+ );
5854
+ assertReasonCode(preview.reasonCode);
5855
+ assertCanonicalHash6(preview.ticketReferenceHash, "ticketReferenceHash");
5856
+ const preparedAt = parseIsoTimestamp(preview.preparedAt);
5857
+ const expiresAt = parseIsoTimestamp(preview.expiresAt);
5858
+ economyAssert(
5859
+ expiresAt > preparedAt,
5860
+ "INVALID_TIME_WINDOW",
5861
+ "Operator adjustment preview must expire after preparation"
5862
+ );
5863
+ if (preview.operation === "credit") {
5864
+ economyAssert(
5865
+ preview.originalSourceLotId === void 0 && preview.originalTransactionId === void 0,
5866
+ "INVALID_CONTRACT",
5867
+ "A credit preview cannot bind an original transaction"
5868
+ );
5869
+ return;
5870
+ }
5871
+ economyAssert(
5872
+ preview.originalSourceLotId !== void 0 && preview.originalTransactionId !== void 0,
5873
+ "INVALID_CONTRACT",
5874
+ "A reversal preview must bind the original lot and transaction"
5875
+ );
5876
+ assertEconomyIdentifier(preview.originalSourceLotId, "originalSourceLotId");
5877
+ assertEconomyIdentifier(
5878
+ preview.originalTransactionId,
5879
+ "originalTransactionId"
5880
+ );
5881
+ }
5882
+ function canonicalOperatorAdjustmentPreviewPayload(preview) {
5883
+ assertOperatorAdjustmentPreview(preview);
5884
+ return JSON.stringify({
5885
+ schemaVersion: preview.schemaVersion,
5886
+ previewId: preview.previewId,
5887
+ adjustmentId: preview.adjustmentId,
5888
+ operation: preview.operation,
5889
+ targetAccountId: preview.targetAccountId,
5890
+ targetComponent: preview.targetComponent,
5891
+ targetWalletId: preview.targetWalletId,
5892
+ targetLedgerAccountId: preview.targetLedgerAccountId,
5893
+ offsetLedgerAccountId: preview.offsetLedgerAccountId,
5894
+ sourceLotId: preview.sourceLotId,
5895
+ amount: preview.amount,
5896
+ reasonCode: preview.reasonCode,
5897
+ ticketReferenceHash: preview.ticketReferenceHash,
5898
+ transferPolicy: preview.transferPolicy,
5899
+ refundPolicy: preview.refundPolicy,
5900
+ ...preview.originalSourceLotId === void 0 ? {} : { originalSourceLotId: preview.originalSourceLotId },
5901
+ ...preview.originalTransactionId === void 0 ? {} : { originalTransactionId: preview.originalTransactionId },
5902
+ preparedAt: preview.preparedAt,
5903
+ expiresAt: preview.expiresAt
5904
+ });
5905
+ }
5906
+ function assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash) {
5907
+ assertOperatorAdjustmentPreview(preview);
5908
+ assertCanonicalHash6(expectedPreviewHash, "expectedPreviewHash");
5909
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5910
+ economyAssert(
5911
+ proposal.schemaVersion === ECONOMY_CONTRACT_VERSION && proposal.status === "pending-approval",
5912
+ "INVALID_CONTRACT",
5913
+ "Unsupported operator adjustment proposal"
5914
+ );
5915
+ assertEconomyIdentifier(proposal.proposalId, "proposalId");
5916
+ assertEconomyIdentifier(proposal.adjustmentId, "adjustmentId");
5917
+ assertCanonicalHash6(proposal.previewHash, "previewHash");
5918
+ assertEconomyIdentifier(
5919
+ proposal.proposedByAccountId,
5920
+ "proposedByAccountId"
5921
+ );
5922
+ economyAssert(
5923
+ proposal.adjustmentId === preview.adjustmentId && proposal.previewHash === expectedPreviewHash,
5924
+ "ADJUSTMENT_PREVIEW_MISMATCH",
5925
+ "Operator adjustment proposal does not match its preview"
5926
+ );
5927
+ const proposedAt = parseIsoTimestamp(proposal.proposedAt);
5928
+ const expiresAt = parseIsoTimestamp(proposal.expiresAt);
5929
+ economyAssert(
5930
+ proposedAt >= parseIsoTimestamp(preview.preparedAt) && expiresAt === parseIsoTimestamp(preview.expiresAt) && expiresAt > proposedAt,
5931
+ "INVALID_TIME_WINDOW",
5932
+ "Operator adjustment proposal times are inconsistent"
5933
+ );
5934
+ }
5935
+ function canonicalOperatorAdjustmentProposalPayload(proposal) {
5936
+ assertExactKeys4(proposal, PROPOSAL_KEYS, "Operator adjustment proposal");
5937
+ return JSON.stringify({
5938
+ schemaVersion: proposal.schemaVersion,
5939
+ proposalId: proposal.proposalId,
5940
+ adjustmentId: proposal.adjustmentId,
5941
+ previewHash: proposal.previewHash,
5942
+ status: proposal.status,
5943
+ proposedByAccountId: proposal.proposedByAccountId,
5944
+ proposedAt: proposal.proposedAt,
5945
+ expiresAt: proposal.expiresAt
5946
+ });
5947
+ }
5948
+ function assertOperatorAdjustmentDecision(decision, proposal, preview, expectedPreviewHash, expectedProposalHash) {
5949
+ assertOperatorAdjustmentProposal(proposal, preview, expectedPreviewHash);
5950
+ assertCanonicalHash6(expectedProposalHash, "expectedProposalHash");
5951
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
5952
+ economyAssert(
5953
+ decision.schemaVersion === ECONOMY_CONTRACT_VERSION && DECISIONS.has(decision.decision),
5954
+ "INVALID_CONTRACT",
5955
+ "Unsupported operator adjustment decision"
5956
+ );
5957
+ assertEconomyIdentifier(decision.decisionId, "decisionId");
5958
+ assertEconomyIdentifier(decision.adjustmentId, "adjustmentId");
5959
+ assertEconomyIdentifier(decision.proposalId, "proposalId");
5960
+ assertCanonicalHash6(decision.proposalHash, "proposalHash");
5961
+ assertCanonicalHash6(decision.previewHash, "previewHash");
5962
+ assertEconomyIdentifier(
5963
+ decision.proposedByAccountId,
5964
+ "proposedByAccountId"
5965
+ );
5966
+ assertEconomyIdentifier(
5967
+ decision.decidedByAccountId,
5968
+ "decidedByAccountId"
5969
+ );
5970
+ economyAssert(
5971
+ decision.proposedByAccountId !== decision.decidedByAccountId,
5972
+ "ADJUSTMENT_SELF_APPROVAL",
5973
+ "Operator adjustment approval requires a distinct operator"
5974
+ );
5975
+ economyAssert(
5976
+ decision.adjustmentId === preview.adjustmentId && decision.proposalId === proposal.proposalId && decision.proposalHash === expectedProposalHash && decision.previewHash === expectedPreviewHash,
5977
+ "ADJUSTMENT_PREVIEW_MISMATCH",
5978
+ "Operator adjustment decision does not match its preview"
5979
+ );
5980
+ const proposedAt = parseIsoTimestamp(decision.proposedAt);
5981
+ const decidedAt = parseIsoTimestamp(decision.decidedAt);
5982
+ economyAssert(
5983
+ decision.proposedByAccountId === proposal.proposedByAccountId && proposedAt === parseIsoTimestamp(proposal.proposedAt) && decidedAt >= proposedAt,
5984
+ "INVALID_TIME_WINDOW",
5985
+ "Operator adjustment decision times are inconsistent"
5986
+ );
5987
+ economyAssert(
5988
+ decidedAt <= parseIsoTimestamp(preview.expiresAt),
5989
+ "ADJUSTMENT_EXPIRED",
5990
+ "Operator adjustment preview has expired"
5991
+ );
5992
+ }
5993
+ function canonicalOperatorAdjustmentDecisionPayload(decision) {
5994
+ assertExactKeys4(decision, DECISION_KEYS, "Operator adjustment decision");
5995
+ return JSON.stringify({
5996
+ schemaVersion: decision.schemaVersion,
5997
+ decisionId: decision.decisionId,
5998
+ adjustmentId: decision.adjustmentId,
5999
+ proposalId: decision.proposalId,
6000
+ proposalHash: decision.proposalHash,
6001
+ previewHash: decision.previewHash,
6002
+ decision: decision.decision,
6003
+ proposedByAccountId: decision.proposedByAccountId,
6004
+ decidedByAccountId: decision.decidedByAccountId,
6005
+ proposedAt: decision.proposedAt,
6006
+ decidedAt: decision.decidedAt
6007
+ });
6008
+ }
6009
+ function assertOperatorAdjustmentExecution(execution, preview, proposal, decision, expectedPreviewHash, expectedProposalHash, expectedDecisionHash) {
6010
+ assertOperatorAdjustmentDecision(
6011
+ decision,
6012
+ proposal,
6013
+ preview,
6014
+ expectedPreviewHash,
6015
+ expectedProposalHash
6016
+ );
6017
+ assertCanonicalHash6(expectedDecisionHash, "expectedDecisionHash");
6018
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
6019
+ economyAssert(
6020
+ execution.schemaVersion === ECONOMY_CONTRACT_VERSION,
6021
+ "INVALID_CONTRACT",
6022
+ "Unsupported operator adjustment execution"
6023
+ );
6024
+ assertEconomyIdentifier(execution.executionId, "executionId");
6025
+ assertEconomyIdentifier(execution.adjustmentId, "adjustmentId");
6026
+ assertCanonicalHash6(execution.previewHash, "previewHash");
6027
+ assertCanonicalHash6(execution.proposalHash, "proposalHash");
6028
+ assertCanonicalHash6(execution.decisionHash, "decisionHash");
6029
+ assertEconomyIdentifier(execution.sourceLotId, "sourceLotId");
6030
+ assertEconomyIdentifier(execution.transactionId, "transactionId");
6031
+ assertEconomyIdentifier(execution.resultReceiptId, "resultReceiptId");
6032
+ economyAssert(
6033
+ decision.decision === "approve",
6034
+ "ADJUSTMENT_NOT_APPROVED",
6035
+ "Only an approved adjustment may execute"
6036
+ );
6037
+ economyAssert(
6038
+ execution.adjustmentId === preview.adjustmentId && execution.previewHash === expectedPreviewHash && execution.proposalHash === expectedProposalHash && execution.decisionHash === expectedDecisionHash && execution.sourceLotId === preview.sourceLotId,
6039
+ "ADJUSTMENT_PREVIEW_MISMATCH",
6040
+ "Operator adjustment execution does not match its approval plan"
6041
+ );
6042
+ economyAssert(
6043
+ parseIsoTimestamp(execution.executedAt) >= parseIsoTimestamp(decision.decidedAt),
6044
+ "INVALID_TIME_WINDOW",
6045
+ "Operator adjustment execution predates its decision"
6046
+ );
6047
+ }
6048
+ function canonicalOperatorAdjustmentExecutionPayload(execution) {
6049
+ assertExactKeys4(execution, EXECUTION_KEYS, "Operator adjustment execution");
6050
+ return JSON.stringify({
6051
+ schemaVersion: execution.schemaVersion,
6052
+ executionId: execution.executionId,
6053
+ adjustmentId: execution.adjustmentId,
6054
+ previewHash: execution.previewHash,
6055
+ proposalHash: execution.proposalHash,
6056
+ decisionHash: execution.decisionHash,
6057
+ sourceLotId: execution.sourceLotId,
6058
+ transactionId: execution.transactionId,
6059
+ resultReceiptId: execution.resultReceiptId,
6060
+ executedAt: execution.executedAt
6061
+ });
6062
+ }
6063
+
4549
6064
  // src/paid-lots.ts
4550
6065
  var ZERO_ARITHMETIC = Object.freeze({
4551
6066
  retainedDelta: serializeTokenSubunits(0n),
@@ -5576,7 +7091,7 @@ function createProjectionSnapshot(transactions, rebuiltAt) {
5576
7091
  }
5577
7092
 
5578
7093
  // src/ports/query.ts
5579
- var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
7094
+ var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
5580
7095
  "purchase",
5581
7096
  "subscription",
5582
7097
  "rewarded-ad",
@@ -5593,14 +7108,14 @@ var ACTIVITY_TYPES2 = /* @__PURE__ */ new Set([
5593
7108
  "event",
5594
7109
  "competition"
5595
7110
  ]);
5596
- var ACTIVITY_STATUSES2 = /* @__PURE__ */ new Set([
7111
+ var ACTIVITY_STATUSES3 = /* @__PURE__ */ new Set([
5597
7112
  "pending",
5598
7113
  "held",
5599
7114
  "settled",
5600
7115
  "reversed",
5601
7116
  "failed"
5602
7117
  ]);
5603
- var ACTIVITY_SOURCES2 = /* @__PURE__ */ new Set([
7118
+ var ACTIVITY_SOURCES3 = /* @__PURE__ */ new Set([
5604
7119
  "shopify",
5605
7120
  "ayet",
5606
7121
  "bitlabs",
@@ -5628,14 +7143,14 @@ function assertSafeDisplayString(value, label) {
5628
7143
  `${label} must be bounded and safe for display`
5629
7144
  );
5630
7145
  }
5631
- function assertOpaqueCursor(value) {
7146
+ function assertOpaqueCursor2(value) {
5632
7147
  economyAssert(
5633
7148
  typeof value === "string" && value.length > 0 && value.length <= 512 && !hasControlCharacters2(value),
5634
7149
  "INVALID_CONTRACT",
5635
7150
  "Activity cursor must be a bounded opaque value"
5636
7151
  );
5637
7152
  }
5638
- function assertUniqueValues(values, allowed, label) {
7153
+ function assertUniqueValues2(values, allowed, label) {
5639
7154
  const unique = new Set(values);
5640
7155
  economyAssert(
5641
7156
  values.length > 0 && values.length === unique.size && values.every((value) => allowed.has(value)),
@@ -5898,7 +7413,7 @@ function assertWalletActivityEntry(entry) {
5898
7413
  assertEconomyIdentifier(entry.activityId, "activityId");
5899
7414
  assertEconomyIdentifier(entry.walletId, "walletId");
5900
7415
  economyAssert(
5901
- ACTIVITY_TYPES2.has(entry.activityType) && ACTIVITY_STATUSES2.has(entry.status) && ACTIVITY_SOURCES2.has(entry.source),
7416
+ ACTIVITY_TYPES3.has(entry.activityType) && ACTIVITY_STATUSES3.has(entry.status) && ACTIVITY_SOURCES3.has(entry.source),
5902
7417
  "INVALID_CONTRACT",
5903
7418
  "Wallet activity type, status, or source is unsupported"
5904
7419
  );
@@ -5946,20 +7461,20 @@ function assertWalletActivityPageRequest(request) {
5946
7461
  "Activity page limit must be between one and 100"
5947
7462
  );
5948
7463
  if (request.cursor !== void 0) {
5949
- assertOpaqueCursor(request.cursor);
7464
+ assertOpaqueCursor2(request.cursor);
5950
7465
  }
5951
7466
  const filter = request.filter;
5952
7467
  if (filter === void 0) {
5953
7468
  return;
5954
7469
  }
5955
7470
  if (filter.activityTypes !== void 0) {
5956
- assertUniqueValues(filter.activityTypes, ACTIVITY_TYPES2, "Activity types");
7471
+ assertUniqueValues2(filter.activityTypes, ACTIVITY_TYPES3, "Activity types");
5957
7472
  }
5958
7473
  if (filter.statuses !== void 0) {
5959
- assertUniqueValues(filter.statuses, ACTIVITY_STATUSES2, "Activity statuses");
7474
+ assertUniqueValues2(filter.statuses, ACTIVITY_STATUSES3, "Activity statuses");
5960
7475
  }
5961
7476
  if (filter.sources !== void 0) {
5962
- assertUniqueValues(filter.sources, ACTIVITY_SOURCES2, "Activity sources");
7477
+ assertUniqueValues2(filter.sources, ACTIVITY_SOURCES3, "Activity sources");
5963
7478
  }
5964
7479
  if (filter.beneficiaryAccountId !== void 0) {
5965
7480
  assertEconomyIdentifier(
@@ -5992,7 +7507,7 @@ function assertWalletActivityPage(page) {
5992
7507
  "Activity pages are bounded and cannot advertise more rows from an empty page"
5993
7508
  );
5994
7509
  if (page.nextCursor !== void 0) {
5995
- assertOpaqueCursor(page.nextCursor);
7510
+ assertOpaqueCursor2(page.nextCursor);
5996
7511
  }
5997
7512
  const activityIds = /* @__PURE__ */ new Set();
5998
7513
  let previous;
@@ -6974,7 +8489,7 @@ var RESULT_OUTCOMES = /* @__PURE__ */ new Set([
6974
8489
  "failed",
6975
8490
  "no-op"
6976
8491
  ]);
6977
- var ACTIVITY_TYPES3 = /* @__PURE__ */ new Set([
8492
+ var ACTIVITY_TYPES4 = /* @__PURE__ */ new Set([
6978
8493
  "purchase",
6979
8494
  "subscription",
6980
8495
  "rewarded-ad",
@@ -7086,7 +8601,7 @@ var PORTABLE_KEYS = /* @__PURE__ */ new Set([
7086
8601
  "signature",
7087
8602
  ...PORTABLE_BODY_KEYS
7088
8603
  ]);
7089
- function assertExactKeys3(value, allowedKeys, label) {
8604
+ function assertExactKeys5(value, allowedKeys, label) {
7090
8605
  economyAssert(
7091
8606
  value !== null && typeof value === "object" && !Array.isArray(value),
7092
8607
  "INVALID_CONTRACT",
@@ -7098,7 +8613,7 @@ function assertExactKeys3(value, allowedKeys, label) {
7098
8613
  `${label} contains an unsupported field`
7099
8614
  );
7100
8615
  }
7101
- function assertCanonicalHash6(value, label) {
8616
+ function assertCanonicalHash7(value, label) {
7102
8617
  economyAssert(
7103
8618
  typeof value === "string" && CANONICAL_HASH.test(value),
7104
8619
  "INVALID_CONTRACT",
@@ -7107,7 +8622,7 @@ function assertCanonicalHash6(value, label) {
7107
8622
  }
7108
8623
  function canonicalHash(payload, hashCanonicalPayload2, label) {
7109
8624
  const value = hashCanonicalPayload2(payload);
7110
- assertCanonicalHash6(value, label);
8625
+ assertCanonicalHash7(value, label);
7111
8626
  return value;
7112
8627
  }
7113
8628
  function assertUnsignedInteger(value, label) {
@@ -7175,7 +8690,7 @@ function canonicalSignatureMetadata(signature) {
7175
8690
  };
7176
8691
  }
7177
8692
  function assertEconomySealedRecoveryPayload(payload) {
7178
- assertExactKeys3(
8693
+ assertExactKeys5(
7179
8694
  payload,
7180
8695
  /* @__PURE__ */ new Set([
7181
8696
  "schemaVersion",
@@ -7205,17 +8720,17 @@ function assertEconomySealedRecoveryPayload(payload) {
7205
8720
  22,
7206
8721
  22
7207
8722
  );
7208
- assertCanonicalHash6(
8723
+ assertCanonicalHash7(
7209
8724
  payload.plaintextContentHash,
7210
8725
  "Recovery plaintext-content hash"
7211
8726
  );
7212
- assertCanonicalHash6(
8727
+ assertCanonicalHash7(
7213
8728
  payload.encryptionContextHash,
7214
8729
  "Recovery encryption-context hash"
7215
8730
  );
7216
8731
  }
7217
8732
  function assertAcceptanceBody(body) {
7218
- assertExactKeys3(
8733
+ assertExactKeys5(
7219
8734
  body,
7220
8735
  "acceptanceEnvelopeId" in body ? ACCEPTANCE_KEYS : ACCEPTANCE_BODY_KEYS,
7221
8736
  "Recovery acceptance body"
@@ -7234,9 +8749,9 @@ function assertAcceptanceBody(body) {
7234
8749
  body.idempotencyFingerprint,
7235
8750
  "economy.idempotency-key.v1"
7236
8751
  );
7237
- assertCanonicalHash6(body.commandEnvelopeHash, "Command-envelope hash");
8752
+ assertCanonicalHash7(body.commandEnvelopeHash, "Command-envelope hash");
7238
8753
  assertEconomyIdentifier(body.acceptedReceiptId, "acceptedReceiptId");
7239
- assertCanonicalHash6(body.acceptedReceiptHash, "Accepted-receipt hash");
8754
+ assertCanonicalHash7(body.acceptedReceiptHash, "Accepted-receipt hash");
7240
8755
  assertEconomySealedRecoveryPayload(body.sealedPayload);
7241
8756
  const preparedAt = parseIsoTimestamp(body.preparedAt);
7242
8757
  const acceptedAt = parseIsoTimestamp(body.acceptedAt);
@@ -7284,7 +8799,7 @@ function createEconomyRecoveryAcceptanceEnvelope(body, hashCanonicalPayload2) {
7284
8799
  };
7285
8800
  }
7286
8801
  function assertEconomyRecoveryAcceptanceEnvelope(envelope, hashCanonicalPayload2) {
7287
- assertExactKeys3(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
8802
+ assertExactKeys5(envelope, ACCEPTANCE_KEYS, "Recovery acceptance envelope");
7288
8803
  assertAcceptanceBody(envelope);
7289
8804
  assertEconomyIdentifier(
7290
8805
  envelope.acceptanceEnvelopeId,
@@ -7325,7 +8840,7 @@ function canonicalEconomyRecoveryAcceptanceEnvelopePayload(envelope, hashCanonic
7325
8840
  });
7326
8841
  }
7327
8842
  function assertCommittedResultBody(body) {
7328
- assertExactKeys3(
8843
+ assertExactKeys5(
7329
8844
  body,
7330
8845
  "committedResultId" in body ? COMMITTED_RESULT_KEYS : COMMITTED_RESULT_BODY_KEYS,
7331
8846
  "Recovery committed-result body"
@@ -7353,7 +8868,7 @@ function assertCommittedResultBody(body) {
7353
8868
  [body.authorityCommitHash, "Authority-commit hash"],
7354
8869
  [body.authorityHeadHashAfter, "Authority-head hash"]
7355
8870
  ]) {
7356
- assertCanonicalHash6(value, label);
8871
+ assertCanonicalHash7(value, label);
7357
8872
  }
7358
8873
  economyAssert(
7359
8874
  RESULT_OUTCOMES.has(body.outcome),
@@ -7376,7 +8891,7 @@ function assertCommittedResultBody(body) {
7376
8891
  assertEconomyIdentifier(body.transactionId, "transactionId");
7377
8892
  }
7378
8893
  if (body.transactionCanonicalHash !== void 0) {
7379
- assertCanonicalHash6(
8894
+ assertCanonicalHash7(
7380
8895
  body.transactionCanonicalHash,
7381
8896
  "Transaction canonical hash"
7382
8897
  );
@@ -7419,7 +8934,7 @@ function createEconomyRecoveryCommittedResult(body, hashCanonicalPayload2) {
7419
8934
  };
7420
8935
  }
7421
8936
  function assertEconomyRecoveryCommittedResult(result, hashCanonicalPayload2) {
7422
- assertExactKeys3(
8937
+ assertExactKeys5(
7423
8938
  result,
7424
8939
  COMMITTED_RESULT_KEYS,
7425
8940
  "Recovery committed result"
@@ -7478,7 +8993,7 @@ function assertEconomyRecoveryResultLink(acceptance, result, hashCanonicalPayloa
7478
8993
  );
7479
8994
  }
7480
8995
  function assertEconomyEvidenceSignatureMetadata(signature) {
7481
- assertExactKeys3(
8996
+ assertExactKeys5(
7482
8997
  signature,
7483
8998
  /* @__PURE__ */ new Set([
7484
8999
  "schemaVersion",
@@ -7498,7 +9013,7 @@ function assertEconomyEvidenceSignatureMetadata(signature) {
7498
9013
  parseIsoTimestamp(signature.signedAt);
7499
9014
  }
7500
9015
  function assertEconomyEvidenceSignature(signature) {
7501
- assertExactKeys3(
9016
+ assertExactKeys5(
7502
9017
  signature,
7503
9018
  /* @__PURE__ */ new Set([
7504
9019
  "schemaVersion",
@@ -7520,7 +9035,7 @@ function assertEconomyEvidenceSignature(signature) {
7520
9035
  assertBase64url(signature.value, "Evidence signature value", 32, 2048);
7521
9036
  }
7522
9037
  function assertRegionalEvidenceBody(body) {
7523
- assertExactKeys3(
9038
+ assertExactKeys5(
7524
9039
  body,
7525
9040
  "evidenceReceiptId" in body ? REGIONAL_KEYS : REGIONAL_BODY_KEYS,
7526
9041
  "Regional evidence-receipt body"
@@ -7552,7 +9067,7 @@ function assertRegionalEvidenceBody(body) {
7552
9067
  "INVALID_CONTRACT",
7553
9068
  "Unsupported recovery record kind"
7554
9069
  );
7555
- assertCanonicalHash6(
9070
+ assertCanonicalHash7(
7556
9071
  body.recoveryRecordContentHash,
7557
9072
  "Recovery-record content hash"
7558
9073
  );
@@ -7568,7 +9083,7 @@ function assertRegionalEvidenceBody(body) {
7568
9083
  "INVALID_CONTRACT",
7569
9084
  "Non-genesis regional evidence receipt requires a previous hash"
7570
9085
  );
7571
- assertCanonicalHash6(
9086
+ assertCanonicalHash7(
7572
9087
  body.previousReceiptHash,
7573
9088
  "Previous evidence-receipt hash"
7574
9089
  );
@@ -7612,7 +9127,7 @@ function createEconomyRegionalEvidenceReceipt(body, signature, hashCanonicalPayl
7612
9127
  };
7613
9128
  }
7614
9129
  function assertEconomyRegionalEvidenceReceipt(receipt, hashCanonicalPayload2) {
7615
- assertExactKeys3(receipt, REGIONAL_KEYS, "Regional evidence receipt");
9130
+ assertExactKeys5(receipt, REGIONAL_KEYS, "Regional evidence receipt");
7616
9131
  assertRegionalEvidenceBody(receipt);
7617
9132
  assertEconomyIdentifier(receipt.evidenceReceiptId, "evidenceReceiptId");
7618
9133
  assertEconomyEvidenceSignature(receipt.signature);
@@ -7743,7 +9258,7 @@ function assertEconomyRegionalEvidenceChain(receipts, expectedPreviousReceiptHas
7743
9258
  "INVALID_CONTRACT",
7744
9259
  "Partial evidence chain requires its trusted preceding hash"
7745
9260
  );
7746
- assertCanonicalHash6(
9261
+ assertCanonicalHash7(
7747
9262
  expectedPreviousReceiptHash,
7748
9263
  "Expected preceding evidence-receipt hash"
7749
9264
  );
@@ -7814,7 +9329,7 @@ function assertEconomyRegionalEvidenceEquality(receipts, expectedRegions, hashCa
7814
9329
  );
7815
9330
  }
7816
9331
  function assertEconomyMerkleInclusionProof(proof) {
7817
- assertExactKeys3(
9332
+ assertExactKeys5(
7818
9333
  proof,
7819
9334
  /* @__PURE__ */ new Set([
7820
9335
  "schemaVersion",
@@ -7835,8 +9350,8 @@ function assertEconomyMerkleInclusionProof(proof) {
7835
9350
  "Unsupported Merkle inclusion proof"
7836
9351
  );
7837
9352
  assertEconomyIdentifier(proof.anchorId, "anchorId");
7838
- assertCanonicalHash6(proof.anchorManifestHash, "Anchor-manifest hash");
7839
- assertCanonicalHash6(proof.leafHash, "Merkle leaf hash");
9353
+ assertCanonicalHash7(proof.anchorManifestHash, "Anchor-manifest hash");
9354
+ assertCanonicalHash7(proof.leafHash, "Merkle leaf hash");
7840
9355
  assertUnsignedInteger(proof.leafIndex, "Merkle leaf index");
7841
9356
  assertUnsignedInteger(proof.leafCount, "Merkle leaf count");
7842
9357
  economyAssert(
@@ -7845,7 +9360,7 @@ function assertEconomyMerkleInclusionProof(proof) {
7845
9360
  "Merkle leaf position is outside its bounded tree"
7846
9361
  );
7847
9362
  for (const step of proof.siblings) {
7848
- assertExactKeys3(
9363
+ assertExactKeys5(
7849
9364
  step,
7850
9365
  /* @__PURE__ */ new Set(["schemaVersion", "side", "hash"]),
7851
9366
  "Merkle proof step"
@@ -7855,7 +9370,7 @@ function assertEconomyMerkleInclusionProof(proof) {
7855
9370
  "INVALID_CONTRACT",
7856
9371
  "Unsupported Merkle proof step"
7857
9372
  );
7858
- assertCanonicalHash6(step.hash, "Merkle sibling hash");
9373
+ assertCanonicalHash7(step.hash, "Merkle sibling hash");
7859
9374
  }
7860
9375
  }
7861
9376
  function canonicalMerkleProof(proof) {
@@ -7934,7 +9449,7 @@ function assertEconomyMerkleInclusion(proof, anchor, hashCanonicalPayload2) {
7934
9449
  );
7935
9450
  }
7936
9451
  function assertPortableEvidenceReference(reference) {
7937
- assertExactKeys3(
9452
+ assertExactKeys5(
7938
9453
  reference,
7939
9454
  /* @__PURE__ */ new Set([
7940
9455
  "schemaVersion",
@@ -7954,7 +9469,7 @@ function assertPortableEvidenceReference(reference) {
7954
9469
  reference.evidenceReceiptId,
7955
9470
  "evidenceReceiptId"
7956
9471
  );
7957
- assertCanonicalHash6(
9472
+ assertCanonicalHash7(
7958
9473
  reference.evidenceReceiptHash,
7959
9474
  "Evidence-receipt hash"
7960
9475
  );
@@ -7971,7 +9486,7 @@ function canonicalPortableEvidenceReference(reference) {
7971
9486
  };
7972
9487
  }
7973
9488
  function assertPortableBody(body) {
7974
- assertExactKeys3(
9489
+ assertExactKeys5(
7975
9490
  body,
7976
9491
  "portableReceiptId" in body ? PORTABLE_KEYS : PORTABLE_BODY_KEYS,
7977
9492
  "Portable customer-receipt body"
@@ -7995,7 +9510,7 @@ function assertPortableBody(body) {
7995
9510
  assertEconomyIdentifier(value, label);
7996
9511
  }
7997
9512
  economyAssert(
7998
- ACTIVITY_TYPES3.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
9513
+ ACTIVITY_TYPES4.has(body.activityType) && (body.direction === "credit" || body.direction === "debit"),
7999
9514
  "INVALID_CONTRACT",
8000
9515
  "Portable customer receipt has an unsupported activity or direction"
8001
9516
  );
@@ -8010,7 +9525,7 @@ function assertPortableBody(body) {
8010
9525
  [body.committedResultContentHash, "Committed-result content hash"],
8011
9526
  [body.authorityCommitHash, "Authority-commit hash"]
8012
9527
  ]) {
8013
- assertCanonicalHash6(value, label);
9528
+ assertCanonicalHash7(value, label);
8014
9529
  }
8015
9530
  assertUnsignedInteger(body.authoritySequence, "Authority sequence");
8016
9531
  economyAssert(
@@ -8095,7 +9610,7 @@ function createEconomyPortableCustomerReceipt(body, signature, hashCanonicalPayl
8095
9610
  };
8096
9611
  }
8097
9612
  function assertEconomyPortableCustomerReceipt(receipt, hashCanonicalPayload2) {
8098
- assertExactKeys3(receipt, PORTABLE_KEYS, "Portable customer receipt");
9613
+ assertExactKeys5(receipt, PORTABLE_KEYS, "Portable customer receipt");
8099
9614
  assertPortableBody(receipt);
8100
9615
  assertEconomyIdentifier(receipt.portableReceiptId, "portableReceiptId");
8101
9616
  assertEconomyEvidenceSignature(receipt.signature);
@@ -8395,7 +9910,7 @@ var DOCUMENT_ID_KEYS = /* @__PURE__ */ new Set([
8395
9910
  "lifetimeProjectionId",
8396
9911
  "outboxEventId"
8397
9912
  ]);
8398
- function assertExactKeys4(value, allowed, label) {
9913
+ function assertExactKeys6(value, allowed, label) {
8399
9914
  economyAssert(
8400
9915
  value !== null && typeof value === "object" && !Array.isArray(value),
8401
9916
  "INVALID_CONTRACT",
@@ -8435,7 +9950,7 @@ function createPersonalWalletInitializationDocumentIds(subjectAccountId, hash) {
8435
9950
  };
8436
9951
  }
8437
9952
  function assertPersonalWalletInitializationCommand(command) {
8438
- assertExactKeys4(command, COMMAND_KEYS, "Wallet initialization command");
9953
+ assertExactKeys6(command, COMMAND_KEYS, "Wallet initialization command");
8439
9954
  economyAssert(
8440
9955
  command.schemaVersion === ECONOMY_CONTRACT_VERSION && command.commandType === "initialize-wallet" && command.walletKind === "personal",
8441
9956
  "INVALID_CONTRACT",
@@ -8459,7 +9974,7 @@ function canonicalPersonalWalletInitializationCommandPayload(command) {
8459
9974
  });
8460
9975
  }
8461
9976
  function assertPersonalWalletInitializationOutboxIntent(intent) {
8462
- assertExactKeys4(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
9977
+ assertExactKeys6(intent, OUTBOX_KEYS, "Wallet initialization outbox intent");
8463
9978
  economyAssert(
8464
9979
  intent.schemaVersion === ECONOMY_CONTRACT_VERSION && intent.eventType === "wallet.initialized.v1",
8465
9980
  "INVALID_CONTRACT",
@@ -8559,8 +10074,8 @@ function createPersonalWalletInitializationState(input, hash) {
8559
10074
  return state;
8560
10075
  }
8561
10076
  function assertPersonalWalletInitializationState(state) {
8562
- assertExactKeys4(state, STATE_KEYS, "Wallet initialization state");
8563
- assertExactKeys4(
10077
+ assertExactKeys6(state, STATE_KEYS, "Wallet initialization state");
10078
+ assertExactKeys6(
8564
10079
  state.documentIds,
8565
10080
  DOCUMENT_ID_KEYS,
8566
10081
  "Wallet initialization document IDs"
@@ -8592,6 +10107,13 @@ function assertPersonalWalletInitializationState(state) {
8592
10107
  }
8593
10108
  // Annotate the CommonJS export names for ESM import in node:
8594
10109
  0 && (module.exports = {
10110
+ ADMIN_TOKEN_ANOMALY_BASELINE_DAYS,
10111
+ ADMIN_TOKEN_DEFAULT_WINDOW_DAYS,
10112
+ ADMIN_TOKEN_MAXIMUM_HOURLY_WINDOW_DAYS,
10113
+ ADMIN_TOKEN_MAXIMUM_PAGE_SIZE,
10114
+ ADMIN_TOKEN_MAXIMUM_TREND_POINTS,
10115
+ ADMIN_TOKEN_MAXIMUM_WINDOW_DAYS,
10116
+ ADMIN_TOKEN_MINIMUM_COHORT_SIZE,
8595
10117
  BASELINE_GBP_CATALOG_VERSION,
8596
10118
  BASELINE_GBP_REFERENCE_RATE,
8597
10119
  BASELINE_GBP_TOKEN_PACKS,
@@ -8619,6 +10141,19 @@ function assertPersonalWalletInitializationState(state) {
8619
10141
  applyWalletBalanceDelta,
8620
10142
  applyWalletLifetimeDeltas,
8621
10143
  assertActivityEntry,
10144
+ assertAdminTokenActivityCursorBinding,
10145
+ assertAdminTokenActivityEntry,
10146
+ assertAdminTokenActivityPage,
10147
+ assertAdminTokenActivityPageForRequest,
10148
+ assertAdminTokenActivityPageRequest,
10149
+ assertAdminTokenEconomySummary,
10150
+ assertAdminTokenTrendRequest,
10151
+ assertAdminTokenTrendResult,
10152
+ assertAdminTokenTrendResultForRequest,
10153
+ assertAdminTokenWalletBalanceCursorBinding,
10154
+ assertAdminTokenWalletBalancePage,
10155
+ assertAdminTokenWalletBalancePageForRequest,
10156
+ assertAdminTokenWalletBalancePageRequest,
8622
10157
  assertAuditedEconomyCommandEnvelope,
8623
10158
  assertBalancedTransaction,
8624
10159
  assertDeterministicWalletBalanceSummary,
@@ -8672,6 +10207,10 @@ function assertPersonalWalletInitializationState(state) {
8672
10207
  assertModuleSpendQuote,
8673
10208
  assertNonNegativeAccounts,
8674
10209
  assertOpenPurchaseIntent,
10210
+ assertOperatorAdjustmentDecision,
10211
+ assertOperatorAdjustmentExecution,
10212
+ assertOperatorAdjustmentPreview,
10213
+ assertOperatorAdjustmentProposal,
8675
10214
  assertPaidLotLifecycle,
8676
10215
  assertPaidLotLifecycleEvent,
8677
10216
  assertPaidLotPurchaseProvenance,
@@ -8735,11 +10274,18 @@ function assertPersonalWalletInitializationState(state) {
8735
10274
  canonicalEconomyRegionalEvidenceReceiptBodyPayload,
8736
10275
  canonicalEconomyRegionalEvidenceReceiptPayload,
8737
10276
  canonicalEconomyRegionalEvidenceReceiptSigningPayload,
10277
+ canonicalOperatorAdjustmentDecisionPayload,
10278
+ canonicalOperatorAdjustmentExecutionPayload,
10279
+ canonicalOperatorAdjustmentPreviewPayload,
10280
+ canonicalOperatorAdjustmentProposalPayload,
8738
10281
  canonicalPersonalWalletInitializationCommandPayload,
8739
10282
  canonicalPersonalWalletInitializationOutboxPayload,
8740
10283
  canonicalTransactionPayload,
8741
10284
  closeModuleAllowance,
8742
10285
  convertRewardPayout,
10286
+ createAdminTokenAnomalyIndicator,
10287
+ createAdminTokenAnomalyUnavailable,
10288
+ createDefaultAdminTokenReportingWindow,
8743
10289
  createEarlyBackerRetentionFromPaidLot,
8744
10290
  createEconomyPortableCustomerReceipt,
8745
10291
  createEconomyRecoveryAcceptanceEnvelope,