payment-kit 1.29.1 → 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.
- package/api/dev.ts +41 -2
- package/api/hono.d.ts +42 -0
- package/api/node-sqlite.d.ts +12 -0
- package/api/src/bootstrap.ts +36 -0
- package/api/src/crons/base.ts +3 -3
- package/api/src/crons/currency.ts +1 -1
- package/api/src/crons/index.ts +27 -24
- package/api/src/crons/metering-subscription-detection.ts +1 -1
- package/api/src/crons/overdue-detection.ts +2 -2
- package/api/src/crons/retry-pending-events.ts +6 -0
- package/api/src/index.ts +22 -161
- package/api/src/integrations/app-store/client.ts +3 -4
- package/api/src/integrations/app-store/handlers/subscription.ts +7 -7
- package/api/src/integrations/app-store/signed-data-verifier.ts +3 -2
- package/api/src/integrations/arcblock/token.ts +21 -7
- package/api/src/integrations/google-play/handlers/subscription.ts +6 -6
- package/api/src/integrations/google-play/handlers/voided.ts +2 -2
- package/api/src/integrations/google-play/verify.ts +3 -2
- package/api/src/integrations/iap-reconcile.ts +3 -5
- package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
- package/api/src/integrations/stripe/handlers/subscription.ts +3 -3
- package/api/src/libs/archive/query.ts +19 -0
- package/api/src/libs/audit.ts +61 -4
- package/api/src/libs/auth.ts +99 -38
- package/api/src/libs/context.ts +78 -1
- package/api/src/libs/currency.ts +2 -2
- package/api/src/libs/dayjs.ts +8 -2
- package/api/src/libs/drivers/auth-storage.ts +118 -0
- package/api/src/libs/drivers/cron.ts +264 -0
- package/api/src/libs/drivers/db.ts +170 -0
- package/api/src/libs/drivers/identity.ts +81 -0
- package/api/src/libs/drivers/index.ts +40 -0
- package/api/src/libs/drivers/locks.ts +226 -0
- package/api/src/libs/drivers/migrate-runner.ts +70 -0
- package/api/src/libs/drivers/queue.ts +104 -0
- package/api/src/libs/drivers/secrets.ts +194 -0
- package/api/src/libs/env.ts +170 -54
- package/api/src/libs/exchange-rate/service.ts +7 -6
- package/api/src/libs/http-fetch-adapter.ts +50 -0
- package/api/src/libs/invoice.ts +1 -1
- package/api/src/libs/lock.ts +51 -47
- package/api/src/libs/logger.ts +48 -8
- package/api/src/libs/notification/index.ts +1 -1
- package/api/src/libs/notification/template/customer-credit-low-balance.ts +2 -1
- package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -1
- package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -1
- package/api/src/libs/overdraft-protection.ts +1 -1
- package/api/src/libs/payout.ts +1 -1
- package/api/src/libs/queue/index.ts +259 -52
- package/api/src/libs/queue/runtime.ts +175 -0
- package/api/src/libs/resource.ts +3 -3
- package/api/src/libs/secrets.ts +38 -0
- package/api/src/libs/session.ts +3 -2
- package/api/src/libs/subscription.ts +5 -5
- package/api/src/libs/tenant.ts +92 -0
- package/api/src/libs/url.ts +3 -3
- package/api/src/libs/util.ts +21 -13
- package/api/src/middlewares/hono/cdn.ts +63 -0
- package/api/src/middlewares/hono/context.ts +73 -0
- package/api/src/middlewares/hono/csrf.ts +72 -0
- package/api/src/middlewares/hono/fallback.ts +194 -0
- package/api/src/middlewares/hono/pipeline.ts +73 -0
- package/api/src/middlewares/hono/resource-mount.ts +42 -0
- package/api/src/middlewares/hono/resource.ts +63 -0
- package/api/src/middlewares/hono/security.ts +214 -0
- package/api/src/middlewares/hono/session.ts +114 -0
- package/api/src/middlewares/hono/xss.ts +61 -0
- package/api/src/queues/auto-recharge.ts +12 -10
- package/api/src/queues/checkout-session.ts +17 -12
- package/api/src/queues/credit-consume.ts +40 -36
- package/api/src/queues/credit-grant.ts +25 -18
- package/api/src/queues/credit-reconciliation.ts +7 -5
- package/api/src/queues/discount-status.ts +9 -6
- package/api/src/queues/event.ts +12 -4
- package/api/src/queues/exchange-rate-health.ts +49 -30
- package/api/src/queues/invoice.ts +18 -15
- package/api/src/queues/notification.ts +14 -7
- package/api/src/queues/payment.ts +41 -28
- package/api/src/queues/payout.ts +9 -5
- package/api/src/queues/refund.ts +18 -12
- package/api/src/queues/subscription.ts +83 -53
- package/api/src/queues/token-transfer.ts +15 -10
- package/api/src/queues/usage-record.ts +8 -5
- package/api/src/queues/vendors/commission.ts +7 -5
- package/api/src/queues/vendors/fulfillment-coordinator.ts +17 -13
- package/api/src/queues/vendors/fulfillment.ts +4 -2
- package/api/src/queues/vendors/return-processor.ts +5 -3
- package/api/src/queues/vendors/return-scanner.ts +5 -4
- package/api/src/queues/vendors/status-check.ts +10 -7
- package/api/src/queues/webhook.ts +60 -32
- package/api/src/routes/connect/shared.ts +1 -2
- package/api/src/routes/connect/subscribe.ts +3 -3
- package/api/src/routes/{archive.ts → hono/archive.ts} +69 -64
- package/api/src/routes/{auto-recharge-configs.ts → hono/auto-recharge-configs.ts} +39 -28
- package/api/src/routes/{checkout-sessions.ts → hono/checkout-sessions.ts} +790 -923
- package/api/src/routes/{coupons.ts → hono/coupons.ts} +93 -76
- package/api/src/routes/{credit-grants.ts → hono/credit-grants.ts} +140 -126
- package/api/src/routes/hono/credit-tokens.ts +43 -0
- package/api/src/routes/{credit-transactions.ts → hono/credit-transactions.ts} +37 -29
- package/api/src/routes/{customers.ts → hono/customers.ts} +193 -223
- package/api/src/routes/{donations.ts → hono/donations.ts} +41 -32
- package/api/src/routes/{entitlements.ts → hono/entitlements.ts} +28 -25
- package/api/src/routes/{events.ts → hono/events.ts} +107 -71
- package/api/src/routes/{exchange-rate-providers.ts → hono/exchange-rate-providers.ts} +138 -126
- package/api/src/routes/hono/exchange-rates.ts +77 -0
- package/api/src/routes/hono/index.ts +115 -0
- package/api/src/routes/{integrations → hono/integrations}/app-store.ts +68 -48
- package/api/src/routes/{integrations → hono/integrations}/google-play.ts +78 -58
- package/api/src/routes/hono/integrations/stripe.ts +74 -0
- package/api/src/routes/{invoices.ts → hono/invoices.ts} +253 -244
- package/api/src/routes/{meter-events.ts → hono/meter-events.ts} +120 -110
- package/api/src/routes/hono/meters.ts +288 -0
- package/api/src/routes/hono/passports.ts +73 -0
- package/api/src/routes/{payment-currencies.ts → hono/payment-currencies.ts} +219 -197
- package/api/src/routes/{payment-intents.ts → hono/payment-intents.ts} +136 -132
- package/api/src/routes/{payment-links.ts → hono/payment-links.ts} +145 -128
- package/api/src/routes/{payment-methods.ts → hono/payment-methods.ts} +125 -93
- package/api/src/routes/{payment-stats.ts → hono/payment-stats.ts} +30 -25
- package/api/src/routes/{payouts.ts → hono/payouts.ts} +55 -47
- package/api/src/routes/{prices.ts → hono/prices.ts} +265 -242
- package/api/src/routes/{pricing-table.ts → hono/pricing-table.ts} +94 -87
- package/api/src/routes/{products.ts → hono/products.ts} +172 -159
- package/api/src/routes/{promotion-codes.ts → hono/promotion-codes.ts} +207 -185
- package/api/src/routes/hono/redirect.ts +24 -0
- package/api/src/routes/{refunds.ts → hono/refunds.ts} +96 -80
- package/api/src/routes/{settings.ts → hono/settings.ts} +64 -55
- package/api/src/routes/{subscription-items.ts → hono/subscription-items.ts} +64 -57
- package/api/src/routes/{subscriptions.ts → hono/subscriptions.ts} +475 -528
- package/api/src/routes/{tax-rates.ts → hono/tax-rates.ts} +71 -70
- package/api/src/routes/hono/tool.ts +69 -0
- package/api/src/routes/{usage-records.ts → hono/usage-records.ts} +47 -42
- package/api/src/routes/{vendor.ts → hono/vendor.ts} +315 -167
- package/api/src/routes/{webhook-attempts.ts → hono/webhook-attempts.ts} +17 -13
- package/api/src/routes/hono/webhook-endpoints.ts +126 -0
- package/api/src/service.ts +667 -0
- package/api/src/store/migrations/20230911-seeding.ts +2 -1
- package/api/src/store/migrations/20260609-remove-did-space-jobs.ts +23 -0
- package/api/src/store/migrations/20260610-tenant-columns.ts +40 -0
- package/api/src/store/migrations/20260611-tenant-backfill.ts +33 -0
- package/api/src/store/models/auto-recharge-config.ts +22 -10
- package/api/src/store/models/checkout-session.ts +15 -14
- package/api/src/store/models/coupon.ts +29 -20
- package/api/src/store/models/credit-grant.ts +38 -29
- package/api/src/store/models/credit-transaction.ts +32 -21
- package/api/src/store/models/customer.ts +19 -17
- package/api/src/store/models/discount.ts +11 -2
- package/api/src/store/models/entitlement-grant.ts +21 -9
- package/api/src/store/models/entitlement-product.ts +21 -9
- package/api/src/store/models/entitlement.ts +19 -10
- package/api/src/store/models/event.ts +18 -9
- package/api/src/store/models/exchange-rate-provider.ts +17 -4
- package/api/src/store/models/invoice-item.ts +18 -9
- package/api/src/store/models/invoice.ts +16 -8
- package/api/src/store/models/meter-event.ts +27 -9
- package/api/src/store/models/meter.ts +31 -22
- package/api/src/store/models/payment-currency.ts +25 -8
- package/api/src/store/models/payment-intent.ts +15 -6
- package/api/src/store/models/payment-link.ts +15 -6
- package/api/src/store/models/payment-method.ts +38 -22
- package/api/src/store/models/payment-stat.ts +18 -9
- package/api/src/store/models/payout.ts +15 -6
- package/api/src/store/models/price-quote.ts +17 -8
- package/api/src/store/models/price.ts +24 -12
- package/api/src/store/models/pricing-table.ts +29 -20
- package/api/src/store/models/product-vendor.ts +20 -10
- package/api/src/store/models/product.ts +15 -6
- package/api/src/store/models/promotion-code.ts +14 -6
- package/api/src/store/models/refund.ts +15 -6
- package/api/src/store/models/revenue-snapshot.ts +21 -9
- package/api/src/store/models/setting.ts +18 -9
- package/api/src/store/models/setup-intent.ts +36 -27
- package/api/src/store/models/subscription-item.ts +21 -9
- package/api/src/store/models/subscription-schedule.ts +21 -9
- package/api/src/store/models/subscription.ts +21 -10
- package/api/src/store/models/tax-rate.ts +29 -21
- package/api/src/store/models/usage-record.ts +11 -2
- package/api/src/store/models/webhook-attempt.ts +18 -9
- package/api/src/store/models/webhook-endpoint.ts +18 -9
- package/api/src/store/scoped-core.ts +55 -0
- package/api/src/store/scoped.ts +247 -0
- package/api/src/store/sequelize.ts +66 -22
- package/api/src/store/sql-migrations.ts +20 -0
- package/api/src/store/tenant-backfill.ts +260 -0
- package/api/src/store/tenant-model.ts +124 -0
- package/api/src/store/tenant-tables.ts +50 -0
- package/api/tests/embedded/embedded-multi-mode-d3.spec.ts +257 -0
- package/api/tests/fixtures/bare-query-violation.ts +13 -0
- package/api/tests/fixtures/core-env-violation.ts +10 -0
- package/api/tests/fixtures/host-read-violation.ts +19 -0
- package/api/tests/fixtures/tenants.ts +4 -0
- package/api/tests/integrations/iap-tenant.spec.ts +284 -0
- package/api/tests/libs/archive-query.spec.ts +26 -0
- package/api/tests/libs/audit-tenant.spec.ts +153 -0
- package/api/tests/libs/context.spec.ts +204 -0
- package/api/tests/libs/core-config.spec.ts +115 -0
- package/api/tests/libs/cron-driver-d2.spec.ts +237 -0
- package/api/tests/libs/crons-conservation-d2.spec.ts +52 -0
- package/api/tests/libs/lock-tenant.spec.ts +66 -0
- package/api/tests/libs/scoped.spec.ts +222 -0
- package/api/tests/libs/secrets-facade.spec.ts +52 -0
- package/api/tests/libs/tenancy-slot-authority.spec.ts +209 -0
- package/api/tests/libs/tenant-middleware.spec.ts +42 -0
- package/api/tests/libs/tenant-scanner.spec.ts +120 -0
- package/api/tests/middlewares/hono/cdn.spec.ts +70 -0
- package/api/tests/middlewares/hono/context.spec.ts +113 -0
- package/api/tests/middlewares/hono/csrf.spec.ts +136 -0
- package/api/tests/middlewares/hono/fallback.spec.ts +67 -0
- package/api/tests/middlewares/hono/pipeline.spec.ts +47 -0
- package/api/tests/middlewares/hono/security.spec.ts +181 -0
- package/api/tests/middlewares/hono/session.spec.ts +42 -0
- package/api/tests/middlewares/hono/xss.spec.ts +81 -0
- package/api/tests/models/tenant-backfill.spec.ts +287 -0
- package/api/tests/models/tenant-columns-model.spec.ts +46 -0
- package/api/tests/models/tenant-columns.spec.ts +161 -0
- package/api/tests/queues/credit-consume-batch.spec.ts +8 -1
- package/api/tests/queues/credit-consume.spec.ts +8 -1
- package/api/tests/queues/event-tenant.spec.ts +236 -0
- package/api/tests/queues/exchange-rate-health-tenant-d6.spec.ts +62 -0
- package/api/tests/queues/queue-parity.spec.ts +249 -0
- package/api/tests/queues/queue-runtime-surface.spec.ts +277 -0
- package/api/tests/queues/queue-teardown-d2.spec.ts +127 -0
- package/api/tests/queues/tenant-matrix-a.spec.ts +245 -0
- package/api/tests/queues/tenant-matrix-b.spec.ts +168 -0
- package/api/tests/routes/connect/hono-attach.spec.ts +107 -0
- package/api/tests/service/collapse.spec.ts +96 -0
- package/api/tests/store/tenant-crosscut.spec.ts +202 -0
- package/api/tests/store/tenant-model-spike.spec.ts +177 -0
- package/api/tests/store/tenant-model.spec.ts +162 -0
- package/api/tests/store/tenant-residual.spec.ts +196 -0
- package/api/third.d.ts +4 -0
- package/blocklet.yml +1 -1
- package/cloudflare/README.md +26 -6
- package/cloudflare/build.ts +28 -13
- package/cloudflare/did-connect-auth.ts +0 -217
- package/cloudflare/migrations/0006_tenant_columns.sql +46 -0
- package/cloudflare/migrations/0007_tenant_backfill_indexes.sql +65 -0
- package/cloudflare/migrations/0008_schema_parity.sql +16 -0
- package/cloudflare/migrations/0009_remove_did_space_jobs.sql +5 -0
- package/cloudflare/queue-runtime-mode.ts +13 -0
- package/cloudflare/run-build.js +10 -56
- package/cloudflare/shims/blocklet-sdk/asset-host-transformer.ts +20 -0
- package/cloudflare/shims/blocklet-sdk/config.ts +8 -1
- package/cloudflare/shims/blocklet-sdk/login.ts +12 -0
- package/cloudflare/shims/blocklet-sdk/service-api.ts +14 -0
- package/cloudflare/shims/blocklet-sdk/session.ts +4 -2
- package/cloudflare/shims/blocklet-sdk/util-constants.ts +8 -0
- package/cloudflare/shims/blocklet-sdk/util-csrf.ts +13 -0
- package/cloudflare/shims/blocklet-sdk/util-wallet.ts +8 -0
- package/cloudflare/shims/cron.ts +38 -158
- package/cloudflare/shims/events.ts +124 -0
- package/cloudflare/shims/fastq.ts +15 -1
- package/cloudflare/shims/nedb-storage.ts +16 -8
- package/cloudflare/shims/xss.ts +8 -0
- package/cloudflare/tenant-middleware.ts +36 -0
- package/cloudflare/tests/tenant-middleware.spec.ts +160 -0
- package/cloudflare/tests/worker-handler-gate.spec.ts +44 -0
- package/cloudflare/worker.ts +204 -433
- package/cloudflare/wrangler.local-e2e.jsonc +26 -0
- package/jest.config.js +3 -1
- package/package.json +33 -38
- package/scripts/core-env-whitelist.json +1 -0
- package/scripts/e2e-12b-runtime.ts +149 -0
- package/scripts/e2e-core-config.ts +125 -0
- package/scripts/e2e-d1-tenancy.ts +116 -0
- package/scripts/e2e-d2-cron-queue.ts +139 -0
- package/scripts/e2e-d3-embedded-multi.ts +171 -0
- package/scripts/e2e-hono-s2.ts +125 -0
- package/scripts/e2e-hono-s3e.ts +135 -0
- package/scripts/e2e-hono-s4.ts +114 -0
- package/scripts/e2e-migration-contract.ts +100 -0
- package/scripts/e2e-s0.ts +61 -0
- package/scripts/e2e-s1.ts +107 -0
- package/scripts/e2e-s2.ts +178 -0
- package/scripts/e2e-s3.ts +110 -0
- package/scripts/e2e-s4.ts +191 -0
- package/scripts/e2e-s5.ts +139 -0
- package/scripts/e2e-s6.ts +127 -0
- package/scripts/e2e-tenant-model.ts +119 -0
- package/scripts/e2e-tenant-worker.ts +199 -0
- package/scripts/gen-sql-migrations.js +46 -0
- package/scripts/phase8-codemod.js +219 -0
- package/scripts/phase9a-env-getters-codemod.js +82 -0
- package/scripts/scan-core-env.js +109 -0
- package/scripts/scan-tenant-queries.js +235 -0
- package/scripts/schema-drift-guard.ts +210 -0
- package/scripts/tenant-scan-whitelist.json +1 -0
- package/src/env.d.ts +13 -1
- package/tsconfig.json +1 -1
- package/api/src/libs/did-space.ts +0 -235
- package/api/src/libs/middleware.ts +0 -50
- package/api/src/libs/security.ts +0 -192
- package/api/src/queues/space.ts +0 -662
- package/api/src/routes/credit-tokens.ts +0 -38
- package/api/src/routes/exchange-rates.ts +0 -87
- package/api/src/routes/index.ts +0 -142
- package/api/src/routes/integrations/stripe.ts +0 -61
- package/api/src/routes/meters.ts +0 -274
- package/api/src/routes/passports.ts +0 -68
- package/api/src/routes/redirect.ts +0 -20
- package/api/src/routes/tool.ts +0 -65
- package/api/src/routes/webhook-endpoints.ts +0 -126
- package/api/tests/routes/credit-grants.spec.ts +0 -1261
- package/cloudflare/shims/did-space-js.ts +0 -17
- package/cloudflare/shims/did-space.ts +0 -11
- package/cloudflare/shims/express-compat/index.ts +0 -80
- package/cloudflare/shims/express-compat/types.ts +0 -41
- package/cloudflare/shims/lock.ts +0 -115
- package/cloudflare/shims/queue.ts +0 -611
- package/cloudflare/tests/shims/queue-delayed-persist.spec.ts +0 -87
- package/cloudflare/tests/shims/queue-scheduled.spec.ts +0 -186
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
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
|
|
|
@@ -10,9 +12,13 @@ export const nextEntitlementGrantId = createIdGenerator('eg', 24);
|
|
|
10
12
|
// Multiple grants for the same (customer, entitlement) can coexist across channels;
|
|
11
13
|
// the "currently effective" grant is determined by status + active_until.
|
|
12
14
|
// eslint-disable-next-line prettier/prettier
|
|
13
|
-
export class EntitlementGrant extends
|
|
15
|
+
export class EntitlementGrant extends TenantModel<
|
|
16
|
+
InferAttributes<EntitlementGrant>,
|
|
17
|
+
InferCreationAttributes<EntitlementGrant>
|
|
18
|
+
> {
|
|
14
19
|
declare id: CreationOptional<string>;
|
|
15
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
|
|
16
22
|
|
|
17
23
|
declare entitlement_id: string;
|
|
18
24
|
declare customer_id: string;
|
|
@@ -90,13 +96,19 @@ export class EntitlementGrant extends Model<InferAttributes<EntitlementGrant>, I
|
|
|
90
96
|
};
|
|
91
97
|
|
|
92
98
|
public static initialize(sequelize: any) {
|
|
93
|
-
this.init(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
this.init(
|
|
100
|
+
{
|
|
101
|
+
...EntitlementGrant.GENESIS_ATTRIBUTES,
|
|
102
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
sequelize,
|
|
106
|
+
modelName: 'EntitlementGrant',
|
|
107
|
+
tableName: 'entitlement_grants',
|
|
108
|
+
createdAt: 'created_at',
|
|
109
|
+
updatedAt: 'updated_at',
|
|
110
|
+
}
|
|
111
|
+
);
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
public static associate(models: any) {
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
2
|
+
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
|
|
3
|
+
import { TenantModel } from '../tenant-model';
|
|
4
|
+
import { getInstanceDid } from '../../libs/context';
|
|
3
5
|
|
|
4
6
|
// Join table: which products unlock which entitlements (many-to-many)
|
|
5
7
|
// eslint-disable-next-line prettier/prettier
|
|
6
|
-
export class EntitlementProduct extends
|
|
8
|
+
export class EntitlementProduct extends TenantModel<
|
|
9
|
+
InferAttributes<EntitlementProduct>,
|
|
10
|
+
InferCreationAttributes<EntitlementProduct>
|
|
11
|
+
> {
|
|
7
12
|
declare entitlement_id: string;
|
|
8
13
|
declare product_id: string;
|
|
14
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
9
15
|
declare created_at: CreationOptional<Date>;
|
|
10
16
|
declare updated_at: CreationOptional<Date>;
|
|
11
17
|
|
|
@@ -33,13 +39,19 @@ export class EntitlementProduct extends Model<InferAttributes<EntitlementProduct
|
|
|
33
39
|
};
|
|
34
40
|
|
|
35
41
|
public static initialize(sequelize: any) {
|
|
36
|
-
this.init(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
this.init(
|
|
43
|
+
{
|
|
44
|
+
...EntitlementProduct.GENESIS_ATTRIBUTES,
|
|
45
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
sequelize,
|
|
49
|
+
modelName: 'EntitlementProduct',
|
|
50
|
+
tableName: 'entitlement_products',
|
|
51
|
+
createdAt: 'created_at',
|
|
52
|
+
updatedAt: 'updated_at',
|
|
53
|
+
}
|
|
54
|
+
);
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
public static associate() {}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
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 nextEntitlementId = createIdGenerator('ent', 24);
|
|
7
9
|
|
|
8
10
|
// eslint-disable-next-line prettier/prettier
|
|
9
|
-
export class Entitlement extends
|
|
11
|
+
export class Entitlement extends TenantModel<InferAttributes<Entitlement>, InferCreationAttributes<Entitlement>> {
|
|
10
12
|
declare id: CreationOptional<string>;
|
|
11
13
|
declare livemode: boolean;
|
|
14
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
12
15
|
|
|
13
16
|
declare key: string;
|
|
14
17
|
declare name?: string;
|
|
@@ -33,7 +36,7 @@ export class Entitlement extends Model<InferAttributes<Entitlement>, InferCreati
|
|
|
33
36
|
key: {
|
|
34
37
|
type: DataTypes.STRING(64),
|
|
35
38
|
allowNull: false,
|
|
36
|
-
|
|
39
|
+
// uniqueness is per tenant since Phase 2: see uq_* composite indexes in tenant-backfill.ts
|
|
37
40
|
},
|
|
38
41
|
name: {
|
|
39
42
|
type: DataTypes.STRING(255),
|
|
@@ -60,13 +63,19 @@ export class Entitlement extends Model<InferAttributes<Entitlement>, InferCreati
|
|
|
60
63
|
};
|
|
61
64
|
|
|
62
65
|
public static initialize(sequelize: any) {
|
|
63
|
-
this.init(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
this.init(
|
|
67
|
+
{
|
|
68
|
+
...Entitlement.GENESIS_ATTRIBUTES,
|
|
69
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
sequelize,
|
|
73
|
+
modelName: 'Entitlement',
|
|
74
|
+
tableName: 'entitlements',
|
|
75
|
+
createdAt: 'created_at',
|
|
76
|
+
updatedAt: 'updated_at',
|
|
77
|
+
}
|
|
78
|
+
);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
public static associate(models: any) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
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 { EventType } from './types';
|
|
@@ -7,10 +9,11 @@ import type { EventType } from './types';
|
|
|
7
9
|
const nextId = createIdGenerator('evt', 24);
|
|
8
10
|
|
|
9
11
|
// eslint-disable-next-line prettier/prettier
|
|
10
|
-
export class Event extends
|
|
12
|
+
export class Event extends TenantModel<InferAttributes<Event>, InferCreationAttributes<Event>> {
|
|
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: EventType;
|
|
16
19
|
declare api_version: string;
|
|
@@ -91,13 +94,19 @@ export class Event extends Model<InferAttributes<Event>, InferCreationAttributes
|
|
|
91
94
|
};
|
|
92
95
|
|
|
93
96
|
public static initialize(sequelize: any) {
|
|
94
|
-
this.init(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
this.init(
|
|
98
|
+
{
|
|
99
|
+
...Event.GENESIS_ATTRIBUTES,
|
|
100
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
sequelize,
|
|
104
|
+
modelName: 'Event',
|
|
105
|
+
tableName: 'events',
|
|
106
|
+
createdAt: 'created_at',
|
|
107
|
+
updatedAt: 'updated_at',
|
|
108
|
+
}
|
|
109
|
+
);
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
public static associate(models: any) {
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
// Phase 11 (W2-3) carve-out: exchange_rate_providers is the platform-global
|
|
2
|
+
// table (W1 §2.2 D2 exemption — exchange rates are a global fact, no instance_did
|
|
3
|
+
// column). Its provider API keys are platform-wide config, NOT per-tenant, so it
|
|
4
|
+
// deliberately uses the platform process key (@blocklet/sdk security) rather than
|
|
5
|
+
// the per-tenant secrets keyring — routing it through the tenant facade would
|
|
6
|
+
// encrypt/decrypt the shared config under a different key per request and break
|
|
7
|
+
// it. Phase 12's shim relocation must preserve this platform-key path.
|
|
1
8
|
import security from '@blocklet/sdk/lib/security';
|
|
2
9
|
import cloneDeep from 'lodash/cloneDeep';
|
|
3
10
|
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model, Op } from 'sequelize';
|
|
4
11
|
import type { LiteralUnion } from 'type-fest';
|
|
5
12
|
|
|
6
|
-
import { createEvent } from '../../libs/audit';
|
|
13
|
+
import { createEvent, reportAuditFailure } from '../../libs/audit';
|
|
7
14
|
import { createIdGenerator } from '../../libs/util';
|
|
8
15
|
|
|
9
16
|
export const nextExchangeRateProviderId = createIdGenerator('erp', 24);
|
|
@@ -100,13 +107,19 @@ export class ExchangeRateProvider extends Model<
|
|
|
100
107
|
updatedAt: 'updated_at',
|
|
101
108
|
hooks: {
|
|
102
109
|
afterCreate: (model: ExchangeRateProvider, options) => {
|
|
103
|
-
createEvent('ExchangeRateProvider', 'exchange_rate_provider.created', model, options).catch(
|
|
110
|
+
createEvent('ExchangeRateProvider', 'exchange_rate_provider.created', model, options).catch(
|
|
111
|
+
reportAuditFailure
|
|
112
|
+
);
|
|
104
113
|
},
|
|
105
114
|
afterUpdate: (model: ExchangeRateProvider, options) => {
|
|
106
|
-
createEvent('ExchangeRateProvider', 'exchange_rate_provider.updated', model, options).catch(
|
|
115
|
+
createEvent('ExchangeRateProvider', 'exchange_rate_provider.updated', model, options).catch(
|
|
116
|
+
reportAuditFailure
|
|
117
|
+
);
|
|
107
118
|
},
|
|
108
119
|
afterDestroy: (model: ExchangeRateProvider, options) => {
|
|
109
|
-
createEvent('ExchangeRateProvider', 'exchange_rate_provider.deleted', model, options).catch(
|
|
120
|
+
createEvent('ExchangeRateProvider', 'exchange_rate_provider.deleted', model, options).catch(
|
|
121
|
+
reportAuditFailure
|
|
122
|
+
);
|
|
110
123
|
},
|
|
111
124
|
},
|
|
112
125
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/indent */
|
|
2
2
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
3
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
3
|
+
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
|
|
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 { DiscountAmount } from './types';
|
|
@@ -13,9 +15,10 @@ export type InvoiceLineItem = {
|
|
|
13
15
|
|
|
14
16
|
// @link https://stripe.com/docs/api/invoiceitems
|
|
15
17
|
// eslint-disable-next-line prettier/prettier
|
|
16
|
-
export class InvoiceItem extends
|
|
18
|
+
export class InvoiceItem extends TenantModel<InferAttributes<InvoiceItem>, InferCreationAttributes<InvoiceItem>> {
|
|
17
19
|
declare id: CreationOptional<string>;
|
|
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
|
|
|
20
23
|
declare amount: string;
|
|
21
24
|
declare quantity: number;
|
|
@@ -149,13 +152,19 @@ export class InvoiceItem extends Model<InferAttributes<InvoiceItem>, InferCreati
|
|
|
149
152
|
};
|
|
150
153
|
|
|
151
154
|
public static initialize(sequelize: any) {
|
|
152
|
-
this.init(
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
this.init(
|
|
156
|
+
{
|
|
157
|
+
...InvoiceItem.GENESIS_ATTRIBUTES,
|
|
158
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
sequelize,
|
|
162
|
+
modelName: 'InvoiceItem',
|
|
163
|
+
tableName: 'invoice_items',
|
|
164
|
+
createdAt: 'created_at',
|
|
165
|
+
updatedAt: 'updated_at',
|
|
166
|
+
}
|
|
167
|
+
);
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
public static associate(models: any) {
|
|
@@ -6,14 +6,15 @@ import {
|
|
|
6
6
|
DataTypes,
|
|
7
7
|
InferAttributes,
|
|
8
8
|
InferCreationAttributes,
|
|
9
|
-
Model,
|
|
10
9
|
Op,
|
|
11
10
|
Sequelize,
|
|
12
11
|
WhereOptions,
|
|
13
12
|
} from 'sequelize';
|
|
14
13
|
import type { LiteralUnion } from 'type-fest';
|
|
14
|
+
import { TenantModel } from '../tenant-model';
|
|
15
|
+
import { getInstanceDid } from '../../libs/context';
|
|
15
16
|
|
|
16
|
-
import { createEvent, createStatusEvent } from '../../libs/audit';
|
|
17
|
+
import { createEvent, createStatusEvent, reportAuditFailure } from '../../libs/audit';
|
|
17
18
|
import { createIdGenerator } from '../../libs/util';
|
|
18
19
|
import type {
|
|
19
20
|
CustomerAddress,
|
|
@@ -29,13 +30,14 @@ import type {
|
|
|
29
30
|
export const nextInvoiceId = createIdGenerator('in', 24);
|
|
30
31
|
|
|
31
32
|
// eslint-disable-next-line prettier/prettier
|
|
32
|
-
export class Invoice extends
|
|
33
|
+
export class Invoice extends TenantModel<InferAttributes<Invoice>, InferCreationAttributes<Invoice>> {
|
|
33
34
|
declare id: CreationOptional<string>;
|
|
34
35
|
|
|
35
36
|
// A unique, identifying string that appears on emails sent to the customer for this invoice
|
|
36
37
|
declare number: string;
|
|
37
38
|
|
|
38
39
|
declare livemode: boolean;
|
|
40
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
39
41
|
declare description?: string;
|
|
40
42
|
declare statement_descriptor: string;
|
|
41
43
|
declare period_end: number;
|
|
@@ -479,6 +481,12 @@ export class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttrib
|
|
|
479
481
|
this.init(
|
|
480
482
|
{
|
|
481
483
|
...Invoice.GENESIS_ATTRIBUTES,
|
|
484
|
+
instance_did: {
|
|
485
|
+
type: DataTypes.STRING(64),
|
|
486
|
+
allowNull: true,
|
|
487
|
+
// bare creates must still land in the active tenant (single mode = app DID)
|
|
488
|
+
defaultValue: () => getInstanceDid(),
|
|
489
|
+
},
|
|
482
490
|
starting_token_balance: {
|
|
483
491
|
type: DataTypes.JSON,
|
|
484
492
|
defaultValue: {},
|
|
@@ -496,23 +504,23 @@ export class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttrib
|
|
|
496
504
|
updatedAt: 'updated_at',
|
|
497
505
|
hooks: {
|
|
498
506
|
afterCreate: (model: Invoice, options) => {
|
|
499
|
-
createEvent('Invoice', 'invoice.created', model, options).catch(
|
|
507
|
+
createEvent('Invoice', 'invoice.created', model, options).catch(reportAuditFailure);
|
|
500
508
|
if (model.status === 'paid') {
|
|
501
|
-
createEvent('Invoice', 'invoice.paid', model, options).catch(
|
|
509
|
+
createEvent('Invoice', 'invoice.paid', model, options).catch(reportAuditFailure);
|
|
502
510
|
}
|
|
503
511
|
},
|
|
504
512
|
afterUpdate: (model: Invoice, options) => {
|
|
505
|
-
createEvent('Invoice', 'invoice.updated', model, options).catch(
|
|
513
|
+
createEvent('Invoice', 'invoice.updated', model, options).catch(reportAuditFailure);
|
|
506
514
|
createStatusEvent(
|
|
507
515
|
'Invoice',
|
|
508
516
|
'invoice',
|
|
509
517
|
{ open: 'finalized', void: 'voided', paid: 'paid', uncollectible: 'marked_uncollectible' },
|
|
510
518
|
model,
|
|
511
519
|
options
|
|
512
|
-
).catch(
|
|
520
|
+
).catch(reportAuditFailure);
|
|
513
521
|
},
|
|
514
522
|
afterDestroy: (model: Invoice, options) => {
|
|
515
|
-
createEvent('Invoice', 'invoice.deleted', model, options).catch(
|
|
523
|
+
createEvent('Invoice', 'invoice.deleted', model, options).catch(reportAuditFailure);
|
|
516
524
|
},
|
|
517
525
|
},
|
|
518
526
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
DataTypes,
|
|
5
5
|
InferAttributes,
|
|
6
6
|
InferCreationAttributes,
|
|
7
|
-
Model,
|
|
8
7
|
Op,
|
|
9
8
|
QueryTypes,
|
|
10
9
|
Sequelize,
|
|
@@ -13,7 +12,9 @@ import {
|
|
|
13
12
|
import type { LiteralUnion } from 'type-fest';
|
|
14
13
|
|
|
15
14
|
import { BN } from '@ocap/util';
|
|
16
|
-
import {
|
|
15
|
+
import { TenantModel } from '../tenant-model';
|
|
16
|
+
import { getInstanceDid } from '../../libs/context';
|
|
17
|
+
import { createEvent, reportAuditFailure } from '../../libs/audit';
|
|
17
18
|
import { createIdGenerator } from '../../libs/util';
|
|
18
19
|
import { GroupedBN, GroupedStrList, MeterEventPayload, MeterEventStatus, SourceData } from './types';
|
|
19
20
|
import { Customer } from './customer';
|
|
@@ -30,13 +31,14 @@ type TMeterEventExpanded = MeterEvent & {
|
|
|
30
31
|
paymentCurrency: TPaymentCurrency;
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
export class MeterEvent extends
|
|
34
|
+
export class MeterEvent extends TenantModel<InferAttributes<MeterEvent>, InferCreationAttributes<MeterEvent>> {
|
|
34
35
|
declare id: CreationOptional<string>;
|
|
35
36
|
declare event_name: string;
|
|
36
37
|
declare payload: MeterEventPayload;
|
|
37
38
|
declare identifier: string; // 防重复的唯一标识
|
|
38
39
|
declare timestamp: number;
|
|
39
40
|
declare livemode: boolean;
|
|
41
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
40
42
|
declare status: MeterEventStatus;
|
|
41
43
|
declare processed_at?: number; // 处理时间
|
|
42
44
|
declare attempt_count: number; // 重试次数
|
|
@@ -85,7 +87,7 @@ export class MeterEvent extends Model<InferAttributes<MeterEvent>, InferCreation
|
|
|
85
87
|
identifier: {
|
|
86
88
|
type: DataTypes.STRING(255),
|
|
87
89
|
allowNull: false,
|
|
88
|
-
|
|
90
|
+
// uniqueness is per tenant since Phase 2: see uq_* composite indexes in tenant-backfill.ts
|
|
89
91
|
},
|
|
90
92
|
livemode: {
|
|
91
93
|
type: DataTypes.BOOLEAN,
|
|
@@ -220,6 +222,12 @@ export class MeterEvent extends Model<InferAttributes<MeterEvent>, InferCreation
|
|
|
220
222
|
this.init(
|
|
221
223
|
{
|
|
222
224
|
...this.GENESIS_ATTRIBUTES,
|
|
225
|
+
instance_did: {
|
|
226
|
+
type: DataTypes.STRING(64),
|
|
227
|
+
allowNull: true,
|
|
228
|
+
// bare creates must still land in the active tenant (single mode = app DID)
|
|
229
|
+
defaultValue: () => getInstanceDid(),
|
|
230
|
+
},
|
|
223
231
|
source_data: {
|
|
224
232
|
type: DataTypes.JSON,
|
|
225
233
|
allowNull: true,
|
|
@@ -231,10 +239,16 @@ export class MeterEvent extends Model<InferAttributes<MeterEvent>, InferCreation
|
|
|
231
239
|
tableName: 'meter_events',
|
|
232
240
|
createdAt: 'created_at',
|
|
233
241
|
updatedAt: 'updated_at',
|
|
234
|
-
|
|
242
|
+
// identifier uniqueness is per tenant since Phase 2 (uq_meter_events_tenant_identifier);
|
|
243
|
+
// these model-level indexes only apply on sync(), which production never calls
|
|
244
|
+
indexes: [
|
|
245
|
+
{ fields: ['instance_did', 'identifier'], unique: true },
|
|
246
|
+
{ fields: ['status'] },
|
|
247
|
+
{ fields: ['event_name'] },
|
|
248
|
+
],
|
|
235
249
|
hooks: {
|
|
236
250
|
afterCreate: (model: MeterEvent, options) => {
|
|
237
|
-
createEvent('MeterEvent', 'billing.meter_event.created', model, options).catch(
|
|
251
|
+
createEvent('MeterEvent', 'billing.meter_event.created', model, options).catch(reportAuditFailure);
|
|
238
252
|
},
|
|
239
253
|
},
|
|
240
254
|
}
|
|
@@ -294,16 +308,20 @@ export class MeterEvent extends Model<InferAttributes<MeterEvent>, InferCreation
|
|
|
294
308
|
const [totalEvents, processedEvents, totalValue] = await Promise.all([
|
|
295
309
|
this.count({ where: whereClause }),
|
|
296
310
|
this.count({ where: { ...whereClause, status: 'completed' } }),
|
|
311
|
+
// 洞 G (Phase 4): raw read on a tenant table — guard with instance_did so
|
|
312
|
+
// the aggregate never crosses tenants (the sibling count() calls above are
|
|
313
|
+
// already scoped by TenantModel; this keeps the raw SUM consistent).
|
|
297
314
|
// @ts-ignore
|
|
298
315
|
this.sequelize.query(
|
|
299
|
-
`SELECT COALESCE(SUM(CAST(payload->>'value' AS DECIMAL)), 0) as total
|
|
300
|
-
FROM meter_events
|
|
301
|
-
WHERE event_name = :eventName
|
|
316
|
+
`SELECT COALESCE(SUM(CAST(payload->>'value' AS DECIMAL)), 0) as total
|
|
317
|
+
FROM meter_events
|
|
318
|
+
WHERE event_name = :eventName AND instance_did = :instance_did
|
|
302
319
|
${startTime ? 'AND created_at >= :startTime' : ''}
|
|
303
320
|
${endTime ? 'AND created_at <= :endTime' : ''}`,
|
|
304
321
|
{
|
|
305
322
|
replacements: {
|
|
306
323
|
eventName,
|
|
324
|
+
instance_did: getInstanceDid(),
|
|
307
325
|
startTime: startTime?.toISOString(),
|
|
308
326
|
endTime: endTime?.toISOString(),
|
|
309
327
|
},
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/lines-between-class-members */
|
|
2
|
-
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes
|
|
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
|
-
import { createEvent } from '../../libs/audit';
|
|
7
|
+
import { createEvent, reportAuditFailure } from '../../libs/audit';
|
|
6
8
|
import { createIdGenerator } from '../../libs/util';
|
|
7
9
|
import type { TPaymentCurrency } from './payment-currency';
|
|
8
10
|
|
|
@@ -12,7 +14,7 @@ export type TMeterExpanded = TMeter & {
|
|
|
12
14
|
paymentCurrency: TPaymentCurrency;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
|
-
export class Meter extends
|
|
17
|
+
export class Meter extends TenantModel<InferAttributes<Meter>, InferCreationAttributes<Meter>> {
|
|
16
18
|
declare id: CreationOptional<string>;
|
|
17
19
|
declare object: CreationOptional<string>;
|
|
18
20
|
declare name: string;
|
|
@@ -23,6 +25,7 @@ export class Meter extends Model<InferAttributes<Meter>, InferCreationAttributes
|
|
|
23
25
|
declare description?: string;
|
|
24
26
|
declare component_did?: string;
|
|
25
27
|
declare livemode: boolean;
|
|
28
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
26
29
|
|
|
27
30
|
declare metadata?: Record<string, any>;
|
|
28
31
|
declare currency_id?: string;
|
|
@@ -54,7 +57,7 @@ export class Meter extends Model<InferAttributes<Meter>, InferCreationAttributes
|
|
|
54
57
|
event_name: {
|
|
55
58
|
type: DataTypes.STRING(128),
|
|
56
59
|
allowNull: false,
|
|
57
|
-
|
|
60
|
+
// uniqueness is per tenant since Phase 2: see uq_* composite indexes in tenant-backfill.ts
|
|
58
61
|
},
|
|
59
62
|
aggregation_method: {
|
|
60
63
|
type: DataTypes.ENUM('sum', 'count', 'last'),
|
|
@@ -115,25 +118,31 @@ export class Meter extends Model<InferAttributes<Meter>, InferCreationAttributes
|
|
|
115
118
|
};
|
|
116
119
|
|
|
117
120
|
public static initialize(sequelize: any) {
|
|
118
|
-
this.init(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
createdAt: 'created_at',
|
|
123
|
-
updatedAt: 'updated_at',
|
|
124
|
-
indexes: [{ fields: ['event_name'] }, { fields: ['currency_id'] }],
|
|
125
|
-
hooks: {
|
|
126
|
-
afterCreate: (model: Meter, options) => {
|
|
127
|
-
createEvent('Meter', 'meter.created', model, options).catch(console.error);
|
|
128
|
-
},
|
|
129
|
-
afterUpdate: (model: Meter, options) => {
|
|
130
|
-
createEvent('Meter', 'meter.updated', model, options).catch(console.error);
|
|
131
|
-
},
|
|
132
|
-
afterDestroy: (model: Meter, options) => {
|
|
133
|
-
createEvent('Meter', 'meter.deleted', model, options).catch(console.error);
|
|
134
|
-
},
|
|
121
|
+
this.init(
|
|
122
|
+
{
|
|
123
|
+
...this.GENESIS_ATTRIBUTES,
|
|
124
|
+
instance_did: { type: DataTypes.STRING(64), allowNull: true, defaultValue: () => getInstanceDid() },
|
|
135
125
|
},
|
|
136
|
-
|
|
126
|
+
{
|
|
127
|
+
sequelize,
|
|
128
|
+
modelName: 'Meter',
|
|
129
|
+
tableName: 'meters',
|
|
130
|
+
createdAt: 'created_at',
|
|
131
|
+
updatedAt: 'updated_at',
|
|
132
|
+
indexes: [{ fields: ['event_name'] }, { fields: ['currency_id'] }],
|
|
133
|
+
hooks: {
|
|
134
|
+
afterCreate: (model: Meter, options) => {
|
|
135
|
+
createEvent('Meter', 'meter.created', model, options).catch(reportAuditFailure);
|
|
136
|
+
},
|
|
137
|
+
afterUpdate: (model: Meter, options) => {
|
|
138
|
+
createEvent('Meter', 'meter.updated', model, options).catch(reportAuditFailure);
|
|
139
|
+
},
|
|
140
|
+
afterDestroy: (model: Meter, options) => {
|
|
141
|
+
createEvent('Meter', 'meter.deleted', model, options).catch(reportAuditFailure);
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
}
|
|
145
|
+
);
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
public static associate(models: any) {
|
|
@@ -5,26 +5,34 @@ import {
|
|
|
5
5
|
FindOptions,
|
|
6
6
|
InferAttributes,
|
|
7
7
|
InferCreationAttributes,
|
|
8
|
-
Model,
|
|
9
8
|
Op,
|
|
10
9
|
QueryTypes,
|
|
11
10
|
} from 'sequelize';
|
|
12
|
-
import
|
|
11
|
+
// Phase 13b2: import the submodule, not the @blocklet/sdk index. The index eagerly
|
|
12
|
+
// require()s ./wallet-authenticator -> @arcblock/did-connect-js, which a host with
|
|
13
|
+
// skewed @arcblock deps (e.g. arc's @arcblock/validator@1.30.24 override dropping
|
|
14
|
+
// the Joi export that the old did-connect-js@1.29.27 needs) crashes at module-init.
|
|
15
|
+
// This model is bound by initialize() during createEmbeddedPaymentService, so the
|
|
16
|
+
// index would otherwise load that whole auth chain on the entitlements path.
|
|
17
|
+
import { getUrl } from '@blocklet/sdk/lib/component';
|
|
13
18
|
import type { LiteralUnion } from 'type-fest';
|
|
14
19
|
import { fromTokenToUnit } from '@ocap/util';
|
|
20
|
+
import { TenantModel } from '../tenant-model';
|
|
21
|
+
import { getInstanceDid } from '../../libs/context';
|
|
15
22
|
import { createIdGenerator } from '../../libs/util';
|
|
16
23
|
import { RechargeConfig, VaultConfig } from './types';
|
|
17
24
|
|
|
18
25
|
const nextId = createIdGenerator('pc', 12);
|
|
19
26
|
|
|
20
27
|
// eslint-disable-next-line prettier/prettier
|
|
21
|
-
export class PaymentCurrency extends
|
|
28
|
+
export class PaymentCurrency extends TenantModel<InferAttributes<PaymentCurrency>, InferCreationAttributes<PaymentCurrency>> {
|
|
22
29
|
// Unique identifier for the object.
|
|
23
30
|
declare id: CreationOptional<string>;
|
|
24
31
|
declare payment_method_id: string;
|
|
25
32
|
|
|
26
33
|
declare active: boolean;
|
|
27
34
|
declare livemode: boolean;
|
|
35
|
+
declare instance_did?: string; // tenant column (Phase 1, W1-1a), nullable until Phase 2 backfill; scoped queries land in Phase 3
|
|
28
36
|
declare locked: boolean;
|
|
29
37
|
declare is_base_currency: boolean;
|
|
30
38
|
|
|
@@ -137,6 +145,12 @@ export class PaymentCurrency extends Model<InferAttributes<PaymentCurrency>, Inf
|
|
|
137
145
|
this.init(
|
|
138
146
|
{
|
|
139
147
|
...PaymentCurrency.GENESIS_ATTRIBUTES,
|
|
148
|
+
instance_did: {
|
|
149
|
+
type: DataTypes.STRING(64),
|
|
150
|
+
allowNull: true,
|
|
151
|
+
// bare creates must still land in the active tenant (single mode = app DID)
|
|
152
|
+
defaultValue: () => getInstanceDid(),
|
|
153
|
+
},
|
|
140
154
|
type: {
|
|
141
155
|
type: DataTypes.ENUM('standard', 'credit'),
|
|
142
156
|
defaultValue: 'standard',
|
|
@@ -203,14 +217,17 @@ export class PaymentCurrency extends Model<InferAttributes<PaymentCurrency>, Inf
|
|
|
203
217
|
if (price) {
|
|
204
218
|
return true;
|
|
205
219
|
}
|
|
220
|
+
// 洞 G (Phase 4): raw read on prices (tenant table) — guard with
|
|
221
|
+
// instance_did so currency-usage never counts another tenant's prices.
|
|
206
222
|
// @ts-ignore
|
|
207
223
|
const [{ count }] = await this.sequelize.query(
|
|
208
|
-
`SELECT count(p.id) AS count
|
|
209
|
-
FROM prices AS p
|
|
210
|
-
JOIN json_each(p.currency_options) AS option
|
|
211
|
-
ON json_extract(option.value, '$.currency_id') =
|
|
224
|
+
`SELECT count(p.id) AS count
|
|
225
|
+
FROM prices AS p
|
|
226
|
+
JOIN json_each(p.currency_options) AS option
|
|
227
|
+
ON json_extract(option.value, '$.currency_id') = :currency_id
|
|
228
|
+
WHERE p.instance_did = :instance_did`,
|
|
212
229
|
{
|
|
213
|
-
replacements:
|
|
230
|
+
replacements: { currency_id: this.id, instance_did: getInstanceDid() },
|
|
214
231
|
type: QueryTypes.SELECT,
|
|
215
232
|
}
|
|
216
233
|
);
|