payment-kit 1.29.0 → 1.29.2

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 (312) 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 +36 -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 +27 -24
  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/index.ts +22 -161
  12. package/api/src/integrations/app-store/client.ts +3 -4
  13. package/api/src/integrations/app-store/handlers/subscription.ts +7 -7
  14. package/api/src/integrations/app-store/signed-data-verifier.ts +3 -2
  15. package/api/src/integrations/arcblock/token.ts +21 -7
  16. package/api/src/integrations/google-play/handlers/subscription.ts +6 -6
  17. package/api/src/integrations/google-play/handlers/voided.ts +2 -2
  18. package/api/src/integrations/google-play/verify.ts +3 -2
  19. package/api/src/integrations/iap-reconcile.ts +3 -5
  20. package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
  21. package/api/src/integrations/stripe/handlers/subscription.ts +3 -3
  22. package/api/src/libs/archive/query.ts +19 -0
  23. package/api/src/libs/audit.ts +61 -4
  24. package/api/src/libs/auth.ts +99 -38
  25. package/api/src/libs/context.ts +78 -1
  26. package/api/src/libs/currency.ts +2 -2
  27. package/api/src/libs/dayjs.ts +8 -2
  28. package/api/src/libs/drivers/auth-storage.ts +118 -0
  29. package/api/src/libs/drivers/cron.ts +264 -0
  30. package/api/src/libs/drivers/db.ts +170 -0
  31. package/api/src/libs/drivers/identity.ts +81 -0
  32. package/api/src/libs/drivers/index.ts +40 -0
  33. package/api/src/libs/drivers/locks.ts +226 -0
  34. package/api/src/libs/drivers/migrate-runner.ts +70 -0
  35. package/api/src/libs/drivers/queue.ts +104 -0
  36. package/api/src/libs/drivers/secrets.ts +194 -0
  37. package/api/src/libs/env.ts +170 -54
  38. package/api/src/libs/exchange-rate/service.ts +7 -6
  39. package/api/src/libs/http-fetch-adapter.ts +50 -0
  40. package/api/src/libs/invoice.ts +1 -1
  41. package/api/src/libs/lock.ts +51 -47
  42. package/api/src/libs/logger.ts +48 -8
  43. package/api/src/libs/notification/index.ts +1 -1
  44. package/api/src/libs/notification/template/customer-credit-low-balance.ts +2 -1
  45. package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -1
  46. package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -1
  47. package/api/src/libs/overdraft-protection.ts +1 -1
  48. package/api/src/libs/payout.ts +1 -1
  49. package/api/src/libs/queue/index.ts +259 -52
  50. package/api/src/libs/queue/runtime.ts +175 -0
  51. package/api/src/libs/resource.ts +3 -3
  52. package/api/src/libs/secrets.ts +38 -0
  53. package/api/src/libs/session.ts +3 -2
  54. package/api/src/libs/subscription.ts +5 -5
  55. package/api/src/libs/tenant.ts +92 -0
  56. package/api/src/libs/url.ts +3 -3
  57. package/api/src/libs/util.ts +21 -13
  58. package/api/src/middlewares/hono/cdn.ts +63 -0
  59. package/api/src/middlewares/hono/context.ts +73 -0
  60. package/api/src/middlewares/hono/csrf.ts +72 -0
  61. package/api/src/middlewares/hono/fallback.ts +194 -0
  62. package/api/src/middlewares/hono/pipeline.ts +73 -0
  63. package/api/src/middlewares/hono/resource-mount.ts +42 -0
  64. package/api/src/middlewares/hono/resource.ts +63 -0
  65. package/api/src/middlewares/hono/security.ts +214 -0
  66. package/api/src/middlewares/hono/session.ts +114 -0
  67. package/api/src/middlewares/hono/xss.ts +61 -0
  68. package/api/src/queues/auto-recharge.ts +12 -10
  69. package/api/src/queues/checkout-session.ts +17 -12
  70. package/api/src/queues/credit-consume.ts +40 -36
  71. package/api/src/queues/credit-grant.ts +25 -18
  72. package/api/src/queues/credit-reconciliation.ts +7 -5
  73. package/api/src/queues/discount-status.ts +9 -6
  74. package/api/src/queues/event.ts +12 -4
  75. package/api/src/queues/exchange-rate-health.ts +49 -30
  76. package/api/src/queues/invoice.ts +18 -15
  77. package/api/src/queues/notification.ts +14 -7
  78. package/api/src/queues/payment.ts +41 -28
  79. package/api/src/queues/payout.ts +9 -5
  80. package/api/src/queues/refund.ts +18 -12
  81. package/api/src/queues/subscription.ts +83 -53
  82. package/api/src/queues/token-transfer.ts +15 -10
  83. package/api/src/queues/usage-record.ts +8 -5
  84. package/api/src/queues/vendors/commission.ts +7 -5
  85. package/api/src/queues/vendors/fulfillment-coordinator.ts +17 -13
  86. package/api/src/queues/vendors/fulfillment.ts +4 -2
  87. package/api/src/queues/vendors/return-processor.ts +5 -3
  88. package/api/src/queues/vendors/return-scanner.ts +5 -4
  89. package/api/src/queues/vendors/status-check.ts +10 -7
  90. package/api/src/queues/webhook.ts +60 -32
  91. package/api/src/routes/connect/shared.ts +1 -2
  92. package/api/src/routes/connect/subscribe.ts +3 -3
  93. package/api/src/routes/{archive.ts → hono/archive.ts} +69 -64
  94. package/api/src/routes/{auto-recharge-configs.ts → hono/auto-recharge-configs.ts} +39 -28
  95. package/api/src/routes/{checkout-sessions.ts → hono/checkout-sessions.ts} +790 -923
  96. package/api/src/routes/{coupons.ts → hono/coupons.ts} +93 -76
  97. package/api/src/routes/{credit-grants.ts → hono/credit-grants.ts} +140 -126
  98. package/api/src/routes/hono/credit-tokens.ts +43 -0
  99. package/api/src/routes/{credit-transactions.ts → hono/credit-transactions.ts} +37 -29
  100. package/api/src/routes/{customers.ts → hono/customers.ts} +193 -223
  101. package/api/src/routes/{donations.ts → hono/donations.ts} +41 -32
  102. package/api/src/routes/{entitlements.ts → hono/entitlements.ts} +28 -25
  103. package/api/src/routes/{events.ts → hono/events.ts} +107 -71
  104. package/api/src/routes/{exchange-rate-providers.ts → hono/exchange-rate-providers.ts} +138 -126
  105. package/api/src/routes/hono/exchange-rates.ts +77 -0
  106. package/api/src/routes/hono/index.ts +115 -0
  107. package/api/src/routes/{integrations → hono/integrations}/app-store.ts +68 -48
  108. package/api/src/routes/{integrations → hono/integrations}/google-play.ts +78 -58
  109. package/api/src/routes/hono/integrations/stripe.ts +74 -0
  110. package/api/src/routes/{invoices.ts → hono/invoices.ts} +253 -244
  111. package/api/src/routes/{meter-events.ts → hono/meter-events.ts} +120 -110
  112. package/api/src/routes/hono/meters.ts +288 -0
  113. package/api/src/routes/hono/passports.ts +73 -0
  114. package/api/src/routes/{payment-currencies.ts → hono/payment-currencies.ts} +219 -197
  115. package/api/src/routes/{payment-intents.ts → hono/payment-intents.ts} +136 -132
  116. package/api/src/routes/{payment-links.ts → hono/payment-links.ts} +145 -128
  117. package/api/src/routes/{payment-methods.ts → hono/payment-methods.ts} +125 -93
  118. package/api/src/routes/{payment-stats.ts → hono/payment-stats.ts} +30 -25
  119. package/api/src/routes/{payouts.ts → hono/payouts.ts} +55 -47
  120. package/api/src/routes/{prices.ts → hono/prices.ts} +265 -242
  121. package/api/src/routes/{pricing-table.ts → hono/pricing-table.ts} +94 -87
  122. package/api/src/routes/{products.ts → hono/products.ts} +172 -159
  123. package/api/src/routes/{promotion-codes.ts → hono/promotion-codes.ts} +207 -185
  124. package/api/src/routes/hono/redirect.ts +24 -0
  125. package/api/src/routes/{refunds.ts → hono/refunds.ts} +96 -80
  126. package/api/src/routes/{settings.ts → hono/settings.ts} +64 -55
  127. package/api/src/routes/{subscription-items.ts → hono/subscription-items.ts} +64 -57
  128. package/api/src/routes/{subscriptions.ts → hono/subscriptions.ts} +475 -528
  129. package/api/src/routes/{tax-rates.ts → hono/tax-rates.ts} +71 -70
  130. package/api/src/routes/hono/tool.ts +69 -0
  131. package/api/src/routes/{usage-records.ts → hono/usage-records.ts} +47 -42
  132. package/api/src/routes/{vendor.ts → hono/vendor.ts} +315 -167
  133. package/api/src/routes/{webhook-attempts.ts → hono/webhook-attempts.ts} +17 -13
  134. package/api/src/routes/hono/webhook-endpoints.ts +126 -0
  135. package/api/src/service.ts +667 -0
  136. package/api/src/store/migrations/20230911-seeding.ts +2 -1
  137. package/api/src/store/migrations/20260609-remove-did-space-jobs.ts +23 -0
  138. package/api/src/store/migrations/20260610-tenant-columns.ts +40 -0
  139. package/api/src/store/migrations/20260611-tenant-backfill.ts +33 -0
  140. package/api/src/store/models/auto-recharge-config.ts +22 -10
  141. package/api/src/store/models/checkout-session.ts +15 -14
  142. package/api/src/store/models/coupon.ts +29 -20
  143. package/api/src/store/models/credit-grant.ts +38 -29
  144. package/api/src/store/models/credit-transaction.ts +32 -21
  145. package/api/src/store/models/customer.ts +19 -17
  146. package/api/src/store/models/discount.ts +11 -2
  147. package/api/src/store/models/entitlement-grant.ts +21 -9
  148. package/api/src/store/models/entitlement-product.ts +21 -9
  149. package/api/src/store/models/entitlement.ts +19 -10
  150. package/api/src/store/models/event.ts +18 -9
  151. package/api/src/store/models/exchange-rate-provider.ts +17 -4
  152. package/api/src/store/models/invoice-item.ts +18 -9
  153. package/api/src/store/models/invoice.ts +16 -8
  154. package/api/src/store/models/meter-event.ts +27 -9
  155. package/api/src/store/models/meter.ts +31 -22
  156. package/api/src/store/models/payment-currency.ts +25 -8
  157. package/api/src/store/models/payment-intent.ts +15 -6
  158. package/api/src/store/models/payment-link.ts +15 -6
  159. package/api/src/store/models/payment-method.ts +38 -22
  160. package/api/src/store/models/payment-stat.ts +18 -9
  161. package/api/src/store/models/payout.ts +15 -6
  162. package/api/src/store/models/price-quote.ts +17 -8
  163. package/api/src/store/models/price.ts +24 -12
  164. package/api/src/store/models/pricing-table.ts +29 -20
  165. package/api/src/store/models/product-vendor.ts +20 -10
  166. package/api/src/store/models/product.ts +15 -6
  167. package/api/src/store/models/promotion-code.ts +14 -6
  168. package/api/src/store/models/refund.ts +15 -6
  169. package/api/src/store/models/revenue-snapshot.ts +21 -9
  170. package/api/src/store/models/setting.ts +18 -9
  171. package/api/src/store/models/setup-intent.ts +36 -27
  172. package/api/src/store/models/subscription-item.ts +21 -9
  173. package/api/src/store/models/subscription-schedule.ts +21 -9
  174. package/api/src/store/models/subscription.ts +21 -10
  175. package/api/src/store/models/tax-rate.ts +29 -21
  176. package/api/src/store/models/usage-record.ts +11 -2
  177. package/api/src/store/models/webhook-attempt.ts +18 -9
  178. package/api/src/store/models/webhook-endpoint.ts +18 -9
  179. package/api/src/store/scoped-core.ts +55 -0
  180. package/api/src/store/scoped.ts +247 -0
  181. package/api/src/store/sequelize.ts +66 -22
  182. package/api/src/store/sql-migrations.ts +20 -0
  183. package/api/src/store/tenant-backfill.ts +260 -0
  184. package/api/src/store/tenant-model.ts +124 -0
  185. package/api/src/store/tenant-tables.ts +50 -0
  186. package/api/tests/embedded/embedded-multi-mode-d3.spec.ts +257 -0
  187. package/api/tests/fixtures/bare-query-violation.ts +13 -0
  188. package/api/tests/fixtures/core-env-violation.ts +10 -0
  189. package/api/tests/fixtures/host-read-violation.ts +19 -0
  190. package/api/tests/fixtures/tenants.ts +4 -0
  191. package/api/tests/integrations/iap-tenant.spec.ts +284 -0
  192. package/api/tests/libs/archive-query.spec.ts +26 -0
  193. package/api/tests/libs/audit-tenant.spec.ts +153 -0
  194. package/api/tests/libs/context.spec.ts +204 -0
  195. package/api/tests/libs/core-config.spec.ts +115 -0
  196. package/api/tests/libs/cron-driver-d2.spec.ts +237 -0
  197. package/api/tests/libs/crons-conservation-d2.spec.ts +52 -0
  198. package/api/tests/libs/lock-tenant.spec.ts +66 -0
  199. package/api/tests/libs/scoped.spec.ts +222 -0
  200. package/api/tests/libs/secrets-facade.spec.ts +52 -0
  201. package/api/tests/libs/tenancy-slot-authority.spec.ts +209 -0
  202. package/api/tests/libs/tenant-middleware.spec.ts +42 -0
  203. package/api/tests/libs/tenant-scanner.spec.ts +120 -0
  204. package/api/tests/middlewares/hono/cdn.spec.ts +70 -0
  205. package/api/tests/middlewares/hono/context.spec.ts +113 -0
  206. package/api/tests/middlewares/hono/csrf.spec.ts +136 -0
  207. package/api/tests/middlewares/hono/fallback.spec.ts +67 -0
  208. package/api/tests/middlewares/hono/pipeline.spec.ts +47 -0
  209. package/api/tests/middlewares/hono/security.spec.ts +181 -0
  210. package/api/tests/middlewares/hono/session.spec.ts +42 -0
  211. package/api/tests/middlewares/hono/xss.spec.ts +81 -0
  212. package/api/tests/models/tenant-backfill.spec.ts +287 -0
  213. package/api/tests/models/tenant-columns-model.spec.ts +46 -0
  214. package/api/tests/models/tenant-columns.spec.ts +161 -0
  215. package/api/tests/queues/credit-consume-batch.spec.ts +8 -1
  216. package/api/tests/queues/credit-consume.spec.ts +8 -1
  217. package/api/tests/queues/event-tenant.spec.ts +236 -0
  218. package/api/tests/queues/exchange-rate-health-tenant-d6.spec.ts +62 -0
  219. package/api/tests/queues/queue-parity.spec.ts +249 -0
  220. package/api/tests/queues/queue-runtime-surface.spec.ts +277 -0
  221. package/api/tests/queues/queue-teardown-d2.spec.ts +127 -0
  222. package/api/tests/queues/tenant-matrix-a.spec.ts +245 -0
  223. package/api/tests/queues/tenant-matrix-b.spec.ts +168 -0
  224. package/api/tests/routes/connect/hono-attach.spec.ts +107 -0
  225. package/api/tests/service/collapse.spec.ts +96 -0
  226. package/api/tests/store/tenant-crosscut.spec.ts +202 -0
  227. package/api/tests/store/tenant-model-spike.spec.ts +177 -0
  228. package/api/tests/store/tenant-model.spec.ts +162 -0
  229. package/api/tests/store/tenant-residual.spec.ts +196 -0
  230. package/api/third.d.ts +4 -0
  231. package/blocklet.yml +1 -1
  232. package/cloudflare/README.md +26 -6
  233. package/cloudflare/build.ts +28 -13
  234. package/cloudflare/did-connect-auth.ts +0 -217
  235. package/cloudflare/docs/2026-06-10-bundle-size-analysis.md +288 -0
  236. package/cloudflare/migrations/0006_tenant_columns.sql +46 -0
  237. package/cloudflare/migrations/0007_tenant_backfill_indexes.sql +65 -0
  238. package/cloudflare/migrations/0008_schema_parity.sql +16 -0
  239. package/cloudflare/migrations/0009_remove_did_space_jobs.sql +5 -0
  240. package/cloudflare/queue-runtime-mode.ts +13 -0
  241. package/cloudflare/run-build.js +31 -56
  242. package/cloudflare/shims/blocklet-sdk/asset-host-transformer.ts +20 -0
  243. package/cloudflare/shims/blocklet-sdk/config.ts +8 -1
  244. package/cloudflare/shims/blocklet-sdk/login.ts +12 -0
  245. package/cloudflare/shims/blocklet-sdk/service-api.ts +14 -0
  246. package/cloudflare/shims/blocklet-sdk/session.ts +4 -2
  247. package/cloudflare/shims/blocklet-sdk/util-constants.ts +8 -0
  248. package/cloudflare/shims/blocklet-sdk/util-csrf.ts +13 -0
  249. package/cloudflare/shims/blocklet-sdk/util-wallet.ts +8 -0
  250. package/cloudflare/shims/cron.ts +38 -158
  251. package/cloudflare/shims/events.ts +124 -0
  252. package/cloudflare/shims/fastq.ts +15 -1
  253. package/cloudflare/shims/nedb-storage.ts +16 -8
  254. package/cloudflare/shims/node-fetch.ts +35 -0
  255. package/cloudflare/shims/xss.ts +8 -0
  256. package/cloudflare/tenant-middleware.ts +36 -0
  257. package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
  258. package/cloudflare/tests/worker-handler-gate.spec.ts +44 -0
  259. package/cloudflare/worker.ts +204 -433
  260. package/cloudflare/wrangler.local-e2e.jsonc +26 -0
  261. package/jest.config.js +3 -1
  262. package/package.json +33 -38
  263. package/scripts/core-env-whitelist.json +1 -0
  264. package/scripts/e2e-12b-runtime.ts +149 -0
  265. package/scripts/e2e-core-config.ts +125 -0
  266. package/scripts/e2e-d1-tenancy.ts +116 -0
  267. package/scripts/e2e-d2-cron-queue.ts +139 -0
  268. package/scripts/e2e-d3-embedded-multi.ts +171 -0
  269. package/scripts/e2e-hono-s2.ts +125 -0
  270. package/scripts/e2e-hono-s3e.ts +135 -0
  271. package/scripts/e2e-hono-s4.ts +114 -0
  272. package/scripts/e2e-migration-contract.ts +100 -0
  273. package/scripts/e2e-s0.ts +61 -0
  274. package/scripts/e2e-s1.ts +107 -0
  275. package/scripts/e2e-s2.ts +178 -0
  276. package/scripts/e2e-s3.ts +110 -0
  277. package/scripts/e2e-s4.ts +191 -0
  278. package/scripts/e2e-s5.ts +139 -0
  279. package/scripts/e2e-s6.ts +127 -0
  280. package/scripts/e2e-tenant-model.ts +119 -0
  281. package/scripts/e2e-tenant-worker.ts +199 -0
  282. package/scripts/gen-sql-migrations.js +46 -0
  283. package/scripts/phase8-codemod.js +219 -0
  284. package/scripts/phase9a-env-getters-codemod.js +82 -0
  285. package/scripts/scan-core-env.js +109 -0
  286. package/scripts/scan-tenant-queries.js +235 -0
  287. package/scripts/schema-drift-guard.ts +210 -0
  288. package/scripts/tenant-scan-whitelist.json +1 -0
  289. package/src/env.d.ts +13 -1
  290. package/tsconfig.json +1 -1
  291. package/api/src/libs/did-space.ts +0 -235
  292. package/api/src/libs/middleware.ts +0 -50
  293. package/api/src/libs/security.ts +0 -192
  294. package/api/src/queues/space.ts +0 -662
  295. package/api/src/routes/credit-tokens.ts +0 -38
  296. package/api/src/routes/exchange-rates.ts +0 -87
  297. package/api/src/routes/index.ts +0 -142
  298. package/api/src/routes/integrations/stripe.ts +0 -61
  299. package/api/src/routes/meters.ts +0 -274
  300. package/api/src/routes/passports.ts +0 -68
  301. package/api/src/routes/redirect.ts +0 -20
  302. package/api/src/routes/tool.ts +0 -65
  303. package/api/src/routes/webhook-endpoints.ts +0 -126
  304. package/api/tests/routes/credit-grants.spec.ts +0 -1261
  305. package/cloudflare/shims/did-space-js.ts +0 -17
  306. package/cloudflare/shims/did-space.ts +0 -11
  307. package/cloudflare/shims/express-compat/index.ts +0 -80
  308. package/cloudflare/shims/express-compat/types.ts +0 -41
  309. package/cloudflare/shims/lock.ts +0 -115
  310. package/cloudflare/shims/queue.ts +0 -611
  311. package/cloudflare/tests/shims/queue-delayed-persist.spec.ts +0 -87
  312. package/cloudflare/tests/shims/queue-scheduled.spec.ts +0 -186
@@ -1,12 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
3
+ import { TenantModel } from '../tenant-model';
4
+ import { getInstanceDid } from '../../libs/context';
3
5
 
4
6
  import { createIdGenerator } from '../../libs/util';
5
7
 
6
8
  export const nextProductVendorId = createIdGenerator('pv', 24);
7
9
 
8
- export class ProductVendor extends Model<InferAttributes<ProductVendor>, InferCreationAttributes<ProductVendor>> {
10
+ export class ProductVendor extends TenantModel<InferAttributes<ProductVendor>, InferCreationAttributes<ProductVendor>> {
9
11
  declare id: CreationOptional<string>;
12
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
10
13
  declare vendor_key: string;
11
14
  declare vendor_type: string;
12
15
  declare name: string;
@@ -35,7 +38,8 @@ export class ProductVendor extends Model<InferAttributes<ProductVendor>, InferCr
35
38
  vendor_key: {
36
39
  type: DataTypes.STRING(50),
37
40
  allowNull: false,
38
- unique: true,
41
+ // uniqueness is per tenant since Phase 2 (decision D3):
42
+ // uq_product_vendors_tenant_key ON (instance_did, vendor_key)
39
43
  },
40
44
  vendor_type: {
41
45
  type: DataTypes.STRING(50),
@@ -98,13 +102,19 @@ export class ProductVendor extends Model<InferAttributes<ProductVendor>, InferCr
98
102
  };
99
103
 
100
104
  public static initialize(sequelize: any) {
101
- this.init(ProductVendor.GENESIS_ATTRIBUTES, {
102
- sequelize,
103
- modelName: 'ProductVendor',
104
- tableName: 'product_vendors',
105
- createdAt: 'created_at',
106
- updatedAt: 'updated_at',
107
- });
105
+ this.init(
106
+ {
107
+ ...ProductVendor.GENESIS_ATTRIBUTES,
108
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
109
+ },
110
+ {
111
+ sequelize,
112
+ modelName: 'ProductVendor',
113
+ tableName: 'product_vendors',
114
+ createdAt: 'created_at',
115
+ updatedAt: 'updated_at',
116
+ }
117
+ );
108
118
  }
109
119
  }
110
120
 
@@ -1,9 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
2
  import pick from 'lodash/pick';
3
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model, Sequelize } from 'sequelize';
3
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Sequelize } from 'sequelize';
4
4
  import type { LiteralUnion } from 'type-fest';
5
+ import { TenantModel } from '../tenant-model';
6
+ import { getInstanceDid } from '../../libs/context';
5
7
 
6
- import { createEvent } from '../../libs/audit';
8
+ import { createEvent, reportAuditFailure } from '../../libs/audit';
7
9
  import { createIdGenerator } from '../../libs/util';
8
10
 
9
11
  export const nextProductId = createIdGenerator('prod', 14);
@@ -11,13 +13,14 @@ export const nextProductId = createIdGenerator('prod', 14);
11
13
  export type ProductFeature = { name: string };
12
14
 
13
15
  // @link https://stripe.com/docs/api/products
14
- export class Product extends Model<InferAttributes<Product>, InferCreationAttributes<Product>> {
16
+ export class Product extends TenantModel<InferAttributes<Product>, InferCreationAttributes<Product>> {
15
17
  // Unique identifier for the object.
16
18
  declare id: CreationOptional<string>;
17
19
 
18
20
  // Whether the product is currently available for purchase.
19
21
  declare active: boolean;
20
22
  declare livemode: boolean;
23
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
21
24
  declare locked: CreationOptional<boolean>;
22
25
 
23
26
  declare type: LiteralUnion<'service' | 'good' | 'credit', string>;
@@ -154,6 +157,12 @@ export class Product extends Model<InferAttributes<Product>, InferCreationAttrib
154
157
  this.init(
155
158
  {
156
159
  ...Product.GENESIS_ATTRIBUTES,
160
+ instance_did: {
161
+ type: DataTypes.STRING(64),
162
+ allowNull: true,
163
+ // bare creates must still land in the active tenant (single mode = app DID)
164
+ defaultValue: () => getInstanceDid(),
165
+ },
157
166
  cross_sell: {
158
167
  type: DataTypes.JSON,
159
168
  allowNull: true,
@@ -171,13 +180,13 @@ export class Product extends Model<InferAttributes<Product>, InferCreationAttrib
171
180
  updatedAt: 'updated_at',
172
181
  hooks: {
173
182
  afterCreate: (model: Product, options) => {
174
- createEvent('Product', 'product.created', model, options).catch(console.error);
183
+ createEvent('Product', 'product.created', model, options).catch(reportAuditFailure);
175
184
  },
176
185
  afterUpdate: (model: Product, options) => {
177
- createEvent('Product', 'product.updated', model, options).catch(console.error);
186
+ createEvent('Product', 'product.updated', model, options).catch(reportAuditFailure);
178
187
  },
179
188
  afterDestroy: (model: Product, options) => {
180
- createEvent('Product', 'product.deleted', model, options).catch(console.error);
189
+ createEvent('Product', 'product.deleted', model, options).catch(reportAuditFailure);
181
190
  },
182
191
  },
183
192
  }
@@ -4,7 +4,6 @@ import {
4
4
  DataTypes,
5
5
  InferAttributes,
6
6
  InferCreationAttributes,
7
- Model,
8
7
  Op,
9
8
  FindOptions,
10
9
  WhereOptions,
@@ -12,19 +11,22 @@ import {
12
11
  import { fromTokenToUnit } from '@ocap/util';
13
12
 
14
13
  import type { LiteralUnion } from 'type-fest';
14
+ import { TenantModel } from '../tenant-model';
15
+ import { getInstanceDid } from '../../libs/context';
15
16
  import { createIdGenerator, formatMetadata } from '../../libs/util';
16
17
  import { trimDecimals } from '../../libs/math-utils';
17
18
  import type { NFTConfig, Restrictions, VCConfig, VerificationType } from './types';
18
19
  import type { TPaymentCurrency } from './payment-currency';
19
- import { createEvent } from '../../libs/audit';
20
+ import { createEvent, reportAuditFailure } from '../../libs/audit';
20
21
 
21
22
  const nextId = createIdGenerator('promo', 24);
22
23
 
23
24
  // @link https://stripe.com/docs/api/promotion_codes
24
25
  // eslint-disable-next-line prettier/prettier
25
- export class PromotionCode extends Model<InferAttributes<PromotionCode>, InferCreationAttributes<PromotionCode>> {
26
+ export class PromotionCode extends TenantModel<InferAttributes<PromotionCode>, InferCreationAttributes<PromotionCode>> {
26
27
  declare id: CreationOptional<string>;
27
28
  declare livemode: boolean;
29
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
28
30
  declare active: boolean;
29
31
  declare locked: CreationOptional<boolean>;
30
32
 
@@ -127,6 +129,12 @@ export class PromotionCode extends Model<InferAttributes<PromotionCode>, InferCr
127
129
  this.init(
128
130
  {
129
131
  ...PromotionCode.GENESIS_ATTRIBUTES,
132
+ instance_did: {
133
+ type: DataTypes.STRING(64),
134
+ allowNull: true,
135
+ // bare creates must still land in the active tenant (single mode = app DID)
136
+ defaultValue: () => getInstanceDid(),
137
+ },
130
138
  verification_type: {
131
139
  type: DataTypes.ENUM('code', 'nft', 'vc', 'user_restricted'),
132
140
  defaultValue: 'code',
@@ -157,13 +165,13 @@ export class PromotionCode extends Model<InferAttributes<PromotionCode>, InferCr
157
165
  updatedAt: 'updated_at',
158
166
  hooks: {
159
167
  afterCreate: (model: PromotionCode, options) => {
160
- createEvent('PromotionCode', 'promotion_code.created', model, options).catch(console.error);
168
+ createEvent('PromotionCode', 'promotion_code.created', model, options).catch(reportAuditFailure);
161
169
  },
162
170
  afterUpdate: (model: PromotionCode, options) => {
163
- createEvent('PromotionCode', 'promotion_code.updated', model, options).catch(console.error);
171
+ createEvent('PromotionCode', 'promotion_code.updated', model, options).catch(reportAuditFailure);
164
172
  },
165
173
  afterDestroy: (model: PromotionCode, options) => {
166
- createEvent('PromotionCode', 'promotion_code.deleted', model, options).catch(console.error);
174
+ createEvent('PromotionCode', 'promotion_code.deleted', model, options).catch(reportAuditFailure);
167
175
  },
168
176
  },
169
177
  }
@@ -1,10 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
2
  /* eslint-disable @typescript-eslint/indent */
3
3
  import { BN } from '@ocap/util';
4
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model, Op, Sequelize } from 'sequelize';
4
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Op, Sequelize } from 'sequelize';
5
5
  import type { LiteralUnion } from 'type-fest';
6
+ import { TenantModel } from '../tenant-model';
7
+ import { getInstanceDid } from '../../libs/context';
6
8
 
7
- import { createEvent, createStatusEvent } from '../../libs/audit';
9
+ import { createEvent, createStatusEvent, reportAuditFailure } from '../../libs/audit';
8
10
  import { createIdGenerator } from '../../libs/util';
9
11
  import type { GroupedBN, PaymentDetails, PaymentError } from './types';
10
12
 
@@ -12,11 +14,12 @@ export const nextRefundId = createIdGenerator('re', 24);
12
14
 
13
15
  // @link https://stripe.com/docs/api/payment_intents
14
16
  // eslint-disable-next-line prettier/prettier
15
- export class Refund extends Model<InferAttributes<Refund>, InferCreationAttributes<Refund>> {
17
+ export class Refund extends TenantModel<InferAttributes<Refund>, InferCreationAttributes<Refund>> {
16
18
  // Unique identifier for the object.
17
19
  declare id: CreationOptional<string>;
18
20
 
19
21
  declare livemode: boolean;
22
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
20
23
  declare description: string;
21
24
 
22
25
  declare amount: string;
@@ -188,6 +191,12 @@ export class Refund extends Model<InferAttributes<Refund>, InferCreationAttribut
188
191
  this.init(
189
192
  {
190
193
  ...Refund.GENESIS_ATTRIBUTES,
194
+ instance_did: {
195
+ type: DataTypes.STRING(64),
196
+ allowNull: true,
197
+ // bare creates must still land in the active tenant (single mode = app DID)
198
+ defaultValue: () => getInstanceDid(),
199
+ },
191
200
  payment_method_id: {
192
201
  type: DataTypes.STRING(30),
193
202
  allowNull: true,
@@ -211,7 +220,7 @@ export class Refund extends Model<InferAttributes<Refund>, InferCreationAttribut
211
220
  updatedAt: 'updated_at',
212
221
  hooks: {
213
222
  afterCreate: (model: Refund, options) => {
214
- createEvent('Refund', 'refund.created', model, options).catch(console.error);
223
+ createEvent('Refund', 'refund.created', model, options).catch(reportAuditFailure);
215
224
  },
216
225
  afterUpdate: (model: Refund, options) => {
217
226
  createStatusEvent(
@@ -220,10 +229,10 @@ export class Refund extends Model<InferAttributes<Refund>, InferCreationAttribut
220
229
  { canceled: 'canceled', processing: 'processing', succeeded: 'succeeded' },
221
230
  model,
222
231
  options
223
- ).catch(console.error);
232
+ ).catch(reportAuditFailure);
224
233
  },
225
234
  afterDestroy: (model: Refund, options) => {
226
- createEvent('Refund', 'refund.deleted', model, options).catch(console.error);
235
+ createEvent('Refund', 'refund.deleted', model, options).catch(reportAuditFailure);
227
236
  },
228
237
  },
229
238
  }
@@ -1,13 +1,19 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
3
+ import { TenantModel } from '../tenant-model';
4
+ import { getInstanceDid } from '../../libs/context';
3
5
 
4
6
  import { createIdGenerator } from '../../libs/util';
5
7
 
6
8
  const nextId = createIdGenerator('rs', 24);
7
9
 
8
- export class RevenueSnapshot extends Model<InferAttributes<RevenueSnapshot>, InferCreationAttributes<RevenueSnapshot>> {
10
+ export class RevenueSnapshot extends TenantModel<
11
+ InferAttributes<RevenueSnapshot>,
12
+ InferCreationAttributes<RevenueSnapshot>
13
+ > {
9
14
  declare id: CreationOptional<string>;
10
15
  declare livemode: boolean;
16
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
11
17
  declare currency_id: string;
12
18
 
13
19
  declare timestamp: number;
@@ -95,13 +101,19 @@ export class RevenueSnapshot extends Model<InferAttributes<RevenueSnapshot>, Inf
95
101
  };
96
102
 
97
103
  public static initialize(sequelize: any) {
98
- this.init(RevenueSnapshot.GENESIS_ATTRIBUTES, {
99
- sequelize,
100
- modelName: 'RevenueSnapshot',
101
- tableName: 'revenue_snapshots',
102
- createdAt: 'created_at',
103
- updatedAt: 'updated_at',
104
- });
104
+ this.init(
105
+ {
106
+ ...RevenueSnapshot.GENESIS_ATTRIBUTES,
107
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
108
+ },
109
+ {
110
+ sequelize,
111
+ modelName: 'RevenueSnapshot',
112
+ tableName: 'revenue_snapshots',
113
+ createdAt: 'created_at',
114
+ updatedAt: 'updated_at',
115
+ }
116
+ );
105
117
  }
106
118
 
107
119
  public static associate() {}
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
3
+ import { TenantModel } from '../tenant-model';
4
+ import { getInstanceDid } from '../../libs/context';
3
5
 
4
6
  import { createIdGenerator } from '../../libs/util';
5
7
  import type { SettingType } from './types';
@@ -7,10 +9,11 @@ import type { SettingType } from './types';
7
9
  const nextId = createIdGenerator('set', 24);
8
10
 
9
11
  // eslint-disable-next-line prettier/prettier
10
- export class Setting extends Model<InferAttributes<Setting>, InferCreationAttributes<Setting>> {
12
+ export class Setting extends TenantModel<InferAttributes<Setting>, InferCreationAttributes<Setting>> {
11
13
  declare id: CreationOptional<string>;
12
14
 
13
15
  declare livemode: boolean;
16
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
14
17
 
15
18
  declare type: SettingType;
16
19
  declare mount_location: string;
@@ -71,13 +74,19 @@ export class Setting extends Model<InferAttributes<Setting>, InferCreationAttrib
71
74
  };
72
75
 
73
76
  public static initialize(sequelize: any) {
74
- this.init(Setting.GENESIS_ATTRIBUTES, {
75
- sequelize,
76
- modelName: 'Setting',
77
- tableName: 'settings',
78
- createdAt: 'created_at',
79
- updatedAt: 'updated_at',
80
- });
77
+ this.init(
78
+ {
79
+ ...Setting.GENESIS_ATTRIBUTES,
80
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
81
+ },
82
+ {
83
+ sequelize,
84
+ modelName: 'Setting',
85
+ tableName: 'settings',
86
+ createdAt: 'created_at',
87
+ updatedAt: 'updated_at',
88
+ }
89
+ );
81
90
  }
82
91
  }
83
92
 
@@ -1,9 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
2
  /* eslint-disable @typescript-eslint/indent */
3
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
3
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
4
4
  import type { LiteralUnion } from 'type-fest';
5
+ import { TenantModel } from '../tenant-model';
6
+ import { getInstanceDid } from '../../libs/context';
5
7
 
6
- import { createEvent, createStatusEvent } from '../../libs/audit';
8
+ import { createEvent, createStatusEvent, reportAuditFailure } from '../../libs/audit';
7
9
  import { createIdGenerator } from '../../libs/util';
8
10
  import type { PaymentDetails, PaymentError, PaymentMethodOptions } from './types';
9
11
 
@@ -11,11 +13,12 @@ const nextId = createIdGenerator('seti', 24);
11
13
 
12
14
  // @link https://stripe.com/docs/api/setup_intents
13
15
  // eslint-disable-next-line prettier/prettier
14
- export class SetupIntent extends Model<InferAttributes<SetupIntent>, InferCreationAttributes<SetupIntent>> {
16
+ export class SetupIntent extends TenantModel<InferAttributes<SetupIntent>, InferCreationAttributes<SetupIntent>> {
15
17
  // Unique identifier for the object.
16
18
  declare id: CreationOptional<string>;
17
19
 
18
20
  declare livemode: boolean;
21
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
19
22
  declare description: string;
20
23
 
21
24
  declare currency_id: string;
@@ -156,31 +159,37 @@ export class SetupIntent extends Model<InferAttributes<SetupIntent>, InferCreati
156
159
  };
157
160
 
158
161
  public static initialize(sequelize: any) {
159
- this.init(SetupIntent.GENESIS_ATTRIBUTES, {
160
- sequelize,
161
- modelName: 'SetupIntent',
162
- tableName: 'setup_intents',
163
- createdAt: 'created_at',
164
- updatedAt: 'updated_at',
165
- hooks: {
166
- afterCreate: (model: SetupIntent, options) => {
167
- createEvent('SetupIntent', 'setup_intent.created', model, options).catch(console.error);
168
- },
169
- afterUpdate: (model: SetupIntent, options) => {
170
- createStatusEvent(
171
- 'SetupIntent',
172
- 'setup_intent',
173
- {
174
- requires_action: 'requires_action',
175
- canceled: 'canceled',
176
- succeeded: 'succeeded',
177
- },
178
- model,
179
- options
180
- ).catch(console.error);
181
- },
162
+ this.init(
163
+ {
164
+ ...SetupIntent.GENESIS_ATTRIBUTES,
165
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
182
166
  },
183
- });
167
+ {
168
+ sequelize,
169
+ modelName: 'SetupIntent',
170
+ tableName: 'setup_intents',
171
+ createdAt: 'created_at',
172
+ updatedAt: 'updated_at',
173
+ hooks: {
174
+ afterCreate: (model: SetupIntent, options) => {
175
+ createEvent('SetupIntent', 'setup_intent.created', model, options).catch(reportAuditFailure);
176
+ },
177
+ afterUpdate: (model: SetupIntent, options) => {
178
+ createStatusEvent(
179
+ 'SetupIntent',
180
+ 'setup_intent',
181
+ {
182
+ requires_action: 'requires_action',
183
+ canceled: 'canceled',
184
+ succeeded: 'succeeded',
185
+ },
186
+ model,
187
+ options
188
+ ).catch(reportAuditFailure);
189
+ },
190
+ },
191
+ }
192
+ );
184
193
  }
185
194
 
186
195
  public static associate(models: any) {
@@ -1,14 +1,20 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
3
+ import { TenantModel } from '../tenant-model';
4
+ import { getInstanceDid } from '../../libs/context';
3
5
 
4
6
  import { createIdGenerator } from '../../libs/util';
5
7
 
6
8
  export const nextSubscriptionItemId = createIdGenerator('si', 14);
7
9
 
8
10
  // eslint-disable-next-line prettier/prettier
9
- export class SubscriptionItem extends Model<InferAttributes<SubscriptionItem>, InferCreationAttributes<SubscriptionItem>> {
11
+ export class SubscriptionItem extends TenantModel<
12
+ InferAttributes<SubscriptionItem>,
13
+ InferCreationAttributes<SubscriptionItem>
14
+ > {
10
15
  declare id: CreationOptional<string>;
11
16
  declare livemode: boolean;
17
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
12
18
 
13
19
  // The identifier of the subscription this item belongs to.
14
20
  declare subscription_id: string;
@@ -74,13 +80,19 @@ export class SubscriptionItem extends Model<InferAttributes<SubscriptionItem>, I
74
80
  };
75
81
 
76
82
  public static initialize(sequelize: any) {
77
- this.init(SubscriptionItem.GENESIS_ATTRIBUTES, {
78
- sequelize,
79
- modelName: 'SubscriptionItem',
80
- tableName: 'subscription_items',
81
- createdAt: 'created_at',
82
- updatedAt: 'updated_at',
83
- });
83
+ this.init(
84
+ {
85
+ ...SubscriptionItem.GENESIS_ATTRIBUTES,
86
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
87
+ },
88
+ {
89
+ sequelize,
90
+ modelName: 'SubscriptionItem',
91
+ tableName: 'subscription_items',
92
+ createdAt: 'created_at',
93
+ updatedAt: 'updated_at',
94
+ }
95
+ );
84
96
  }
85
97
 
86
98
  public static associate(models: any) {
@@ -1,6 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/lines-between-class-members */
2
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from 'sequelize';
2
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
3
3
  import type { LiteralUnion } from 'type-fest';
4
+ import { TenantModel } from '../tenant-model';
5
+ import { getInstanceDid } from '../../libs/context';
4
6
 
5
7
  import { createIdGenerator } from '../../libs/util';
6
8
  import type { SubscriptionSchedulePhase } from './types';
@@ -8,10 +10,14 @@ import type { SubscriptionSchedulePhase } from './types';
8
10
  const nextId = createIdGenerator('ss', 24);
9
11
 
10
12
  // eslint-disable-next-line prettier/prettier
11
- export class SubscriptionSchedule extends Model<InferAttributes<SubscriptionSchedule>, InferCreationAttributes<SubscriptionSchedule>> {
13
+ export class SubscriptionSchedule extends TenantModel<
14
+ InferAttributes<SubscriptionSchedule>,
15
+ InferCreationAttributes<SubscriptionSchedule>
16
+ > {
12
17
  declare id: CreationOptional<string>;
13
18
 
14
19
  declare livemode: boolean;
20
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
15
21
 
16
22
  declare current_phase: {
17
23
  end_date: Date;
@@ -137,13 +143,19 @@ export class SubscriptionSchedule extends Model<InferAttributes<SubscriptionSche
137
143
  };
138
144
 
139
145
  public static initialize(sequelize: any) {
140
- this.init(SubscriptionSchedule.GENESIS_ATTRIBUTES, {
141
- sequelize,
142
- modelName: 'SubscriptionSchedule',
143
- tableName: 'subscription_schedules',
144
- createdAt: 'created_at',
145
- updatedAt: 'updated_at',
146
- });
146
+ this.init(
147
+ {
148
+ ...SubscriptionSchedule.GENESIS_ATTRIBUTES,
149
+ instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
150
+ },
151
+ {
152
+ sequelize,
153
+ modelName: 'SubscriptionSchedule',
154
+ tableName: 'subscription_schedules',
155
+ createdAt: 'created_at',
156
+ updatedAt: 'updated_at',
157
+ }
158
+ );
147
159
  }
148
160
 
149
161
  public static associate(models: any) {
@@ -1,9 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/indent */
2
2
  /* eslint-disable @typescript-eslint/lines-between-class-members */
3
- import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model, Sequelize } from 'sequelize';
3
+ import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Sequelize } from 'sequelize';
4
4
  import type { LiteralUnion } from 'type-fest';
5
+ import { TenantModel } from '../tenant-model';
6
+ import { getInstanceDid } from '../../libs/context';
5
7
 
6
- import { createCustomEvent, createEvent, createStatusEvent } from '../../libs/audit';
8
+ import { createCustomEvent, createEvent, createStatusEvent, reportAuditFailure } from '../../libs/audit';
7
9
  import logger from '../../libs/logger';
8
10
  import { createIdGenerator } from '../../libs/util';
9
11
  import { Invoice } from './invoice';
@@ -20,10 +22,11 @@ export const nextSubscriptionId = createIdGenerator('sub', 24);
20
22
 
21
23
  // FIXME: subscription settings https://dashboard.stripe.com/settings/billing/automatic
22
24
  // eslint-disable-next-line prettier/prettier
23
- export class Subscription extends Model<InferAttributes<Subscription>, InferCreationAttributes<Subscription>> {
25
+ export class Subscription extends TenantModel<InferAttributes<Subscription>, InferCreationAttributes<Subscription>> {
24
26
  declare id: CreationOptional<string>;
25
27
 
26
28
  declare livemode: boolean;
29
+ declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
27
30
 
28
31
  declare currency_id: string;
29
32
  declare customer_id: string;
@@ -299,6 +302,12 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
299
302
  this.init(
300
303
  {
301
304
  ...Subscription.GENESIS_ATTRIBUTES,
305
+ instance_did: {
306
+ type: DataTypes.STRING(64),
307
+ allowNull: true,
308
+ // bare creates must still land in the active tenant (single mode = app DID)
309
+ defaultValue: () => getInstanceDid(),
310
+ },
302
311
  proration_behavior: {
303
312
  type: DataTypes.ENUM('always_invoice', 'create_prorations', 'none'),
304
313
  defaultValue: 'none',
@@ -369,10 +378,10 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
369
378
  updatedAt: 'updated_at',
370
379
  hooks: {
371
380
  afterCreate: (model: Subscription, options) => {
372
- createEvent('Subscription', 'customer.subscription.created', model, options).catch(console.error);
381
+ createEvent('Subscription', 'customer.subscription.created', model, options).catch(reportAuditFailure);
373
382
  },
374
383
  afterUpdate: async (model: Subscription, options) => {
375
- createEvent('Subscription', 'customer.subscription.updated', model, options).catch(console.error);
384
+ createEvent('Subscription', 'customer.subscription.updated', model, options).catch(reportAuditFailure);
376
385
 
377
386
  if (model.trial_start) {
378
387
  const previousLatestInvoiceId = model.previous('latest_invoice_id');
@@ -389,7 +398,9 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
389
398
  });
390
399
  if (count === 2) {
391
400
  // 当且仅当 有试用期的订阅更新了 && 恰好有 2 次账单,此时订阅的试用期刚好结束
392
- createEvent('Subscription', 'customer.subscription.trial_end', model, options).catch(console.error);
401
+ createEvent('Subscription', 'customer.subscription.trial_end', model, options).catch(
402
+ reportAuditFailure
403
+ );
393
404
  }
394
405
  }
395
406
  }
@@ -400,9 +411,9 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
400
411
  { canceled: 'deleted', past_due: 'past_due' },
401
412
  model,
402
413
  options
403
- ).catch(console.error);
414
+ ).catch(reportAuditFailure);
404
415
  createCustomEvent('Subscription', 'customer.subscription', getSubscriptionEventType, model, options).catch(
405
- console.error
416
+ reportAuditFailure
406
417
  );
407
418
  },
408
419
  },
@@ -482,11 +493,11 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
482
493
  if (this.trial_end && this.trial_end > Date.now() / 1000) {
483
494
  if (this.status !== 'trialing') {
484
495
  await this.update({ status: 'trialing' });
485
- createEvent('Subscription', 'customer.subscription.trial_start', this).catch(console.error);
496
+ createEvent('Subscription', 'customer.subscription.trial_start', this).catch(reportAuditFailure);
486
497
  }
487
498
  } else {
488
499
  await this.update({ status: 'active' });
489
- createEvent('Subscription', 'customer.subscription.started', this).catch(console.error);
500
+ createEvent('Subscription', 'customer.subscription.started', this).catch(reportAuditFailure);
490
501
  }
491
502
 
492
503
  return true;