payment-kit 1.29.1 → 1.29.3

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 (343) hide show
  1. package/api/dev.ts +41 -2
  2. package/api/hono.d.ts +42 -0
  3. package/api/node-sqlite.d.ts +12 -0
  4. package/api/src/bootstrap.ts +47 -0
  5. package/api/src/crons/base.ts +3 -3
  6. package/api/src/crons/currency.ts +1 -1
  7. package/api/src/crons/index.ts +41 -37
  8. package/api/src/crons/metering-subscription-detection.ts +1 -1
  9. package/api/src/crons/overdue-detection.ts +2 -2
  10. package/api/src/crons/retry-pending-events.ts +6 -0
  11. package/api/src/crons/tenant-fanout.ts +82 -0
  12. package/api/src/host-node/did-connect-runtime-node.ts +33 -0
  13. package/api/src/host-node/serve-static-arc.ts +68 -0
  14. package/api/src/host-node/serve-static.ts +41 -0
  15. package/api/src/index.ts +22 -161
  16. package/api/src/integrations/app-store/client.ts +3 -4
  17. package/api/src/integrations/app-store/handlers/subscription.ts +7 -7
  18. package/api/src/integrations/app-store/signed-data-verifier.ts +3 -2
  19. package/api/src/integrations/arcblock/token.ts +21 -7
  20. package/api/src/integrations/google-play/handlers/subscription.ts +6 -6
  21. package/api/src/integrations/google-play/handlers/voided.ts +2 -2
  22. package/api/src/integrations/google-play/verify.ts +3 -2
  23. package/api/src/integrations/iap-reconcile.ts +3 -5
  24. package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
  25. package/api/src/integrations/stripe/handlers/subscription.ts +3 -3
  26. package/api/src/libs/archive/query.ts +19 -0
  27. package/api/src/libs/audit.ts +61 -4
  28. package/api/src/libs/auth.ts +247 -47
  29. package/api/src/libs/context.ts +89 -1
  30. package/api/src/libs/currency.ts +2 -2
  31. package/api/src/libs/dayjs.ts +8 -2
  32. package/api/src/libs/did-connect/runtime-did-connect-js.ts +88 -0
  33. package/api/src/libs/did-connect/tenant-identity.ts +221 -0
  34. package/api/src/libs/drivers/auth-storage.ts +118 -0
  35. package/api/src/libs/drivers/cron.ts +264 -0
  36. package/api/src/libs/drivers/db.ts +170 -0
  37. package/api/src/libs/drivers/identity.ts +142 -0
  38. package/api/src/libs/drivers/index.ts +40 -0
  39. package/api/src/libs/drivers/locks.ts +226 -0
  40. package/api/src/libs/drivers/migrate-runner.ts +70 -0
  41. package/api/src/libs/drivers/queue.ts +104 -0
  42. package/api/src/libs/drivers/secrets.ts +194 -0
  43. package/api/src/libs/env.ts +170 -54
  44. package/api/src/libs/exchange-rate/service.ts +7 -6
  45. package/api/src/libs/http-fetch-adapter.ts +60 -0
  46. package/api/src/libs/invoice.ts +1 -1
  47. package/api/src/libs/lock.ts +51 -47
  48. package/api/src/libs/logger.ts +48 -8
  49. package/api/src/libs/notification/index.ts +1 -1
  50. package/api/src/libs/notification/template/customer-credit-low-balance.ts +2 -1
  51. package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -1
  52. package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -1
  53. package/api/src/libs/overdraft-protection.ts +1 -1
  54. package/api/src/libs/payout.ts +1 -1
  55. package/api/src/libs/queue/index.ts +271 -52
  56. package/api/src/libs/queue/runtime.ts +175 -0
  57. package/api/src/libs/resource.ts +3 -3
  58. package/api/src/libs/secrets.ts +38 -0
  59. package/api/src/libs/session.ts +3 -2
  60. package/api/src/libs/subscription.ts +5 -5
  61. package/api/src/libs/tenant.ts +92 -0
  62. package/api/src/libs/url.ts +3 -3
  63. package/api/src/libs/util.ts +21 -13
  64. package/api/src/middlewares/hono/cdn.ts +63 -0
  65. package/api/src/middlewares/hono/context.ts +80 -0
  66. package/api/src/middlewares/hono/csrf.ts +83 -0
  67. package/api/src/middlewares/hono/fallback.ts +194 -0
  68. package/api/src/middlewares/hono/pipeline.ts +73 -0
  69. package/api/src/middlewares/hono/resource-mount.ts +42 -0
  70. package/api/src/middlewares/hono/resource.ts +63 -0
  71. package/api/src/middlewares/hono/security.ts +209 -0
  72. package/api/src/middlewares/hono/session.ts +114 -0
  73. package/api/src/middlewares/hono/xss.ts +61 -0
  74. package/api/src/queues/auto-recharge.ts +12 -10
  75. package/api/src/queues/checkout-session.ts +38 -21
  76. package/api/src/queues/credit-consume.ts +40 -36
  77. package/api/src/queues/credit-grant.ts +25 -18
  78. package/api/src/queues/credit-reconciliation.ts +7 -5
  79. package/api/src/queues/discount-status.ts +9 -6
  80. package/api/src/queues/event.ts +41 -11
  81. package/api/src/queues/exchange-rate-health.ts +49 -30
  82. package/api/src/queues/invoice.ts +18 -15
  83. package/api/src/queues/notification.ts +14 -7
  84. package/api/src/queues/payment.ts +64 -37
  85. package/api/src/queues/payout.ts +37 -21
  86. package/api/src/queues/refund.ts +36 -18
  87. package/api/src/queues/subscription.ts +83 -53
  88. package/api/src/queues/token-transfer.ts +15 -10
  89. package/api/src/queues/usage-record.ts +8 -5
  90. package/api/src/queues/vendors/commission.ts +7 -5
  91. package/api/src/queues/vendors/fulfillment-coordinator.ts +17 -13
  92. package/api/src/queues/vendors/fulfillment.ts +4 -2
  93. package/api/src/queues/vendors/return-processor.ts +5 -3
  94. package/api/src/queues/vendors/return-scanner.ts +5 -4
  95. package/api/src/queues/vendors/status-check.ts +10 -7
  96. package/api/src/queues/webhook.ts +60 -32
  97. package/api/src/routes/connect/shared.ts +1 -2
  98. package/api/src/routes/connect/subscribe.ts +3 -3
  99. package/api/src/routes/{archive.ts → hono/archive.ts} +69 -64
  100. package/api/src/routes/{auto-recharge-configs.ts → hono/auto-recharge-configs.ts} +39 -28
  101. package/api/src/routes/{checkout-sessions.ts → hono/checkout-sessions.ts} +790 -923
  102. package/api/src/routes/{coupons.ts → hono/coupons.ts} +93 -76
  103. package/api/src/routes/{credit-grants.ts → hono/credit-grants.ts} +140 -126
  104. package/api/src/routes/hono/credit-tokens.ts +43 -0
  105. package/api/src/routes/{credit-transactions.ts → hono/credit-transactions.ts} +37 -29
  106. package/api/src/routes/{customers.ts → hono/customers.ts} +199 -224
  107. package/api/src/routes/{donations.ts → hono/donations.ts} +41 -32
  108. package/api/src/routes/{entitlements.ts → hono/entitlements.ts} +28 -25
  109. package/api/src/routes/{events.ts → hono/events.ts} +107 -71
  110. package/api/src/routes/{exchange-rate-providers.ts → hono/exchange-rate-providers.ts} +138 -126
  111. package/api/src/routes/hono/exchange-rates.ts +77 -0
  112. package/api/src/routes/hono/index.ts +115 -0
  113. package/api/src/routes/{integrations → hono/integrations}/app-store.ts +68 -48
  114. package/api/src/routes/{integrations → hono/integrations}/google-play.ts +78 -58
  115. package/api/src/routes/hono/integrations/stripe.ts +74 -0
  116. package/api/src/routes/{invoices.ts → hono/invoices.ts} +253 -244
  117. package/api/src/routes/{meter-events.ts → hono/meter-events.ts} +120 -110
  118. package/api/src/routes/hono/meters.ts +288 -0
  119. package/api/src/routes/hono/passports.ts +73 -0
  120. package/api/src/routes/{payment-currencies.ts → hono/payment-currencies.ts} +219 -197
  121. package/api/src/routes/{payment-intents.ts → hono/payment-intents.ts} +136 -132
  122. package/api/src/routes/{payment-links.ts → hono/payment-links.ts} +145 -128
  123. package/api/src/routes/{payment-methods.ts → hono/payment-methods.ts} +125 -93
  124. package/api/src/routes/{payment-stats.ts → hono/payment-stats.ts} +30 -25
  125. package/api/src/routes/{payouts.ts → hono/payouts.ts} +55 -47
  126. package/api/src/routes/{prices.ts → hono/prices.ts} +265 -242
  127. package/api/src/routes/{pricing-table.ts → hono/pricing-table.ts} +94 -87
  128. package/api/src/routes/{products.ts → hono/products.ts} +172 -159
  129. package/api/src/routes/{promotion-codes.ts → hono/promotion-codes.ts} +207 -185
  130. package/api/src/routes/hono/redirect.ts +24 -0
  131. package/api/src/routes/{refunds.ts → hono/refunds.ts} +98 -83
  132. package/api/src/routes/{settings.ts → hono/settings.ts} +64 -55
  133. package/api/src/routes/{subscription-items.ts → hono/subscription-items.ts} +64 -57
  134. package/api/src/routes/{subscriptions.ts → hono/subscriptions.ts} +475 -528
  135. package/api/src/routes/{tax-rates.ts → hono/tax-rates.ts} +71 -70
  136. package/api/src/routes/hono/tool.ts +69 -0
  137. package/api/src/routes/{usage-records.ts → hono/usage-records.ts} +47 -42
  138. package/api/src/routes/{vendor.ts → hono/vendor.ts} +315 -167
  139. package/api/src/routes/{webhook-attempts.ts → hono/webhook-attempts.ts} +17 -13
  140. package/api/src/routes/hono/webhook-endpoints.ts +126 -0
  141. package/api/src/service.ts +814 -0
  142. package/api/src/store/migrations/20230911-seeding.ts +2 -1
  143. package/api/src/store/migrations/20260609-remove-did-space-jobs.ts +23 -0
  144. package/api/src/store/migrations/20260610-tenant-columns.ts +40 -0
  145. package/api/src/store/migrations/20260611-tenant-backfill.ts +33 -0
  146. package/api/src/store/models/auto-recharge-config.ts +22 -10
  147. package/api/src/store/models/checkout-session.ts +15 -14
  148. package/api/src/store/models/coupon.ts +29 -20
  149. package/api/src/store/models/credit-grant.ts +38 -29
  150. package/api/src/store/models/credit-transaction.ts +32 -21
  151. package/api/src/store/models/customer.ts +19 -17
  152. package/api/src/store/models/discount.ts +11 -2
  153. package/api/src/store/models/entitlement-grant.ts +21 -9
  154. package/api/src/store/models/entitlement-product.ts +21 -9
  155. package/api/src/store/models/entitlement.ts +19 -10
  156. package/api/src/store/models/event.ts +18 -9
  157. package/api/src/store/models/exchange-rate-provider.ts +17 -4
  158. package/api/src/store/models/invoice-item.ts +18 -9
  159. package/api/src/store/models/invoice.ts +16 -8
  160. package/api/src/store/models/meter-event.ts +27 -9
  161. package/api/src/store/models/meter.ts +31 -22
  162. package/api/src/store/models/payment-currency.ts +25 -8
  163. package/api/src/store/models/payment-intent.ts +15 -6
  164. package/api/src/store/models/payment-link.ts +15 -6
  165. package/api/src/store/models/payment-method.ts +38 -22
  166. package/api/src/store/models/payment-stat.ts +18 -9
  167. package/api/src/store/models/payout.ts +15 -6
  168. package/api/src/store/models/price-quote.ts +17 -8
  169. package/api/src/store/models/price.ts +24 -12
  170. package/api/src/store/models/pricing-table.ts +29 -20
  171. package/api/src/store/models/product-vendor.ts +20 -10
  172. package/api/src/store/models/product.ts +15 -6
  173. package/api/src/store/models/promotion-code.ts +14 -6
  174. package/api/src/store/models/refund.ts +15 -6
  175. package/api/src/store/models/revenue-snapshot.ts +21 -9
  176. package/api/src/store/models/setting.ts +18 -9
  177. package/api/src/store/models/setup-intent.ts +36 -27
  178. package/api/src/store/models/subscription-item.ts +21 -9
  179. package/api/src/store/models/subscription-schedule.ts +21 -9
  180. package/api/src/store/models/subscription.ts +21 -10
  181. package/api/src/store/models/tax-rate.ts +29 -21
  182. package/api/src/store/models/usage-record.ts +11 -2
  183. package/api/src/store/models/webhook-attempt.ts +18 -9
  184. package/api/src/store/models/webhook-endpoint.ts +18 -9
  185. package/api/src/store/scoped-core.ts +55 -0
  186. package/api/src/store/scoped.ts +247 -0
  187. package/api/src/store/sequelize.ts +82 -23
  188. package/api/src/store/sql-migrations.ts +20 -0
  189. package/api/src/store/tenant-backfill.ts +260 -0
  190. package/api/src/store/tenant-model.ts +124 -0
  191. package/api/src/store/tenant-tables.ts +50 -0
  192. package/api/tests/bootstrap/bootstrap.spec.ts +162 -0
  193. package/api/tests/crons/tenant-fanout.spec.ts +158 -0
  194. package/api/tests/embedded/embedded-multi-mode-d3.spec.ts +257 -0
  195. package/api/tests/fixtures/bare-query-violation.ts +13 -0
  196. package/api/tests/fixtures/core-env-violation.ts +10 -0
  197. package/api/tests/fixtures/host-read-violation.ts +19 -0
  198. package/api/tests/fixtures/tenants.ts +4 -0
  199. package/api/tests/integrations/iap-tenant.spec.ts +284 -0
  200. package/api/tests/libs/archive-query.spec.ts +26 -0
  201. package/api/tests/libs/audit-tenant.spec.ts +153 -0
  202. package/api/tests/libs/context.spec.ts +204 -0
  203. package/api/tests/libs/core-config.spec.ts +115 -0
  204. package/api/tests/libs/cron-driver-d2.spec.ts +237 -0
  205. package/api/tests/libs/crons-conservation-d2.spec.ts +52 -0
  206. package/api/tests/libs/did-connect-runtime-js.spec.ts +98 -0
  207. package/api/tests/libs/did-connect-tenant-identity.spec.ts +159 -0
  208. package/api/tests/libs/lock-tenant.spec.ts +66 -0
  209. package/api/tests/libs/scoped.spec.ts +222 -0
  210. package/api/tests/libs/secrets-facade.spec.ts +52 -0
  211. package/api/tests/libs/service-host.spec.ts +37 -0
  212. package/api/tests/libs/tenancy-slot-authority.spec.ts +209 -0
  213. package/api/tests/libs/tenant-middleware.spec.ts +42 -0
  214. package/api/tests/libs/tenant-scanner.spec.ts +120 -0
  215. package/api/tests/middlewares/hono/cdn.spec.ts +70 -0
  216. package/api/tests/middlewares/hono/context.spec.ts +113 -0
  217. package/api/tests/middlewares/hono/csrf.spec.ts +136 -0
  218. package/api/tests/middlewares/hono/fallback.spec.ts +67 -0
  219. package/api/tests/middlewares/hono/pipeline.spec.ts +47 -0
  220. package/api/tests/middlewares/hono/security.spec.ts +181 -0
  221. package/api/tests/middlewares/hono/session.spec.ts +42 -0
  222. package/api/tests/middlewares/hono/xss.spec.ts +81 -0
  223. package/api/tests/models/tenant-backfill.spec.ts +287 -0
  224. package/api/tests/models/tenant-columns-model.spec.ts +46 -0
  225. package/api/tests/models/tenant-columns.spec.ts +161 -0
  226. package/api/tests/queues/credit-consume-batch.spec.ts +8 -1
  227. package/api/tests/queues/credit-consume.spec.ts +8 -1
  228. package/api/tests/queues/event-tenant.spec.ts +292 -0
  229. package/api/tests/queues/exchange-rate-health-tenant-d6.spec.ts +62 -0
  230. package/api/tests/queues/queue-parity.spec.ts +249 -0
  231. package/api/tests/queues/queue-runtime-surface.spec.ts +277 -0
  232. package/api/tests/queues/queue-teardown-d2.spec.ts +127 -0
  233. package/api/tests/queues/tenant-matrix-a.spec.ts +245 -0
  234. package/api/tests/queues/tenant-matrix-b.spec.ts +168 -0
  235. package/api/tests/routes/connect/hono-attach.spec.ts +107 -0
  236. package/api/tests/service/collapse.spec.ts +96 -0
  237. package/api/tests/service/didconnect-storage-slot.spec.ts +60 -0
  238. package/api/tests/service/fail-closed-http.spec.ts +79 -0
  239. package/api/tests/service/static-arc-handler.spec.ts +101 -0
  240. package/api/tests/service/static-externalized.spec.ts +48 -0
  241. package/api/tests/store/tenant-crosscut.spec.ts +202 -0
  242. package/api/tests/store/tenant-model-spike.spec.ts +177 -0
  243. package/api/tests/store/tenant-model.spec.ts +162 -0
  244. package/api/tests/store/tenant-residual.spec.ts +196 -0
  245. package/api/third.d.ts +4 -0
  246. package/blocklet.yml +1 -1
  247. package/cloudflare/MIGRATION-RUNBOOK.md +3 -8
  248. package/cloudflare/README.md +34 -27
  249. package/cloudflare/STAGING-MIGRATION-GUIDE.md +3 -15
  250. package/cloudflare/build.ts +33 -13
  251. package/cloudflare/cf-adapter.ts +419 -0
  252. package/cloudflare/did-connect-runtime.ts +96 -0
  253. package/cloudflare/did-connect-token-storage.ts +151 -0
  254. package/cloudflare/esbuild-cf-config.cjs +407 -0
  255. package/cloudflare/migrations/0006_tenant_columns.sql +46 -0
  256. package/cloudflare/migrations/0007_tenant_backfill_indexes.sql +65 -0
  257. package/cloudflare/migrations/0008_schema_parity.sql +16 -0
  258. package/cloudflare/migrations/0009_remove_did_space_jobs.sql +5 -0
  259. package/cloudflare/queue-runtime-mode.ts +13 -0
  260. package/cloudflare/run-build.js +33 -403
  261. package/cloudflare/scripts/cf-package-import-probe.mjs +90 -0
  262. package/cloudflare/scripts/didconnect-mock-smoke.mjs +140 -0
  263. package/cloudflare/shims/blocklet-sdk/asset-host-transformer.ts +20 -0
  264. package/cloudflare/shims/blocklet-sdk/config.ts +8 -1
  265. package/cloudflare/shims/blocklet-sdk/login.ts +12 -0
  266. package/cloudflare/shims/blocklet-sdk/service-api.ts +14 -0
  267. package/cloudflare/shims/blocklet-sdk/session.ts +4 -2
  268. package/cloudflare/shims/blocklet-sdk/util-constants.ts +8 -0
  269. package/cloudflare/shims/blocklet-sdk/wallet-authenticator.ts +16 -1
  270. package/cloudflare/shims/blocklet-sdk/wallet-handler.ts +18 -3
  271. package/cloudflare/shims/cron.ts +38 -158
  272. package/cloudflare/shims/events.ts +124 -0
  273. package/cloudflare/shims/fastq.ts +15 -1
  274. package/cloudflare/shims/nedb-storage.ts +16 -8
  275. package/cloudflare/shims/xss.ts +8 -0
  276. package/cloudflare/tenant-middleware.ts +36 -0
  277. package/cloudflare/tests/cf-adapter.spec.ts +244 -0
  278. package/cloudflare/tests/did-connect-token-storage.spec.ts +105 -0
  279. package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
  280. package/cloudflare/tests/worker-handler-gate.spec.ts +69 -0
  281. package/cloudflare/vite.config.ts +53 -45
  282. package/cloudflare/worker.ts +261 -448
  283. package/cloudflare/wrangler.json +0 -6
  284. package/cloudflare/wrangler.jsonc +0 -6
  285. package/cloudflare/wrangler.local-e2e.jsonc +25 -0
  286. package/cloudflare/wrangler.staging.json +0 -6
  287. package/jest.config.js +3 -1
  288. package/package.json +33 -38
  289. package/scripts/bootstrap-inject.ts +166 -0
  290. package/scripts/core-env-whitelist.json +1 -0
  291. package/scripts/e2e-12b-runtime.ts +149 -0
  292. package/scripts/e2e-core-config.ts +125 -0
  293. package/scripts/e2e-d1-tenancy.ts +116 -0
  294. package/scripts/e2e-d2-cron-queue.ts +139 -0
  295. package/scripts/e2e-d3-embedded-multi.ts +171 -0
  296. package/scripts/e2e-hono-s2.ts +125 -0
  297. package/scripts/e2e-hono-s3e.ts +135 -0
  298. package/scripts/e2e-hono-s4.ts +114 -0
  299. package/scripts/e2e-migration-contract.ts +100 -0
  300. package/scripts/e2e-s0.ts +61 -0
  301. package/scripts/e2e-s1.ts +107 -0
  302. package/scripts/e2e-s2.ts +178 -0
  303. package/scripts/e2e-s3.ts +110 -0
  304. package/scripts/e2e-s4.ts +191 -0
  305. package/scripts/e2e-s5.ts +139 -0
  306. package/scripts/e2e-s6.ts +127 -0
  307. package/scripts/e2e-tenant-model.ts +119 -0
  308. package/scripts/e2e-tenant-worker.ts +199 -0
  309. package/scripts/gen-sql-migrations.js +46 -0
  310. package/scripts/phase8-codemod.js +219 -0
  311. package/scripts/phase9a-env-getters-codemod.js +82 -0
  312. package/scripts/scan-core-env.js +109 -0
  313. package/scripts/scan-tenant-queries.js +235 -0
  314. package/scripts/schema-drift-guard.ts +210 -0
  315. package/scripts/tenant-scan-whitelist.json +1 -0
  316. package/src/app.tsx +2 -1
  317. package/src/env.d.ts +13 -1
  318. package/src/libs/service-host.ts +13 -0
  319. package/tsconfig.json +1 -1
  320. package/vite.arc.config.ts +159 -0
  321. package/api/src/libs/did-space.ts +0 -235
  322. package/api/src/libs/middleware.ts +0 -50
  323. package/api/src/libs/security.ts +0 -192
  324. package/api/src/queues/space.ts +0 -662
  325. package/api/src/routes/credit-tokens.ts +0 -38
  326. package/api/src/routes/exchange-rates.ts +0 -87
  327. package/api/src/routes/index.ts +0 -142
  328. package/api/src/routes/integrations/stripe.ts +0 -61
  329. package/api/src/routes/meters.ts +0 -274
  330. package/api/src/routes/passports.ts +0 -68
  331. package/api/src/routes/redirect.ts +0 -20
  332. package/api/src/routes/tool.ts +0 -65
  333. package/api/src/routes/webhook-endpoints.ts +0 -126
  334. package/api/tests/routes/credit-grants.spec.ts +0 -1261
  335. package/cloudflare/did-connect-auth.ts +0 -527
  336. package/cloudflare/shims/did-space-js.ts +0 -17
  337. package/cloudflare/shims/did-space.ts +0 -11
  338. package/cloudflare/shims/express-compat/index.ts +0 -80
  339. package/cloudflare/shims/express-compat/types.ts +0 -41
  340. package/cloudflare/shims/lock.ts +0 -115
  341. package/cloudflare/shims/queue.ts +0 -611
  342. package/cloudflare/tests/shims/queue-delayed-persist.spec.ts +0 -87
  343. package/cloudflare/tests/shims/queue-scheduled.spec.ts +0 -186
@@ -2,8 +2,9 @@ import dayjs from '../libs/dayjs';
2
2
  import { events } from '../libs/event';
3
3
  import logger from '../libs/logger';
4
4
  import { getGasPayerExtra } from '../libs/payment';
5
- import createQueue from '../libs/queue';
5
+ import createQueue, { assertJobObjectTenant } from '../libs/queue';
6
6
  import { wallet, ethWallet } from '../libs/auth';
7
+ import { withTenant } from '../libs/context';
7
8
  import { sendErc20ToUser } from '../integrations/ethereum/token';
8
9
  import { PaymentMethod } from '../store/models/payment-method';
9
10
  import { PaymentCurrency } from '../store/models/payment-currency';
@@ -11,6 +12,7 @@ import { Payout } from '../store/models/payout';
11
12
  import { EVM_CHAIN_TYPES } from '../libs/constants';
12
13
  import type { PaymentError } from '../store/models/types';
13
14
  import { getNextRetry, MAX_RETRY_COUNT } from '../libs/util';
15
+ import { systemFindAll, systemFindByPk } from '../store/scoped';
14
16
 
15
17
  type PayoutJob = {
16
18
  payoutId: string;
@@ -23,28 +25,31 @@ type ValidationResult =
23
25
 
24
26
  // Validate payout and fetch required data
25
27
  async function validatePayoutAndFetchData(job: PayoutJob): Promise<ValidationResult> {
26
- const payout = await Payout.findByPk(job.payoutId);
28
+ const payout = await systemFindByPk(Payout, job.payoutId);
27
29
  if (!payout) {
28
30
  logger.warn('Payout not found', { id: job.payoutId });
29
31
  return { valid: false };
30
32
  }
33
+ assertJobObjectTenant(payout);
31
34
 
32
35
  if (payout.status !== 'pending') {
33
36
  logger.warn('Payout status not expected', { id: payout.id, status: payout.status });
34
37
  return { valid: false };
35
38
  }
36
39
 
37
- const paymentMethod = await PaymentMethod.findByPk(payout.payment_method_id);
40
+ const paymentMethod = await systemFindByPk(PaymentMethod, payout.payment_method_id);
38
41
  if (!paymentMethod) {
39
42
  logger.warn('PaymentMethod not found', { id: payout.payment_method_id });
40
43
  return { valid: false };
41
44
  }
45
+ assertJobObjectTenant(paymentMethod);
42
46
 
43
- const paymentCurrency = await PaymentCurrency.findByPk(payout.currency_id);
47
+ const paymentCurrency = await systemFindByPk(PaymentCurrency, payout.currency_id);
44
48
  if (!paymentCurrency) {
45
49
  logger.warn('PaymentCurrency not found', { id: payout.currency_id });
46
50
  return { valid: false };
47
51
  }
52
+ assertJobObjectTenant(paymentCurrency);
48
53
 
49
54
  return {
50
55
  valid: true,
@@ -234,30 +239,41 @@ payoutQueue.on('failed', ({ id, job, error }) => {
234
239
 
235
240
  // Start queue, find all payouts with "pending" status
236
241
  export const startPayoutQueue = async () => {
237
- const payouts = await Payout.findAll({
242
+ const payouts = await systemFindAll(Payout, {
238
243
  where: {
239
244
  status: 'pending',
240
245
  },
241
246
  });
242
247
 
243
- payouts.forEach(async (payout) => {
244
- const exist = await payoutQueue.get(payout.id);
245
- if (!exist) {
246
- // Use next attempt time if set
247
- if (payout.next_attempt && payout.next_attempt > dayjs().unix()) {
248
- payoutQueue.push({
249
- id: payout.id,
250
- job: { payoutId: payout.id, retryOnError: true },
251
- runAt: payout.next_attempt,
252
- });
253
- } else {
254
- payoutQueue.push({
255
- id: payout.id,
256
- job: { payoutId: payout.id, retryOnError: true },
257
- });
248
+ // Per-record tenant context: queue push stamps the job tenant via getInstanceDid,
249
+ // which fails closed in multi mode without it. for-of + await (not forEach(async),
250
+ // which leaks an unhandledRejection → FATAL on boot); per-record catch isolates.
251
+ for (const payout of payouts) {
252
+ const dispatch = async () => {
253
+ const exist = await payoutQueue.get(payout.id);
254
+ if (!exist) {
255
+ // Use next attempt time if set
256
+ if (payout.next_attempt && payout.next_attempt > dayjs().unix()) {
257
+ payoutQueue.push({
258
+ id: payout.id,
259
+ job: { payoutId: payout.id, retryOnError: true },
260
+ runAt: payout.next_attempt,
261
+ });
262
+ } else {
263
+ payoutQueue.push({
264
+ id: payout.id,
265
+ job: { payoutId: payout.id, retryOnError: true },
266
+ });
267
+ }
258
268
  }
269
+ };
270
+ try {
271
+ // eslint-disable-next-line no-await-in-loop
272
+ await (payout.instance_did ? withTenant(payout.instance_did, dispatch) : dispatch());
273
+ } catch (error) {
274
+ logger.error('startPayoutQueue: re-queue failed', { id: payout.id, error });
259
275
  }
260
- });
276
+ }
261
277
  };
262
278
 
263
279
  // Listen for newly created payouts
@@ -3,11 +3,12 @@ import { isRefundReasonSupportedByStripe } from '../libs/refund';
3
3
  import { checkRemainingStake, getSubscriptionStakeAddress } from '../libs/subscription';
4
4
  import { sendErc20ToUser } from '../integrations/ethereum/token';
5
5
  import { wallet } from '../libs/auth';
6
+ import { withTenant } from '../libs/context';
6
7
  import CustomError, { NonRetryableError } from '../libs/error';
7
8
  import { events } from '../libs/event';
8
9
  import logger from '../libs/logger';
9
10
  import { getGasPayerExtra, isBalanceSufficientForRefund } from '../libs/payment';
10
- import createQueue from '../libs/queue';
11
+ import createQueue, { assertJobObjectTenant } from '../libs/queue';
11
12
  import { MAX_RETRY_COUNT, getNextRetry } from '../libs/util';
12
13
  import { Customer } from '../store/models/customer';
13
14
  import { PaymentCurrency } from '../store/models/payment-currency';
@@ -20,6 +21,7 @@ import { Invoice } from '../store/models/invoice';
20
21
  import { burnToken, getAccountState } from '../integrations/arcblock/token';
21
22
  import type { EVMChainType, PaymentError } from '../store/models/types';
22
23
  import { EVM_CHAIN_TYPES } from '../libs/constants';
24
+ import { systemFindAll, systemFindByPk } from '../store/scoped';
23
25
 
24
26
  type RefundJob = {
25
27
  refundId: string;
@@ -83,11 +85,12 @@ export const handleRefundFailed = (refund: Refund, error: PaymentError) => {
83
85
  export const handleRefund = async (job: RefundJob) => {
84
86
  logger.info('handle refund', job);
85
87
 
86
- const refund = await Refund.findByPk(job.refundId);
88
+ const refund = await systemFindByPk(Refund, job.refundId);
87
89
  if (!refund) {
88
90
  logger.warn(`refund not found: ${job.refundId}`);
89
91
  return;
90
92
  }
93
+ assertJobObjectTenant(refund);
91
94
 
92
95
  if (['pending'].includes(refund.status) === false) {
93
96
  logger.warn(`refund status not expected: ${refund.status}`);
@@ -106,25 +109,28 @@ export const handleRefund = async (job: RefundJob) => {
106
109
  return;
107
110
  }
108
111
 
109
- const paymentCurrency = await PaymentCurrency.findByPk(refund.currency_id);
112
+ const paymentCurrency = await systemFindByPk(PaymentCurrency, refund.currency_id);
110
113
  if (!paymentCurrency) {
111
114
  logger.warn(`PaymentCurrency not found: ${refund.currency_id}`);
112
115
  await markRefundNonRetryable(refund, 'CURRENCY_NOT_FOUND', 'Payment currency not found');
113
116
  return;
114
117
  }
115
- const paymentMethod = await PaymentMethod.findByPk(paymentCurrency.payment_method_id);
118
+ assertJobObjectTenant(paymentCurrency);
119
+ const paymentMethod = await systemFindByPk(PaymentMethod, paymentCurrency.payment_method_id);
116
120
  if (!paymentMethod) {
117
121
  logger.warn(`PaymentMethod not found: ${paymentCurrency.payment_method_id}`);
118
122
  await markRefundNonRetryable(refund, 'PAYMENT_METHOD_NOT_FOUND', 'Payment method not found');
119
123
  return;
120
124
  }
125
+ assertJobObjectTenant(paymentMethod);
121
126
 
122
- const customer = await Customer.findByPk(refund.customer_id);
127
+ const customer = await systemFindByPk(Customer, refund.customer_id);
123
128
  if (!customer) {
124
129
  logger.warn(`Customer not found: ${refund.customer_id}`);
125
130
  await markRefundNonRetryable(refund, 'CUSTOMER_NOT_FOUND', 'Customer not found', paymentMethod);
126
131
  return;
127
132
  }
133
+ assertJobObjectTenant(customer);
128
134
 
129
135
  if (refund?.type === 'stake_return') {
130
136
  await handleStakeReturnJob(job, refund, paymentCurrency, paymentMethod, customer);
@@ -197,10 +203,11 @@ const handleRefundJob = async (
197
203
  if (!refund.payment_intent_id) {
198
204
  throw new NonRetryableError('PAYMENT_INTENT_NOT_FOUND', 'payment_intent_id is missing for refund');
199
205
  }
200
- const paymentIntent = await PaymentIntent.findByPk(refund.payment_intent_id);
206
+ const paymentIntent = await systemFindByPk(PaymentIntent, refund.payment_intent_id);
201
207
  if (!paymentIntent) {
202
208
  throw new NonRetryableError('PAYMENT_INTENT_NOT_FOUND', 'PaymentIntent not found');
203
209
  }
210
+ assertJobObjectTenant(paymentIntent);
204
211
  let result;
205
212
  if (paymentMethod.type === 'arcblock') {
206
213
  const client = paymentMethod.getOcapClient();
@@ -378,7 +385,7 @@ const handleStakeReturnJob = async (
378
385
  return;
379
386
  }
380
387
  const client = paymentMethod.getOcapClient();
381
- const subscription = await Subscription.findByPk(refund.subscription_id);
388
+ const subscription = await systemFindByPk(Subscription, refund.subscription_id);
382
389
  const address =
383
390
  arcblockDetail?.staking?.address ||
384
391
  (await getSubscriptionStakeAddress(subscription!, customer.did, paymentMethod));
@@ -486,14 +493,25 @@ export const refundQueue = createQueue<RefundJob>({
486
493
  });
487
494
 
488
495
  export const startRefundQueue = async () => {
489
- const refunds = await Refund.findAll({ where: { status: ['pending'] } });
490
- refunds.forEach(async (x) => {
491
- const exist = await refundQueue.get(x.id);
492
- if (!exist) {
493
- refundQueue.push({ id: x.id, job: { refundId: x.id } });
494
- logger.info('Re-queued pending refund', { id: x.id });
496
+ const refunds = await systemFindAll(Refund, { where: { status: ['pending'] } });
497
+ // Per-record tenant context: queue push stamps the job tenant via getInstanceDid,
498
+ // which fails closed in multi mode without it. for-of + await (not forEach(async),
499
+ // which leaks an unhandledRejection → FATAL on boot); per-record catch isolates.
500
+ for (const x of refunds) {
501
+ const dispatch = async () => {
502
+ const exist = await refundQueue.get(x.id);
503
+ if (!exist) {
504
+ refundQueue.push({ id: x.id, job: { refundId: x.id } });
505
+ logger.info('Re-queued pending refund', { id: x.id });
506
+ }
507
+ };
508
+ try {
509
+ // eslint-disable-next-line no-await-in-loop
510
+ await (x.instance_did ? withTenant(x.instance_did, dispatch) : dispatch());
511
+ } catch (error) {
512
+ logger.error('startRefundQueue: re-queue failed', { id: x.id, error });
495
513
  }
496
- });
514
+ }
497
515
  };
498
516
 
499
517
  refundQueue.on('failed', ({ id, job, error }) => {
@@ -528,8 +546,8 @@ export async function handleCreditRefund(refund: Refund): Promise<string | undef
528
546
  return undefined;
529
547
  }
530
548
 
531
- const invoice = await Invoice.findByPk(refund.invoice_id);
532
- const customer = await Customer.findByPk(refund.customer_id);
549
+ const invoice = await systemFindByPk(Invoice, refund.invoice_id);
550
+ const customer = await systemFindByPk(Customer, refund.customer_id);
533
551
 
534
552
  if (!invoice || !customer?.did) {
535
553
  throw new Error('Invoice or customer not found for refund');
@@ -541,7 +559,7 @@ export async function handleCreditRefund(refund: Refund): Promise<string | undef
541
559
  }
542
560
 
543
561
  // Find ALL credit grants related to this invoice (both on-chain and off-chain).
544
- const allGrants = await CreditGrant.findAll({
562
+ const allGrants = await systemFindAll(CreditGrant, {
545
563
  where: {
546
564
  customer_id: refund.customer_id,
547
565
  status: ['pending', 'granted'],
@@ -570,7 +588,7 @@ export async function handleCreditRefund(refund: Refund): Promise<string | undef
570
588
  for (const creditGrant of creditGrants) {
571
589
  // Get the currency for THIS grant
572
590
  // eslint-disable-next-line no-await-in-loop
573
- const grantCurrency = await PaymentCurrency.findByPk(creditGrant.currency_id);
591
+ const grantCurrency = await systemFindByPk(PaymentCurrency, creditGrant.currency_id);
574
592
 
575
593
  if (!grantCurrency) {
576
594
  logger.error('Payment currency not found for credit grant refund', {