@wopr-network/platform-core 1.13.3 → 1.14.1

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 (220) hide show
  1. package/.github/workflows/dependabot-auto-merge.yml +1 -2
  2. package/dist/api/routes/admin-credits.d.ts +2 -2
  3. package/dist/api/routes/admin-credits.js +9 -4
  4. package/dist/api/routes/quota.d.ts +2 -2
  5. package/dist/api/routes/verify-email.d.ts +3 -3
  6. package/dist/backup/on-demand-snapshot-service.d.ts +2 -2
  7. package/dist/billing/payram/webhook.d.ts +3 -3
  8. package/dist/billing/payram/webhook.js +5 -1
  9. package/dist/billing/payram/webhook.test.js +5 -4
  10. package/dist/billing/stripe/stripe-payment-processor.d.ts +2 -2
  11. package/dist/billing/stripe/stripe-payment-processor.test.js +7 -0
  12. package/dist/billing/stripe/tenant-store.d.ts +1 -1
  13. package/dist/billing/stripe/tenant-store.js +1 -1
  14. package/dist/credits/auto-topup-charge.d.ts +2 -2
  15. package/dist/credits/auto-topup-charge.js +5 -1
  16. package/dist/credits/auto-topup-charge.test.js +5 -4
  17. package/dist/credits/auto-topup-usage.d.ts +2 -2
  18. package/dist/credits/auto-topup-usage.test.js +53 -12
  19. package/dist/credits/credit-expiry-cron.d.ts +2 -2
  20. package/dist/credits/credit-expiry-cron.js +7 -4
  21. package/dist/credits/credit-expiry-cron.test.js +25 -8
  22. package/dist/credits/credit-ledger.d.ts +2 -2
  23. package/dist/credits/credit-ledger.js +1 -1
  24. package/dist/credits/dividend-cron.d.ts +4 -6
  25. package/dist/credits/dividend-cron.js +10 -16
  26. package/dist/credits/dividend-cron.test.js +31 -44
  27. package/dist/credits/dividend-repository.js +19 -22
  28. package/dist/credits/dividend-repository.test.js +4 -3
  29. package/dist/credits/index.d.ts +4 -2
  30. package/dist/credits/index.js +2 -1
  31. package/dist/credits/ledger.d.ts +195 -0
  32. package/dist/credits/ledger.js +561 -0
  33. package/dist/credits/ledger.test.js +418 -0
  34. package/dist/credits/signup-grant.d.ts +2 -2
  35. package/dist/credits/signup-grant.js +4 -4
  36. package/dist/credits/signup-grant.test.js +5 -3
  37. package/dist/credits/trial-balance-cron.d.ts +19 -0
  38. package/dist/credits/trial-balance-cron.js +30 -0
  39. package/dist/credits/trial-balance-cron.test.js +55 -0
  40. package/dist/db/schema/index.d.ts +1 -0
  41. package/dist/db/schema/index.js +1 -0
  42. package/dist/db/schema/ledger.d.ts +442 -0
  43. package/dist/db/schema/ledger.js +76 -0
  44. package/dist/gateway/credit-gate.d.ts +2 -2
  45. package/dist/gateway/credit-gate.js +5 -1
  46. package/dist/gateway/credit-gate.test.js +35 -33
  47. package/dist/gateway/protocol/deps.d.ts +2 -2
  48. package/dist/gateway/protocol/handlers.test.js +461 -0
  49. package/dist/gateway/proxy.d.ts +2 -2
  50. package/dist/gateway/types.d.ts +2 -2
  51. package/dist/metering/reconciliation-cron.test.js +9 -8
  52. package/dist/metering/reconciliation-repository.js +12 -10
  53. package/dist/metering/reconciliation-repository.test.js +9 -8
  54. package/dist/monetization/affiliate/affiliate-admin-repository.js +10 -8
  55. package/dist/monetization/affiliate/affiliate-admin-repository.test.js +32 -13
  56. package/dist/monetization/affiliate/credit-match.d.ts +2 -2
  57. package/dist/monetization/affiliate/credit-match.js +4 -1
  58. package/dist/monetization/affiliate/credit-match.test.js +58 -13
  59. package/dist/monetization/affiliate/new-user-bonus.d.ts +2 -2
  60. package/dist/monetization/affiliate/new-user-bonus.js +4 -1
  61. package/dist/monetization/affiliate/new-user-bonus.test.js +4 -3
  62. package/dist/monetization/credits/auto-topup-charge.d.ts +2 -2
  63. package/dist/monetization/credits/auto-topup-charge.js +5 -1
  64. package/dist/monetization/credits/auto-topup-charge.test.js +5 -4
  65. package/dist/monetization/credits/auto-topup-usage.d.ts +2 -2
  66. package/dist/monetization/credits/auto-topup-usage.test.js +53 -12
  67. package/dist/monetization/credits/bot-billing.d.ts +3 -3
  68. package/dist/monetization/credits/bot-billing.test.js +18 -5
  69. package/dist/monetization/credits/credit-expiry-cron.test.js +25 -8
  70. package/dist/monetization/credits/dividend-cron.d.ts +2 -4
  71. package/dist/monetization/credits/dividend-cron.js +7 -4
  72. package/dist/monetization/credits/dividend-cron.test.js +26 -46
  73. package/dist/monetization/credits/dividend-repository.js +15 -24
  74. package/dist/monetization/credits/dividend-repository.test.js +4 -3
  75. package/dist/monetization/credits/index.d.ts +2 -2
  76. package/dist/monetization/credits/index.js +1 -1
  77. package/dist/monetization/credits/member-usage.test.js +23 -10
  78. package/dist/monetization/credits/phone-billing.d.ts +2 -2
  79. package/dist/monetization/credits/phone-billing.js +5 -1
  80. package/dist/monetization/credits/phone-billing.test.js +9 -12
  81. package/dist/monetization/credits/runtime-cron.d.ts +2 -2
  82. package/dist/monetization/credits/runtime-cron.js +32 -8
  83. package/dist/monetization/credits/runtime-cron.test.js +28 -27
  84. package/dist/monetization/credits/runtime-scheduler.d.ts +2 -2
  85. package/dist/monetization/credits/runtime-scheduler.test.js +1 -1
  86. package/dist/monetization/credits/signup-grant.test.js +5 -3
  87. package/dist/monetization/credits/storage-tier-cron.test.js +3 -2
  88. package/dist/monetization/credits/trial-balance-cron.test.js +42 -0
  89. package/dist/monetization/feature-gate.d.ts +3 -3
  90. package/dist/monetization/index.d.ts +3 -3
  91. package/dist/monetization/index.js +1 -1
  92. package/dist/monetization/metering/reconciliation-cron.test.js +9 -8
  93. package/dist/monetization/metering/reconciliation-repository.js +11 -10
  94. package/dist/monetization/metering/reconciliation-repository.test.js +9 -8
  95. package/dist/monetization/payram/webhook.d.ts +2 -2
  96. package/dist/monetization/payram/webhook.js +5 -1
  97. package/dist/monetization/payram/webhook.test.js +5 -4
  98. package/dist/monetization/promotions/engine.d.ts +2 -2
  99. package/dist/monetization/promotions/engine.js +4 -1
  100. package/dist/monetization/promotions/engine.test.js +3 -1
  101. package/dist/monetization/repository-types.d.ts +1 -1
  102. package/dist/monetization/stripe/stripe-payment-processor.d.ts +2 -2
  103. package/dist/monetization/stripe/stripe-payment-processor.test.js +7 -0
  104. package/dist/monetization/stripe/webhook.d.ts +2 -2
  105. package/dist/monetization/stripe/webhook.js +70 -6
  106. package/dist/monetization/stripe/webhook.test.js +20 -15
  107. package/dist/onboarding/onboarding-service.d.ts +2 -2
  108. package/dist/onboarding/onboarding-service.js +6 -2
  109. package/drizzle/migrations/0003_double_entry_ledger.sql +82 -0
  110. package/drizzle/migrations/meta/_journal.json +7 -0
  111. package/package.json +1 -1
  112. package/src/api/routes/admin-credits.ts +11 -14
  113. package/src/api/routes/quota.ts +2 -2
  114. package/src/api/routes/verify-email.ts +4 -4
  115. package/src/backup/on-demand-snapshot-service.test.ts +3 -3
  116. package/src/backup/on-demand-snapshot-service.ts +3 -3
  117. package/src/billing/payram/webhook.test.ts +7 -5
  118. package/src/billing/payram/webhook.ts +8 -11
  119. package/src/billing/stripe/stripe-payment-processor.test.ts +10 -3
  120. package/src/billing/stripe/stripe-payment-processor.ts +3 -3
  121. package/src/billing/stripe/tenant-store.ts +1 -1
  122. package/src/credits/auto-topup-charge.test.ts +7 -5
  123. package/src/credits/auto-topup-charge.ts +7 -10
  124. package/src/credits/auto-topup-usage.test.ts +55 -13
  125. package/src/credits/auto-topup-usage.ts +2 -2
  126. package/src/credits/credit-expiry-cron.test.ts +26 -45
  127. package/src/credits/credit-expiry-cron.ts +9 -12
  128. package/src/credits/credit-ledger.ts +3 -3
  129. package/src/credits/dividend-cron.test.ts +38 -45
  130. package/src/credits/dividend-cron.ts +12 -26
  131. package/src/credits/dividend-repository.test.ts +4 -3
  132. package/src/credits/dividend-repository.ts +21 -23
  133. package/src/credits/index.ts +23 -4
  134. package/src/credits/ledger.test.ts +514 -0
  135. package/src/credits/ledger.ts +851 -0
  136. package/src/credits/signup-grant.test.ts +7 -4
  137. package/src/credits/signup-grant.ts +6 -12
  138. package/src/credits/trial-balance-cron.test.ts +68 -0
  139. package/src/credits/trial-balance-cron.ts +46 -0
  140. package/src/db/schema/index.ts +1 -0
  141. package/src/db/schema/ledger.ts +94 -0
  142. package/src/gateway/credit-gate-wiring.test.ts +3 -3
  143. package/src/gateway/credit-gate.test.ts +35 -33
  144. package/src/gateway/credit-gate.ts +6 -10
  145. package/src/gateway/gateway-routes.test.ts +5 -5
  146. package/src/gateway/protocol/deps.ts +2 -2
  147. package/src/gateway/protocol/handlers.test.ts +549 -1
  148. package/src/gateway/proxy.ts +2 -2
  149. package/src/gateway/route-mounting.test.ts +2 -2
  150. package/src/gateway/types.ts +2 -2
  151. package/src/metering/reconciliation-cron.test.ts +10 -9
  152. package/src/metering/reconciliation-repository.test.ts +10 -9
  153. package/src/metering/reconciliation-repository.ts +14 -11
  154. package/src/monetization/affiliate/affiliate-admin-repository.test.ts +32 -19
  155. package/src/monetization/affiliate/affiliate-admin-repository.ts +16 -8
  156. package/src/monetization/affiliate/credit-match.test.ts +60 -14
  157. package/src/monetization/affiliate/credit-match.ts +6 -9
  158. package/src/monetization/affiliate/new-user-bonus.test.ts +6 -4
  159. package/src/monetization/affiliate/new-user-bonus.ts +6 -9
  160. package/src/monetization/credits/auto-topup-charge.test.ts +7 -5
  161. package/src/monetization/credits/auto-topup-charge.ts +7 -10
  162. package/src/monetization/credits/auto-topup-usage.test.ts +55 -13
  163. package/src/monetization/credits/auto-topup-usage.ts +2 -2
  164. package/src/monetization/credits/bot-billing.test.ts +20 -6
  165. package/src/monetization/credits/bot-billing.ts +3 -3
  166. package/src/monetization/credits/credit-expiry-cron.test.ts +26 -45
  167. package/src/monetization/credits/dividend-cron.test.ts +34 -48
  168. package/src/monetization/credits/dividend-cron.ts +9 -14
  169. package/src/monetization/credits/dividend-repository.test.ts +4 -3
  170. package/src/monetization/credits/dividend-repository.ts +19 -25
  171. package/src/monetization/credits/index.ts +4 -4
  172. package/src/monetization/credits/member-usage.test.ts +25 -11
  173. package/src/monetization/credits/phone-billing.test.ts +18 -26
  174. package/src/monetization/credits/phone-billing.ts +7 -10
  175. package/src/monetization/credits/runtime-cron.test.ts +29 -28
  176. package/src/monetization/credits/runtime-cron.ts +34 -58
  177. package/src/monetization/credits/runtime-scheduler.test.ts +1 -1
  178. package/src/monetization/credits/runtime-scheduler.ts +2 -2
  179. package/src/monetization/credits/signup-grant.test.ts +7 -4
  180. package/src/monetization/credits/storage-tier-cron.test.ts +5 -3
  181. package/src/monetization/credits/trial-balance-cron.test.ts +52 -0
  182. package/src/monetization/feature-gate.ts +3 -3
  183. package/src/monetization/index.ts +4 -4
  184. package/src/monetization/metering/reconciliation-cron.test.ts +10 -9
  185. package/src/monetization/metering/reconciliation-repository.test.ts +11 -9
  186. package/src/monetization/metering/reconciliation-repository.ts +13 -11
  187. package/src/monetization/payram/webhook.test.ts +7 -5
  188. package/src/monetization/payram/webhook.ts +7 -10
  189. package/src/monetization/promotions/engine.test.ts +6 -5
  190. package/src/monetization/promotions/engine.ts +6 -3
  191. package/src/monetization/repository-types.ts +1 -1
  192. package/src/monetization/stripe/stripe-payment-processor.test.ts +10 -3
  193. package/src/monetization/stripe/stripe-payment-processor.ts +3 -3
  194. package/src/monetization/stripe/webhook.test.ts +22 -16
  195. package/src/monetization/stripe/webhook.ts +75 -50
  196. package/src/onboarding/onboarding-service.ts +8 -11
  197. package/dist/credits/credit-ledger-extra.test.js +0 -40
  198. package/dist/credits/credit-ledger.bench.js +0 -33
  199. package/dist/credits/credit-ledger.test.d.ts +0 -4
  200. package/dist/credits/credit-ledger.test.js +0 -203
  201. package/dist/credits/credit-transaction-repository.test.js +0 -232
  202. package/dist/monetization/credits/credit-ledger-extra.test.d.ts +0 -1
  203. package/dist/monetization/credits/credit-ledger-extra.test.js +0 -39
  204. package/dist/monetization/credits/credit-ledger.bench.d.ts +0 -1
  205. package/dist/monetization/credits/credit-ledger.bench.js +0 -32
  206. package/dist/monetization/credits/credit-ledger.test.d.ts +0 -4
  207. package/dist/monetization/credits/credit-ledger.test.js +0 -202
  208. package/dist/monetization/credits/credit-transaction-repository.test.d.ts +0 -1
  209. package/dist/monetization/credits/credit-transaction-repository.test.js +0 -232
  210. package/src/credits/credit-ledger-extra.test.ts +0 -57
  211. package/src/credits/credit-ledger.bench.ts +0 -56
  212. package/src/credits/credit-ledger.test.ts +0 -276
  213. package/src/credits/credit-transaction-repository.test.ts +0 -274
  214. package/src/monetization/credits/credit-ledger-extra.test.ts +0 -56
  215. package/src/monetization/credits/credit-ledger.bench.ts +0 -55
  216. package/src/monetization/credits/credit-ledger.test.ts +0 -275
  217. package/src/monetization/credits/credit-transaction-repository.test.ts +0 -274
  218. /package/dist/credits/{credit-ledger-extra.test.d.ts → ledger.test.d.ts} +0 -0
  219. /package/dist/credits/{credit-ledger.bench.d.ts → trial-balance-cron.test.d.ts} +0 -0
  220. /package/dist/{credits/credit-transaction-repository.test.d.ts → monetization/credits/trial-balance-cron.test.d.ts} +0 -0
@@ -0,0 +1,442 @@
1
+ export declare const accountTypeEnum: import("drizzle-orm/pg-core").PgEnum<["asset", "liability", "equity", "revenue", "expense"]>;
2
+ export declare const entrySideEnum: import("drizzle-orm/pg-core").PgEnum<["debit", "credit"]>;
3
+ /**
4
+ * Chart of accounts — every account that can appear in a journal line.
5
+ *
6
+ * System accounts (tenant_id IS NULL) are seeded at migration time.
7
+ * Per-tenant liability accounts are created lazily on first transaction.
8
+ */
9
+ export declare const accounts: import("drizzle-orm/pg-core").PgTableWithColumns<{
10
+ name: "accounts";
11
+ schema: undefined;
12
+ columns: {
13
+ id: import("drizzle-orm/pg-core").PgColumn<{
14
+ name: "id";
15
+ tableName: "accounts";
16
+ dataType: "string";
17
+ columnType: "PgText";
18
+ data: string;
19
+ driverParam: string;
20
+ notNull: true;
21
+ hasDefault: false;
22
+ isPrimaryKey: true;
23
+ isAutoincrement: false;
24
+ hasRuntimeDefault: false;
25
+ enumValues: [string, ...string[]];
26
+ baseColumn: never;
27
+ identity: undefined;
28
+ generated: undefined;
29
+ }, {}, {}>;
30
+ code: import("drizzle-orm/pg-core").PgColumn<{
31
+ name: "code";
32
+ tableName: "accounts";
33
+ dataType: "string";
34
+ columnType: "PgText";
35
+ data: string;
36
+ driverParam: string;
37
+ notNull: true;
38
+ hasDefault: false;
39
+ isPrimaryKey: false;
40
+ isAutoincrement: false;
41
+ hasRuntimeDefault: false;
42
+ enumValues: [string, ...string[]];
43
+ baseColumn: never;
44
+ identity: undefined;
45
+ generated: undefined;
46
+ }, {}, {}>;
47
+ name: import("drizzle-orm/pg-core").PgColumn<{
48
+ name: "name";
49
+ tableName: "accounts";
50
+ dataType: "string";
51
+ columnType: "PgText";
52
+ data: string;
53
+ driverParam: string;
54
+ notNull: true;
55
+ hasDefault: false;
56
+ isPrimaryKey: false;
57
+ isAutoincrement: false;
58
+ hasRuntimeDefault: false;
59
+ enumValues: [string, ...string[]];
60
+ baseColumn: never;
61
+ identity: undefined;
62
+ generated: undefined;
63
+ }, {}, {}>;
64
+ type: import("drizzle-orm/pg-core").PgColumn<{
65
+ name: "type";
66
+ tableName: "accounts";
67
+ dataType: "string";
68
+ columnType: "PgEnumColumn";
69
+ data: "asset" | "liability" | "equity" | "revenue" | "expense";
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: ["asset", "liability", "equity", "revenue", "expense"];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {}>;
81
+ normalSide: import("drizzle-orm/pg-core").PgColumn<{
82
+ name: "normal_side";
83
+ tableName: "accounts";
84
+ dataType: "string";
85
+ columnType: "PgEnumColumn";
86
+ data: "debit" | "credit";
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: false;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: ["debit", "credit"];
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {}>;
98
+ tenantId: import("drizzle-orm/pg-core").PgColumn<{
99
+ name: "tenant_id";
100
+ tableName: "accounts";
101
+ dataType: "string";
102
+ columnType: "PgText";
103
+ data: string;
104
+ driverParam: string;
105
+ notNull: false;
106
+ hasDefault: false;
107
+ isPrimaryKey: false;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: [string, ...string[]];
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {}>;
115
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
116
+ name: "created_at";
117
+ tableName: "accounts";
118
+ dataType: "string";
119
+ columnType: "PgText";
120
+ data: string;
121
+ driverParam: string;
122
+ notNull: true;
123
+ hasDefault: true;
124
+ isPrimaryKey: false;
125
+ isAutoincrement: false;
126
+ hasRuntimeDefault: false;
127
+ enumValues: [string, ...string[]];
128
+ baseColumn: never;
129
+ identity: undefined;
130
+ generated: undefined;
131
+ }, {}, {}>;
132
+ };
133
+ dialect: "pg";
134
+ }>;
135
+ /**
136
+ * Journal entries — the header for each balanced transaction.
137
+ * One business event = one journal entry = two or more journal lines that sum to zero.
138
+ */
139
+ export declare const journalEntries: import("drizzle-orm/pg-core").PgTableWithColumns<{
140
+ name: "journal_entries";
141
+ schema: undefined;
142
+ columns: {
143
+ id: import("drizzle-orm/pg-core").PgColumn<{
144
+ name: "id";
145
+ tableName: "journal_entries";
146
+ dataType: "string";
147
+ columnType: "PgText";
148
+ data: string;
149
+ driverParam: string;
150
+ notNull: true;
151
+ hasDefault: false;
152
+ isPrimaryKey: true;
153
+ isAutoincrement: false;
154
+ hasRuntimeDefault: false;
155
+ enumValues: [string, ...string[]];
156
+ baseColumn: never;
157
+ identity: undefined;
158
+ generated: undefined;
159
+ }, {}, {}>;
160
+ postedAt: import("drizzle-orm/pg-core").PgColumn<{
161
+ name: "posted_at";
162
+ tableName: "journal_entries";
163
+ dataType: "string";
164
+ columnType: "PgText";
165
+ data: string;
166
+ driverParam: string;
167
+ notNull: true;
168
+ hasDefault: true;
169
+ isPrimaryKey: false;
170
+ isAutoincrement: false;
171
+ hasRuntimeDefault: false;
172
+ enumValues: [string, ...string[]];
173
+ baseColumn: never;
174
+ identity: undefined;
175
+ generated: undefined;
176
+ }, {}, {}>;
177
+ entryType: import("drizzle-orm/pg-core").PgColumn<{
178
+ name: "entry_type";
179
+ tableName: "journal_entries";
180
+ dataType: "string";
181
+ columnType: "PgText";
182
+ data: string;
183
+ driverParam: string;
184
+ notNull: true;
185
+ hasDefault: false;
186
+ isPrimaryKey: false;
187
+ isAutoincrement: false;
188
+ hasRuntimeDefault: false;
189
+ enumValues: [string, ...string[]];
190
+ baseColumn: never;
191
+ identity: undefined;
192
+ generated: undefined;
193
+ }, {}, {}>;
194
+ description: import("drizzle-orm/pg-core").PgColumn<{
195
+ name: "description";
196
+ tableName: "journal_entries";
197
+ dataType: "string";
198
+ columnType: "PgText";
199
+ data: string;
200
+ driverParam: string;
201
+ notNull: false;
202
+ hasDefault: false;
203
+ isPrimaryKey: false;
204
+ isAutoincrement: false;
205
+ hasRuntimeDefault: false;
206
+ enumValues: [string, ...string[]];
207
+ baseColumn: never;
208
+ identity: undefined;
209
+ generated: undefined;
210
+ }, {}, {}>;
211
+ referenceId: import("drizzle-orm/pg-core").PgColumn<{
212
+ name: "reference_id";
213
+ tableName: "journal_entries";
214
+ dataType: "string";
215
+ columnType: "PgText";
216
+ data: string;
217
+ driverParam: string;
218
+ notNull: false;
219
+ hasDefault: false;
220
+ isPrimaryKey: false;
221
+ isAutoincrement: false;
222
+ hasRuntimeDefault: false;
223
+ enumValues: [string, ...string[]];
224
+ baseColumn: never;
225
+ identity: undefined;
226
+ generated: undefined;
227
+ }, {}, {}>;
228
+ tenantId: import("drizzle-orm/pg-core").PgColumn<{
229
+ name: "tenant_id";
230
+ tableName: "journal_entries";
231
+ dataType: "string";
232
+ columnType: "PgText";
233
+ data: string;
234
+ driverParam: string;
235
+ notNull: true;
236
+ hasDefault: false;
237
+ isPrimaryKey: false;
238
+ isAutoincrement: false;
239
+ hasRuntimeDefault: false;
240
+ enumValues: [string, ...string[]];
241
+ baseColumn: never;
242
+ identity: undefined;
243
+ generated: undefined;
244
+ }, {}, {}>;
245
+ metadata: import("drizzle-orm/pg-core").PgColumn<{
246
+ name: "metadata";
247
+ tableName: "journal_entries";
248
+ dataType: "json";
249
+ columnType: "PgJsonb";
250
+ data: unknown;
251
+ driverParam: unknown;
252
+ notNull: false;
253
+ hasDefault: false;
254
+ isPrimaryKey: false;
255
+ isAutoincrement: false;
256
+ hasRuntimeDefault: false;
257
+ enumValues: undefined;
258
+ baseColumn: never;
259
+ identity: undefined;
260
+ generated: undefined;
261
+ }, {}, {}>;
262
+ createdBy: import("drizzle-orm/pg-core").PgColumn<{
263
+ name: "created_by";
264
+ tableName: "journal_entries";
265
+ dataType: "string";
266
+ columnType: "PgText";
267
+ data: string;
268
+ driverParam: string;
269
+ notNull: false;
270
+ hasDefault: false;
271
+ isPrimaryKey: false;
272
+ isAutoincrement: false;
273
+ hasRuntimeDefault: false;
274
+ enumValues: [string, ...string[]];
275
+ baseColumn: never;
276
+ identity: undefined;
277
+ generated: undefined;
278
+ }, {}, {}>;
279
+ };
280
+ dialect: "pg";
281
+ }>;
282
+ /**
283
+ * Journal lines — the individual debits and credits within a journal entry.
284
+ * Invariant: for every journal_entry, SUM(debit amounts) = SUM(credit amounts).
285
+ * Amount is always positive; `side` determines the direction.
286
+ * Stored in nanodollars (Credit.toRaw()).
287
+ */
288
+ export declare const journalLines: import("drizzle-orm/pg-core").PgTableWithColumns<{
289
+ name: "journal_lines";
290
+ schema: undefined;
291
+ columns: {
292
+ id: import("drizzle-orm/pg-core").PgColumn<{
293
+ name: "id";
294
+ tableName: "journal_lines";
295
+ dataType: "string";
296
+ columnType: "PgText";
297
+ data: string;
298
+ driverParam: string;
299
+ notNull: true;
300
+ hasDefault: false;
301
+ isPrimaryKey: true;
302
+ isAutoincrement: false;
303
+ hasRuntimeDefault: false;
304
+ enumValues: [string, ...string[]];
305
+ baseColumn: never;
306
+ identity: undefined;
307
+ generated: undefined;
308
+ }, {}, {}>;
309
+ journalEntryId: import("drizzle-orm/pg-core").PgColumn<{
310
+ name: "journal_entry_id";
311
+ tableName: "journal_lines";
312
+ dataType: "string";
313
+ columnType: "PgText";
314
+ data: string;
315
+ driverParam: string;
316
+ notNull: true;
317
+ hasDefault: false;
318
+ isPrimaryKey: false;
319
+ isAutoincrement: false;
320
+ hasRuntimeDefault: false;
321
+ enumValues: [string, ...string[]];
322
+ baseColumn: never;
323
+ identity: undefined;
324
+ generated: undefined;
325
+ }, {}, {}>;
326
+ accountId: import("drizzle-orm/pg-core").PgColumn<{
327
+ name: "account_id";
328
+ tableName: "journal_lines";
329
+ dataType: "string";
330
+ columnType: "PgText";
331
+ data: string;
332
+ driverParam: string;
333
+ notNull: true;
334
+ hasDefault: false;
335
+ isPrimaryKey: false;
336
+ isAutoincrement: false;
337
+ hasRuntimeDefault: false;
338
+ enumValues: [string, ...string[]];
339
+ baseColumn: never;
340
+ identity: undefined;
341
+ generated: undefined;
342
+ }, {}, {}>;
343
+ amount: import("drizzle-orm/pg-core").PgColumn<{
344
+ name: "amount";
345
+ tableName: "journal_lines";
346
+ dataType: "number";
347
+ columnType: "PgBigInt53";
348
+ data: number;
349
+ driverParam: string | number;
350
+ notNull: true;
351
+ hasDefault: false;
352
+ isPrimaryKey: false;
353
+ isAutoincrement: false;
354
+ hasRuntimeDefault: false;
355
+ enumValues: undefined;
356
+ baseColumn: never;
357
+ identity: undefined;
358
+ generated: undefined;
359
+ }, {}, {}>;
360
+ side: import("drizzle-orm/pg-core").PgColumn<{
361
+ name: "side";
362
+ tableName: "journal_lines";
363
+ dataType: "string";
364
+ columnType: "PgEnumColumn";
365
+ data: "debit" | "credit";
366
+ driverParam: string;
367
+ notNull: true;
368
+ hasDefault: false;
369
+ isPrimaryKey: false;
370
+ isAutoincrement: false;
371
+ hasRuntimeDefault: false;
372
+ enumValues: ["debit", "credit"];
373
+ baseColumn: never;
374
+ identity: undefined;
375
+ generated: undefined;
376
+ }, {}, {}>;
377
+ };
378
+ dialect: "pg";
379
+ }>;
380
+ /**
381
+ * Materialized account balances — cache derived from journal_lines.
382
+ * Updated atomically within the same transaction as the journal line insert.
383
+ * Can always be reconstructed from journal_lines if corrupted.
384
+ */
385
+ export declare const accountBalances: import("drizzle-orm/pg-core").PgTableWithColumns<{
386
+ name: "account_balances";
387
+ schema: undefined;
388
+ columns: {
389
+ accountId: import("drizzle-orm/pg-core").PgColumn<{
390
+ name: "account_id";
391
+ tableName: "account_balances";
392
+ dataType: "string";
393
+ columnType: "PgText";
394
+ data: string;
395
+ driverParam: string;
396
+ notNull: true;
397
+ hasDefault: false;
398
+ isPrimaryKey: true;
399
+ isAutoincrement: false;
400
+ hasRuntimeDefault: false;
401
+ enumValues: [string, ...string[]];
402
+ baseColumn: never;
403
+ identity: undefined;
404
+ generated: undefined;
405
+ }, {}, {}>;
406
+ balance: import("drizzle-orm/pg-core").PgColumn<{
407
+ name: "balance";
408
+ tableName: "account_balances";
409
+ dataType: "number";
410
+ columnType: "PgBigInt53";
411
+ data: number;
412
+ driverParam: string | number;
413
+ notNull: true;
414
+ hasDefault: true;
415
+ isPrimaryKey: false;
416
+ isAutoincrement: false;
417
+ hasRuntimeDefault: false;
418
+ enumValues: undefined;
419
+ baseColumn: never;
420
+ identity: undefined;
421
+ generated: undefined;
422
+ }, {}, {}>;
423
+ lastUpdated: import("drizzle-orm/pg-core").PgColumn<{
424
+ name: "last_updated";
425
+ tableName: "account_balances";
426
+ dataType: "string";
427
+ columnType: "PgText";
428
+ data: string;
429
+ driverParam: string;
430
+ notNull: true;
431
+ hasDefault: true;
432
+ isPrimaryKey: false;
433
+ isAutoincrement: false;
434
+ hasRuntimeDefault: false;
435
+ enumValues: [string, ...string[]];
436
+ baseColumn: never;
437
+ identity: undefined;
438
+ generated: undefined;
439
+ }, {}, {}>;
440
+ };
441
+ dialect: "pg";
442
+ }>;
@@ -0,0 +1,76 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { bigint, index, jsonb, pgEnum, pgTable, text, uniqueIndex } from "drizzle-orm/pg-core";
3
+ export const accountTypeEnum = pgEnum("account_type", ["asset", "liability", "equity", "revenue", "expense"]);
4
+ export const entrySideEnum = pgEnum("entry_side", ["debit", "credit"]);
5
+ /**
6
+ * Chart of accounts — every account that can appear in a journal line.
7
+ *
8
+ * System accounts (tenant_id IS NULL) are seeded at migration time.
9
+ * Per-tenant liability accounts are created lazily on first transaction.
10
+ */
11
+ export const accounts = pgTable("accounts", {
12
+ id: text("id").primaryKey(),
13
+ code: text("code").notNull(),
14
+ name: text("name").notNull(),
15
+ type: accountTypeEnum("type").notNull(),
16
+ normalSide: entrySideEnum("normal_side").notNull(),
17
+ tenantId: text("tenant_id"), // NULL = system account
18
+ createdAt: text("created_at").notNull().default(sql `(now())`),
19
+ }, (table) => [
20
+ uniqueIndex("idx_accounts_code").on(table.code),
21
+ index("idx_accounts_tenant").on(table.tenantId).where(sql `${table.tenantId} IS NOT NULL`),
22
+ index("idx_accounts_type").on(table.type),
23
+ ]);
24
+ /**
25
+ * Journal entries — the header for each balanced transaction.
26
+ * One business event = one journal entry = two or more journal lines that sum to zero.
27
+ */
28
+ export const journalEntries = pgTable("journal_entries", {
29
+ id: text("id").primaryKey(),
30
+ postedAt: text("posted_at").notNull().default(sql `(now())`),
31
+ entryType: text("entry_type").notNull(), // purchase, usage, grant, refund, dividend, expiry, correction
32
+ description: text("description"),
33
+ referenceId: text("reference_id"),
34
+ tenantId: text("tenant_id").notNull(),
35
+ metadata: jsonb("metadata"), // funding_source, attributed_user_id, stripe_fingerprint, etc.
36
+ createdBy: text("created_by"), // system, admin:<id>, cron:expiry, etc.
37
+ }, (table) => [
38
+ uniqueIndex("idx_je_reference").on(table.referenceId).where(sql `${table.referenceId} IS NOT NULL`),
39
+ index("idx_je_tenant").on(table.tenantId),
40
+ index("idx_je_type").on(table.entryType),
41
+ index("idx_je_posted").on(table.postedAt),
42
+ index("idx_je_tenant_posted").on(table.tenantId, table.postedAt),
43
+ ]);
44
+ /**
45
+ * Journal lines — the individual debits and credits within a journal entry.
46
+ * Invariant: for every journal_entry, SUM(debit amounts) = SUM(credit amounts).
47
+ * Amount is always positive; `side` determines the direction.
48
+ * Stored in nanodollars (Credit.toRaw()).
49
+ */
50
+ export const journalLines = pgTable("journal_lines", {
51
+ id: text("id").primaryKey(),
52
+ journalEntryId: text("journal_entry_id")
53
+ .notNull()
54
+ .references(() => journalEntries.id),
55
+ accountId: text("account_id")
56
+ .notNull()
57
+ .references(() => accounts.id),
58
+ amount: bigint("amount", { mode: "number" }).notNull(), // nanodollars, always positive
59
+ side: entrySideEnum("side").notNull(),
60
+ }, (table) => [
61
+ index("idx_jl_entry").on(table.journalEntryId),
62
+ index("idx_jl_account").on(table.accountId),
63
+ index("idx_jl_account_side").on(table.accountId, table.side),
64
+ ]);
65
+ /**
66
+ * Materialized account balances — cache derived from journal_lines.
67
+ * Updated atomically within the same transaction as the journal line insert.
68
+ * Can always be reconstructed from journal_lines if corrupted.
69
+ */
70
+ export const accountBalances = pgTable("account_balances", {
71
+ accountId: text("account_id")
72
+ .primaryKey()
73
+ .references(() => accounts.id),
74
+ balance: bigint("balance", { mode: "number" }).notNull().default(0), // net balance in nanodollars
75
+ lastUpdated: text("last_updated").notNull().default(sql `(now())`),
76
+ });
@@ -5,11 +5,11 @@
5
5
  * (OpenAI, Anthropic) to ensure consistent credit billing across all
6
6
  * gateway endpoints.
7
7
  */
8
- import type { ICreditLedger } from "@wopr-network/platform-core/credits";
8
+ import type { ILedger } from "@wopr-network/platform-core/credits";
9
9
  import type { Context } from "hono";
10
10
  import type { GatewayAuthEnv } from "./service-key-auth.js";
11
11
  export interface CreditGateDeps {
12
- creditLedger?: ICreditLedger;
12
+ creditLedger?: ILedger;
13
13
  topUpUrl: string;
14
14
  /** Maximum negative balance allowed before hard-stop, in cents. Default: 50 (-$0.50). */
15
15
  graceBufferCents?: number;
@@ -71,7 +71,11 @@ export async function debitCredits(deps, tenantId, costUsd, margin, capability,
71
71
  return;
72
72
  }
73
73
  try {
74
- await deps.creditLedger.debit(tenantId, chargeCredit, "adapter_usage", `Gateway ${capability} via ${provider}`, undefined, true, attributedUserId);
74
+ await deps.creditLedger.debit(tenantId, chargeCredit, "adapter_usage", {
75
+ description: `Gateway ${capability} via ${provider}`,
76
+ allowNegative: true,
77
+ attributedUserId,
78
+ });
75
79
  // Only fire on first zero-crossing (balance was positive before, now ≤ 0)
76
80
  if (deps.onBalanceExhausted) {
77
81
  const newBalance = await deps.creditLedger.balance(tenantId);