@voltro/plugin-economy 0.0.0-stage → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +2719 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9841 -0
  6. package/dist/amount.js +20 -0
  7. package/dist/appleIap.server.js +262 -0
  8. package/dist/appleIapNotifications.server.js +162 -0
  9. package/dist/appleIapTrust.server.js +30 -0
  10. package/dist/bundleValue.server.js +112 -0
  11. package/dist/canonicalDataJson.js +10 -0
  12. package/dist/capture.js +53 -0
  13. package/dist/codePort.fixture.js +123 -0
  14. package/dist/codeStore.server.js +439 -0
  15. package/dist/codeTables.entity.js +43 -0
  16. package/dist/codes.d.ts +150 -0
  17. package/dist/codes.js +82 -0
  18. package/dist/components.d.ts +397 -0
  19. package/dist/components.js +283 -0
  20. package/dist/consistency.server.js +115 -0
  21. package/dist/containerStore.server.js +687 -0
  22. package/dist/containerStore.testFixtures.js +75 -0
  23. package/dist/containerTables.entity.js +45 -0
  24. package/dist/containers.d.ts +311 -0
  25. package/dist/containers.fixture.js +128 -0
  26. package/dist/containers.js +214 -0
  27. package/dist/containers.server.js +39 -0
  28. package/dist/containersPort.fixture.js +74 -0
  29. package/dist/currency.js +32 -0
  30. package/dist/declarationFixtures.js +61 -0
  31. package/dist/economy-app/events/economy.refundReversed.event.ts +1 -0
  32. package/dist/economy-app/events/economy.refunded.event.ts +1 -0
  33. package/dist/economyPort.fixture.js +124 -0
  34. package/dist/errors.d.ts +14 -0
  35. package/dist/errors.js +21 -0
  36. package/dist/events.d.ts +46 -0
  37. package/dist/events.js +1 -0
  38. package/dist/googleIap.server.js +391 -0
  39. package/dist/googleIapNotifications.server.js +130 -0
  40. package/dist/googleIapSubscription.server.js +183 -0
  41. package/dist/iap.d.ts +309 -0
  42. package/dist/iap.js +303 -0
  43. package/dist/iap.testFixtures.js +144 -0
  44. package/dist/iapAccountTables.entity.js +39 -0
  45. package/dist/iapAccounts.server.js +200 -0
  46. package/dist/iapBinding.server.js +523 -0
  47. package/dist/iapCheckout.server.js +97 -0
  48. package/dist/iapCompletion.server.js +55 -0
  49. package/dist/iapCurrentState.server.js +107 -0
  50. package/dist/iapCurrentState.testFixtures.js +22 -0
  51. package/dist/iapCurrentStatePort.fixture.js +63 -0
  52. package/dist/iapEntitlements.d.ts +79 -0
  53. package/dist/iapEntitlements.js +57 -0
  54. package/dist/iapEntitlements.server.js +48 -0
  55. package/dist/iapEntitlementsBinding.server.js +105 -0
  56. package/dist/iapEntitlementsPort.fixture.js +80 -0
  57. package/dist/iapInstalledEntitlements.testFixtures.js +75 -0
  58. package/dist/iapInstalledNotifications.testFixtures.js +93 -0
  59. package/dist/iapInventoryRefunds.server.js +261 -0
  60. package/dist/iapNotificationCustodyPort.fixture.js +67 -0
  61. package/dist/iapNotificationPort.fixture.js +73 -0
  62. package/dist/iapNotificationProcessor.server.js +134 -0
  63. package/dist/iapNotificationProcessor.testFixtures.js +63 -0
  64. package/dist/iapNotificationProcessorPort.fixture.js +55 -0
  65. package/dist/iapNotificationSchedule.server.js +69 -0
  66. package/dist/iapNotificationStore.server.js +352 -0
  67. package/dist/iapNotificationStore.testFixtures.js +31 -0
  68. package/dist/iapNotificationTables.entity.js +48 -0
  69. package/dist/iapNotificationTarget.server.js +36 -0
  70. package/dist/iapNotificationTarget.testFixtures.js +29 -0
  71. package/dist/iapNotifications.d.ts +644 -0
  72. package/dist/iapNotifications.js +6 -0
  73. package/dist/iapNotifications.server.js +95 -0
  74. package/dist/iapNotificationsBinding.server.js +232 -0
  75. package/dist/iapNotificationsSystemPort.fixture.js +50 -0
  76. package/dist/iapPlugin.testFixtures.js +59 -0
  77. package/dist/iapPort.fixture.js +74 -0
  78. package/dist/iapProviderCapture.server.js +17 -0
  79. package/dist/iapRecovery.d.ts +146 -0
  80. package/dist/iapRecovery.js +89 -0
  81. package/dist/iapRefundEventDelivery.server.js +82 -0
  82. package/dist/iapRefundEvents.js +44 -0
  83. package/dist/iapRefundEventsPort.fixture.js +59 -0
  84. package/dist/iapRefundPort.fixture.js +54 -0
  85. package/dist/iapRefundTables.entity.js +55 -0
  86. package/dist/iapRefunds.d.ts +755 -0
  87. package/dist/iapRefunds.js +6 -0
  88. package/dist/iapRefunds.server.js +553 -0
  89. package/dist/iapRefunds.testFixtures.js +64 -0
  90. package/dist/iapSpendAdmission.server.js +98 -0
  91. package/dist/iapStore.server.js +740 -0
  92. package/dist/iapStore.testFixtures.js +127 -0
  93. package/dist/iapTables.entity.js +80 -0
  94. package/dist/iapVerification.server.js +120 -0
  95. package/dist/index.d.ts +2984 -0
  96. package/dist/index.js +15 -0
  97. package/dist/intentionRecovery.js +133 -0
  98. package/dist/ledger.js +77 -0
  99. package/dist/loyalty.d.ts +274 -0
  100. package/dist/loyalty.fixture.js +92 -0
  101. package/dist/loyalty.js +311 -0
  102. package/dist/loyaltyBinding.server.js +203 -0
  103. package/dist/loyaltyPort.fixture.js +86 -0
  104. package/dist/loyaltyShopSource.server.js +90 -0
  105. package/dist/loyaltyStore.server.js +552 -0
  106. package/dist/loyaltyStore.testFixtures.js +82 -0
  107. package/dist/loyaltyTables.entity.js +49 -0
  108. package/dist/offerMerchandising.fixture.js +114 -0
  109. package/dist/offerMerchandising.js +282 -0
  110. package/dist/offerPolicies.d.ts +441 -0
  111. package/dist/offerPolicies.fixture.js +53 -0
  112. package/dist/offerPolicies.js +267 -0
  113. package/dist/piggyBanks.d.ts +272 -0
  114. package/dist/piggyBanks.fixture.js +70 -0
  115. package/dist/piggyBanks.js +200 -0
  116. package/dist/piggyBinding.server.js +204 -0
  117. package/dist/piggyPort.fixture.js +72 -0
  118. package/dist/piggyStore.server.js +610 -0
  119. package/dist/piggyStore.testFixtures.js +97 -0
  120. package/dist/piggyTables.entity.js +40 -0
  121. package/dist/plugin.js +1047 -0
  122. package/dist/port.js +12 -0
  123. package/dist/price.d.ts +99 -0
  124. package/dist/price.js +143 -0
  125. package/dist/purchaseRecovery.js +55 -0
  126. package/dist/reports.server.js +114 -0
  127. package/dist/rpc.d.ts +3201 -0
  128. package/dist/rpc.js +1200 -0
  129. package/dist/sanctionsTradeAuthority.server.js +79 -0
  130. package/dist/server.d.ts +3856 -0
  131. package/dist/server.js +43 -0
  132. package/dist/shop.d.ts +279 -0
  133. package/dist/shop.js +195 -0
  134. package/dist/shop.testFixtures.js +113 -0
  135. package/dist/shopPort.fixture.js +71 -0
  136. package/dist/shopPresentation.js +67 -0
  137. package/dist/shopStore.server.js +623 -0
  138. package/dist/shopTables.entity.js +62 -0
  139. package/dist/shopUiCopy.js +56 -0
  140. package/dist/spendLimits.d.ts +140 -0
  141. package/dist/spendLimits.fixture.js +52 -0
  142. package/dist/spendLimits.js +154 -0
  143. package/dist/spendLimitsPort.fixture.js +119 -0
  144. package/dist/subscriptionBinding.server.js +210 -0
  145. package/dist/subscriptionStore.server.js +642 -0
  146. package/dist/subscriptionStore.testFixtures.js +71 -0
  147. package/dist/subscriptionTables.entity.js +36 -0
  148. package/dist/subscriptions.d.ts +394 -0
  149. package/dist/subscriptions.fixture.js +96 -0
  150. package/dist/subscriptions.js +212 -0
  151. package/dist/subscriptionsPort.fixture.js +75 -0
  152. package/dist/systemFixtures.js +88 -0
  153. package/dist/tables.entity.js +82 -0
  154. package/dist/testing.d.ts +4615 -0
  155. package/dist/testing.js +29 -0
  156. package/dist/tradeAuthority.server.js +171 -0
  157. package/dist/tradeBinding.server.js +200 -0
  158. package/dist/tradeComponents.js +341 -0
  159. package/dist/tradeEscrow.server.js +231 -0
  160. package/dist/tradeEscrow.testFixtures.js +132 -0
  161. package/dist/tradeExpiry.server.js +42 -0
  162. package/dist/tradeRecovery.js +47 -0
  163. package/dist/tradeStore.server.js +749 -0
  164. package/dist/tradeStore.testFixtures.js +72 -0
  165. package/dist/tradeTables.entity.js +65 -0
  166. package/dist/tradeUiCopy.js +78 -0
  167. package/dist/trades.d.ts +246 -0
  168. package/dist/trades.fixture.js +102 -0
  169. package/dist/trades.js +288 -0
  170. package/dist/tradesPort.fixture.js +93 -0
  171. package/dist/walletEscrow.js +105 -0
  172. package/dist/walletEscrow.server.js +375 -0
  173. package/dist/walletKeys.server.js +4 -0
  174. package/dist/walletStore.js +570 -0
  175. package/dist/web.d.ts +2257 -0
  176. package/dist/web.js +8 -0
  177. package/package.json +161 -4
@@ -0,0 +1,755 @@
1
+ import { BrandedScheduleDefinition } from '@voltro/runtime';
2
+ import { ColumnBuilder } from '@voltro/database';
3
+ import { Context } from 'effect';
4
+ import { DataStore } from '@voltro/database';
5
+ import { DeclaredAccess } from '@voltro/protocol';
6
+ import { Effect } from 'effect';
7
+ import { EventDescriptor } from '@voltro/protocol';
8
+ import { EventPublishContext } from '@voltro/runtime';
9
+ import { FieldDefinitions } from '@voltro/database';
10
+ import { InventorySqlService } from '@voltro/plugin-inventory/server';
11
+ import { PluginPrivacyTarget } from '@voltro/protocol';
12
+ import { PreparedSqlMutation } from '@voltro/database/sql';
13
+ import { SanctionsService } from '@voltro/plugin-sanctions/port';
14
+ import { Schema } from 'effect';
15
+ import { Subject } from '@voltro/protocol';
16
+ import { Table } from '@voltro/database';
17
+ import { YieldableError } from 'effect/Cause';
18
+
19
+ declare const acceptedCompletion: unique symbol;
20
+
21
+ /** SQL-issued capability. A player reference or serialized object cannot authorize provider completion. */
22
+ declare interface AcceptedIapCompletion {
23
+ readonly [acceptedCompletion]: true;
24
+ readonly orderId: string;
25
+ }
26
+
27
+ /** Read-only SQL custody capability, never current provider state or refund authority. */
28
+ declare interface AcceptedIapNotificationTarget {
29
+ readonly [acceptedNotificationTarget]: true;
30
+ readonly orderId: string;
31
+ readonly noticeId: string;
32
+ }
33
+
34
+ declare const acceptedNotificationTarget: unique symbol;
35
+
36
+ export declare const captureIapRefundService: (input: IapRefundService) => IapRefundService;
37
+
38
+ declare interface CurrencyDefinition {
39
+ readonly id: string;
40
+ readonly kind: 'soft' | 'hard';
41
+ readonly cap?: EconomyAmountInput;
42
+ readonly premium?: boolean;
43
+ readonly display?: {
44
+ readonly nameKey: string;
45
+ } | null;
46
+ }
47
+
48
+ export declare const dataStoreIapRefunds: (store: DataStore, input: IapRefundOptions) => IapRefundSqlService;
49
+
50
+ /** SQL pending history survives process loss. Signals are idempotent; publication may repeat before acknowledgement. */
51
+ export declare const deliverIapRefundEvents: (input: IapRefundEventDeliveryOptions) => Effect.Effect<IapRefundEventDeliveryResult, EconomyError>;
52
+
53
+ declare type EconomyAccount = {
54
+ readonly kind: 'wallet';
55
+ readonly ownerId: string;
56
+ readonly ownerKind: WalletOwnerKind;
57
+ } | {
58
+ readonly kind: 'system';
59
+ readonly id: string;
60
+ };
61
+
62
+ declare type EconomyAmountInput = string | number | bigint;
63
+
64
+ declare type EconomyChannel = 'web' | 'ios' | 'android' | 'steam';
65
+
66
+ /** Redacted codes; never carries owners, amounts or provider payloads. */
67
+ declare class EconomyError extends EconomyError_base {
68
+ }
69
+
70
+ declare const EconomyError_base: Schema.Class<EconomyError, Schema.TaggedStruct<"EconomyError", {
71
+ readonly code: Schema.Literals<readonly ["invalid_currency", "invalid_amount", "overflow", "invalid_price", "real_money_disabled", "invalid_input", "invalid_record", "currency_cap_reached", "insufficient_funds", "conflict", "forbidden", "unavailable", "not_found", "erased", "limit_exceeded", "already_redeemed"]>;
72
+ }>, YieldableError>;
73
+
74
+ declare interface EconomyReceipt {
75
+ readonly txId: string;
76
+ readonly currency: string;
77
+ readonly amount: string;
78
+ readonly at: number;
79
+ }
80
+
81
+ declare interface EconomyReference {
82
+ readonly kind: string;
83
+ readonly id: string;
84
+ }
85
+
86
+ /** Guarded server-produced metadata. Ephemeral listeners are not the durable SQL audience. */
87
+ export declare const economyRefunded: EventDescriptor<"economy.refunded", Schema.Struct<{
88
+ readonly subjectId: Schema.String;
89
+ }>, Schema.Struct<{
90
+ readonly eventId: Schema.String;
91
+ readonly orderId: Schema.String;
92
+ readonly sequence: Schema.Number;
93
+ readonly state: Schema.Literals<readonly ["active", "partially-refunded", "revoked"]>;
94
+ readonly refundNumerator: Schema.Number;
95
+ readonly refundDenominator: Schema.Number;
96
+ readonly observedAt: Schema.Number;
97
+ }>, DeclaredAccess<{
98
+ readonly subjectId: string;
99
+ }>>;
100
+
101
+ export declare const economyRefundReversed: EventDescriptor<"economy.refundReversed", Schema.Struct<{
102
+ readonly subjectId: Schema.String;
103
+ }>, Schema.Struct<{
104
+ readonly eventId: Schema.String;
105
+ readonly orderId: Schema.String;
106
+ readonly sequence: Schema.Number;
107
+ readonly state: Schema.Literals<readonly ["active", "partially-refunded", "revoked"]>;
108
+ readonly refundNumerator: Schema.Number;
109
+ readonly refundDenominator: Schema.Number;
110
+ readonly observedAt: Schema.Number;
111
+ }>, DeclaredAccess<{
112
+ readonly subjectId: string;
113
+ }>>;
114
+
115
+ declare interface EconomyService {
116
+ /** Trusted server transfer, never a player-authored value mutation. */
117
+ readonly transfer: (subject: Subject, input: LedgerTransferInput) => Effect.Effect<EconomyReceipt, EconomyError>;
118
+ readonly mine: (subject: Subject) => Effect.Effect<readonly EconomyWallet[], EconomyError>;
119
+ readonly auditWallet: (subject: Subject, tenantId: string, account: EconomyAccount, currency: string) => Effect.Effect<EconomyWalletAudit, EconomyError>;
120
+ readonly rebuildWallet: (subject: Subject, tenantId: string, account: EconomyAccount, currency: string) => Effect.Effect<EconomyWalletAudit, EconomyError>;
121
+ }
122
+
123
+ declare interface EconomySqlService extends EconomySystemService, WalletEscrowParticipant {
124
+ /** Trusted original purchase evidence required; no player price, owner or state authority. */
125
+ readonly prepareIapRefund: (subject: Subject, proof: VerifiedIapCurrentState, input: IapWalletRefundInput) => Effect.Effect<PreparedSqlMutation<EconomyReceipt>, EconomyError>;
126
+ readonly prepareTransfer: (subject: Subject, input: LedgerTransferInput) => Effect.Effect<PreparedSqlMutation<EconomyReceipt>, EconomyError>;
127
+ }
128
+
129
+ /** Full installed replacement adds both privacy hooks; the dependent port stays four methods. */
130
+ declare interface EconomySystemService extends EconomyService {
131
+ readonly exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<unknown, EconomyError>;
132
+ readonly eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, EconomyError>;
133
+ }
134
+
135
+ declare interface EconomyWallet {
136
+ readonly currency: string;
137
+ readonly balance: string;
138
+ readonly updatedAt: number | null;
139
+ }
140
+
141
+ declare interface EconomyWalletAudit {
142
+ readonly currency: string;
143
+ readonly balance: string;
144
+ readonly ledgerBalance: string;
145
+ readonly ledgerRows: number;
146
+ readonly matches: boolean;
147
+ }
148
+
149
+ declare type EscrowWallet = Extract<EconomyAccount, {
150
+ readonly kind: 'wallet';
151
+ }>;
152
+
153
+ declare interface IapCurrentPurchaseState {
154
+ readonly orderId: string;
155
+ readonly channel: IapRefundChannel;
156
+ readonly state: 'active' | 'partially-refunded' | 'revoked';
157
+ /** Exact cumulative provider refund share; never floating point or money sent by a player. */
158
+ readonly refundNumerator: number;
159
+ readonly refundDenominator: number;
160
+ readonly observedAt: number;
161
+ readonly revokedAt: number | null;
162
+ }
163
+
164
+ export declare type IapDebtPolicy = 'allowNegative' | 'blockSpend';
165
+
166
+ declare type IapEnvironment = 'sandbox' | 'production';
167
+
168
+ export declare interface IapInventoryRefundOptions {
169
+ readonly inventory: Pick<InventorySqlService, 'prepareConsume' | 'prepareGrant'>;
170
+ /** Explicit studio decision. Missing/traded/consumed items never count as recovered. */
171
+ readonly disposition: IapItemRefundDisposition;
172
+ }
173
+
174
+ export declare interface IapInventoryRefundReceipt {
175
+ readonly disposition: IapItemRefundDisposition;
176
+ readonly items: readonly ItemDisposition[];
177
+ readonly operations: readonly Movement[];
178
+ readonly targets: readonly number[];
179
+ }
180
+
181
+ export declare type IapItemRefundDisposition = 'requireAll' | 'recoverRemaining';
182
+
183
+ declare interface IapNotificationTargetOptions {
184
+ readonly realMoney: boolean;
185
+ readonly channel: IapRefundChannel;
186
+ readonly applicationId: string;
187
+ readonly environment: IapEnvironment;
188
+ }
189
+
190
+ declare type IapOrderObservation = {
191
+ readonly requestId: string;
192
+ readonly state: 'not-observed' | 'pending';
193
+ } | {
194
+ readonly requestId: string;
195
+ readonly state: 'fulfilled';
196
+ readonly receipt: IapOrderReceipt;
197
+ readonly refund?: IapRefundDisposition;
198
+ } | {
199
+ readonly requestId: string;
200
+ readonly state: 'partially-refunded' | 'refunded';
201
+ readonly receipt: IapOrderReceipt;
202
+ readonly refund: IapRefundDisposition;
203
+ };
204
+
205
+ declare interface IapOrderReceipt {
206
+ readonly orderId: string;
207
+ readonly offerId: string;
208
+ readonly offerVersion: string;
209
+ readonly quantity: number;
210
+ readonly at: number;
211
+ readonly pricePaid: IapPaidAmount | null;
212
+ readonly transfers: readonly {
213
+ readonly txId: string;
214
+ readonly currency: string;
215
+ readonly amount: string;
216
+ readonly at: number;
217
+ }[];
218
+ readonly grants: readonly {
219
+ readonly operationId: string;
220
+ readonly kind: 'grant';
221
+ readonly changes: readonly {
222
+ readonly instanceId: string;
223
+ readonly delta: number;
224
+ }[];
225
+ readonly at: number;
226
+ }[];
227
+ }
228
+
229
+ /** Provider units retain their own decimal scale. Reference prices are never substituted. */
230
+ declare interface IapPaidAmount {
231
+ readonly currency: string;
232
+ readonly units: string;
233
+ readonly scale: number;
234
+ }
235
+
236
+ declare interface IapProduct {
237
+ readonly offer: ShopOffer;
238
+ readonly channel: EconomyChannel;
239
+ readonly kind: IapProductKind;
240
+ readonly storeProductId: string;
241
+ }
242
+
243
+ declare type IapProductKind = 'consumable' | 'non-consumable' | 'subscription';
244
+
245
+ declare interface IapReceiptIntent {
246
+ readonly channel: EconomyChannel;
247
+ readonly offerId: string;
248
+ readonly offerVersion: string;
249
+ readonly requestId: string;
250
+ /** Opaque store evidence. Never log or persist this in player receipts. */
251
+ readonly receipt: string;
252
+ }
253
+
254
+ /** Read-only original-intention reference. Never send raw receipts in query parameters. */
255
+ declare interface IapReceiptReference {
256
+ readonly channel: EconomyChannel;
257
+ readonly offerId: string;
258
+ readonly offerVersion: string;
259
+ readonly requestId: string;
260
+ readonly receiptDigest: string;
261
+ }
262
+
263
+ export declare interface IapRefundAbuseDecision {
264
+ readonly confidence: number;
265
+ }
266
+
267
+ export declare type IapRefundAbusePolicy = (context: IapRefundEventContext) => IapRefundAbuseDecision | null;
268
+
269
+ export declare const iapRefundAdjustmentsTable: Table<"_voltro_eco_iap_refund_adjustments", FieldDefinitions<{
270
+ readonly id: ColumnBuilder<string, "id", boolean>;
271
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
272
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
273
+ readonly ownerKey: ColumnBuilder<string, "text", boolean>;
274
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
275
+ readonly orderId: ColumnBuilder<string, "text", boolean>;
276
+ readonly sequence: ColumnBuilder<number, "integer", boolean>;
277
+ readonly receipt: ColumnBuilder<unknown, "json", boolean>;
278
+ readonly at: ColumnBuilder<Date, "timestamp", boolean>;
279
+ readonly eventState: ColumnBuilder<string, "text", boolean>;
280
+ readonly eventDeliveryVersion: ColumnBuilder<string | null, "text", boolean>;
281
+ }>, true, "voltro_eco_iap_refund_adjustments_owner_idx">;
282
+
283
+ export declare interface IapRefundAssetContext {
284
+ readonly original: IapSqlOriginalPurchase;
285
+ readonly state: IapCurrentPurchaseState;
286
+ readonly previous: IapRefundReceipt | null;
287
+ readonly sequence: number;
288
+ }
289
+
290
+ /** Mandatory for orders with item grants. It must use the same real store and original grant custody. */
291
+ export declare interface IapRefundAssetParticipant {
292
+ readonly prepare: (input: IapRefundAssetContext) => Effect.Effect<PreparedSqlMutation<unknown>, EconomyError>;
293
+ readonly validate: (input: IapRefundAssetContext, receipt: unknown) => unknown;
294
+ /** SQL-only audit of accepted movement receipts; no provider/application callbacks. */
295
+ readonly audit: (tx: DataStore, input: IapRefundAssetContext, receipt: unknown) => Promise<void>;
296
+ }
297
+
298
+ /** Channels whose providers report refunds and revocations to the economy. */
299
+ declare type IapRefundChannel = 'ios' | 'android' | 'web';
300
+
301
+ export declare interface IapRefundCurrency {
302
+ readonly currency: string;
303
+ readonly original: string;
304
+ readonly refunded: string;
305
+ }
306
+
307
+ /** Accepted SQL refund history only. This projection never authorizes a grant or completion. */
308
+ declare interface IapRefundDisposition {
309
+ readonly sequence: number;
310
+ readonly state: 'active' | 'partially-refunded' | 'revoked';
311
+ readonly refundNumerator: number;
312
+ readonly refundDenominator: number;
313
+ readonly observedAt: number;
314
+ }
315
+
316
+ /** Borrowed transaction read only: no provider, nested transaction, seed, clock or mutation. */
317
+ declare interface IapRefundDispositionSource {
318
+ readonly read: (tx: DataStore, original: IapSqlOriginalPurchase) => Promise<IapRefundDisposition | null>;
319
+ }
320
+
321
+ export declare interface IapRefundEventContext {
322
+ readonly namespace: string;
323
+ readonly tenantId: string;
324
+ readonly subjectId: string;
325
+ readonly payload: IapRefundEventPayload;
326
+ /** Complete bounded accepted history; these are observations, never a fraud verdict. */
327
+ readonly refundedOrders: number;
328
+ readonly observedOrders: number;
329
+ readonly refundAdjustments: number;
330
+ }
331
+
332
+ export declare interface IapRefundEventDeliveryOptions {
333
+ readonly events: IapRefundEventsService;
334
+ readonly publisher: IapRefundEventPublisherSource;
335
+ readonly version: string;
336
+ readonly maxEvents?: number | undefined;
337
+ readonly sanctions?: Pick<SanctionsService, 'recordSignal'> | undefined;
338
+ readonly abusePolicy?: IapRefundAbusePolicy | undefined;
339
+ }
340
+
341
+ export declare interface IapRefundEventDeliveryResult {
342
+ readonly scannedRows: number;
343
+ readonly deliveredEvents: number;
344
+ readonly classifiedSignals: number;
345
+ }
346
+
347
+ export declare type IapRefundEventPayload = typeof IapRefundEventPayloadSchema.Type;
348
+
349
+ export declare const IapRefundEventPayloadSchema: Schema.Struct<{
350
+ readonly eventId: Schema.String;
351
+ readonly orderId: Schema.String;
352
+ readonly sequence: Schema.Number;
353
+ readonly state: Schema.Literals<readonly ["active", "partially-refunded", "revoked"]>;
354
+ readonly refundNumerator: Schema.Number;
355
+ readonly refundDenominator: Schema.Number;
356
+ readonly observedAt: Schema.Number;
357
+ }>;
358
+
359
+ export declare interface IapRefundEventPublisherSource {
360
+ /** Actual tenant-bound framework context, including its durable workflow audience when configured. */
361
+ readonly read: (tenantId: string) => Effect.Effect<EventPublishContext, EconomyError>;
362
+ }
363
+
364
+ /** Ordinary discovered schedule. It starts no timer and supplies no invented event bus or tenant. */
365
+ export declare const iapRefundEventSchedule: (input: IapRefundEventScheduleOptions) => BrandedScheduleDefinition;
366
+
367
+ export declare interface IapRefundEventScheduleOptions extends IapRefundEventDeliveryOptions {
368
+ readonly name: string;
369
+ readonly cron: string;
370
+ readonly timezone?: string;
371
+ }
372
+
373
+ export declare class IapRefundEventsPort extends IapRefundEventsPort_base {
374
+ }
375
+
376
+ declare const IapRefundEventsPort_base: Context.ServiceClass<IapRefundEventsPort, "@voltro/IapRefundEventsPort", IapRefundEventsService>;
377
+
378
+ export declare interface IapRefundEventsService {
379
+ readonly pending: (subject: Subject) => Effect.Effect<readonly PendingIapRefundEvent[], EconomyError>;
380
+ readonly read: (subject: Subject, event: PendingIapRefundEvent) => Effect.Effect<IapRefundEventContext, EconomyError>;
381
+ readonly acknowledge: (subject: Subject, event: PendingIapRefundEvent, deliveryVersion: string) => Effect.Effect<void, EconomyError>;
382
+ }
383
+
384
+ export declare const iapRefundNamespacesTable: Table<"_voltro_eco_iap_refund_namespaces", FieldDefinitions<{
385
+ readonly id: ColumnBuilder<string, "id", boolean>;
386
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
387
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
388
+ readonly configurationDigest: ColumnBuilder<string, "text", boolean>;
389
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
390
+ }>, true, never>;
391
+
392
+ export declare interface IapRefundOptions {
393
+ readonly realMoney: boolean;
394
+ readonly namespace: string;
395
+ readonly debtPolicy: IapDebtPolicy;
396
+ readonly orders: Pick<IapSqlService, 'prepareCurrentState'>;
397
+ readonly economy: Pick<EconomySqlService, 'prepareTransfer' | 'prepareIapRefund'>;
398
+ readonly assets?: IapRefundAssetParticipant | undefined;
399
+ readonly assetsVersion?: string | undefined;
400
+ readonly maxHistoryRows?: number | undefined;
401
+ }
402
+
403
+ export declare const iapRefundOrdersTable: Table<"_voltro_eco_iap_refund_orders", FieldDefinitions<{
404
+ readonly id: ColumnBuilder<string, "id", boolean>;
405
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
406
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
407
+ readonly ownerKey: ColumnBuilder<string, "text", boolean>;
408
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
409
+ readonly orderId: ColumnBuilder<string, "text", boolean>;
410
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
411
+ readonly configurationDigest: ColumnBuilder<string, "text", boolean>;
412
+ readonly receipt: ColumnBuilder<unknown, "json", boolean>;
413
+ readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
414
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
415
+ }>, true, "voltro_eco_iap_refund_orders_owner_idx">;
416
+
417
+ export declare class IapRefundPort extends IapRefundPort_base {
418
+ }
419
+
420
+ declare const IapRefundPort_base: Context.ServiceClass<IapRefundPort, "@voltro/IapRefundPort", IapRefundService>;
421
+
422
+ export declare interface IapRefundReceipt {
423
+ readonly orderId: string;
424
+ readonly sequence: number;
425
+ readonly state: IapCurrentPurchaseState['state'];
426
+ readonly refundNumerator: number;
427
+ readonly refundDenominator: number;
428
+ readonly observedAt: number;
429
+ readonly noticeId: string;
430
+ readonly fingerprint: string;
431
+ readonly debtPolicy: IapDebtPolicy;
432
+ readonly currencies: readonly IapRefundCurrency[];
433
+ readonly transfers: readonly EconomyReceipt[];
434
+ /** Opaque actual asset participant receipt, validated by its captured participant. */
435
+ readonly assets: unknown;
436
+ }
437
+
438
+ export declare interface IapRefundService {
439
+ readonly reconcile: (proof: VerifiedIapCurrentState) => Effect.Effect<IapRefundReceipt, EconomyError>;
440
+ readonly rebuild: (proof: VerifiedIapCurrentState) => Effect.Effect<IapRefundReceipt | null, EconomyError>;
441
+ readonly observe: (scope: IapScope, orderId: string) => Effect.Effect<IapRefundReceipt | null, EconomyError>;
442
+ readonly exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<unknown, EconomyError>;
443
+ readonly eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, EconomyError>;
444
+ }
445
+
446
+ /** SQL remains refund history and rebuild source. External provider I/O is complete before this writer. */
447
+ export declare interface IapRefundSqlService extends IapRefundService {
448
+ readonly events: IapRefundEventsService;
449
+ readonly readDisposition: IapRefundDispositionSource['read'];
450
+ }
451
+
452
+ export declare const iapRefundSubjectsTable: Table<"_voltro_eco_iap_refund_subjects", FieldDefinitions<{
453
+ readonly id: ColumnBuilder<string, "id", boolean>;
454
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
455
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
456
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
457
+ readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
458
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
459
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
460
+ }>, true, never>;
461
+
462
+ export declare const iapRefundTables: readonly [ Table<"_voltro_eco_iap_refund_namespaces", FieldDefinitions<{
463
+ readonly id: ColumnBuilder<string, "id", boolean>;
464
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
465
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
466
+ readonly configurationDigest: ColumnBuilder<string, "text", boolean>;
467
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
468
+ }>, true, never>, Table<"_voltro_eco_iap_refund_subjects", FieldDefinitions<{
469
+ readonly id: ColumnBuilder<string, "id", boolean>;
470
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
471
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
472
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
473
+ readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
474
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
475
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
476
+ }>, true, never>, Table<"_voltro_eco_iap_refund_orders", FieldDefinitions<{
477
+ readonly id: ColumnBuilder<string, "id", boolean>;
478
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
479
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
480
+ readonly ownerKey: ColumnBuilder<string, "text", boolean>;
481
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
482
+ readonly orderId: ColumnBuilder<string, "text", boolean>;
483
+ readonly admission: ColumnBuilder<number, "integer", boolean>;
484
+ readonly configurationDigest: ColumnBuilder<string, "text", boolean>;
485
+ readonly receipt: ColumnBuilder<unknown, "json", boolean>;
486
+ readonly erased: ColumnBuilder<boolean, "boolean", boolean>;
487
+ readonly rowsCount: ColumnBuilder<number, "integer", boolean>;
488
+ }>, true, "voltro_eco_iap_refund_orders_owner_idx">, Table<"_voltro_eco_iap_refund_adjustments", FieldDefinitions<{
489
+ readonly id: ColumnBuilder<string, "id", boolean>;
490
+ readonly namespace: ColumnBuilder<string, "text", boolean>;
491
+ readonly tenantId: ColumnBuilder<string, "text", boolean>;
492
+ readonly ownerKey: ColumnBuilder<string, "text", boolean>;
493
+ readonly ownerId: ColumnBuilder<string | null, "text", boolean>;
494
+ readonly orderId: ColumnBuilder<string, "text", boolean>;
495
+ readonly sequence: ColumnBuilder<number, "integer", boolean>;
496
+ readonly receipt: ColumnBuilder<unknown, "json", boolean>;
497
+ readonly at: ColumnBuilder<Date, "timestamp", boolean>;
498
+ readonly eventState: ColumnBuilder<string, "text", boolean>;
499
+ readonly eventDeliveryVersion: ColumnBuilder<string | null, "text", boolean>;
500
+ }>, true, "voltro_eco_iap_refund_adjustments_owner_idx">];
501
+
502
+ declare interface IapScope {
503
+ readonly tenantId: string;
504
+ readonly ownerId: string;
505
+ }
506
+
507
+ declare interface IapService {
508
+ readonly redeem: (subject: Subject, input: IapReceiptIntent) => Effect.Effect<IapOrderReceipt, EconomyError>;
509
+ readonly receipt: (subject: Subject, input: IapReceiptReference) => Effect.Effect<IapOrderObservation, EconomyError>;
510
+ readonly exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<unknown, EconomyError>;
511
+ readonly eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, EconomyError>;
512
+ }
513
+
514
+ /** SQL original after the owning adapter has validated its immutable custody and receipt. */
515
+ declare interface IapSqlOriginalPurchase {
516
+ readonly orderId: string;
517
+ readonly scope: IapScope;
518
+ readonly receipt: IapOrderReceipt;
519
+ readonly product: IapProduct;
520
+ readonly facts: IapTransactionFacts;
521
+ readonly currencies: readonly CurrencyDefinition[];
522
+ }
523
+
524
+ declare interface IapSqlService extends IapService {
525
+ /** Complete owned accepted subscription periods. SQL reads only; never current provider status. */
526
+ readonly subscriptionPeriods: (subject: Subject) => Effect.Effect<readonly IapSubscriptionPeriod[], EconomyError>;
527
+ /** Server only: the provider's original transaction IDs (a Stripe subscription) of the owner's
528
+ * accepted subscription orders on `channel`, newest period first. Never a player projection. */
529
+ readonly subscriptionOriginals: (subject: Subject, channel: EconomyChannel) => Effect.Effect<readonly string[], EconomyError>;
530
+ /** Actual original IAP/account/retained-notice SQL fences; joins the same-store financial mutation group. */
531
+ readonly prepareCurrentState: (evidence: VerifiedIapCurrentState) => Effect.Effect<PreparedSqlMutation<IapCurrentPurchaseState>, EconomyError>;
532
+ /** Trusted server declaration + authenticated notice; read accepted SQL, never seed or fulfill. */
533
+ readonly prepareNotification: (options: IapNotificationTargetOptions, notice: VerifiedIapNotification) => Effect.Effect<AcceptedIapNotificationTarget, EconomyError>;
534
+ /** Read accepted SQL original and issue a revalidated capability; no grant, clock or provider call. */
535
+ readonly prepareCompletion: (subject: Subject, intent: Parameters<IapService['redeem']>[1]) => Effect.Effect<AcceptedIapCompletion, EconomyError>;
536
+ }
537
+
538
+ /** An accepted store period, not a fresh provider observation or financial capability. */
539
+ declare interface IapSubscriptionPeriod {
540
+ readonly orderId: string;
541
+ readonly offerId: string;
542
+ readonly offerVersion: string;
543
+ readonly channel: EconomyChannel;
544
+ readonly startsAt: number;
545
+ readonly expiresAt: number;
546
+ readonly refund: IapRefundDisposition | null;
547
+ }
548
+
549
+ declare interface IapTransactionFacts {
550
+ readonly channel: EconomyChannel;
551
+ readonly environment: IapEnvironment;
552
+ readonly applicationId: string;
553
+ readonly transactionId: string;
554
+ readonly originalTransactionId: string | null;
555
+ readonly storeProductId: string;
556
+ readonly kind: IapProductKind;
557
+ readonly quantity: number;
558
+ readonly purchasedAt: number;
559
+ readonly expiresAt: number | null;
560
+ readonly paid: IapPaidAmount | null;
561
+ readonly acknowledgement: 'none' | 'pending' | 'acknowledged';
562
+ readonly consumption: 'none' | 'available' | 'consumed';
563
+ }
564
+
565
+ export declare interface IapWalletRefundInput {
566
+ readonly requestId: string;
567
+ readonly currency: string;
568
+ readonly amount: string;
569
+ readonly debtPolicy: IapDebtPolicy;
570
+ }
571
+
572
+ /** Same SQL inventory movement writer, original grant journal and receiver-captured participant. */
573
+ export declare const inventoryIapRefundAssets: (store: DataStore, input: IapInventoryRefundOptions) => IapRefundAssetParticipant;
574
+
575
+ declare interface ItemDisposition {
576
+ readonly grantId: string;
577
+ readonly instanceId: string;
578
+ readonly itemId: string;
579
+ readonly original: number;
580
+ readonly requested: number;
581
+ readonly recovered: number;
582
+ readonly unrecoverable: number;
583
+ readonly candidates: readonly string[];
584
+ }
585
+
586
+ declare interface LedgerTransferInput {
587
+ readonly tenantId: string;
588
+ readonly requestId: string;
589
+ readonly currency: string;
590
+ readonly from: EconomyAccount;
591
+ readonly to: EconomyAccount;
592
+ readonly amount: EconomyAmountInput;
593
+ readonly reason: string;
594
+ readonly ref: EconomyReference;
595
+ }
596
+
597
+ declare interface Movement {
598
+ readonly operationId: string;
599
+ readonly kind: 'consume' | 'grant';
600
+ readonly changes: readonly {
601
+ readonly instanceId: string;
602
+ readonly delta: number;
603
+ }[];
604
+ readonly at: number;
605
+ }
606
+
607
+ /** A refund observation alone establishes no abuse. Operators supply an actual classification policy. */
608
+ export declare const noRefundAbuseSignal: IapRefundAbusePolicy;
609
+
610
+ /** Actual pending SQL event authority. Copies and serialized payloads cannot authorize delivery acknowledgement. */
611
+ export declare interface PendingIapRefundEvent {
612
+ readonly [refundEvent]: true;
613
+ readonly eventId: string;
614
+ }
615
+
616
+ declare type Price = {
617
+ readonly kind: 'virtual';
618
+ readonly options: readonly ResolvedVirtualPriceOption[];
619
+ } | ({
620
+ readonly kind: 'real';
621
+ } & RealPriceDefinition) | {
622
+ readonly kind: 'mixed';
623
+ readonly real: RealPriceDefinition;
624
+ readonly virtual: readonly ResolvedVirtualPriceOption[];
625
+ } | {
626
+ readonly kind: 'free';
627
+ };
628
+
629
+ declare interface RealPriceDefinition {
630
+ /** Integer minor-unit references; verified store receipts remain authoritative. */
631
+ readonly prices: Readonly<Record<string, number>>;
632
+ readonly storeProductIds: Partial<Readonly<Record<EconomyChannel, string>>>;
633
+ }
634
+
635
+ declare const refundEvent: unique symbol;
636
+
637
+ declare interface ResolvedVirtualPriceOption {
638
+ readonly currency: string;
639
+ readonly amount: string;
640
+ }
641
+
642
+ declare interface ShopItemGrant {
643
+ readonly itemId: string;
644
+ readonly qty: number;
645
+ }
646
+
647
+ declare interface ShopOffer {
648
+ readonly id: string;
649
+ readonly version: string;
650
+ readonly titleKey: string;
651
+ readonly price: Price;
652
+ readonly items: readonly ShopItemGrant[];
653
+ readonly currencies: readonly {
654
+ readonly currency: string;
655
+ readonly amount: string;
656
+ }[];
657
+ readonly from: number | null;
658
+ readonly until: number | null;
659
+ readonly segment: string | null;
660
+ readonly flag: string | null;
661
+ readonly countries: readonly string[];
662
+ readonly limits: {
663
+ readonly perPlayer: number | null;
664
+ readonly perDay: number | null;
665
+ readonly global: number | null;
666
+ };
667
+ readonly oneTime: boolean;
668
+ readonly maxQuantity: number;
669
+ }
670
+
671
+ declare const verifiedCurrentState: unique symbol;
672
+
673
+ /** Fresh provider observation bound to revalidated original SQL. Never copied player refund authority. */
674
+ declare interface VerifiedIapCurrentState {
675
+ readonly [verifiedCurrentState]: true;
676
+ readonly orderId: string;
677
+ }
678
+
679
+ /** Authenticated notice, never current purchase state or grant/refund authority. */
680
+ declare interface VerifiedIapNotification {
681
+ readonly [verifiedNotification]: true;
682
+ readonly noticeId: string;
683
+ readonly channel: IapRefundChannel;
684
+ }
685
+
686
+ declare const verifiedNotification: unique symbol;
687
+
688
+ declare interface WalletEscrowFundedSettlementReceipt {
689
+ readonly reserve: EconomyReceipt;
690
+ readonly settlement: WalletEscrowSettlementReceipt;
691
+ }
692
+
693
+ declare interface WalletEscrowInput {
694
+ readonly tenantId: string;
695
+ readonly owner: EscrowWallet;
696
+ readonly reservationId: string;
697
+ readonly currency: string;
698
+ }
699
+
700
+ declare type WalletEscrowObservation = {
701
+ readonly reservationId: string;
702
+ readonly currency: string;
703
+ readonly state: 'not-observed';
704
+ } | {
705
+ readonly reservationId: string;
706
+ readonly currency: string;
707
+ readonly amount: string;
708
+ readonly state: 'held' | 'released' | 'settled';
709
+ readonly receipt: EconomyReceipt;
710
+ readonly closingReceipt: EconomyReceipt | null;
711
+ readonly taxReceipt: EconomyReceipt | null;
712
+ };
713
+
714
+ declare interface WalletEscrowParticipant {
715
+ readonly prepareEscrowReserve: (subject: Subject, input: WalletEscrowReserveInput) => Effect.Effect<PreparedSqlMutation<EconomyReceipt>, EconomyError>;
716
+ readonly prepareEscrowRelease: (subject: Subject, input: WalletEscrowInput) => Effect.Effect<PreparedSqlMutation<EconomyReceipt>, EconomyError>;
717
+ /** Whole gross payout; use prepareEscrowTaxSettle for an exact net/sink split. */
718
+ readonly prepareEscrowSettle: (subject: Subject, input: WalletEscrowSettleInput) => Effect.Effect<PreparedSqlMutation<EconomyReceipt>, EconomyError>;
719
+ readonly prepareEscrowTaxSettle: (subject: Subject, input: WalletEscrowTaxSettleInput) => Effect.Effect<PreparedSqlMutation<WalletEscrowSettlementReceipt>, EconomyError>;
720
+ readonly prepareEscrowReserveTaxSettle: (subject: Subject, input: WalletEscrowReserveTaxSettleInput) => Effect.Effect<PreparedSqlMutation<WalletEscrowFundedSettlementReceipt>, EconomyError>;
721
+ readonly escrow: (subject: Subject, input: WalletEscrowInput) => Effect.Effect<WalletEscrowObservation, EconomyError>;
722
+ }
723
+
724
+ declare interface WalletEscrowReserveInput extends WalletEscrowInput {
725
+ readonly amount: EconomyAmountInput;
726
+ }
727
+
728
+ declare interface WalletEscrowReserveTaxSettleInput extends WalletEscrowReserveInput {
729
+ readonly to: EscrowWallet;
730
+ readonly taxAmount: EconomyAmountInput;
731
+ readonly taxAccountId?: string | undefined;
732
+ }
733
+
734
+ declare interface WalletEscrowSettleInput extends WalletEscrowInput {
735
+ readonly to: EscrowWallet;
736
+ }
737
+
738
+ declare interface WalletEscrowSettlementReceipt {
739
+ readonly reservationId: string;
740
+ readonly currency: string;
741
+ readonly gross: string;
742
+ readonly net: string;
743
+ readonly tax: string;
744
+ readonly payout: EconomyReceipt | null;
745
+ readonly taxReceipt: EconomyReceipt | null;
746
+ }
747
+
748
+ declare interface WalletEscrowTaxSettleInput extends WalletEscrowSettleInput {
749
+ readonly taxAmount: EconomyAmountInput;
750
+ readonly taxAccountId?: string | undefined;
751
+ }
752
+
753
+ declare type WalletOwnerKind = 'player' | 'guild';
754
+
755
+ export { }