@happyvertical/smrt-subscriptions 0.60.18 → 0.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["options","adapterType","plan","planVersion","evaluations","tenantId"],"sources":["../src/__smrt-register__.ts","../src/billing/config.ts","../src/models/TenantSubscription.ts","../src/collections/TenantSubscriptionCollection.ts","../src/models/BillingCheckoutSession.ts","../src/billing/events.ts","../src/billing/plans.ts","../src/billing/apply.ts","../src/billing/checkout-sessions.ts","../src/billing/signing.ts","../src/billing/types.ts","../src/billing/host.ts","../src/models/TenantUsageMetric.ts","../src/collections/TenantUsageMetricCollection.ts","../src/migrations/moneyMinorUnits.ts","../src/migrations/planVersions.ts","../src/models/commercial.ts","../src/models/reseller.ts","../src/recipes.ts","../src/services/reseller-errors.ts","../src/services/commercial.ts","../src/services/threshold-evaluator.ts","../src/services/usage-meter.ts","../src/services/subscription-resolver.ts","../src/services/subscription-feature-source.ts","../src/services/entitlement-changes.ts","../src/services/hosted-ai-spend.ts","../src/services/reseller.ts","../src/vault-account/errors.ts","../src/vault-account/actions.ts","../src/vault-account/relay-admin-client.ts"],"sourcesContent":["// Generated by @happyvertical/smrt-core smrtPlugin at library build time.\n// The package manifest is inlined so self-registration cannot miss when a\n// downstream bundler relocates this module away from dist/manifest.json\n// (https://github.com/happyvertical/smrt/issues/1506,\n// https://github.com/happyvertical/smrt/issues/1507).\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(JSON.parse(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":0,\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"packageVersion\\\":\\\"0.60.18\\\",\\\"objects\\\":{\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanCollection\\\":{\\\"name\\\":\\\"subscriptionplancollection\\\",\\\"className\\\":\\\"SubscriptionPlanCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanCollection\\\",\\\"collection\\\":\\\"subscriptionplans\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/SubscriptionPlanCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByPlanKey\\\":{\\\"name\\\":\\\"findByPlanKey\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"planKey\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findActive\\\":{\\\"name\\\":\\\"findActive\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<SubscriptionPlan[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByProviderPriceId\\\":{\\\"name\\\":\\\"findByProviderPriceId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"providerPriceId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByStripePriceId\\\":{\\\"name\\\":\\\"findByStripePriceId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"stripePriceId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SubscriptionPlan\\\",\\\"exportName\\\":\\\"SubscriptionPlanCollection\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plans\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"sort_order\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"provider_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"provider_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"sort_order\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_plan_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plans_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"458e59be\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersionCollection\\\":{\\\"name\\\":\\\"subscriptionplanversioncollection\\\",\\\"className\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersionCollection\\\",\\\"collection\\\":\\\"subscriptionplanversions\\\",\\\"description\\\":\\\"Effective-dated plan versions (#4032).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/SubscriptionPlanVersionCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findVisibleById\\\":{\\\"name\\\":\\\"findVisibleById\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"id\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listForPlan\\\":{\\\"name\\\":\\\"listForPlan\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findLatest\\\":{\\\"name\\\":\\\"findLatest\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":true,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findInForce\\\":{\\\"name\\\":\\\"findInForce\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"at\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SubscriptionPlanVersion\\\",\\\"exportName\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanVersionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plan_versions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plan_versions_plan_id_version_idx\\\",\\\"columns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"f42156f9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantSubscriptionCollection\\\":{\\\"name\\\":\\\"tenantsubscriptioncollection\\\",\\\"className\\\":\\\"TenantSubscriptionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscriptionCollection\\\",\\\"collection\\\":\\\"tenantsubscriptions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/TenantSubscriptionCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByTenant\\\":{\\\"name\\\":\\\"findByTenant\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantSubscription[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findCurrentForTenant\\\":{\\\"name\\\":\\\"findCurrentForTenant\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findCurrentForSubscriber\\\":{\\\"name\\\":\\\"findCurrentForSubscriber\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"subscriber\\\",\\\"type\\\":\\\"Subscriber\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByStripeSubscriptionId\\\":{\\\"name\\\":\\\"findByStripeSubscriptionId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"stripeSubscriptionId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantSubscription\\\",\\\"exportName\\\":\\\"TenantSubscriptionCollection\\\",\\\"collectionExportName\\\":\\\"TenantSubscriptionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_subscriptions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'incomplete',\\\\n \\\\\\\"started_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"trial_ends_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"cancel_at_period_end\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"canceled_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"agreed_amount\\\\\\\" INTEGER,\\\\n \\\\\\\"plan_version_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_version_pinned_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"plan_version_pin_reason\\\\\\\" TEXT,\\\\n \\\\\\\"plan_version_pin_note\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retains_paid_period\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_customer_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_subscription_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_checkout_session_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"incomplete\\\"},\\\"started_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"trial_ends_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"cancel_at_period_end\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"canceled_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"agreed_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_version_pinned_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_note\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retains_paid_period\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_customer_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_subscription_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_checkout_session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_id_idx\\\",\\\"columns\\\":[\\\"plan_id\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_version_id_idx\\\",\\\"columns\\\":[\\\"plan_version_id\\\"]}],\\\"version\\\":\\\"c281741d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantUsageMetricCollection\\\":{\\\"name\\\":\\\"tenantusagemetriccollection\\\",\\\"className\\\":\\\"TenantUsageMetricCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetricCollection\\\",\\\"collection\\\":\\\"tenantusagemetrics\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/TenantUsageMetricCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"recordUsage\\\":{\\\"name\\\":\\\"recordUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"RecordUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantUsageMetric>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByTenantAndMetric\\\":{\\\"name\\\":\\\"findByTenantAndMetric\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"metricKey\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantUsageMetric[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeUsage\\\":{\\\"name\\\":\\\"summarizeUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<UsageSummary>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeUsageBatch\\\":{\\\"name\\\":\\\"summarizeUsageBatch\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeUsageBatchOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<UsageSummary[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeTenantAiUsage\\\":{\\\"name\\\":\\\"summarizeTenantAiUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeAiUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<AiUsageSummary>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantUsageMetric\\\",\\\"exportName\\\":\\\"TenantUsageMetricCollection\\\",\\\"collectionExportName\\\":\\\"TenantUsageMetricCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_usage_metrics\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"window_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"window_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"dimensions\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"window_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"window_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"4884a70d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\":{\\\"name\\\":\\\"billingcheckoutsession\\\",\\\"className\\\":\\\"BillingCheckoutSession\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\",\\\"collection\\\":\\\"billingcheckoutsessions\\\",\\\"description\\\":\\\"One Checkout session created by the billing host, recorded when the host creates it and required when the paid session completes, so signed metadata copied onto another integration's session is never…\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/BillingCheckoutSession.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"sessionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"targetTenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The tenant the host created the session for.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The tenant the host created the session for.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"pending\\\",\\\"enum\\\":[\\\"pending\\\",\\\"completed\\\",\\\"needs_reconciliation\\\",\\\"dismissed\\\"]},\\\"expiresAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"completedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"conflictColumns\\\":[\\\"session_id\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"BillingCheckoutSession\\\",\\\"collectionExportName\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"validationRules\\\":[{\\\"field\\\":\\\"sessionId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"text\\\"}],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_checkout_sessions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"session_id\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"target_tenant_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'pending',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"completed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"detail\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"target_tenant_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"pending\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"completed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_session_id_idx\\\",\\\"columns\\\":[\\\"session_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"c1924881\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSessionCollection\\\":{\\\"name\\\":\\\"billingcheckoutsessioncollection\\\",\\\"className\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSessionCollection\\\",\\\"collection\\\":\\\"billingcheckoutsessions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/BillingCheckoutSession.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"BillingCheckoutSession\\\",\\\"exportName\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"collectionExportName\\\":\\\"BillingCheckoutSessionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_checkout_sessions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"session_id\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"target_tenant_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'pending',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"completed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"detail\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"target_tenant_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"pending\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"completed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_session_id_idx\\\",\\\"columns\\\":[\\\"session_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"c1924881\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\":{\\\"name\\\":\\\"subscriptionplan\\\",\\\"className\\\":\\\"SubscriptionPlan\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"collection\\\":\\\"subscriptionplans\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/SubscriptionPlan.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"nullable\\\":true,\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":false,\\\"autoPopulate\\\":true,\\\"nullable\\\":true,\\\"mode\\\":\\\"optional\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"planKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"A short code that identifies the plan, such as starter or pro.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"A short code that identifies the plan, such as starter or pro.\\\"}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What the plan is called, as customers see it.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan is called, as customers see it.\\\"}},\\\"description\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"A sentence or two about what the plan offers.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"A sentence or two about what the plan offers.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"description\\\":\\\"Whether the plan is a draft, on sale (active) or archived.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan is a draft, on sale (active) or archived.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"archived\\\",\\\"draft\\\"]},\\\"sortOrder\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"Where the plan sits when plans are listed; lower numbers come first.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the plan sits when plans are listed; lower numbers come first.\\\"}},\\\"priceAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What the plan costs each billing period, in cents, as a whole number.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan costs each billing period, in cents, as a whole number.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the price is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the price is in, such as USD.\\\"}},\\\"billingInterval\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"description\\\":\\\"How often the subscriber is billed: every day, week, month or year.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How often the subscriber is billed: every day, week, month or year.\\\"},\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\"]},\\\"pricingMode\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed\\\",\\\"description\\\":\\\"Whether the plan is free, has a fixed price, or lets the subscriber choose what to pay. It cannot change once the plan is saved.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan is free, has a fixed price, or lets the subscriber choose what to pay. It cannot change once the plan is saved.\\\"},\\\"enum\\\":[\\\"free\\\",\\\"fixed\\\",\\\"pay_what_you_can\\\"]},\\\"minimumAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber may pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber may pay, in cents.\\\"}},\\\"suggestedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\"}},\\\"externalProvider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"providerProductId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"providerPriceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripeProductId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripePriceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"features\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanTerms\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"save\\\":{\\\"name\\\":\\\"save\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SmrtSaveOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<this>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"publishTerms\\\":{\\\"name\\\":\\\"publishTerms\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"object\\\",\\\"optional\\\":true,\\\"memberTypes\\\":[\\\"Date\\\"]}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getVersionInForce\\\":{\\\"name\\\":\\\"getVersionInForce\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"at\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureGrants\\\":{\\\"name\\\":\\\"getFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanFeatureGrant[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setFeatureGrants\\\":{\\\"name\\\":\\\"setFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"grants\\\",\\\"type\\\":\\\"Array<string | PlanFeatureGrant>\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureKeys\\\":{\\\"name\\\":\\\"getFeatureKeys\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"string[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getThresholds\\\":{\\\"name\\\":\\\"getThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanThreshold[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setThresholds\\\":{\\\"name\\\":\\\"setThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"thresholds\\\",\\\"type\\\":\\\"PlanThreshold[]\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getMetadata\\\":{\\\"name\\\":\\\"getMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setMetadata\\\":{\\\"name\\\":\\\"setMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"metadata\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"cli\\\":{\\\"skipApiCheck\\\":true},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"optional\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SubscriptionPlan\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plans\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"sort_order\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"provider_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"provider_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"sort_order\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_plan_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plans_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"458e59be\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\":{\\\"name\\\":\\\"subscriptionplanversion\\\",\\\"className\\\":\\\"SubscriptionPlanVersion\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"collection\\\":\\\"subscriptionplanversions\\\",\\\"description\\\":\\\"An immutable, effective-dated snapshot of a plan's terms (#4032).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/SubscriptionPlanVersion.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"nullable\\\":true,\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":false,\\\"autoPopulate\\\":true,\\\"nullable\\\":true,\\\"mode\\\":\\\"optional\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"planId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlan\\\",\\\"description\\\":\\\"The plan this version belongs to.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan this version belongs to.\\\"}},\\\"planKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The plan code at the time this version was published.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan code at the time this version was published.\\\"}},\\\"version\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"Which version of the plan this is, counting from 1.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Which version of the plan this is, counting from 1.\\\"}},\\\"effectiveFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"The date and time from which these terms apply.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The date and time from which these terms apply.\\\"}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What the plan was called when this version was published.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan was called when this version was published.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"description\\\":\\\"Whether the plan was a draft, on sale (active) or archived under this version.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan was a draft, on sale (active) or archived under this version.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"archived\\\",\\\"draft\\\"]},\\\"priceAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What the plan cost each billing period under this version, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan cost each billing period under this version, in cents.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the price is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the price is in, such as USD.\\\"}},\\\"billingInterval\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"description\\\":\\\"How often the subscriber was billed: every day, week, month or year.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How often the subscriber was billed: every day, week, month or year.\\\"},\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\"]},\\\"pricingMode\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed\\\",\\\"description\\\":\\\"Whether the plan was free, had a fixed price, or let the subscriber choose what to pay.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan was free, had a fixed price, or let the subscriber choose what to pay.\\\"},\\\"enum\\\":[\\\"free\\\",\\\"fixed\\\",\\\"pay_what_you_can\\\"]},\\\"minimumAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber could pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber could pay, in cents.\\\"}},\\\"suggestedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\"}},\\\"features\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanTerms\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureGrants\\\":{\\\"name\\\":\\\"getFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanFeatureGrant[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureKeys\\\":{\\\"name\\\":\\\"getFeatureKeys\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"string[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getThresholds\\\":{\\\"name\\\":\\\"getThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanThreshold[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"refuseDelete\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"optional\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SubscriptionPlanVersion\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plan_versions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plan_versions_plan_id_version_idx\\\",\\\"columns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"f42156f9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\":{\\\"name\\\":\\\"tenantsubscription\\\",\\\"className\\\":\\\"TenantSubscription\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"collection\\\":\\\"tenantsubscriptions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/TenantSubscription.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\",\\\"description\\\":\\\"Whether the subscriber is your own workspace (tenant) or an outside customer (external).\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the subscriber is your own workspace (tenant) or an outside customer (external).\\\"},\\\"enum\\\":[\\\"tenant\\\",\\\"external\\\"]},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"Who the outside subscriber is, when the subscriber type is external.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Who the outside subscriber is, when the subscriber type is external.\\\"}},\\\"planId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlan\\\",\\\"description\\\":\\\"The plan this subscription is for.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan this subscription is for.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"incomplete\\\",\\\"description\\\":\\\"Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"canceled\\\",\\\"incomplete\\\",\\\"past_due\\\",\\\"trialing\\\",\\\"unpaid\\\"]},\\\"startedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"The day the subscription began.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The day the subscription began.\\\"}},\\\"currentPeriodStart\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the current billing period began.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the current billing period began.\\\"}},\\\"currentPeriodEnd\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the current billing period ends and the next one is due.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the current billing period ends and the next one is due.\\\"}},\\\"trialEndsAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the free trial ends, if there is one.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the free trial ends, if there is one.\\\"}},\\\"cancelAtPeriodEnd\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":false,\\\"description\\\":\\\"Tick to let the subscription run out at the end of the current period instead of renewing.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Tick to let the subscription run out at the end of the current period instead of renewing.\\\"}},\\\"canceledAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the subscription was cancelled.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the subscription was cancelled.\\\"}},\\\"agreedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.\\\"}},\\\"planVersionId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlanVersion\\\",\\\"description\\\":\\\"The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.\\\"}},\\\"planVersionPinnedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"planVersionPinReason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"enum\\\":[\\\"period_start\\\",\\\"renewal\\\",\\\"upgrade\\\",\\\"authorized\\\",\\\"migration\\\"]},\\\"planVersionPinNote\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"retainsPaidPeriod\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":false},\\\"externalProvider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripeCustomerId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripeSubscriptionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripeCheckoutSessionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"replacePlanVersion\\\":{\\\"name\\\":\\\"replacePlanVersion\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":false,\\\"typeUnresolved\\\":true}],\\\"returnType\\\":\\\"Promise<this>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isEntitled\\\":{\\\"name\\\":\\\"isEntitled\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getSubscriber\\\":{\\\"name\\\":\\\"getSubscriber\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Subscriber | null\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getMetadata\\\":{\\\"name\\\":\\\"getMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setMetadata\\\":{\\\"name\\\":\\\"setMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"metadata\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"cli\\\":{\\\"skipApiCheck\\\":true},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantSubscription\\\",\\\"collectionExportName\\\":\\\"TenantSubscriptionCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_subscriptions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'incomplete',\\\\n \\\\\\\"started_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"trial_ends_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"cancel_at_period_end\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"canceled_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"agreed_amount\\\\\\\" INTEGER,\\\\n \\\\\\\"plan_version_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_version_pinned_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"plan_version_pin_reason\\\\\\\" TEXT,\\\\n \\\\\\\"plan_version_pin_note\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retains_paid_period\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_customer_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_subscription_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_checkout_session_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"incomplete\\\"},\\\"started_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"trial_ends_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"cancel_at_period_end\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"canceled_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"agreed_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_version_pinned_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_note\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retains_paid_period\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_customer_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_subscription_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_checkout_session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_id_idx\\\",\\\"columns\\\":[\\\"plan_id\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_version_id_idx\\\",\\\"columns\\\":[\\\"plan_version_id\\\"]}],\\\"version\\\":\\\"c281741d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\":{\\\"name\\\":\\\"tenantusagemetric\\\",\\\"className\\\":\\\"TenantUsageMetric\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\",\\\"collection\\\":\\\"tenantusagemetrics\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/TenantUsageMetric.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\",\\\"enum\\\":[\\\"tenant\\\",\\\"external\\\"]},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"windowStart\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"windowEnd\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"getSubscriber\\\":{\\\"name\\\":\\\"getSubscriber\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Subscriber | null\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getDimensions\\\":{\\\"name\\\":\\\"getDimensions\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setDimensions\\\":{\\\"name\\\":\\\"setDimensions\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"dimensions\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantUsageMetric\\\",\\\"collectionExportName\\\":\\\"TenantUsageMetricCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_usage_metrics\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"window_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"window_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"dimensions\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"window_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"window_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"4884a70d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PricingRule\\\":{\\\"name\\\":\\\"pricingrule\\\",\\\"className\\\":\\\"PricingRule\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PricingRule\\\",\\\"collection\\\":\\\"pricingrules\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"ruleKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed_unit\\\",\\\"enum\\\":[\\\"fixed_unit\\\",\\\"cost_plus\\\",\\\"multiplier\\\",\\\"tiered\\\",\\\"included_overage\\\",\\\"flat\\\",\\\"custom\\\"]},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effectiveFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"effectiveTo\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"}},\\\"methods\\\":{\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setTerms\\\":{\\\"name\\\":\\\"setTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"Record<string, unknown>\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"api\\\":true,\\\"cli\\\":true,\\\"mcp\\\":true,\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PricingRule\\\",\\\"collectionExportName\\\":\\\"PricingRuleCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_pricing_rules\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"rule_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"strategy\\\\\\\" TEXT DEFAULT 'fixed_unit',\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"effective_to\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"terms\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"rule_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed_unit\\\"},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"effective_to\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_pricing_rules_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_pricing_rules_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_pricing_rules_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"37fd6ea9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\":{\\\"name\\\":\\\"clientcharge\\\",\\\"className\\\":\\\"ClientCharge\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"collection\\\":\\\"clientcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"usageEventId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"TenantUsageMetric\\\"},\\\"usageTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"Who supplied the service that was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Who supplied the service that was used.\\\"}},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The service that was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The service that was used.\\\"}},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What was used, such as messages sent or minutes of audio.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What was used, such as messages sent or minutes of audio.\\\"}},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"How much of it was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How much of it was used.\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What it cost, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What it cost, in cents.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the amount is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the amount is in, such as USD.\\\"}},\\\"pricingRuleId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PricingRule\\\"},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"pricingSnapshot\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"draft\\\",\\\"description\\\":\\\"Where the charge stands: draft, approved or adjusted.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the charge stands: draft, approved or adjusted.\\\"},\\\"enum\\\":[\\\"draft\\\",\\\"approved\\\",\\\"adjusted\\\"]},\\\"approvedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the charge was approved.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the charge was approved.\\\"}}},\\\"methods\\\":{\\\"getPricingSnapshot\\\":{\\\"name\\\":\\\"getPricingSnapshot\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"usage_event_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"ClientCharge\\\",\\\"collectionExportName\\\":\\\"ClientChargeCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_client_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"usage_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_client_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_client_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_usage_tenant_id_idx\\\",\\\"columns\\\":[\\\"usage_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"92fb8003\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\":{\\\"name\\\":\\\"billingadjustment\\\",\\\"className\\\":\\\"BillingAdjustment\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\",\\\"collection\\\":\\\"billingadjustments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"clientChargeId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"ClientCharge\\\"},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"createdBy\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"BillingAdjustment\\\",\\\"collectionExportName\\\":\\\"BillingAdjustmentCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_adjustments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"created_by\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"created_by\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_adjustments_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_adjustments_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_billing_adjustments_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]}],\\\"version\\\":\\\"cfbd2832\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\":{\\\"name\\\":\\\"spendingpolicy\\\",\\\"className\\\":\\\"SpendingPolicy\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\",\\\"collection\\\":\\\"spendingpolicies\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\",\\\"rolling\\\",\\\"balance\\\"]},\\\"rollingSeconds\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"limitAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"observe\\\",\\\"enum\\\":[\\\"observe\\\",\\\"warn\\\",\\\"block\\\",\\\"approval_required\\\"]},\\\"priority\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"billed\\\",\\\"enum\\\":[\\\"billed\\\",\\\"retail\\\",\\\"wholesale\\\"]},\\\"setByTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"balanceFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"api\\\":true,\\\"cli\\\":true,\\\"mcp\\\":true,\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"assertDelegationAuthority\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SpendingPolicy\\\",\\\"collectionExportName\\\":\\\"SpendingPolicyCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_spending_policies\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"period\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"rolling_seconds\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"limit_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"behavior\\\\\\\" TEXT DEFAULT 'observe',\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"basis\\\\\\\" TEXT DEFAULT 'billed',\\\\n \\\\\\\"set_by_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"balance_from\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"rolling_seconds\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"limit_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"observe\\\"},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"billed\\\"},\\\"set_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"balance_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_spending_policies_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_set_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"set_by_tenant_id\\\"]}],\\\"version\\\":\\\"21fbbb20\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PricingRuleCollection\\\":{\\\"name\\\":\\\"pricingrulecollection\\\",\\\"className\\\":\\\"PricingRuleCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PricingRuleCollection\\\",\\\"collection\\\":\\\"pricingrules\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\"},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PricingRule\\\",\\\"exportName\\\":\\\"PricingRuleCollection\\\",\\\"collectionExportName\\\":\\\"PricingRuleCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PricingRule\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_pricing_rules\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"rule_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"strategy\\\\\\\" TEXT DEFAULT 'fixed_unit',\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"effective_to\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"terms\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"rule_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed_unit\\\"},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"effective_to\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_pricing_rules_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_pricing_rules_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_pricing_rules_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"37fd6ea9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:ClientChargeCollection\\\":{\\\"name\\\":\\\"clientchargecollection\\\",\\\"className\\\":\\\"ClientChargeCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:ClientChargeCollection\\\",\\\"collection\\\":\\\"clientcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"ClientCharge\\\",\\\"exportName\\\":\\\"ClientChargeCollection\\\",\\\"collectionExportName\\\":\\\"ClientChargeCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_client_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"usage_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_client_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_client_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_usage_tenant_id_idx\\\",\\\"columns\\\":[\\\"usage_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"92fb8003\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingAdjustmentCollection\\\":{\\\"name\\\":\\\"billingadjustmentcollection\\\",\\\"className\\\":\\\"BillingAdjustmentCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustmentCollection\\\",\\\"collection\\\":\\\"billingadjustments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"BillingAdjustment\\\",\\\"exportName\\\":\\\"BillingAdjustmentCollection\\\",\\\"collectionExportName\\\":\\\"BillingAdjustmentCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_adjustments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"created_by\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"created_by\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_adjustments_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_adjustments_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_billing_adjustments_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]}],\\\"version\\\":\\\"cfbd2832\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SpendingPolicyCollection\\\":{\\\"name\\\":\\\"spendingpolicycollection\\\",\\\"className\\\":\\\"SpendingPolicyCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicyCollection\\\",\\\"collection\\\":\\\"spendingpolicies\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\"},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SpendingPolicy\\\",\\\"exportName\\\":\\\"SpendingPolicyCollection\\\",\\\"collectionExportName\\\":\\\"SpendingPolicyCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_spending_policies\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"period\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"rolling_seconds\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"limit_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"behavior\\\\\\\" TEXT DEFAULT 'observe',\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"basis\\\\\\\" TEXT DEFAULT 'billed',\\\\n \\\\\\\"set_by_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"balance_from\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"rolling_seconds\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"limit_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"observe\\\"},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"billed\\\"},\\\"set_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"balance_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_spending_policies_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_set_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"set_by_tenant_id\\\"]}],\\\"version\\\":\\\"21fbbb20\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBook\\\":{\\\"name\\\":\\\"pricebook\\\",\\\"className\\\":\\\"PriceBook\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBook\\\",\\\"collection\\\":\\\"pricebooks\\\",\\\"description\\\":\\\"A named set of prices published by one seller tenant. Its prices are ordinary PricingRule rows that carry this book's id and the same tenant; one rule per currency gives a price in several currencies.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"bookKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"retail\\\",\\\"enum\\\":[\\\"wholesale\\\",\\\"retail\\\"]},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false,\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PriceBook\\\",\\\"collectionExportName\\\":\\\"PriceBookCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_books\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"book_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"kind\\\\\\\" TEXT DEFAULT 'retail',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"book_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"retail\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_books_tenant_id_book_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_price_books_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_books_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"56296d2f\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\":{\\\"name\\\":\\\"pricebookassignment\\\",\\\"className\\\":\\\"PriceBookAssignment\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\",\\\"collection\\\":\\\"pricebookassignments\\\",\\\"description\\\":\\\"Which price books rate one child tenant's usage, keyed like the tenancy billing relationship it belongs to (one row per child).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"childTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":true,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"resellerTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":true,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"wholesalePriceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"wholesaleCurrency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"retailPriceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"retailCurrency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"conflictColumns\\\":[\\\"child_tenant_id\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PriceBookAssignment\\\",\\\"collectionExportName\\\":\\\"PriceBookAssignmentCollection\\\",\\\"validationRules\\\":[{\\\"field\\\":\\\"childTenantId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"crossPackageRef\\\"},{\\\"field\\\":\\\"resellerTenantId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"crossPackageRef\\\"}],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_book_assignments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"child_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"wholesale_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"wholesale_currency\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retail_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"retail_currency\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"child_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"wholesale_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"wholesale_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retail_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"retail_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_book_assignments_child_tenant_id_idx\\\",\\\"columns\\\":[\\\"child_tenant_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_price_book_assignments_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_wholesale_price_book_id_idx\\\",\\\"columns\\\":[\\\"wholesale_price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_retail_price_book_id_idx\\\",\\\"columns\\\":[\\\"retail_price_book_id\\\"]}],\\\"version\\\":\\\"990da9b7\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\":{\\\"name\\\":\\\"retailcharge\\\",\\\"className\\\":\\\"RetailCharge\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\",\\\"collection\\\":\\\"retailcharges\\\",\\\"description\\\":\\\"What a reseller charges one child for one usage event, priced from the reseller's retail book.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"resellerTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"usageEventId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"TenantUsageMetric\\\"},\\\"clientChargeId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"ClientCharge\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"pricingRuleId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PricingRule\\\"},\\\"pricingSnapshot\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"draft\\\",\\\"enum\\\":[\\\"draft\\\",\\\"approved\\\"]},\\\"approvedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{\\\"getPricingSnapshot\\\":{\\\"name\\\":\\\"getPricingSnapshot\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"usage_event_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"RetailCharge\\\",\\\"collectionExportName\\\":\\\"RetailChargeCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_retail_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_retail_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_retail_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]}],\\\"version\\\":\\\"ad6930a8\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\":{\\\"name\\\":\\\"creditgrant\\\",\\\"className\\\":\\\"CreditGrant\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\",\\\"collection\\\":\\\"creditgrants\\\",\\\"description\\\":\\\"An append-only credit on a prepaid (period: 'balance') spending policy. Positive amounts add credit; a negative amount reverses an earlier grant.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"spendingPolicyId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SpendingPolicy\\\"},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"grantedByTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"refuseDelete\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"CreditGrant\\\",\\\"collectionExportName\\\":\\\"CreditGrantCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_credit_grants\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"spending_policy_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"granted_by_tenant_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"spending_policy_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_spending_policies\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"granted_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_credit_grants_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_credit_grants_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_spending_policy_id_idx\\\",\\\"columns\\\":[\\\"spending_policy_id\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_granted_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"granted_by_tenant_id\\\"]}],\\\"version\\\":\\\"e11305fc\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookCollection\\\":{\\\"name\\\":\\\"pricebookcollection\\\",\\\"className\\\":\\\"PriceBookCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookCollection\\\",\\\"collection\\\":\\\"pricebooks\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PriceBook\\\",\\\"exportName\\\":\\\"PriceBookCollection\\\",\\\"collectionExportName\\\":\\\"PriceBookCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PriceBook\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_books\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"book_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"kind\\\\\\\" TEXT DEFAULT 'retail',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"book_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"retail\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_books_tenant_id_book_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_price_books_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_books_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"56296d2f\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookAssignmentCollection\\\":{\\\"name\\\":\\\"pricebookassignmentcollection\\\",\\\"className\\\":\\\"PriceBookAssignmentCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignmentCollection\\\",\\\"collection\\\":\\\"pricebookassignments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PriceBookAssignment\\\",\\\"exportName\\\":\\\"PriceBookAssignmentCollection\\\",\\\"collectionExportName\\\":\\\"PriceBookAssignmentCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_book_assignments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"child_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"wholesale_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"wholesale_currency\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retail_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"retail_currency\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"child_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"wholesale_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"wholesale_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retail_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"retail_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_book_assignments_child_tenant_id_idx\\\",\\\"columns\\\":[\\\"child_tenant_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_price_book_assignments_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_wholesale_price_book_id_idx\\\",\\\"columns\\\":[\\\"wholesale_price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_retail_price_book_id_idx\\\",\\\"columns\\\":[\\\"retail_price_book_id\\\"]}],\\\"version\\\":\\\"990da9b7\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:RetailChargeCollection\\\":{\\\"name\\\":\\\"retailchargecollection\\\",\\\"className\\\":\\\"RetailChargeCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:RetailChargeCollection\\\",\\\"collection\\\":\\\"retailcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"RetailCharge\\\",\\\"exportName\\\":\\\"RetailChargeCollection\\\",\\\"collectionExportName\\\":\\\"RetailChargeCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_retail_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_retail_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_retail_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]}],\\\"version\\\":\\\"ad6930a8\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:CreditGrantCollection\\\":{\\\"name\\\":\\\"creditgrantcollection\\\",\\\"className\\\":\\\"CreditGrantCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrantCollection\\\",\\\"collection\\\":\\\"creditgrants\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"CreditGrant\\\",\\\"exportName\\\":\\\"CreditGrantCollection\\\",\\\"collectionExportName\\\":\\\"CreditGrantCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_credit_grants\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"spending_policy_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"granted_by_tenant_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"spending_policy_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_spending_policies\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"granted_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_credit_grants_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_credit_grants_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_spending_policy_id_idx\\\",\\\"columns\\\":[\\\"spending_policy_id\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_granted_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"granted_by_tenant_id\\\"]}],\\\"version\\\":\\\"e11305fc\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"}},\\\"moduleType\\\":\\\"smrt\\\",\\\"recipes\\\":[{\\\"id\\\":\\\"subscriptions.plans\\\",\\\"className\\\":\\\"SubscriptionPlansRecipe\\\",\\\"label\\\":\\\"Subscriptions\\\",\\\"summary\\\":\\\"Sell plans that renew, see who is subscribed to which, and what their usage cost.\\\",\\\"synonyms\\\":[\\\"subscriptions\\\",\\\"subscription plans\\\",\\\"plans\\\",\\\"memberships\\\",\\\"recurring billing\\\",\\\"pricing tiers\\\"],\\\"models\\\":[\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\"],\\\"nav\\\":[{\\\"label\\\":\\\"Plans\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"icon\\\":\\\"tag\\\",\\\"description\\\":\\\"The plans you sell, with their price and how often they bill.\\\",\\\"noun\\\":\\\"plan\\\"},{\\\"label\\\":\\\"Subscriptions\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"icon\\\":\\\"repeat\\\",\\\"description\\\":\\\"Who is subscribed to which plan, and where each one stands.\\\",\\\"noun\\\":\\\"subscription\\\"},{\\\"label\\\":\\\"Plan versions\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"icon\\\":\\\"fileText\\\",\\\"description\\\":\\\"Every set of terms a plan has had, and from when each applied.\\\",\\\"noun\\\":\\\"plan version\\\"},{\\\"label\\\":\\\"Charges\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"icon\\\":\\\"receipt\\\",\\\"description\\\":\\\"What each subscriber used and what it cost them.\\\",\\\"noun\\\":\\\"charge\\\"}],\\\"requires\\\":[],\\\"section\\\":{\\\"id\\\":\\\"sales\\\",\\\"label\\\":\\\"Sales\\\",\\\"icon\\\":\\\"shoppingBag\\\",\\\"description\\\":\\\"Customers, orders and quotes: everything you sell.\\\"},\\\"options\\\":{\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\":{\\\"fields\\\":{\\\"name\\\":{\\\"order\\\":1},\\\"planKey\\\":{\\\"label\\\":\\\"Plan code\\\",\\\"order\\\":2},\\\"description\\\":{\\\"order\\\":3},\\\"status\\\":{\\\"order\\\":4},\\\"priceAmount\\\":{\\\"label\\\":\\\"Price (in cents)\\\",\\\"order\\\":5},\\\"currency\\\":{\\\"order\\\":6},\\\"billingInterval\\\":{\\\"label\\\":\\\"Billed every\\\",\\\"order\\\":7},\\\"pricingMode\\\":{\\\"label\\\":\\\"How it is priced\\\",\\\"order\\\":8},\\\"minimumAmount\\\":{\\\"label\\\":\\\"Minimum (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"suggestedAmount\\\":{\\\"label\\\":\\\"Suggested (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"sortOrder\\\":{\\\"label\\\":\\\"Position in list\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"features\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"thresholds\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"externalProvider\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"providerProductId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"providerPriceId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeProductId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripePriceId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"metadata\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\":{\\\"fields\\\":{\\\"planId\\\":{\\\"label\\\":\\\"Plan\\\",\\\"order\\\":1},\\\"version\\\":{\\\"label\\\":\\\"Version number\\\",\\\"order\\\":2},\\\"effectiveFrom\\\":{\\\"label\\\":\\\"In force from\\\",\\\"order\\\":3},\\\"name\\\":{\\\"order\\\":4},\\\"status\\\":{\\\"order\\\":5},\\\"priceAmount\\\":{\\\"label\\\":\\\"Price (in cents)\\\",\\\"order\\\":6},\\\"currency\\\":{\\\"order\\\":7},\\\"billingInterval\\\":{\\\"label\\\":\\\"Billed every\\\",\\\"order\\\":8},\\\"planKey\\\":{\\\"label\\\":\\\"Plan code\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"pricingMode\\\":{\\\"label\\\":\\\"How it is priced\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"minimumAmount\\\":{\\\"label\\\":\\\"Minimum (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"suggestedAmount\\\":{\\\"label\\\":\\\"Suggested (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"features\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"thresholds\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\":{\\\"fields\\\":{\\\"planId\\\":{\\\"label\\\":\\\"Plan\\\",\\\"order\\\":1},\\\"status\\\":{\\\"order\\\":2},\\\"startedAt\\\":{\\\"label\\\":\\\"Started on\\\",\\\"order\\\":3},\\\"currentPeriodStart\\\":{\\\"label\\\":\\\"Current period starts\\\",\\\"order\\\":4},\\\"currentPeriodEnd\\\":{\\\"label\\\":\\\"Current period ends\\\",\\\"order\\\":5},\\\"trialEndsAt\\\":{\\\"label\\\":\\\"Trial ends\\\",\\\"order\\\":6},\\\"cancelAtPeriodEnd\\\":{\\\"label\\\":\\\"Cancel at end of period\\\",\\\"order\\\":7},\\\"canceledAt\\\":{\\\"label\\\":\\\"Cancelled on\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"agreedAmount\\\":{\\\"label\\\":\\\"Agreed amount (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"subscriberKind\\\":{\\\"label\\\":\\\"Subscriber type\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"subscriberExternalId\\\":{\\\"label\\\":\\\"Outside subscriber\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"planVersionId\\\":{\\\"label\\\":\\\"Plan version\\\",\\\"visibility\\\":\\\"advanced\\\",\\\"locked\\\":true},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinnedAt\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinReason\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinNote\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"retainsPaidPeriod\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"externalProvider\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeCustomerId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeSubscriptionId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeCheckoutSessionId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"metadata\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\":{\\\"fields\\\":{\\\"metricKey\\\":{\\\"label\\\":\\\"What was used\\\",\\\"order\\\":1},\\\"quantity\\\":{\\\"label\\\":\\\"How much\\\",\\\"order\\\":2},\\\"amount\\\":{\\\"label\\\":\\\"Amount (in cents)\\\",\\\"order\\\":3},\\\"currency\\\":{\\\"order\\\":4},\\\"status\\\":{\\\"order\\\":5},\\\"approvedAt\\\":{\\\"label\\\":\\\"Approved on\\\",\\\"order\\\":6},\\\"serviceKey\\\":{\\\"label\\\":\\\"Service\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"provider\\\":{\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"usageEventId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"usageTenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"subscriberKind\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"subscriberExternalId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"projectId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"workRefType\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"workRefId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"pricingRuleId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"priceBookId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"pricingSnapshot\\\":{\\\"visibility\\\":\\\"hidden\\\"}}}},\\\"help\\\":{\\\"markdown\\\":\\\"## Overview\\\\n\\\\nSubscriptions is where you sell plans that renew. A plan says what it costs,\\\\nhow often it bills and whether it is free, a fixed price or pay what you can.\\\\nA subscription joins a subscriber to a plan and shows where it stands, from\\\\ntrial to active to cancelled. Every time you change a plan's terms, the\\\\nearlier terms are kept as a plan version, so a subscriber who already paid for\\\\na period keeps what they paid for until it renews. Charges show what each\\\\nsubscriber used and what it cost them.\\\\n\\\\nAll amounts are whole numbers of cents, with no decimal point.\\\\n\\\\n## Tasks\\\\n\\\\n### Set up a plan\\\\n\\\\n1. Open the plans and choose **New**.\\\\n2. Type the **{field:SubscriptionPlan.name}** customers will see and a short **{field:SubscriptionPlan.planKey}** such as \\\\\\\"starter\\\\\\\".\\\\n3. Choose **{field:SubscriptionPlan.pricingMode}**: free, a fixed price, or pay what you can. This cannot change once the plan is saved; make a new plan instead.\\\\n4. For a fixed price, enter the **{field:SubscriptionPlan.priceAmount}** in cents and the **{field:SubscriptionPlan.currency}**.\\\\n5. Set how often it bills in **{field:SubscriptionPlan.billingInterval}**.\\\\n6. Set the **{field:SubscriptionPlan.status}** to active when it is ready to sell.\\\\n7. Save.\\\\n\\\\n### Change a plan's price or terms\\\\n\\\\n1. Open the plan and edit the **{field:SubscriptionPlan.priceAmount}**, **{field:SubscriptionPlan.billingInterval}** or **{field:SubscriptionPlan.status}**.\\\\n2. Save. The new terms apply to new subscribers and to existing ones from their next renewal; a period already paid for keeps its old terms.\\\\n\\\\n### Retire a plan\\\\n\\\\n1. Open the plan and set its **{field:SubscriptionPlan.status}** to archived.\\\\n2. Save. No one new can subscribe to it; existing subscribers keep going until they cancel.\\\\n\\\\n### Subscribe someone to a plan\\\\n\\\\n1. Open the subscriptions and choose **New**.\\\\n2. Pick the **{field:TenantSubscription.planId}**.\\\\n3. Enter the day it **{field:TenantSubscription.startedAt}** and, if there is a free trial, when the **{field:TenantSubscription.trialEndsAt}**.\\\\n4. Save. The **{field:TenantSubscription.status}** shows where the subscription stands once it has been paid for.\\\\n\\\\n### See where a subscription stands\\\\n\\\\n1. Open the subscriptions and find the one you want.\\\\n2. The **{field:TenantSubscription.status}** shows whether it is still incomplete, on trial, active, past due, unpaid or cancelled.\\\\n3. **{field:TenantSubscription.currentPeriodStart}** and **{field:TenantSubscription.currentPeriodEnd}** show the period that has been paid for.\\\\n\\\\n### Cancel a subscription\\\\n\\\\n1. Open the subscription.\\\\n2. Tick **{field:TenantSubscription.cancelAtPeriodEnd}** so it runs out when the current period ends instead of renewing.\\\\n3. Save.\\\\n\\\\n### Look up the terms a subscriber was sold\\\\n\\\\nPlan versions are written automatically whenever a plan is saved with changed\\\\nterms; you cannot add or edit them here.\\\\n\\\\n1. Open the plan versions and find the **{field:SubscriptionPlanVersion.planId}** you are interested in.\\\\n2. Each row shows the **{field:SubscriptionPlanVersion.version}** and the date it was **{field:SubscriptionPlanVersion.effectiveFrom}**.\\\\n3. Read the **{field:SubscriptionPlanVersion.priceAmount}**, **{field:SubscriptionPlanVersion.currency}** and **{field:SubscriptionPlanVersion.billingInterval}** that applied under it.\\\\n\\\\n### See what a subscriber was charged\\\\n\\\\nCharges are created by the usage and billing service as usage is recorded;\\\\nyou cannot add or edit them here.\\\\n\\\\n1. Open the charges.\\\\n2. Each row shows **{field:ClientCharge.metricKey}**, **{field:ClientCharge.quantity}** and the **{field:ClientCharge.amount}** in cents.\\\\n3. The **{field:ClientCharge.status}** shows whether the charge is still a draft, approved or adjusted.\\\\n\\\",\\\"fieldRefs\\\":[\\\"ClientCharge.amount\\\",\\\"ClientCharge.metricKey\\\",\\\"ClientCharge.quantity\\\",\\\"ClientCharge.status\\\",\\\"SubscriptionPlan.billingInterval\\\",\\\"SubscriptionPlan.currency\\\",\\\"SubscriptionPlan.name\\\",\\\"SubscriptionPlan.planKey\\\",\\\"SubscriptionPlan.priceAmount\\\",\\\"SubscriptionPlan.pricingMode\\\",\\\"SubscriptionPlan.status\\\",\\\"SubscriptionPlanVersion.billingInterval\\\",\\\"SubscriptionPlanVersion.currency\\\",\\\"SubscriptionPlanVersion.effectiveFrom\\\",\\\"SubscriptionPlanVersion.planId\\\",\\\"SubscriptionPlanVersion.priceAmount\\\",\\\"SubscriptionPlanVersion.version\\\",\\\"TenantSubscription.cancelAtPeriodEnd\\\",\\\"TenantSubscription.currentPeriodEnd\\\",\\\"TenantSubscription.currentPeriodStart\\\",\\\"TenantSubscription.planId\\\",\\\"TenantSubscription.startedAt\\\",\\\"TenantSubscription.status\\\",\\\"TenantSubscription.trialEndsAt\\\"]},\\\"demo\\\":{\\\"mode\\\":\\\"server\\\",\\\"reasons\\\":[\\\"Needs a server because its package does not build for a browser: core migrations (node:crypto, node:os); and its package depends on @happyvertical/smrt-profiles, @happyvertical/smrt-tenancy, @happyvertical/smrt-users, which do not build for a browser (#3617, #3624, #3626).\\\"]}}],\\\"smrtDependencies\\\":[\\\"@happyvertical/smrt-core\\\",\\\"@happyvertical/smrt-features\\\",\\\"@happyvertical/smrt-tenancy\\\",\\\"@happyvertical/smrt-users\\\"],\\\"browser\\\":{\\\"status\\\":\\\"server-only\\\",\\\"issues\\\":[\\\"#3617\\\",\\\"#3624\\\",\\\"#3626\\\"],\\\"reason\\\":\\\"core migrations (node:crypto, node:os)\\\",\\\"via\\\":[\\\"@happyvertical/smrt-profiles\\\",\\\"@happyvertical/smrt-tenancy\\\",\\\"@happyvertical/smrt-users\\\"]},\\\"stampsConstructors\\\":true}\"));\n","/**\n * Host configuration surface for the billing glue (#4786).\n *\n * Environment variables, with the secrets held in non-enumerable properties so\n * a stray `JSON.stringify(config)` or `console.log(config)` cannot print them.\n * Error messages name the variable and never its value.\n */\nimport type { BillingUrls } from './types.js';\n\nexport const BILLING_ENV = {\n secretKey: 'STRIPE_SECRET_KEY',\n webhookSecret: 'STRIPE_WEBHOOK_SECRET',\n webhookTolerance: 'STRIPE_WEBHOOK_TOLERANCE',\n metadataSecret: 'BILLING_METADATA_SECRET',\n metadataPreviousSecrets: 'BILLING_METADATA_PREVIOUS_SECRETS',\n successUrl: 'BILLING_SUCCESS_URL',\n cancelUrl: 'BILLING_CANCEL_URL',\n portalReturnUrl: 'BILLING_PORTAL_RETURN_URL',\n} as const;\n\nexport const DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;\nexport const MAX_WEBHOOK_TOLERANCE_SECONDS = 900;\n\n/** The env var holding the provider price id for a plan key. */\nexport function priceEnvName(planKey: string): string {\n return `STRIPE_PRICE_${planKey.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}`;\n}\n\nexport interface BillingEnvOptions {\n /** Plan keys whose `STRIPE_PRICE_<KEY>` variables should be read. */\n planKeys: readonly string[];\n}\n\nexport interface BillingEnvConfig {\n /**\n * Provider credentials for `getAccountingProvider({ type: 'stripe', … })`.\n * `secretKey` and `webhookSecret` are non-enumerable (they do not survive\n * a spread, `JSON.stringify` or `console.log`), so read them by name.\n */\n stripe: {\n readonly secretKey: string;\n readonly webhookSecret: string;\n webhookTolerance: number;\n };\n /**\n * Checkout-metadata signing (#4786). `signingSecret` is unset unless\n * `BILLING_METADATA_SECRET` is configured (the host then falls back to the\n * webhook secret). `previousSecrets` (comma-separated\n * `BILLING_METADATA_PREVIOUS_SECRETS`) are still accepted when a completed\n * checkout is verified, so rotating a secret does not drop sessions created\n * before the rotation. Both are non-enumerable.\n */\n metadata: {\n readonly signingSecret: string | undefined;\n readonly previousSecrets: readonly string[];\n };\n urls: BillingUrls;\n /** Plan key to price id for every plan whose variable is set. */\n prices: Record<string, string>;\n}\n\ntype Env = Record<string, string | undefined>;\n\nfunction read(env: Env, name: string): string | undefined {\n const value = env[name]?.trim();\n return value ? value : undefined;\n}\n\nfunction required(env: Env, name: string): string {\n const value = read(env, name);\n if (!value) throw new Error(`${name} is required.`);\n return value;\n}\n\n/**\n * Validate a redirect destination: absolute, no embedded credentials, and\n * https (plain http only for loopback development hosts).\n */\nexport function assertBillingUrl(name: string, value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`${name} must be an absolute URL.`);\n }\n const loopback =\n url.hostname === 'localhost' ||\n url.hostname === '127.0.0.1' ||\n url.hostname === '[::1]' ||\n url.hostname.endsWith('.localhost');\n if (url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback)) {\n throw new Error(`${name} must use https.`);\n }\n if (url.username || url.password) {\n throw new Error(`${name} must not contain credentials.`);\n }\n // Returned as given: Checkout expands a literal `{CHECKOUT_SESSION_ID}`\n // placeholder that URL normalisation would percent-encode.\n return value;\n}\n\nexport function assertWebhookTolerance(seconds: number): number {\n if (\n !Number.isInteger(seconds) ||\n seconds < 1 ||\n seconds > MAX_WEBHOOK_TOLERANCE_SECONDS\n ) {\n throw new Error(\n `The webhook tolerance must be a whole number of seconds from 1 to ${MAX_WEBHOOK_TOLERANCE_SECONDS}.`,\n );\n }\n return seconds;\n}\n\n/** Read and validate billing configuration from an environment map. */\nexport function readBillingEnv(\n env: Env,\n options: BillingEnvOptions,\n): BillingEnvConfig {\n const secretKey = required(env, BILLING_ENV.secretKey);\n if (!/^(sk|rk)_/.test(secretKey)) {\n throw new Error(\n `${BILLING_ENV.secretKey} must be a secret key (sk_ or rk_).`,\n );\n }\n const webhookSecret = required(env, BILLING_ENV.webhookSecret);\n if (!webhookSecret.startsWith('whsec_')) {\n throw new Error(\n `${BILLING_ENV.webhookSecret} must be a webhook signing secret (whsec_).`,\n );\n }\n const toleranceText = read(env, BILLING_ENV.webhookTolerance);\n const tolerance = toleranceText\n ? Number(toleranceText)\n : DEFAULT_WEBHOOK_TOLERANCE_SECONDS;\n try {\n assertWebhookTolerance(tolerance);\n } catch {\n throw new Error(\n `${BILLING_ENV.webhookTolerance} must be a whole number of seconds from 1 to ${MAX_WEBHOOK_TOLERANCE_SECONDS}.`,\n );\n }\n\n const prices: Record<string, string> = {};\n for (const planKey of options.planKeys) {\n const price = read(env, priceEnvName(planKey));\n if (price) prices[planKey] = price;\n }\n\n const stripe = { webhookTolerance: tolerance } as BillingEnvConfig['stripe'];\n Object.defineProperty(stripe, 'secretKey', {\n value: secretKey,\n enumerable: false,\n });\n Object.defineProperty(stripe, 'webhookSecret', {\n value: webhookSecret,\n enumerable: false,\n });\n\n const metadata = {} as BillingEnvConfig['metadata'];\n Object.defineProperty(metadata, 'signingSecret', {\n value: read(env, BILLING_ENV.metadataSecret),\n enumerable: false,\n });\n Object.defineProperty(metadata, 'previousSecrets', {\n value: (read(env, BILLING_ENV.metadataPreviousSecrets) ?? '')\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean),\n enumerable: false,\n });\n\n return {\n stripe,\n metadata,\n prices,\n urls: {\n successUrl: assertBillingUrl(\n BILLING_ENV.successUrl,\n required(env, BILLING_ENV.successUrl),\n ),\n cancelUrl: assertBillingUrl(\n BILLING_ENV.cancelUrl,\n required(env, BILLING_ENV.cancelUrl),\n ),\n portalReturnUrl: assertBillingUrl(\n BILLING_ENV.portalReturnUrl,\n required(env, BILLING_ENV.portalReturnUrl),\n ),\n },\n };\n}\n","import { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSystemContext,\n TenantScoped,\n tenantId,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport {\n type PlanVersionReplacement,\n pinSubscriptionPlanVersion,\n} from '../plan-versioning.js';\nimport type {\n JsonObject,\n PlanVersionPinReason,\n Subscriber,\n SubscriberKind,\n SubscriptionStatus,\n TenantSubscriptionOptions,\n} from '../types.js';\nimport {\n assertSubscriberInvariant,\n parseJsonObject,\n stringifyJson,\n} from '../utils.js';\n\n/** In-period replacements requested through `replacePlanVersion()`. */\nconst pendingReplacements = new WeakMap<\n TenantSubscription,\n PlanVersionReplacement\n>();\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_tenant_subscriptions',\n api: { include: ['list', 'get', 'create', 'update'] },\n cli: { skipApiCheck: true },\n mcp: { include: ['list', 'get'] },\n // The conflict key includes the subscriber discriminator so an issuing tenant\n // can host many distinct external subscribers without collisions on the\n // unique index:\n // - tenant-kind rows always have subscriber_external_id = '' → uniqueness\n // reduces to (tenant_id, 'tenant', '') = at most one tenant-kind row per\n // tenant (preserves the pre-polymorphic invariant).\n // - external-kind rows are unique on (tenant_id, 'external', externalId) =\n // at most one active subscription per (issuer, external subscriber).\n //\n // UPGRADE NOTE: databases created against the pre-#1454 conflict key\n // ['tenant_id'] still carry the legacy `_smrt_tenant_subscriptions_tenant_id_idx`.\n // `smrt db:migrate` does not sweep orphan indexes by default, so the legacy\n // index persists and continues to reject external subscriptions until it's\n // dropped. Run scripts/migrate-1454-drop-legacy-conflict-index.ts once on\n // upgrade, or pass `--drop-indexes` to `db:migrate`. Fresh databases need\n // neither — the generated schema already reflects the new key.\n conflictColumns: ['tenant_id', 'subscriber_kind', 'subscriber_external_id'],\n})\nexport class TenantSubscription extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId()\n tenantId?: string;\n\n /**\n * Discriminator for the subscriber identity.\n *\n * - `'tenant'` (default): the subscriber IS the owning `tenantId` — the\n * pre-polymorphic shape. All existing rows continue to behave this way.\n * - `'external'`: the subscriber is `subscriberExternalId`, scoped under the\n * issuing `tenantId`. Used for B2C buyers, anonymous-email subscribers,\n * agent identities, and any other caller-defined identity.\n */\n @field({\n description:\n 'Whether the subscriber is your own workspace (tenant) or an outside customer (external).',\n })\n subscriberKind: SubscriberKind = 'tenant';\n\n /**\n * Caller-namespaced opaque identifier for the subscriber when\n * `subscriberKind === 'external'`. Empty string when kind is `'tenant'`.\n *\n * The package treats this as opaque — no FK, no inferred semantics. Callers\n * are expected to namespace (e.g. `buyer-contact:abc123`,\n * `agent:hermes-7`, `email:foo@example.com`).\n */\n @field({\n description:\n 'Who the outside subscriber is, when the subscriber type is external.',\n })\n subscriberExternalId: string = '';\n\n @field({ description: 'The plan this subscription is for.' })\n @foreignKey('SubscriptionPlan')\n planId: string = '';\n\n @field({\n description:\n 'Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.',\n })\n status: SubscriptionStatus = 'incomplete';\n @field({ description: 'The day the subscription began.' })\n startedAt: Date = new Date();\n @field({ description: 'When the current billing period began.' })\n currentPeriodStart: Date | null = null;\n @field({\n description:\n 'When the current billing period ends and the next one is due.',\n })\n currentPeriodEnd: Date | null = null;\n @field({ description: 'When the free trial ends, if there is one.' })\n trialEndsAt: Date | null = null;\n @field({\n description:\n 'Tick to let the subscription run out at the end of the current period instead of renewing.',\n })\n cancelAtPeriodEnd: boolean = false;\n @field({ description: 'When the subscription was cancelled.' })\n canceledAt: Date | null = null;\n /** Amount selected for this subscription, in integer minor units. */\n @field({\n description:\n 'For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.',\n })\n agreedAmount: number | null = null;\n /**\n * The immutable `SubscriptionPlanVersion` frozen for the current period\n * (#4032). Maintained on save: pinned at period start, re-pinned when\n * `currentPeriodStart` moves (renewal), and replaced mid-period only by an\n * entitlement upgrade or an authorized {@link replacePlanVersion}. Null\n * only for subscriptions to unmigrated legacy plans with no versions.\n */\n @field({\n description:\n 'The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.',\n })\n @foreignKey('SubscriptionPlanVersion')\n planVersionId: string | null = null;\n /** When {@link planVersionId} was last set. */\n planVersionPinnedAt: Date | null = null;\n /** Why {@link planVersionId} was last set (audit). */\n planVersionPinReason: PlanVersionPinReason | null = null;\n /** Caller-supplied reason for an `upgrade`/`authorized` replacement. */\n planVersionPinNote: string = '';\n /**\n * Set when the row was canceled while it entitled (`active`/`trialing`\n * within its period), so the paid period runs to `currentPeriodEnd`.\n * Derived on save from the stored row and never taken from the caller: a\n * subscription canceled while `incomplete`, `past_due` or `unpaid` (for\n * example a provider's `incomplete_expired`) entitles nothing.\n */\n retainsPaidPeriod: boolean = false;\n externalProvider: string | null = null;\n stripeCustomerId: string = '';\n stripeSubscriptionId: string = '';\n stripeCheckoutSessionId: string = '';\n metadata: string = '{}';\n\n constructor(options: TenantSubscriptionOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.subscriberKind !== undefined)\n this.subscriberKind = options.subscriberKind;\n if (options.subscriberExternalId !== undefined)\n this.subscriberExternalId = options.subscriberExternalId;\n // Enforce the subscriber XOR invariant at construction time so callers\n // catch mistakes early. The same check also runs in `validateBeforeSave`\n // below so the generated PUT/PATCH update path — which mutates an existing\n // instance via `Object.assign()` and bypasses this constructor — can't\n // sneak a malformed row past us either.\n assertSubscriberInvariant('TenantSubscription', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (options.planId !== undefined) this.planId = options.planId;\n if (options.status !== undefined) this.status = options.status;\n if (options.startedAt !== undefined) this.startedAt = options.startedAt;\n if (options.currentPeriodStart !== undefined) {\n this.currentPeriodStart = options.currentPeriodStart;\n }\n if (options.currentPeriodEnd !== undefined) {\n this.currentPeriodEnd = options.currentPeriodEnd;\n }\n if (options.trialEndsAt !== undefined)\n this.trialEndsAt = options.trialEndsAt;\n if (options.cancelAtPeriodEnd !== undefined) {\n this.cancelAtPeriodEnd = options.cancelAtPeriodEnd;\n }\n if (options.canceledAt !== undefined) this.canceledAt = options.canceledAt;\n if (options.agreedAmount !== undefined)\n this.agreedAmount = options.agreedAmount;\n if (options.planVersionId !== undefined)\n this.planVersionId = options.planVersionId;\n if (options.planVersionPinnedAt !== undefined)\n this.planVersionPinnedAt = options.planVersionPinnedAt;\n if (options.planVersionPinReason !== undefined)\n this.planVersionPinReason = options.planVersionPinReason;\n if (options.planVersionPinNote !== undefined)\n this.planVersionPinNote = options.planVersionPinNote;\n if (options.retainsPaidPeriod !== undefined)\n this.retainsPaidPeriod = options.retainsPaidPeriod;\n if (options.externalProvider !== undefined) {\n this.externalProvider = options.externalProvider;\n }\n if (options.stripeCustomerId !== undefined) {\n this.stripeCustomerId = options.stripeCustomerId;\n }\n if (options.stripeSubscriptionId !== undefined) {\n this.stripeSubscriptionId = options.stripeSubscriptionId;\n }\n if (options.stripeCheckoutSessionId !== undefined) {\n this.stripeCheckoutSessionId = options.stripeCheckoutSessionId;\n }\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Validates the subscriber XOR invariant before every save. Critical for the\n * generated update path: `SmrtCollection.update()` mutates the existing\n * instance via `Object.assign()` and calls `save()` directly — the\n * constructor never re-runs, so without this hook a partial update like\n * `{ subscriberExternalId: 'buyer:alice' }` on a tenant-kind row would\n * persist a malformed conflict key and let two tenant-kind rows coexist\n * under the same tenant.\n */\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n assertSubscriberInvariant('TenantSubscription', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (\n this.agreedAmount !== null &&\n (!Number.isSafeInteger(this.agreedAmount) || this.agreedAmount < 0)\n ) {\n throw new Error(\n 'agreedAmount must be a non-negative integer minor-unit amount',\n );\n }\n const plans = await SubscriptionPlanCollection.create({ db: this.db });\n // Ordinary reads inherit the caller's tenancy. The bounded global fallback\n // permits legacy public plans without exposing any other tenant's plan.\n const scopedPlan = await plans.get({ id: this.planId }, { cache: false });\n const plan =\n scopedPlan ??\n (await withSystemContext(() =>\n plans.get({ id: this.planId, tenantId: null }, { cache: false }),\n ));\n if (\n !plan ||\n (!isSystemContext() &&\n plan.tenantId !== null &&\n plan.tenantId !== (this.tenantId ?? getTenantId() ?? null))\n ) {\n throw new Error('Subscription plan is unavailable');\n }\n if (plan.pricingMode === 'pay_what_you_can') {\n if (\n this.agreedAmount === null ||\n this.agreedAmount < plan.minimumAmount\n ) {\n throw new Error('agreedAmount must meet the plan minimumAmount');\n }\n } else if (this.agreedAmount !== null) {\n throw new Error('agreedAmount requires a pay_what_you_can plan');\n }\n const replacement = pendingReplacements.get(this);\n pendingReplacements.delete(this);\n const { TenantSubscriptionCollection } = await import(\n '../collections/TenantSubscriptionCollection.js'\n );\n // The row this save replaces: by id, or — for a create that will\n // upsert onto an existing subscriber row — by the natural key, so a\n // re-create cannot bypass the paid-period rules.\n const subscriptions = await TenantSubscriptionCollection.create({\n db: this.db,\n });\n const persisted =\n (this.id\n ? await subscriptions.get({ id: String(this.id) }, { cache: false })\n : null) ??\n (this.isPersisted\n ? null\n : ((\n await subscriptions.list({\n where: {\n tenantId: this.tenantId ?? getTenantId() ?? null,\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n },\n limit: 1,\n })\n )[0] ?? null));\n if (this.status !== 'canceled') {\n this.retainsPaidPeriod = false;\n } else if (persisted?.status === 'canceled') {\n this.retainsPaidPeriod = persisted.retainsPaidPeriod;\n } else {\n this.retainsPaidPeriod =\n persisted !== null &&\n (persisted.status === 'active' || persisted.status === 'trialing') &&\n persisted.isEntitled();\n }\n await pinSubscriptionPlanVersion(this, persisted, replacement);\n }\n\n /**\n * Replace the plan version frozen for the current period and save (#4032).\n *\n * - `policy: 'upgrade'` succeeds only when the target's entitlements cover\n * the frozen version's (see `isEntitlementUpgrade`); otherwise the save\n * is rejected and the paid period keeps its terms.\n * - `policy: 'authorized'` accepts any target and requires a `reason`,\n * recorded with `planVersionPinReason: 'authorized'` for audit — use it\n * for an operator-approved downgrade, refund, or correction.\n *\n * The target is `planVersionId`, else the version of `planId` (as set on\n * this instance) in force now. A plain `planId` change in the same period\n * is treated as `policy: 'upgrade'`.\n */\n async replacePlanVersion(\n options: PlanVersionReplacement & { planId?: string },\n ): Promise<this> {\n const { planId, ...replacement } = options;\n if (planId !== undefined) this.planId = planId;\n pendingReplacements.set(this, replacement);\n try {\n return await this.save();\n } finally {\n pendingReplacements.delete(this);\n }\n }\n\n /**\n * Whether the subscription grants entitlements at `now`. Active and\n * trialing subscriptions entitle until `currentPeriodEnd`. A subscription\n * canceled while it entitled keeps its paid period ({@link\n * retainsPaidPeriod}) until `currentPeriodEnd`, never without one (#4032).\n * For an immediate cancellation (for example with a refund) set\n * `currentPeriodEnd` to the cancellation time.\n */\n isEntitled(now = new Date()): boolean {\n const end = this.currentPeriodEnd\n ? new Date(this.currentPeriodEnd).getTime()\n : null;\n if (this.status === 'canceled') {\n return this.retainsPaidPeriod && end !== null && now.getTime() <= end;\n }\n if (this.status !== 'active' && this.status !== 'trialing') {\n return false;\n }\n if (end !== null && end < now.getTime()) {\n return false;\n }\n return true;\n }\n\n /**\n * Project this row's polymorphic subscriber columns onto the\n * {@link Subscriber} discriminated union. Returns `null` when the owning\n * tenant is absent — that's an invalid row that should not be acted on.\n */\n getSubscriber(): Subscriber | null {\n if (!this.tenantId) {\n return null;\n }\n if (this.subscriberKind === 'external') {\n if (!this.subscriberExternalId) {\n return null;\n }\n return {\n kind: 'external',\n tenantId: this.tenantId,\n externalId: this.subscriberExternalId,\n };\n }\n return { kind: 'tenant', tenantId: this.tenantId };\n }\n\n getMetadata(): JsonObject {\n return parseJsonObject(this.metadata, {});\n }\n\n setMetadata(metadata: JsonObject): void {\n this.metadata = stringifyJson(metadata);\n }\n}\n\nexport default TenantSubscription;\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { TenantSubscription } from '../models/TenantSubscription.js';\nimport type { Subscriber } from '../types.js';\n\nexport class TenantSubscriptionCollection extends SmrtCollection<TenantSubscription> {\n static readonly _itemClass = TenantSubscription;\n\n /**\n * List subscriptions whose owning tenant scope is `tenantId`. Includes both\n * `'tenant'`-kind (subscriber == owner) and `'external'`-kind (subscriber is\n * an external identity scoped under this tenant) rows.\n */\n async findByTenant(tenantId: string): Promise<TenantSubscription[]> {\n return this.list({\n where: { tenantId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Legacy single-tenant accessor: returns the current subscription where the\n * tenant IS the subscriber (`subscriberKind = 'tenant'`). External-kind rows\n * scoped under this tenant are intentionally excluded so existing callers\n * are not surprised by buyer/agent subscriptions.\n */\n async findCurrentForTenant(\n tenantId: string,\n now = new Date(),\n ): Promise<TenantSubscription | null> {\n return this.findCurrentForSubscriber({ kind: 'tenant', tenantId }, now);\n }\n\n /**\n * Polymorphic current-subscription accessor.\n *\n * For `'tenant'` subscribers we match rows with `subscriberKind = 'tenant'`\n * under the same `tenantId`. For `'external'` subscribers we match by\n * `(tenantId, subscriberExternalId)` with `subscriberKind = 'external'`.\n */\n async findCurrentForSubscriber(\n subscriber: Subscriber,\n now = new Date(),\n ): Promise<TenantSubscription | null> {\n const where: Record<string, unknown> = {\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n };\n if (subscriber.kind === 'external') {\n where.subscriberExternalId = subscriber.externalId;\n }\n\n const subscriptions = await this.list({\n where,\n orderBy: 'created_at DESC',\n });\n return (\n subscriptions.find((subscription) => subscription.isEntitled(now)) ??\n subscriptions[0] ??\n null\n );\n }\n\n async findByStripeSubscriptionId(\n stripeSubscriptionId: string,\n ): Promise<TenantSubscription | null> {\n const subscriptions = await this.list({\n where: { stripeSubscriptionId },\n limit: 1,\n });\n return subscriptions[0] ?? null;\n }\n}\n","import {\n field,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Where a Checkout session the billing host created stands (#4814).\n *\n * - `pending`: created by the host, not yet completed.\n * - `completed`: the paid session was linked to its tenant (single use).\n * - `needs_reconciliation`: a paid session whose record was missing, expired\n * or did not match. It is not linked; an operator links it on purpose with\n * `BillingHost.reconcileCheckout()`.\n */\nexport type BillingCheckoutSessionStatus =\n | 'pending'\n | 'completed'\n | 'needs_reconciliation'\n | 'dismissed';\n\n/**\n * One Checkout session created by the billing host, recorded when the host\n * creates it and required when the paid session completes, so signed\n * metadata copied onto another integration's session is never trusted.\n * `sessionId` is the provider's unguessable, unique id and doubles as the\n * single-use nonce.\n *\n * A system table managed through `createBillingHost()`, like\n * `_smrt_price_book_assignments`; it has no generated API surface. It is a\n * root export because the published manifest advertises it. `tenantId` is the\n * tenant the host created the session for (`''` on a row opened for a session\n * the host never recorded).\n */\n@smrt({\n tableName: '_smrt_billing_checkout_sessions',\n conflictColumns: ['session_id'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class BillingCheckoutSession extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @field({ required: true })\n sessionId: string = '';\n @field({ description: 'The tenant the host created the session for.' })\n targetTenantId: string = '';\n status: BillingCheckoutSessionStatus = 'pending';\n expiresAt: Date = new Date(0);\n completedAt: Date | null = null;\n /** Why the row needs reconciliation (a code, never provider text). */\n reason: string = '';\n /** JSON ids needed to reconcile: event, subscription, customer, plan. */\n detail: string = '{}';\n}\n\nexport class BillingCheckoutSessionCollection extends SmrtCollection<BillingCheckoutSession> {\n static readonly _itemClass = BillingCheckoutSession;\n}\n","/**\n * Normalise verified Stripe webhook payloads into the facts this module acts\n * on (#4786). Pure: no I/O, no trust decisions beyond reading shapes.\n */\nimport type { SubscriptionStatus } from '../types.js';\nimport type { BillingSubscriptionState } from './types.js';\n\nexport const SUBSCRIPTION_EVENT_TYPES = new Set([\n 'customer.subscription.created',\n 'customer.subscription.updated',\n 'customer.subscription.deleted',\n 'customer.subscription.paused',\n 'customer.subscription.resumed',\n]);\n\nexport const CHECKOUT_COMPLETED = 'checkout.session.completed';\nexport const SUBSCRIPTION_DELETED = 'customer.subscription.deleted';\n\n/** What the provider says about one subscription at a point in time. */\nexport interface SubscriptionSnapshot {\n subscriptionId: string;\n customerId: string;\n status: SubscriptionStatus;\n priceId?: string;\n startedAt?: Date | null;\n currentPeriodStart?: Date | null;\n currentPeriodEnd?: Date | null;\n trialEndsAt?: Date | null;\n cancelAtPeriodEnd?: boolean;\n canceledAt?: Date | null;\n endedAt?: Date | null;\n}\n\nexport interface CheckoutCompletedFacts {\n sessionId: string;\n mode: string | undefined;\n paymentStatus: string | undefined;\n customerId: string | undefined;\n subscriptionId: string | undefined;\n metadata: Record<string, string>;\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport function asRecord(value: unknown): UnknownRecord | null {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nexport function asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\n/** A Stripe id that is either a string or an expanded `{ id }` object. */\nexport function externalId(value: unknown): string | undefined {\n return asString(value) ?? asString(asRecord(value)?.id);\n}\n\nexport function stripeObject(payload: unknown): UnknownRecord | null {\n return asRecord(asRecord(asRecord(payload)?.data)?.object);\n}\n\nexport function toDate(value: unknown): Date | null {\n if (value instanceof Date) {\n return Number.isFinite(value.getTime()) ? value : null;\n }\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) {\n return new Date(value * 1000);\n }\n return null;\n}\n\nconst STATUS_MAP: Record<string, SubscriptionStatus> = {\n active: 'active',\n trialing: 'trialing',\n past_due: 'past_due',\n unpaid: 'unpaid',\n canceled: 'canceled',\n incomplete: 'incomplete',\n // An abandoned first payment never entitled anything.\n incomplete_expired: 'canceled',\n // Paused subscriptions do not entitle.\n paused: 'unpaid',\n};\n\n/** Unknown provider statuses fail closed to a non-entitling status. */\nexport function mapSubscriptionStatus(\n value: string | undefined,\n): SubscriptionStatus {\n return (value && STATUS_MAP[value]) || 'incomplete';\n}\n\nfunction stringMap(value: unknown): Record<string, string> {\n const result: Record<string, string> = {};\n const record = asRecord(value);\n if (!record) return result;\n for (const [key, entry] of Object.entries(record)) {\n if (typeof entry === 'string') result[key] = entry;\n }\n return result;\n}\n\nfunction itemList(object: UnknownRecord): UnknownRecord[] {\n const data = asRecord(object.items)?.data;\n return Array.isArray(data)\n ? data.map(asRecord).filter((item): item is UnknownRecord => item !== null)\n : [];\n}\n\n/** The first line-item price id: what the provider actually bills. */\nexport function subscriptionPriceId(object: UnknownRecord): string | undefined {\n for (const item of itemList(object)) {\n const price = externalId(asRecord(item.price)?.id ?? item.price);\n if (price) return price;\n }\n return undefined;\n}\n\n/**\n * Billing periods live on the subscription in older API versions and on its\n * items in newer ones; read either.\n */\nfunction periodDate(\n object: UnknownRecord,\n key: 'current_period_start' | 'current_period_end',\n): Date | null | undefined {\n if (key in object) return toDate(object[key]);\n for (const item of itemList(object)) {\n if (key in item) return toDate(item[key]);\n }\n return undefined;\n}\n\n/** Facts from a `customer.subscription.*` event object. */\nexport function subscriptionSnapshotFromObject(\n object: UnknownRecord,\n eventType: string,\n): SubscriptionSnapshot | null {\n const subscriptionId = asString(object.id);\n const customerId = externalId(object.customer);\n if (!subscriptionId || !customerId) return null;\n return {\n subscriptionId,\n customerId,\n status:\n eventType === SUBSCRIPTION_DELETED\n ? 'canceled'\n : mapSubscriptionStatus(asString(object.status)),\n priceId: subscriptionPriceId(object),\n startedAt: toDate(object.start_date),\n currentPeriodStart: periodDate(object, 'current_period_start'),\n currentPeriodEnd: periodDate(object, 'current_period_end'),\n trialEndsAt: 'trial_end' in object ? toDate(object.trial_end) : undefined,\n cancelAtPeriodEnd:\n typeof object.cancel_at_period_end === 'boolean'\n ? object.cancel_at_period_end\n : undefined,\n canceledAt:\n 'canceled_at' in object ? toDate(object.canceled_at) : undefined,\n endedAt: 'ended_at' in object ? toDate(object.ended_at) : undefined,\n };\n}\n\n/** Facts from a provider subscription read back through the SDK. */\nexport function subscriptionSnapshotFromState(\n state: BillingSubscriptionState,\n): SubscriptionSnapshot {\n const raw = asRecord(state.raw);\n return {\n subscriptionId: state.externalId,\n customerId: state.customerExternalId,\n status: mapSubscriptionStatus(state.status),\n priceId: raw ? subscriptionPriceId(raw) : undefined,\n startedAt: raw && 'start_date' in raw ? toDate(raw.start_date) : undefined,\n currentPeriodStart:\n state.currentPeriodStart ??\n (raw ? periodDate(raw, 'current_period_start') : undefined),\n currentPeriodEnd:\n state.currentPeriodEnd ??\n (raw ? periodDate(raw, 'current_period_end') : undefined),\n trialEndsAt: state.trialEnd ?? null,\n cancelAtPeriodEnd: state.cancelAtPeriodEnd,\n canceledAt: state.canceledAt ?? null,\n endedAt: raw && 'ended_at' in raw ? toDate(raw.ended_at) : undefined,\n };\n}\n\nexport function checkoutFactsFromObject(\n object: UnknownRecord,\n): CheckoutCompletedFacts | null {\n const sessionId = asString(object.id);\n if (!sessionId) return null;\n return {\n sessionId,\n mode: asString(object.mode),\n paymentStatus: asString(object.payment_status),\n customerId: externalId(object.customer),\n subscriptionId: externalId(object.subscription),\n metadata: stringMap(object.metadata),\n };\n}\n","/**\n * Plan lookup, price mapping and purchasability for the billing glue (#4786).\n *\n * Plans are read in a system context and then checked explicitly: a plan is\n * visible to a tenant only when it is the tenant's own or a global\n * (`tenantId: null`) plan. The provider price always comes from server\n * configuration or the plan's own binding, never from a request.\n */\n\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\n\nexport function planVisibleToTenant(\n plan: SubscriptionPlan,\n tenantId: string,\n): boolean {\n return plan.tenantId === null || plan.tenantId === tenantId;\n}\n\nfunction providerIsStripe(plan: SubscriptionPlan): boolean {\n return !plan.externalProvider || plan.externalProvider === 'stripe';\n}\n\n/** The provider price id a plan is sold under, or undefined when unset. */\nexport function priceIdForPlan(\n plan: SubscriptionPlan,\n prices: Record<string, string> | undefined,\n): string | undefined {\n const configured = prices?.[plan.planKey]?.trim();\n if (configured) return configured;\n if (!providerIsStripe(plan)) return undefined;\n return (\n plan.providerPriceId?.trim() || plan.stripePriceId?.trim() || undefined\n );\n}\n\n/**\n * Whose plans may be sold and resolved from a provider price. `deny` (the\n * default) is operator plans only: a tenant that can write its own\n * `SubscriptionPlan` rows (for example through a mounted generated API) cannot\n * mint a plan, or shadow a global plan key, and buy the entitlements it wrote.\n */\nexport type TenantPlanPolicy = 'deny' | 'allow';\n\nexport class PlanDirectory {\n constructor(\n private readonly db: DatabaseInterface,\n private readonly prices: Record<string, string> | undefined,\n private readonly tenantPlans: TenantPlanPolicy = 'deny',\n ) {}\n\n private sellable(plan: SubscriptionPlan, tenantId: string): boolean {\n return this.tenantPlans === 'allow'\n ? planVisibleToTenant(plan, tenantId)\n : plan.tenantId === null;\n }\n\n /**\n * The plan a subscription row already points at, for status-only updates:\n * visibility only, so a row on a legacy tenant plan keeps resolving.\n */\n async findExisting(\n tenantId: string,\n planId: string,\n ): Promise<SubscriptionPlan | null> {\n return withSystemContext(async () => {\n const plan = await (await this.collection()).get(\n { id: planId },\n { cache: false },\n );\n return plan && planVisibleToTenant(plan, tenantId) ? plan : null;\n });\n }\n\n private collection(): Promise<SubscriptionPlanCollection> {\n return SubscriptionPlanCollection.create({ db: this.db });\n }\n\n /** A plan `tenantId` may buy, by key (own plan first if allowed) or by id. */\n async find(\n tenantId: string,\n ref: { planKey?: string; planId?: string },\n ): Promise<SubscriptionPlan | null> {\n return withSystemContext(async () => {\n const plans = await this.collection();\n if (ref.planId) {\n const plan = await plans.get({ id: ref.planId }, { cache: false });\n return plan && this.sellable(plan, tenantId) ? plan : null;\n }\n if (ref.planKey) {\n const own =\n this.tenantPlans === 'allow'\n ? await plans.findByPlanKey(tenantId, ref.planKey)\n : null;\n return own ?? (await plans.findByPlanKey(null, ref.planKey));\n }\n return null;\n });\n }\n\n /**\n * The plan a provider price id is sold as, for `tenantId`: configured\n * price map first, then plan price bindings. The tenant's own plan beats a\n * global one.\n */\n async findByPriceId(\n tenantId: string,\n priceId: string,\n ): Promise<SubscriptionPlan | null> {\n const mappedKeys = Object.entries(this.prices ?? {})\n .filter(([, price]) => price === priceId)\n .map(([planKey]) => planKey);\n return withSystemContext(async () => {\n const plans = await this.collection();\n const candidates: SubscriptionPlan[] = [];\n for (const planKey of mappedKeys) {\n const own =\n this.tenantPlans === 'allow'\n ? await plans.findByPlanKey(tenantId, planKey)\n : null;\n const global = await plans.findByPlanKey(null, planKey);\n if (own) candidates.push(own);\n if (global) candidates.push(global);\n }\n if (candidates.length === 0) {\n candidates.push(\n ...(await plans.list({ where: { providerPriceId: priceId } })),\n ...(await plans.list({ where: { stripePriceId: priceId } })),\n );\n }\n const visible = candidates\n .filter(\n (plan) => this.sellable(plan, tenantId) && providerIsStripe(plan),\n )\n .sort(\n (a, b) =>\n Number(b.tenantId === tenantId) - Number(a.tenantId === tenantId),\n );\n return visible[0] ?? null;\n });\n }\n}\n","/**\n * Apply verified provider facts to `TenantSubscription` (#4786).\n *\n * Runs inside the idempotency transaction, so every read and write here uses\n * the transaction handle it is given. Provider ids link a subscription to\n * exactly one tenant; an event that disagrees with an existing link is\n * refused (and reported), never merged.\n *\n * Out-of-order delivery converges because each applied event records its\n * provider `created` time on the row and an older event is skipped; a\n * cancellation also wins a same-second tie. A plan change is applied as an\n * authorised plan-version replacement so a downgrade made in the provider is\n * honoured mid-period (the provider, which billed it, is the authority) while\n * the pinning audit trail records why.\n */\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport type { JsonObject, SubscriptionStatus } from '../types.js';\nimport { CHECKOUT_COMPLETED, type SubscriptionSnapshot } from './events.js';\nimport { PlanDirectory } from './plans.js';\nimport type { BillingLogger } from './types.js';\n\n/** JSON-safe result stored with the idempotency claim and replayed. */\nexport interface AppliedOutcome {\n action: 'applied' | 'ignored' | 'needs_reconciliation';\n reason?: string;\n}\n\nexport interface ApplyContext {\n db: DatabaseInterface;\n tenantPlans: 'deny' | 'allow';\n /** PostgreSQL: serialize concurrent events for one subscription or tenant. */\n postgres: boolean;\n prices: Record<string, string> | undefined;\n logger: BillingLogger | undefined;\n}\n\ninterface EventFacts {\n eventId: string;\n eventType: string;\n /** The provider's own event time (whole seconds). */\n eventCreated: Date;\n /** When the snapshot was read, if it was read rather than delivered. */\n observedAt?: Date;\n}\n\nconst ENTITLEMENT_CLAIMING = new Set([\n 'active',\n 'trialing',\n 'past_due',\n 'unpaid',\n]);\n\n/**\n * Serialize applies that touch the same provider subscription or tenant on\n * PostgreSQL, where two transactions can otherwise both read the row before\n * either writes and let an older event overwrite a newer one. Transaction-\n * scoped, taken in sorted order. Embedded engines already have one writer.\n */\nexport async function lockBillingKeys(\n ctx: Pick<ApplyContext, 'db' | 'postgres'>,\n keys: string[],\n): Promise<void> {\n if (!ctx.postgres) return;\n for (const key of [...new Set(keys)].sort()) {\n await ctx.db.query(\n 'SELECT pg_advisory_xact_lock(hashtextextended($1, 0))',\n `smrt-subscriptions:billing:${key}`,\n );\n }\n}\n\nfunction ignored(\n ctx: ApplyContext,\n facts: EventFacts,\n reason: string,\n fields: Record<string, unknown> = {},\n): AppliedOutcome {\n ctx.logger?.warn?.('billing.event.ignored', {\n eventId: facts.eventId,\n eventType: facts.eventType,\n reason,\n ...fields,\n });\n return { action: 'ignored', reason };\n}\n\ninterface LastApplied {\n eventId?: string;\n at?: Date;\n terminal: boolean;\n}\n\nfunction readLastApplied(row: TenantSubscription): LastApplied {\n const stripe = row.getMetadata().stripe;\n if (!stripe || typeof stripe !== 'object' || Array.isArray(stripe)) {\n return { terminal: false };\n }\n const block = stripe as JsonObject;\n const at =\n typeof block.lastEventAt === 'string' ? new Date(block.lastEventAt) : null;\n return {\n eventId:\n typeof block.lastEventId === 'string' ? block.lastEventId : undefined,\n at: at && Number.isFinite(at.getTime()) ? at : undefined,\n terminal: block.terminal === true,\n };\n}\n\n/** The price the row was last granted for (`metadata.stripe.priceId`). */\nfunction readRecordedPrice(row: TenantSubscription): string | undefined {\n const stripe = row.getMetadata().stripe;\n if (!stripe || typeof stripe !== 'object' || Array.isArray(stripe)) {\n return undefined;\n }\n const price = (stripe as JsonObject).priceId;\n return typeof price === 'string' && price ? price : undefined;\n}\n\n/**\n * A row held for an unmapped price still has a live provider subscription\n * (`metadata.stripe.held`): checkout must not sell a second one over it.\n */\nexport function isHeldSubscription(row: TenantSubscription): boolean {\n const stripe = row.getMetadata().stripe;\n return (\n row.status !== 'canceled' &&\n !!stripe &&\n typeof stripe === 'object' &&\n !Array.isArray(stripe) &&\n (stripe as JsonObject).held === HELD_PRICE_UNMAPPED\n );\n}\n\nconst HELD_PRICE_UNMAPPED = 'price_unmapped';\n\n/** Entitling statuses become `incomplete` while an unmapped price is held. */\nconst HELD_STATUS: Partial<Record<SubscriptionStatus, SubscriptionStatus>> = {\n active: 'incomplete',\n trialing: 'incomplete',\n past_due: 'incomplete',\n};\n\nfunction isStale(last: LastApplied, facts: EventFacts): boolean {\n if (last.eventId && last.eventId === facts.eventId) return true;\n if (!last.at) return false;\n const delta = facts.eventCreated.getTime() - last.at.getTime();\n if (delta < 0) return true;\n // Events carry whole-second times; a cancellation wins a same-second tie.\n return delta === 0 && last.terminal && facts.eventType !== CHECKOUT_COMPLETED;\n}\n\nfunction stripeMetadata(\n row: TenantSubscription | null,\n facts: EventFacts,\n snapshot: SubscriptionSnapshot,\n planKey: string,\n resetProvider: boolean,\n held = false,\n): JsonObject {\n const base = row ? row.getMetadata() : {};\n // A different provider subscription starts its own event history.\n const prior =\n !resetProvider &&\n base.stripe &&\n typeof base.stripe === 'object' &&\n !Array.isArray(base.stripe)\n ? (base.stripe as JsonObject)\n : {};\n const observed = facts.observedAt\n ? new Date(Math.floor(facts.observedAt.getTime() / 1000) * 1000)\n : undefined;\n const at =\n observed && observed.getTime() > facts.eventCreated.getTime()\n ? observed\n : facts.eventCreated;\n const { held: _previouslyHeld, ...carried } = prior;\n return {\n ...base,\n planKey,\n stripe: {\n ...carried,\n ...(held ? { held: HELD_PRICE_UNMAPPED } : {}),\n lastEventId: facts.eventId,\n lastEventType: facts.eventType,\n lastEventAt: at.toISOString(),\n priceId:\n snapshot.priceId ?? (prior.priceId as string | undefined) ?? null,\n terminal: snapshot.status === 'canceled',\n },\n };\n}\n\nasync function listRows(\n db: DatabaseInterface,\n where: Record<string, unknown>,\n): Promise<TenantSubscription[]> {\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n return subscriptions.list({ where, limit: 3 });\n}\n\nfunction dateOrKeep(\n next: Date | null | undefined,\n current: Date | null | undefined,\n): Date | null {\n return next !== undefined ? next : (current ?? null);\n}\n\ninterface RowWrite {\n tenantId: string;\n existing: TenantSubscription | null;\n plan: SubscriptionPlan;\n snapshot: SubscriptionSnapshot;\n facts: EventFacts;\n checkoutSessionId?: string;\n /** The row is held for an unmapped price (see `isHeldSubscription`). */\n held?: boolean;\n}\n\nasync function writeRow(\n ctx: ApplyContext,\n write: RowWrite,\n): Promise<AppliedOutcome> {\n const { existing, plan, snapshot, facts } = write;\n const planId = String(plan.id);\n const newSubscription =\n !existing || existing.stripeSubscriptionId !== snapshot.subscriptionId;\n const base = newSubscription ? null : existing;\n\n let periodEnd = dateOrKeep(snapshot.currentPeriodEnd, base?.currentPeriodEnd);\n if (snapshot.status === 'canceled') {\n // Cancellation ends access when it happened, not at the paid-through date\n // of an immediately cancelled subscription, and never later than now (a\n // provider timestamp ahead of this clock must not extend access).\n const endedAt = new Date(\n Math.min(\n (\n snapshot.endedAt ??\n snapshot.canceledAt ??\n facts.eventCreated\n ).getTime(),\n Date.now(),\n ),\n );\n if (!periodEnd || periodEnd.getTime() > endedAt.getTime()) {\n periodEnd = endedAt;\n }\n }\n const fields = {\n status: snapshot.status,\n startedAt: snapshot.startedAt ?? base?.startedAt ?? facts.eventCreated,\n currentPeriodStart: dateOrKeep(\n snapshot.currentPeriodStart,\n base?.currentPeriodStart,\n ),\n currentPeriodEnd: periodEnd,\n trialEndsAt: dateOrKeep(snapshot.trialEndsAt, base?.trialEndsAt),\n cancelAtPeriodEnd:\n snapshot.cancelAtPeriodEnd ?? base?.cancelAtPeriodEnd ?? false,\n canceledAt:\n snapshot.canceledAt !== undefined\n ? snapshot.canceledAt\n : snapshot.status === 'canceled'\n ? (base?.canceledAt ?? facts.eventCreated)\n : (base?.canceledAt ?? null),\n externalProvider: 'stripe',\n stripeCustomerId: snapshot.customerId,\n stripeSubscriptionId: snapshot.subscriptionId,\n stripeCheckoutSessionId:\n write.checkoutSessionId ?? base?.stripeCheckoutSessionId ?? '',\n };\n\n const subscriptions = await TenantSubscriptionCollection.create({\n db: ctx.db,\n });\n let row: TenantSubscription;\n if (existing) {\n Object.assign(existing, fields);\n existing.setMetadata(\n stripeMetadata(\n existing,\n facts,\n snapshot,\n plan.planKey,\n newSubscription,\n write.held,\n ),\n );\n if (existing.planId !== planId) {\n await existing.replacePlanVersion({\n planId,\n policy: 'authorized',\n reason: `stripe:${facts.eventId}`,\n });\n } else {\n await existing.save();\n }\n row = existing;\n } else {\n row = await subscriptions.create({\n tenantId: write.tenantId,\n subscriberKind: 'tenant',\n subscriberExternalId: '',\n planId,\n ...fields,\n metadata: JSON.stringify(\n stripeMetadata(null, facts, snapshot, plan.planKey, true),\n ),\n });\n }\n ctx.logger?.info?.('billing.subscription.applied', {\n eventId: facts.eventId,\n eventType: facts.eventType,\n tenantId: write.tenantId,\n subscriptionRowId: String(row.id),\n planKey: plan.planKey,\n status: snapshot.status,\n });\n return { action: 'applied' };\n}\n\n/** A `customer.subscription.*` event for an already-linked subscription. */\nexport async function applySubscriptionEvent(\n ctx: ApplyContext,\n facts: EventFacts,\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n return withSystemContext(async () => {\n await lockBillingKeys(ctx, [`subscription:${snapshot.subscriptionId}`]);\n const linked = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n if (linked.length === 0) {\n // Not ours (or its checkout has not landed; the checkout event reads\n // the subscription back, so nothing is lost by not guessing here).\n return ignored(ctx, facts, 'unlinked_subscription');\n }\n if (linked.length > 1) return ignored(ctx, facts, 'ambiguous_subscription');\n const tenantId = String((linked[0] as TenantSubscription).tenantId);\n // A checkout for the same tenant locks the tenant too; take it, then read\n // the row again so the staleness decision sees the committed state.\n await lockBillingKeys(ctx, [\n `subscription:${snapshot.subscriptionId}`,\n `tenant:${tenantId}`,\n ]);\n const current = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n if (current.length !== 1 || current[0]?.tenantId !== tenantId) {\n return ignored(ctx, facts, 'unlinked_subscription');\n }\n const row = current[0] as TenantSubscription;\n if (row.stripeCustomerId && row.stripeCustomerId !== snapshot.customerId) {\n return ignored(ctx, facts, 'customer_mismatch', { tenantId });\n }\n if (isStale(readLastApplied(row), facts)) {\n return ignored(ctx, facts, 'stale_event', { tenantId });\n }\n\n const directory = new PlanDirectory(ctx.db, ctx.prices, ctx.tenantPlans);\n const priced = snapshot.priceId\n ? await directory.findByPriceId(tenantId, snapshot.priceId)\n : null;\n const plan = priced ?? (await directory.findExisting(tenantId, row.planId));\n if (!plan) throw new Error('The subscription plan could not be resolved.');\n if (!priced && snapshot.priceId) {\n const recorded = readRecordedPrice(row);\n if (snapshot.priceId !== recorded) {\n // The provider bills a price this host cannot map and it is not the\n // one the row was granted for: the previous plan's entitlements must\n // not carry over to an unknown product. Hold (non-entitling status,\n // plan and recorded price untouched) until the mapping is fixed or\n // the price returns, so every later event is held too.\n ctx.logger?.error?.('billing.price.unmapped_held', {\n eventId: facts.eventId,\n tenantId,\n providerStatus: snapshot.status,\n });\n return writeRow(ctx, {\n tenantId,\n existing: row,\n plan,\n snapshot: {\n ...snapshot,\n status: HELD_STATUS[snapshot.status] ?? snapshot.status,\n priceId: recorded,\n },\n facts,\n // A cancelled subscription is not billing: nothing left to protect.\n held: snapshot.status !== 'canceled',\n });\n }\n ctx.logger?.warn?.('billing.price.unmapped', {\n eventId: facts.eventId,\n tenantId,\n });\n }\n return writeRow(ctx, { tenantId, existing: row, plan, snapshot, facts });\n });\n}\n\nexport interface CheckoutLink {\n tenantId: string;\n planId: string;\n checkoutSessionId: string;\n}\n\n/**\n * A completed Checkout whose signed metadata names the tenant and plan. The\n * snapshot is the subscription read back from the provider after the event,\n * so the row reflects current state however the events were ordered.\n */\nexport async function applyCheckoutCompleted(\n ctx: ApplyContext,\n facts: EventFacts,\n link: CheckoutLink,\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n return withSystemContext(async () => {\n const { tenantId } = link;\n await lockBillingKeys(ctx, [\n `subscription:${snapshot.subscriptionId}`,\n `tenant:${tenantId}`,\n ]);\n const bySubscription = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n const byCustomer = await listRows(ctx.db, {\n stripeCustomerId: snapshot.customerId,\n });\n const foreign = [...bySubscription, ...byCustomer].some(\n (row) => row.tenantId !== tenantId,\n );\n if (foreign) {\n return ignored(ctx, facts, 'tenant_mismatch', { tenantId });\n }\n if (bySubscription.length > 1) {\n return ignored(ctx, facts, 'ambiguous_subscription', { tenantId });\n }\n const ownRows = await listRows(ctx.db, {\n tenantId,\n subscriberKind: 'tenant',\n });\n const existing = bySubscription[0] ?? ownRows[0] ?? null;\n if (\n existing?.stripeSubscriptionId &&\n existing.stripeSubscriptionId !== snapshot.subscriptionId &&\n (ENTITLEMENT_CLAIMING.has(existing.status) ||\n isHeldSubscription(existing))\n ) {\n // The buyer paid for a second subscription that is not tracked. Cancel\n // or refund it at the provider: this is an operator alert, not noise.\n if (ENTITLEMENT_CLAIMING.has(snapshot.status)) {\n ctx.logger?.error?.('billing.checkout.orphaned_subscription', {\n eventId: facts.eventId,\n tenantId,\n subscriptionId: snapshot.subscriptionId,\n });\n }\n return ignored(ctx, facts, 'already_subscribed', { tenantId });\n }\n if (\n existing &&\n existing.stripeSubscriptionId === snapshot.subscriptionId &&\n isStale(readLastApplied(existing), facts)\n ) {\n return ignored(ctx, facts, 'stale_event', { tenantId });\n }\n\n const directory = new PlanDirectory(ctx.db, ctx.prices, ctx.tenantPlans);\n const priced = snapshot.priceId\n ? await directory.findByPriceId(tenantId, snapshot.priceId)\n : null;\n const named = await directory.find(tenantId, { planId: link.planId });\n if (priced && named && priced.id !== named.id) {\n ctx.logger?.warn?.('billing.checkout.plan_price_disagree', {\n eventId: facts.eventId,\n tenantId,\n });\n }\n // What the provider bills is what the tenant has; the signed metadata\n // names the intent and covers a price the host never mapped.\n const plan = priced ?? named;\n if (!plan) throw new Error('The checkout plan could not be resolved.');\n return writeRow(ctx, {\n tenantId,\n existing,\n plan,\n snapshot,\n facts,\n checkoutSessionId: link.checkoutSessionId,\n });\n });\n}\n","/**\n * Binding a completed Checkout to the session the host created (#4814).\n *\n * The signed metadata alone is copyable: another integration on the same\n * Stripe account can put it on its own session and pay first. So the host\n * records each session id when it creates the session, and a paid session\n * links a tenant only when a pending record for exactly that id names the\n * same tenant and the signed expiry has not passed at the event time.\n * Anything else is never linked and never dropped: the paid session is\n * recorded as `needs_reconciliation` for an operator.\n */\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n type BillingCheckoutSession,\n BillingCheckoutSessionCollection,\n} from '../models/BillingCheckoutSession.js';\nimport {\n type AppliedOutcome,\n type ApplyContext,\n applyCheckoutCompleted,\n lockBillingKeys,\n} from './apply.js';\nimport { CHECKOUT_COMPLETED, type SubscriptionSnapshot } from './events.js';\n\n/** Signed metadata key holding the expiry, in whole epoch seconds. */\nexport const METADATA_EXPIRY_KEY = 'smrt_exp';\n/**\n * Stripe expires a Checkout session after 24 hours; the host allows an hour\n * more. The expiry is checked against the event time, not the delivery time,\n * so a late webhook retry of an in-time payment still completes.\n */\nexport const CHECKOUT_SESSION_TTL_MS = 25 * 60 * 60 * 1000;\n\nexport type CheckoutRefusal =\n | 'session_record_missing'\n | 'session_record_mismatch'\n | 'session_expired';\n\ntype Verdict =\n | { kind: 'bound' }\n | { kind: 'replay'; reason: string }\n | { kind: 'reconcile'; reason: CheckoutRefusal };\n\n/** The binding rules, in order. Pure: no I/O. */\nexport function checkBinding(\n record: BillingCheckoutSession | null,\n input: { tenantId: string; exp: string | undefined; eventTime: Date },\n): Verdict {\n if (!record) return { kind: 'reconcile', reason: 'session_record_missing' };\n if (record.status === 'completed') {\n return { kind: 'replay', reason: 'session_already_completed' };\n }\n if (record.status === 'needs_reconciliation') {\n return { kind: 'replay', reason: 'session_needs_reconciliation' };\n }\n if (record.targetTenantId !== input.tenantId) {\n return { kind: 'reconcile', reason: 'session_record_mismatch' };\n }\n if (!input.exp || !/^\\d{1,12}$/.test(input.exp)) {\n return { kind: 'reconcile', reason: 'session_record_mismatch' };\n }\n const at = input.eventTime.getTime();\n if (\n at > Number.parseInt(input.exp, 10) * 1000 ||\n at > new Date(record.expiresAt).getTime()\n ) {\n return { kind: 'reconcile', reason: 'session_expired' };\n }\n return { kind: 'bound' };\n}\n\n/** Record a session the host just created. Idempotent per session id. */\nexport async function recordCheckoutSession(\n db: DatabaseInterface,\n input: { sessionId: string; tenantId: string; expiresAt: Date },\n): Promise<void> {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n if (await sessions.get({ sessionId: input.sessionId })) return;\n try {\n await sessions.create({\n sessionId: input.sessionId,\n targetTenantId: input.tenantId,\n status: 'pending',\n expiresAt: input.expiresAt,\n });\n } catch (error) {\n // A concurrent identical request recorded it first.\n if (!(await sessions.get({ sessionId: input.sessionId }))) throw error;\n }\n}\n\nexport interface ReconcileContext {\n eventId: string;\n eventCreated: string;\n subscriptionId: string;\n customerId: string;\n planId: string;\n claimedTenantId: string;\n}\n\nexport function parseReconcileContext(\n record: BillingCheckoutSession,\n): ReconcileContext | null {\n try {\n const value = JSON.parse(record.detail) as Record<string, unknown>;\n const text = (key: string) =>\n typeof value[key] === 'string' ? (value[key] as string) : '';\n const parsed = {\n eventId: text('eventId'),\n eventCreated: text('eventCreated'),\n subscriptionId: text('subscriptionId'),\n customerId: text('customerId'),\n planId: text('planId'),\n claimedTenantId: text('claimedTenantId'),\n };\n return parsed.subscriptionId &&\n parsed.customerId &&\n Number.isFinite(Date.parse(parsed.eventCreated))\n ? parsed\n : null;\n } catch {\n return null;\n }\n}\n\nexport interface BoundCompletion {\n sessionId: string;\n /** From the verified signed metadata. */\n tenantId: string;\n planId: string;\n exp: string | undefined;\n eventId: string;\n eventTime: Date;\n}\n\n/**\n * Inside the idempotency transaction: bind the paid session to its record,\n * then link the tenant. `ctx.db` is the transaction handle.\n */\nexport async function completeBoundCheckout(\n ctx: ApplyContext,\n input: BoundCompletion,\n facts: Parameters<typeof applyCheckoutCompleted>[1],\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const sessions = await BillingCheckoutSessionCollection.create({\n db: ctx.db,\n });\n const record = await sessions.get({ sessionId: input.sessionId });\n const verdict = checkBinding(record, input);\n\n if (verdict.kind === 'replay') {\n ctx.logger?.warn?.('billing.checkout.not_relinked', {\n eventId: input.eventId,\n sessionId: input.sessionId,\n reason: verdict.reason,\n });\n return { action: 'ignored', reason: verdict.reason };\n }\n if (verdict.kind === 'reconcile') {\n const context: ReconcileContext = {\n eventId: input.eventId,\n eventCreated: input.eventTime.toISOString(),\n subscriptionId: snapshot.subscriptionId,\n customerId: snapshot.customerId,\n planId: input.planId,\n claimedTenantId: input.tenantId,\n };\n if (record) {\n record.status = 'needs_reconciliation';\n record.reason = verdict.reason;\n record.detail = JSON.stringify(context);\n await record.save();\n } else {\n await sessions.create({\n sessionId: input.sessionId,\n targetTenantId: '',\n status: 'needs_reconciliation',\n expiresAt: input.eventTime,\n reason: verdict.reason,\n detail: JSON.stringify(context),\n });\n }\n // A paid purchase nobody has linked: loud, with codes and ids only.\n ctx.logger?.error?.('billing.checkout.needs_reconciliation', {\n eventId: input.eventId,\n sessionId: input.sessionId,\n reason: verdict.reason,\n claimedTenantId: input.tenantId,\n subscriptionId: snapshot.subscriptionId,\n });\n return { action: 'needs_reconciliation', reason: verdict.reason };\n }\n\n const outcome = await applyCheckoutCompleted(\n ctx,\n facts,\n {\n tenantId: input.tenantId,\n planId: input.planId,\n checkoutSessionId: input.sessionId,\n },\n snapshot,\n );\n if (outcome.action === 'applied' && record) {\n record.status = 'completed';\n record.completedAt = new Date();\n await record.save();\n }\n return outcome;\n}\n\n/** A flagged session and the ids captured when it was flagged. */\nexport async function loadFlaggedCheckout(\n db: DatabaseInterface,\n sessionId: string,\n): Promise<{\n record: BillingCheckoutSession;\n flagged: ReconcileContext;\n} | null> {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n const record = await sessions.get({ sessionId });\n if (record?.status !== 'needs_reconciliation') return null;\n const flagged = parseReconcileContext(record);\n return flagged ? { record, flagged } : null;\n}\n\n/**\n * Operator action, inside one transaction (`ctx.db`): link a flagged paid\n * session to `tenantId` on purpose. `snapshot` is the subscription read back\n * from the provider before the transaction; it must still be the one recorded\n * when the session was flagged. The row is re-read under the lock, so a\n * session is reconciled at most once.\n */\nexport async function reconcileFlaggedCheckout(\n ctx: ApplyContext,\n input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n operatorId: string;\n snapshot: SubscriptionSnapshot;\n },\n): Promise<AppliedOutcome | null> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const loaded = await loadFlaggedCheckout(ctx.db, input.sessionId);\n const planId = input.planId ?? loaded?.flagged.planId;\n if (!loaded || !planId) return null;\n const { record, flagged } = loaded;\n if (\n input.snapshot.subscriptionId !== flagged.subscriptionId ||\n input.snapshot.customerId !== flagged.customerId\n ) {\n return { action: 'ignored', reason: 'checkout_subscription_mismatch' };\n }\n const outcome = await applyCheckoutCompleted(\n ctx,\n {\n eventId: `reconcile:${input.sessionId}`,\n eventType: CHECKOUT_COMPLETED,\n eventCreated: new Date(flagged.eventCreated),\n observedAt: new Date(),\n },\n {\n tenantId: input.tenantId,\n planId,\n checkoutSessionId: input.sessionId,\n },\n input.snapshot,\n );\n if (outcome.action === 'applied') {\n record.status = 'completed';\n record.targetTenantId = input.tenantId;\n record.reason = 'reconciled';\n record.completedAt = new Date();\n await record.save();\n ctx.logger?.warn?.('billing.checkout.reconciled', {\n sessionId: input.sessionId,\n tenantId: input.tenantId,\n operatorId: input.operatorId,\n subscriptionId: flagged.subscriptionId,\n });\n }\n return outcome;\n}\n\n/**\n * Operator action, inside one transaction (`ctx.db`): close a flagged session\n * without linking it. The row is re-read under the lock, so a session is\n * dismissed or reconciled at most once, whichever comes first.\n */\nexport async function dismissFlaggedCheckout(\n ctx: ApplyContext,\n input: { sessionId: string; operatorId: string; reason: string },\n): Promise<boolean> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const loaded = await loadFlaggedCheckout(ctx.db, input.sessionId);\n if (!loaded) return false;\n loaded.record.status = 'dismissed';\n loaded.record.reason = 'dismissed';\n loaded.record.completedAt = new Date();\n await loaded.record.save();\n ctx.logger?.warn?.('billing.checkout.dismissed', {\n sessionId: input.sessionId,\n operatorId: input.operatorId,\n reason: input.reason,\n subscriptionId: loaded.flagged.subscriptionId,\n });\n return true;\n}\n","/**\n * Signed Checkout metadata and secret hygiene (#4786).\n *\n * Another integration on the same Stripe account can create Checkout Sessions\n * with any metadata it likes. A completed session is only trusted to link a\n * tenant and plan when its `smrt_*` metadata carries an HMAC made with a\n * server-side secret at session creation. Uses WebCrypto so the module loads\n * in every runtime the package does.\n */\n\nexport const METADATA_SIGNATURE_KEY = 'smrt_sig';\nexport const METADATA_PURPOSE = 'tenant_subscription';\n\nconst encoder = new TextEncoder();\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join(\n '',\n );\n}\n\nasync function hmacHex(secret: string, message: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(\n new Uint8Array(\n await crypto.subtle.sign('HMAC', key, encoder.encode(message)),\n ),\n );\n}\n\n/** Compare without an early exit on the first differing character. */\nexport function constantTimeEqual(left: string, right: string): boolean {\n if (left.length !== right.length) return false;\n let diff = 0;\n for (let index = 0; index < left.length; index += 1) {\n diff |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return diff === 0;\n}\n\nfunction canonical(metadata: Record<string, string>): string {\n return JSON.stringify(\n Object.entries(metadata)\n .filter(\n ([key, value]) =>\n key.startsWith('smrt_') &&\n key !== METADATA_SIGNATURE_KEY &&\n value !== '',\n )\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),\n );\n}\n\n/** Add the signature to `metadata`. Only `smrt_*` keys are covered. */\nexport async function signCheckoutMetadata(\n metadata: Record<string, string>,\n secret: string,\n): Promise<Record<string, string>> {\n return {\n ...metadata,\n [METADATA_SIGNATURE_KEY]: await hmacHex(\n `smrt-subscription-checkout:${secret}`,\n canonical(metadata),\n ),\n };\n}\n\nexport async function checkoutMetadataValid(\n metadata: Record<string, string>,\n secret: string,\n): Promise<boolean> {\n const given = metadata[METADATA_SIGNATURE_KEY];\n if (!given) return false;\n return constantTimeEqual(\n given,\n await hmacHex(`smrt-subscription-checkout:${secret}`, canonical(metadata)),\n );\n}\n\nconst SECRET_PATTERN = /\\b(?:sk|rk|pk|whsec)_[A-Za-z0-9_]{4,}/g;\n\n/**\n * Strip anything shaped like a Stripe key or signing secret. Applied to every\n * error message before it reaches a log, as provider errors can echo the\n * credential they were called with.\n */\nexport function redactSecrets(text: string): string {\n return text.replace(SECRET_PATTERN, '[redacted]');\n}\n\nexport function safeErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return redactSecrets(message).slice(0, 300);\n}\n","/**\n * Types for the billing host glue (#4786).\n *\n * The provider port is structural: `StripeAccountingProvider` from\n * `@happyvertical/accounting` satisfies it (a compile-time test pins that), so\n * this package carries no runtime or type dependency on the SDK. Every\n * provider call goes through that SDK; nothing here talks to Stripe directly.\n */\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\n\n/** A line item priced by a provider price id (never by a client-sent amount). */\nexport interface BillingCheckoutLineItem {\n price: string;\n quantity: number;\n}\n\nexport interface BillingCheckoutSessionInput {\n mode?: 'subscription';\n successUrl: string;\n cancelUrl: string;\n customerExternalId?: string;\n customerEmail?: string;\n clientReferenceId?: string;\n lineItems: BillingCheckoutLineItem[];\n metadata: Record<string, string>;\n idempotencyKey?: string;\n}\n\n/** The slice of a provider subscription this module reads. */\nexport interface BillingSubscriptionState {\n externalId: string;\n status: string;\n customerExternalId: string;\n currentPeriodStart?: Date;\n currentPeriodEnd?: Date;\n cancelAtPeriodEnd: boolean;\n canceledAt?: Date;\n trialEnd?: Date;\n raw?: unknown;\n}\n\n/** A parsed (not yet trusted until `verify` passed) webhook event. */\nexport interface BillingProviderWebhookEvent {\n id?: string;\n type: string;\n timestamp: Date;\n payload: unknown;\n}\n\n/**\n * The provider operations the glue needs. `StripeAccountingProvider` from\n * `@happyvertical/accounting` is assignable to this.\n */\nexport interface BillingProviderPort {\n readonly webhooks: {\n verify(payload: string, signature: string, secret: string): boolean;\n parse(payload: string): BillingProviderWebhookEvent;\n };\n readonly billing: {\n createCheckoutSession(\n input: BillingCheckoutSessionInput,\n ): Promise<{ externalId: string; url: string | null }>;\n createCustomerPortalSession(input: {\n customerExternalId: string;\n returnUrl: string;\n }): Promise<{ url: string }>;\n retrieveSubscriptionStatus(\n subscriptionExternalId: string,\n ): Promise<BillingSubscriptionState>;\n };\n}\n\n/** Fixed, host-configured destinations. Never taken from a request. */\nexport interface BillingUrls {\n /** Where Checkout sends the buyer after paying. */\n successUrl: string;\n /** Where Checkout sends the buyer when they back out. */\n cancelUrl: string;\n /** Where the customer portal returns to. */\n portalReturnUrl: string;\n}\n\n/**\n * Structured, secret-free log sink. Every field passed is safe to persist:\n * event ids, types, tenant ids and reason codes only.\n */\nexport interface BillingLogger {\n info?(message: string, fields?: Record<string, unknown>): void;\n warn?(message: string, fields?: Record<string, unknown>): void;\n error?(message: string, fields?: Record<string, unknown>): void;\n}\n\nexport interface BillingPlanPurchaseContext {\n tenantId: string;\n plan: SubscriptionPlan;\n}\n\nexport interface BillingHostOptions {\n /** The accounting provider (Stripe) from `@happyvertical/accounting`. */\n provider: BillingProviderPort;\n /**\n * Resolved database handle with `transaction()` support (SQLite or\n * PostgreSQL). Event idempotency and the subscription write share one\n * transaction on it. Take it from any collection, for example\n * `(await TenantSubscriptionCollection.create(config)).db`.\n */\n db: DatabaseInterface;\n /** Webhook endpoint signing secret (`whsec_…`). Required, never defaulted. */\n webhookSecret: string;\n /**\n * Secret used to sign new Checkout metadata. Defaults to `webhookSecret`, so\n * rotating the webhook secret also changes it: list the retired secret in\n * `metadataVerificationSecrets` for as long as sessions created under it can\n * still complete, or give the host its own stable secret here.\n */\n metadataSigningSecret?: string;\n /**\n * Retired secrets still accepted when a completed Checkout is verified (never\n * used to sign). Needed across a rotation of the signing secret, otherwise a\n * session paid after the rotation is not trusted and the purchase is dropped.\n */\n metadataVerificationSecrets?: readonly string[];\n /** Maximum webhook signature age in seconds (default 300, at most 900). */\n webhookToleranceSeconds?: number;\n /** Largest accepted webhook body in bytes (default 1 MiB). */\n maxWebhookBodyBytes?: number;\n urls: BillingUrls;\n /**\n * Whether tenant-owned plans (`SubscriptionPlan.tenantId` set) may be sold.\n * Default `deny`: only operator-owned global plans are sold, so a tenant\n * that can write plan rows cannot buy entitlements it defined itself. Use\n * `allow` only when tenants cannot write plans.\n */\n tenantPlans?: 'deny' | 'allow';\n /** Plan key to provider price id. Wins over the plan's own price binding. */\n prices?: Record<string, string>;\n /**\n * Extra purchase policy, evaluated after the built-in checks (plan visible\n * to the tenant, active, fixed price, price configured, tenant not already\n * subscribed). Return false to refuse.\n */\n canPurchasePlan?: (\n context: BillingPlanPurchaseContext,\n ) => boolean | Promise<boolean>;\n /** Namespaces the idempotency claim when several accounts share a database. */\n accountKey?: string;\n logger?: BillingLogger;\n}\n\n/** The tenant a host has already authenticated and authorised for billing. */\nexport interface BillingAuth {\n tenantId: string;\n /** Prefilled on Checkout for a tenant with no billing customer yet. */\n email?: string;\n}\n\nexport type BillingHostErrorCode =\n | 'invalid_request'\n | 'tenant_mismatch'\n | 'plan_unavailable'\n | 'plan_forbidden'\n | 'plan_not_purchasable'\n | 'price_unconfigured'\n | 'already_subscribed'\n | 'no_billing_account'\n | 'checkout_not_reconcilable'\n | 'provider_error';\n\nconst STATUS_BY_CODE: Record<BillingHostErrorCode, number> = {\n invalid_request: 400,\n tenant_mismatch: 403,\n plan_forbidden: 403,\n plan_unavailable: 404,\n plan_not_purchasable: 409,\n already_subscribed: 409,\n no_billing_account: 409,\n checkout_not_reconcilable: 409,\n price_unconfigured: 503,\n provider_error: 502,\n};\n\nconst MESSAGE_BY_CODE: Record<BillingHostErrorCode, string> = {\n invalid_request: 'The request is not valid.',\n tenant_mismatch: 'The request does not match the signed-in workspace.',\n plan_unavailable: 'That plan is not available.',\n plan_forbidden: 'This workspace cannot buy that plan.',\n plan_not_purchasable: 'That plan cannot be bought online.',\n price_unconfigured: 'Billing is not configured for that plan.',\n already_subscribed:\n 'This workspace already has a subscription. Use the billing portal to change it.',\n no_billing_account: 'This workspace has no billing account yet.',\n checkout_not_reconcilable: 'That checkout cannot be reconciled.',\n provider_error: 'The billing provider could not complete the request.',\n};\n\n/**\n * A refusal with a stable code and a fixed message. The message never carries\n * provider text, ids or configuration, so it is safe to return to a browser.\n */\nexport class BillingHostError extends Error {\n readonly code: BillingHostErrorCode;\n readonly status: number;\n\n constructor(code: BillingHostErrorCode) {\n super(MESSAGE_BY_CODE[code]);\n this.name = 'BillingHostError';\n this.code = code;\n this.status = STATUS_BY_CODE[code];\n }\n}\n\nexport interface BillingCheckoutResult {\n /** Hosted checkout page to send the buyer to. */\n url: string;\n sessionId: string;\n}\n\nexport interface BillingPortalResult {\n url: string;\n}\n\nexport type BillingWebhookOutcome =\n | 'applied'\n | 'ignored'\n | 'duplicate'\n /**\n * A paid first-purchase Checkout could not be tied to a session this host\n * created. It was not linked and not discarded: it is stored for an\n * operator (`listCheckoutsNeedingReconciliation`, `reconcileCheckout`).\n */\n | 'needs_reconciliation';\n\n/** A paid Checkout session waiting for an operator. Ids and codes only. */\nexport interface BillingUnreconciledCheckout {\n sessionId: string;\n /** `session_record_missing`, `session_record_mismatch` or `session_expired`. */\n reason: string;\n /** The tenant the signed metadata named (not trusted). */\n claimedTenantId: string;\n subscriptionId: string;\n /**\n * The provider customer that paid. Confirm it is the claimed tenant's own\n * customer before reconciling: it is the one value that decides who gets\n * control of the tenant's billing portal.\n */\n customerId: string;\n /** The tenant the host recorded the session for (empty when no record). */\n targetTenantId: string;\n /**\n * True when the claimed tenant has its own pending or completed session\n * recorded by this host, which suggests the flagged payment is a copy of\n * that tenant's signed metadata rather than the tenant's purchase.\n */\n claimedTenantHasOwnSession: boolean;\n eventId: string;\n flaggedAt: Date;\n}\n\nexport interface BillingWebhookResponse {\n status: number;\n body: {\n received: boolean;\n outcome?: BillingWebhookOutcome;\n error?: string;\n };\n}\n\nexport interface BillingHost {\n createCheckout(\n auth: BillingAuth,\n input: { planKey?: string; planId?: string },\n ): Promise<BillingCheckoutResult>;\n createPortalLink(auth: BillingAuth): Promise<BillingPortalResult>;\n /** Paid Checkout sessions flagged `needs_reconciliation`, oldest first. */\n listCheckoutsNeedingReconciliation(options?: {\n /** Page size, 1..1000 (default 200). */\n limit?: number;\n offset?: number;\n }): Promise<BillingUnreconciledCheckout[]>;\n /** How many paid sessions are flagged, so a page is never mistaken for all. */\n countCheckoutsNeedingReconciliation(): Promise<number>;\n /**\n * Operator-only (same rules as `reconcileCheckout`): close a flagged session\n * on purpose WITHOUT linking it (for example a payment from another\n * integration on the same account). Terminal state `dismissed`, logged with\n * the operator id and reason; throws `checkout_not_reconcilable` when the\n * session is not flagged.\n */\n dismissCheckout(input: {\n sessionId: string;\n operatorId: string;\n reason: string;\n }): Promise<void>;\n /**\n * Operator-only, called by host code that has already authenticated and\n * authorised an operator (never wired to a request handler). Links a flagged\n * paid session to `tenantId` on purpose, once: the subscription is re-read\n * from the provider and must be the one recorded when the session was\n * flagged. `planId` defaults to the plan the signed metadata named. Throws\n * `checkout_not_reconcilable` when the session is not flagged (or was\n * already reconciled); otherwise reports whether the link was `applied` or\n * `ignored` with a reason (for example `already_subscribed`).\n */\n reconcileCheckout(input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n /** Who is acting; recorded in the audit log. */\n operatorId: string;\n }): Promise<{ outcome: 'applied' | 'ignored'; reason?: string }>;\n handleWebhook(input: {\n payload: string;\n signature: string | null;\n }): Promise<BillingWebhookResponse>;\n /**\n * Fetch-API handlers for any framework (`+server.ts`, Hono, Workers). The\n * host authenticates and authorises the caller first and passes the tenant;\n * checkout and portal never read a tenant, price or URL from the request.\n */\n handlers: {\n checkout(request: Request, auth: BillingAuth): Promise<Response>;\n portal(request: Request, auth: BillingAuth): Promise<Response>;\n webhook(request: Request): Promise<Response>;\n };\n}\n","/**\n * Reusable billing host glue (#4786): hosted checkout, a verified idempotent\n * webhook, and a customer-portal link, for hosts that sell `SubscriptionPlan`s\n * through Stripe.\n *\n * Every provider call goes through `@happyvertical/accounting` (the\n * {@link BillingProviderPort}); this module owns the trust decisions around\n * it:\n *\n * - **Webhook**: signature and timestamp are checked on the raw body before\n * anything is parsed; the event id is claimed durably with the subscription\n * write in one transaction (`runOnce`), so a replay is a 2xx no-op and a\n * failed apply rolls the claim back for the provider's retry.\n * - **Checkout/portal**: the host authenticates and authorises the caller and\n * passes the tenant; price, URLs and customer come from server state only.\n * - **Responses and logs** carry fixed messages, ids and reason codes, never\n * provider text or configuration.\n */\nimport {\n deriveRunOnceClaimKey,\n digestRunOnceContent,\n isPostgresDatabase,\n RUN_ONCE_CLAIMS_TABLE,\n RunOnceClaimError,\n runOnce,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n withSystemContext,\n withTenant,\n} from '@happyvertical/smrt-tenancy';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport { BillingCheckoutSessionCollection } from '../models/BillingCheckoutSession.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport {\n type AppliedOutcome,\n applySubscriptionEvent,\n isHeldSubscription,\n} from './apply.js';\nimport {\n CHECKOUT_SESSION_TTL_MS,\n completeBoundCheckout,\n dismissFlaggedCheckout,\n loadFlaggedCheckout,\n METADATA_EXPIRY_KEY,\n parseReconcileContext,\n reconcileFlaggedCheckout,\n recordCheckoutSession,\n} from './checkout-sessions.js';\nimport {\n assertBillingUrl,\n assertWebhookTolerance,\n DEFAULT_WEBHOOK_TOLERANCE_SECONDS,\n} from './config.js';\nimport {\n CHECKOUT_COMPLETED,\n checkoutFactsFromObject,\n SUBSCRIPTION_EVENT_TYPES,\n stripeObject,\n subscriptionSnapshotFromObject,\n subscriptionSnapshotFromState,\n} from './events.js';\nimport { PlanDirectory, priceIdForPlan } from './plans.js';\nimport {\n checkoutMetadataValid,\n METADATA_PURPOSE,\n safeErrorMessage,\n signCheckoutMetadata,\n} from './signing.js';\nimport {\n type BillingAuth,\n type BillingCheckoutResult,\n type BillingHost,\n BillingHostError,\n type BillingHostOptions,\n type BillingPortalResult,\n type BillingUnreconciledCheckout,\n type BillingWebhookResponse,\n} from './types.js';\n\nconst DEFAULT_MAX_WEBHOOK_BODY_BYTES = 1024 * 1024;\nconst MAX_REQUEST_BODY_BYTES = 8 * 1024;\nconst CLAIM_SCOPE = 'smrt-subscriptions:billing-webhook';\nconst CHECKOUT_KEY_WINDOW_MS = 10 * 60 * 1000;\nconst REF_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;\nconst EMAIL_PATTERN = /^[^\\s@]{1,64}@[^\\s@]{1,190}\\.[^\\s@]{1,63}$/;\n/** Subscriptions that are still the tenant's live Stripe billing. */\nconst LIVE_STATUSES = new Set(['active', 'trialing', 'past_due', 'unpaid']);\n\nconst encoder = new TextEncoder();\n\nasync function sha256Hex(value: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', encoder.encode(value));\n return Array.from(new Uint8Array(digest), (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n}\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = {},\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n ...headers,\n },\n });\n}\n\n/**\n * The `t=` timestamp of a Stripe-Signature header, in seconds. A header with\n * more than one `t=` part is refused: the SDK verifier and this check could\n * otherwise read different ones.\n */\nfunction signatureTimestamp(header: string): number | null {\n let found: number | null = null;\n for (const part of header.split(',')) {\n const [key, value] = part.trim().split('=', 2);\n if (key !== 't') continue;\n if (found !== null || !value || !/^\\d{1,12}$/.test(value)) return null;\n found = Number.parseInt(value, 10);\n }\n return found;\n}\n\n/**\n * Read a request body as text, stopping as soon as it exceeds `limit` bytes\n * (a chunked body has no trustworthy Content-Length). Returns null when over.\n */\nasync function readBoundedText(\n request: Request,\n limit: number,\n): Promise<string | null> {\n const declared = Number(request.headers.get('content-length') ?? 0);\n if (declared > limit) return null;\n if (!request.body) return '';\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > limit) {\n await reader.cancel();\n return null;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(bytes);\n}\n\nexport function createBillingHost(options: BillingHostOptions): BillingHost {\n const {\n provider,\n db,\n urls: rawUrls,\n prices,\n canPurchasePlan,\n logger,\n } = options;\n // Held in closures only: the returned host exposes no secret.\n if (\n typeof options.webhookSecret !== 'string' ||\n options.webhookSecret.trim() === ''\n ) {\n throw new Error('A webhook signing secret is required.');\n }\n const webhookSecret = options.webhookSecret.trim();\n const signingSecret = options.metadataSigningSecret?.trim() || webhookSecret;\n // New sessions are signed with one secret; a completed one may verify under\n // it or a retired one, so a rotation does not drop in-flight purchases.\n const verificationSecrets = [\n ...new Set([\n signingSecret,\n ...(options.metadataVerificationSecrets ?? [])\n .map((secret) => secret.trim())\n .filter(Boolean),\n ]),\n ];\n if (typeof db?.transaction !== 'function') {\n throw new Error(\n 'The billing host needs a database handle with transaction() support.',\n );\n }\n const toleranceSeconds = assertWebhookTolerance(\n options.webhookToleranceSeconds ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS,\n );\n const maxBodyBytes =\n options.maxWebhookBodyBytes ?? DEFAULT_MAX_WEBHOOK_BODY_BYTES;\n if (!Number.isSafeInteger(maxBodyBytes) || maxBodyBytes < 1) {\n throw new Error('maxWebhookBodyBytes must be a positive integer.');\n }\n const urls = {\n successUrl: assertBillingUrl('successUrl', rawUrls.successUrl),\n cancelUrl: assertBillingUrl('cancelUrl', rawUrls.cancelUrl),\n portalReturnUrl: assertBillingUrl(\n 'portalReturnUrl',\n rawUrls.portalReturnUrl,\n ),\n };\n const postgres = isPostgresDatabase(db);\n const tenantPlans = options.tenantPlans ?? 'deny';\n if (tenantPlans !== 'deny' && tenantPlans !== 'allow') {\n throw new Error(\"tenantPlans must be 'deny' or 'allow'.\");\n }\n const claimActor = `billing-webhook:${options.accountKey ?? 'default'}`;\n\n // -------------------------------------------------------------------------\n // Tenant, plan and subscription reads for checkout and portal\n // -------------------------------------------------------------------------\n\n function assertTenant(auth: BillingAuth): string {\n const tenantId = auth?.tenantId;\n if (typeof tenantId !== 'string' || tenantId.trim() === '') {\n throw new BillingHostError('invalid_request');\n }\n const ambient = getTenantId();\n if (ambient && ambient !== tenantId) {\n throw new BillingHostError('tenant_mismatch');\n }\n return tenantId;\n }\n\n async function currentSubscription(\n tenantId: string,\n ): Promise<TenantSubscription | null> {\n return withTenant({ tenantId }, async () => {\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n const rows = await subscriptions.list({\n where: { tenantId, subscriberKind: 'tenant' },\n limit: 1,\n });\n const row = rows[0] ?? null;\n return row && row.tenantId === tenantId ? row : null;\n });\n }\n\n // -------------------------------------------------------------------------\n // Checkout\n // -------------------------------------------------------------------------\n\n async function createCheckout(\n auth: BillingAuth,\n input: { planKey?: string; planId?: string },\n ): Promise<BillingCheckoutResult> {\n const tenantId = assertTenant(auth);\n const planKey = input?.planKey;\n const planId = input?.planId;\n if (\n (planKey === undefined) === (planId === undefined) ||\n (planKey !== undefined && !REF_PATTERN.test(planKey)) ||\n (planId !== undefined && !REF_PATTERN.test(planId))\n ) {\n throw new BillingHostError('invalid_request');\n }\n const email = auth.email?.trim();\n if (email && !EMAIL_PATTERN.test(email)) {\n throw new BillingHostError('invalid_request');\n }\n\n // Another tenant's plan, an unknown plan and an archived plan all look the\n // same to the caller.\n const plan = await new PlanDirectory(db, prices, tenantPlans).find(\n tenantId,\n {\n planKey,\n planId,\n },\n );\n if (!plan?.isActive()) {\n throw new BillingHostError('plan_unavailable');\n }\n if (\n plan.pricingMode !== 'fixed' ||\n plan.priceAmount <= 0 ||\n (plan.externalProvider && plan.externalProvider !== 'stripe')\n ) {\n throw new BillingHostError('plan_not_purchasable');\n }\n const priceId = priceIdForPlan(plan, prices);\n if (!priceId) throw new BillingHostError('price_unconfigured');\n\n const current = await currentSubscription(tenantId);\n if (\n current?.stripeSubscriptionId &&\n (LIVE_STATUSES.has(current.status) || isHeldSubscription(current))\n ) {\n throw new BillingHostError('already_subscribed');\n }\n if (canPurchasePlan && !(await canPurchasePlan({ tenantId, plan }))) {\n throw new BillingHostError('plan_forbidden');\n }\n\n const customerExternalId = current?.stripeCustomerId || undefined;\n const bucket = Math.floor(Date.now() / CHECKOUT_KEY_WINDOW_MS);\n // Same for every request in one idempotency window, so a repeated click\n // sends the provider identical parameters. Signed with the metadata.\n const expiresAt = new Date(\n (bucket + 1) * CHECKOUT_KEY_WINDOW_MS + CHECKOUT_SESSION_TTL_MS,\n );\n const idempotencyKey = `smrt-sub-checkout:${(\n await sha256Hex(\n [\n tenantId,\n String(plan.id),\n priceId,\n customerExternalId ?? email ?? '',\n bucket,\n ].join('|'),\n )\n ).slice(0, 48)}`;\n\n let session: { externalId: string; url: string | null };\n try {\n session = await provider.billing.createCheckoutSession({\n mode: 'subscription',\n successUrl: urls.successUrl,\n cancelUrl: urls.cancelUrl,\n ...(customerExternalId\n ? { customerExternalId }\n : email\n ? { customerEmail: email }\n : {}),\n clientReferenceId: tenantId,\n lineItems: [{ price: priceId, quantity: 1 }],\n metadata: await signCheckoutMetadata(\n {\n smrt_purpose: METADATA_PURPOSE,\n smrt_tenant_id: tenantId,\n smrt_plan_id: String(plan.id),\n // Bind the server-chosen price and, once known, the billing\n // customer: copied metadata cannot be reused for another price\n // or another customer's subscription.\n smrt_price_id: priceId,\n [METADATA_EXPIRY_KEY]: String(\n Math.floor(expiresAt.getTime() / 1000),\n ),\n ...(customerExternalId\n ? { smrt_customer_id: customerExternalId }\n : {}),\n },\n signingSecret,\n ),\n idempotencyKey,\n });\n if (!session.url) throw new Error('Checkout returned no URL.');\n } catch (error) {\n logger?.error?.('billing.checkout.provider_error', {\n tenantId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n // Record the session before the buyer gets its URL: a failure here\n // propagates, so no session is ever sold that completion cannot match.\n await withSystemContext(() =>\n recordCheckoutSession(db, {\n sessionId: session.externalId,\n tenantId,\n expiresAt,\n }),\n );\n return { url: session.url, sessionId: session.externalId };\n }\n\n // -------------------------------------------------------------------------\n // Customer portal\n // -------------------------------------------------------------------------\n\n async function createPortalLink(\n auth: BillingAuth,\n ): Promise<BillingPortalResult> {\n const tenantId = assertTenant(auth);\n // The customer is read from this tenant's own subscription row, never from\n // the request, so a link can only open the caller's own billing account.\n const current = await currentSubscription(tenantId);\n if (!current?.stripeCustomerId) {\n throw new BillingHostError('no_billing_account');\n }\n try {\n const session = await provider.billing.createCustomerPortalSession({\n customerExternalId: current.stripeCustomerId,\n returnUrl: urls.portalReturnUrl,\n });\n if (!session.url) throw new Error('Portal returned no URL.');\n return { url: session.url };\n } catch (error) {\n logger?.error?.('billing.portal.provider_error', {\n tenantId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n }\n\n // -------------------------------------------------------------------------\n // Webhook\n // -------------------------------------------------------------------------\n\n function reject(\n status: number,\n error: string,\n reason: string,\n fields: Record<string, unknown> = {},\n ): BillingWebhookResponse {\n logger?.warn?.('billing.webhook.rejected', { reason, ...fields });\n return { status, body: { received: false, error } };\n }\n\n async function claimExists(eventId: string): Promise<boolean> {\n const claimKey = deriveRunOnceClaimKey({\n tenantId: CLAIM_SCOPE,\n actor: claimActor,\n token: eventId,\n contentDigest: digestRunOnceContent({ provider: 'stripe' }),\n });\n const row = (await db.get(RUN_ONCE_CLAIMS_TABLE, {\n claim_key: claimKey,\n tenant_id: CLAIM_SCOPE,\n })) as { status?: string } | null;\n return row?.status === 'completed';\n }\n\n async function handleWebhook(input: {\n payload: string;\n signature: string | null;\n }): Promise<BillingWebhookResponse> {\n const { payload, signature } = input;\n if (typeof payload !== 'string') {\n return reject(400, 'invalid_payload', 'payload_not_text');\n }\n if (encoder.encode(payload).byteLength > maxBodyBytes) {\n return reject(413, 'payload_too_large', 'payload_too_large');\n }\n if (!signature)\n return reject(400, 'invalid_signature', 'missing_signature');\n\n const timestamp = signatureTimestamp(signature);\n if (timestamp === null) {\n return reject(400, 'invalid_signature', 'malformed_signature');\n }\n const ageSeconds = Math.abs(Date.now() / 1000 - timestamp);\n if (ageSeconds > toleranceSeconds) {\n return reject(400, 'invalid_signature', 'timestamp_outside_tolerance');\n }\n let verified = false;\n try {\n verified = provider.webhooks.verify(payload, signature, webhookSecret);\n } catch {\n verified = false;\n }\n if (!verified) return reject(400, 'invalid_signature', 'bad_signature');\n\n // From here the body is authentic and fresh.\n let event: ReturnType<BillingHostOptions['provider']['webhooks']['parse']>;\n try {\n event = provider.webhooks.parse(payload);\n } catch {\n return reject(400, 'invalid_payload', 'unparseable_payload');\n }\n const eventId = event.id;\n if (!eventId) return reject(400, 'invalid_payload', 'missing_event_id');\n\n const object = stripeObject(event.payload);\n const eventLog = { eventId, eventType: event.type };\n const ignoredResponse = (reason: string): BillingWebhookResponse => {\n logger?.info?.('billing.webhook.ignored', { ...eventLog, reason });\n return { status: 200, body: { received: true, outcome: 'ignored' } };\n };\n\n const isSubscriptionEvent = SUBSCRIPTION_EVENT_TYPES.has(event.type);\n if (!isSubscriptionEvent && event.type !== CHECKOUT_COMPLETED) {\n return ignoredResponse('event_type_not_handled');\n }\n if (!object) return ignoredResponse('malformed_object');\n\n const facts = {\n eventId,\n eventType: event.type,\n eventCreated: event.timestamp,\n };\n try {\n if (await claimExists(eventId)) {\n logger?.info?.('billing.webhook.duplicate', eventLog);\n return { status: 200, body: { received: true, outcome: 'duplicate' } };\n }\n let work: (tx: BillingHostOptions['db']) => Promise<AppliedOutcome>;\n if (isSubscriptionEvent) {\n const snapshot = subscriptionSnapshotFromObject(object, event.type);\n if (!snapshot) return ignoredResponse('malformed_object');\n work = (tx) =>\n applySubscriptionEvent(\n { db: tx, postgres, tenantPlans, prices, logger },\n facts,\n snapshot,\n );\n } else {\n const checkout = checkoutFactsFromObject(object);\n if (checkout?.mode !== 'subscription') {\n return ignoredResponse('not_a_subscription_checkout');\n }\n const { metadata } = checkout;\n if (metadata.smrt_purpose !== METADATA_PURPOSE) {\n // Not one of ours: another integration's session.\n logger?.warn?.('billing.webhook.unsigned_checkout', eventLog);\n return ignoredResponse('checkout_metadata_not_signed');\n }\n let signedByUs = false;\n for (const secret of verificationSecrets) {\n if (await checkoutMetadataValid(metadata, secret)) {\n signedByUs = true;\n break;\n }\n }\n if (!signedByUs) {\n // Claims to be ours but does not verify: a forgery, or a genuine\n // purchase whose signing secret rotated out of the accepted set (it\n // is then paid for and dropped). Loud so an operator sees the second.\n logger?.error?.('billing.webhook.checkout_signature_invalid', {\n ...eventLog,\n sessionId: checkout.sessionId,\n });\n return ignoredResponse('checkout_metadata_not_signed');\n }\n const tenantId = metadata.smrt_tenant_id;\n const planId = metadata.smrt_plan_id;\n if (\n !tenantId ||\n !planId ||\n !checkout.subscriptionId ||\n !checkout.customerId\n ) {\n return ignoredResponse('checkout_incomplete');\n }\n // Read the subscription back (outside the transaction): the row then\n // reflects current provider state however the events were ordered.\n const observedAt = new Date();\n const state = await provider.billing.retrieveSubscriptionStatus(\n checkout.subscriptionId,\n );\n if (\n state.externalId !== checkout.subscriptionId ||\n state.customerExternalId !== checkout.customerId\n ) {\n return ignoredResponse('checkout_subscription_mismatch');\n }\n const snapshot = subscriptionSnapshotFromState(state);\n if (\n !metadata.smrt_price_id ||\n snapshot.priceId !== metadata.smrt_price_id ||\n (metadata.smrt_customer_id &&\n metadata.smrt_customer_id !== checkout.customerId)\n ) {\n // The subscription is not the one this checkout was created for:\n // reused signed metadata, or a price remapped mid-checkout.\n logger?.error?.('billing.checkout.binding_mismatch', {\n ...eventLog,\n subscriptionId: state.externalId,\n });\n return ignoredResponse('checkout_binding_mismatch');\n }\n // Create the table on the base handle, outside the transaction.\n await BillingCheckoutSessionCollection.create({ db });\n work = (tx) =>\n completeBoundCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n {\n sessionId: checkout.sessionId,\n tenantId,\n planId,\n exp: metadata[METADATA_EXPIRY_KEY],\n eventId,\n eventTime: event.timestamp,\n },\n { ...facts, observedAt },\n snapshot,\n );\n }\n\n const outcome = await withSystemContext(() =>\n runOnce(\n {\n db,\n tenantId: CLAIM_SCOPE,\n actor: claimActor,\n token: eventId,\n content: { provider: 'stripe' },\n },\n work,\n ),\n );\n logger?.info?.('billing.webhook.processed', {\n ...eventLog,\n outcome: outcome.action,\n ...(outcome.reason ? { reason: outcome.reason } : {}),\n });\n return {\n status: 200,\n body: { received: true, outcome: outcome.action },\n };\n } catch (error) {\n if (error instanceof RunOnceClaimError) {\n // The same event is being applied right now; ask for a later retry\n // rather than acknowledge work that may yet fail.\n logger?.warn?.('billing.webhook.in_flight', eventLog);\n return { status: 409, body: { received: false, error: 'in_flight' } };\n }\n logger?.error?.('billing.webhook.failed', {\n ...eventLog,\n message: safeErrorMessage(error),\n });\n // Non-2xx: the provider retries, and the rolled-back claim lets it run.\n return {\n status: 500,\n body: { received: false, error: 'processing_failed' },\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Operator reconciliation of paid sessions that could not be bound (#4814)\n // -------------------------------------------------------------------------\n\n async function listCheckoutsNeedingReconciliation(options?: {\n limit?: number;\n offset?: number;\n }): Promise<BillingUnreconciledCheckout[]> {\n const limit = Math.min(\n Math.max(Math.trunc(Number(options?.limit ?? 200)) || 200, 1),\n 1000,\n );\n const offset = Math.max(Math.trunc(Number(options?.offset ?? 0)) || 0, 0);\n return withSystemContext(async () => {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n const rows = await sessions.list({\n where: { status: 'needs_reconciliation' },\n orderBy: 'created_at ASC',\n limit,\n offset,\n });\n const result: BillingUnreconciledCheckout[] = [];\n for (const row of rows) {\n const flagged = parseReconcileContext(row);\n const claimed = flagged?.claimedTenantId ?? '';\n let hasOwn = false;\n if (claimed) {\n for (const status of ['pending', 'completed'] as const) {\n const own = await sessions.list({\n where: { targetTenantId: claimed, status },\n limit: 1,\n });\n if (own.length > 0) hasOwn = true;\n }\n }\n result.push({\n sessionId: row.sessionId,\n reason: row.reason,\n claimedTenantId: claimed,\n subscriptionId: flagged?.subscriptionId ?? '',\n customerId: flagged?.customerId ?? '',\n targetTenantId: row.targetTenantId,\n claimedTenantHasOwnSession: hasOwn,\n eventId: flagged?.eventId ?? '',\n flaggedAt: new Date(row.updated_at ?? row.created_at ?? Date.now()),\n });\n }\n return result;\n });\n }\n\n async function countCheckoutsNeedingReconciliation(): Promise<number> {\n return withSystemContext(async () => {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n return sessions.count({ where: { status: 'needs_reconciliation' } });\n });\n }\n\n async function dismissCheckout(input: {\n sessionId: string;\n operatorId: string;\n reason: string;\n }): Promise<void> {\n const { sessionId, operatorId, reason } = input ?? {};\n if (\n typeof sessionId !== 'string' ||\n !REF_PATTERN.test(sessionId) ||\n typeof operatorId !== 'string' ||\n !/^\\S{1,128}$/.test(operatorId) ||\n typeof reason !== 'string' ||\n reason.trim().length === 0 ||\n reason.length > 200\n ) {\n throw new BillingHostError('invalid_request');\n }\n await withSystemContext(async () => {\n const done = await db.transaction?.((tx) =>\n dismissFlaggedCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n { sessionId, operatorId, reason: reason.trim() },\n ),\n );\n if (!done) throw new BillingHostError('checkout_not_reconcilable');\n });\n }\n\n async function reconcileCheckout(input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n operatorId: string;\n }): Promise<{ outcome: 'applied' | 'ignored'; reason?: string }> {\n const { sessionId, tenantId, planId, operatorId } = input ?? {};\n if (\n typeof sessionId !== 'string' ||\n !REF_PATTERN.test(sessionId) ||\n typeof tenantId !== 'string' ||\n !REF_PATTERN.test(tenantId) ||\n (planId !== undefined &&\n (typeof planId !== 'string' || !REF_PATTERN.test(planId))) ||\n typeof operatorId !== 'string' ||\n !/^\\S{1,128}$/.test(operatorId)\n ) {\n throw new BillingHostError('invalid_request');\n }\n return withSystemContext(async () => {\n const loaded = await loadFlaggedCheckout(db, sessionId);\n if (!loaded) throw new BillingHostError('checkout_not_reconcilable');\n let snapshot: ReturnType<typeof subscriptionSnapshotFromState>;\n try {\n snapshot = subscriptionSnapshotFromState(\n await provider.billing.retrieveSubscriptionStatus(\n loaded.flagged.subscriptionId,\n ),\n );\n } catch (error) {\n logger?.error?.('billing.reconcile.provider_error', {\n sessionId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n const outcome = await db.transaction?.((tx) =>\n reconcileFlaggedCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n { sessionId, tenantId, planId, operatorId, snapshot },\n ),\n );\n if (!outcome) throw new BillingHostError('checkout_not_reconcilable');\n return {\n outcome: outcome.action === 'applied' ? 'applied' : 'ignored',\n ...(outcome.reason ? { reason: outcome.reason } : {}),\n };\n });\n }\n\n // -------------------------------------------------------------------------\n // Fetch-API handlers\n // -------------------------------------------------------------------------\n\n function errorResponse(error: unknown): Response {\n if (error instanceof BillingHostError) {\n return jsonResponse(error.status, {\n error: error.code,\n message: error.message,\n });\n }\n logger?.error?.('billing.request.failed', {\n message: safeErrorMessage(error),\n });\n return jsonResponse(500, { error: 'internal_error' });\n }\n\n async function readSmallBody(request: Request): Promise<string> {\n const text = await readBoundedText(request, MAX_REQUEST_BODY_BYTES);\n if (text === null) throw new BillingHostError('invalid_request');\n return text;\n }\n\n async function readPlanRef(\n request: Request,\n ): Promise<{ planKey?: string; planId?: string }> {\n const type = request.headers.get('content-type') ?? '';\n let values: Record<string, unknown>;\n try {\n if (type.includes('application/json')) {\n const parsed: unknown = JSON.parse(await readSmallBody(request));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('not an object');\n }\n values = parsed as Record<string, unknown>;\n } else {\n const form = new URLSearchParams(await readSmallBody(request));\n values = Object.fromEntries(form.entries());\n }\n } catch (error) {\n if (error instanceof BillingHostError) throw error;\n throw new BillingHostError('invalid_request');\n }\n // Only these two fields are read: a price, amount, tenant or URL sent by\n // the client is ignored.\n const ref: { planKey?: string; planId?: string } = {};\n if (values.planKey !== undefined) {\n if (typeof values.planKey !== 'string') {\n throw new BillingHostError('invalid_request');\n }\n ref.planKey = values.planKey;\n }\n if (values.planId !== undefined) {\n if (typeof values.planId !== 'string') {\n throw new BillingHostError('invalid_request');\n }\n ref.planId = values.planId;\n }\n return ref;\n }\n\n const handlers: BillingHost['handlers'] = {\n async checkout(request, auth) {\n if (request.method !== 'POST') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'POST' },\n );\n }\n try {\n return jsonResponse(\n 200,\n await createCheckout(auth, await readPlanRef(request)),\n );\n } catch (error) {\n return errorResponse(error);\n }\n },\n\n async portal(request, auth) {\n if (request.method !== 'POST' && request.method !== 'GET') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'GET, POST' },\n );\n }\n try {\n return jsonResponse(200, await createPortalLink(auth));\n } catch (error) {\n return errorResponse(error);\n }\n },\n\n async webhook(request) {\n if (request.method !== 'POST') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'POST' },\n );\n }\n let payload: string | null;\n try {\n payload = await readBoundedText(request, maxBodyBytes);\n } catch {\n const rejected = reject(400, 'invalid_payload', 'unreadable_body');\n return jsonResponse(rejected.status, rejected.body);\n }\n if (payload === null) {\n const rejected = reject(413, 'payload_too_large', 'payload_too_large');\n return jsonResponse(rejected.status, rejected.body);\n }\n const result = await handleWebhook({\n payload,\n signature: request.headers.get('stripe-signature'),\n });\n return jsonResponse(result.status, result.body);\n },\n };\n\n return {\n createCheckout,\n createPortalLink,\n listCheckoutsNeedingReconciliation,\n countCheckoutsNeedingReconciliation,\n dismissCheckout,\n reconcileCheckout,\n handleWebhook,\n handlers,\n };\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n JsonObject,\n Subscriber,\n SubscriberKind,\n TenantUsageMetricOptions,\n} from '../types.js';\nimport {\n assertSubscriberInvariant,\n parseJsonObject,\n stringifyJson,\n} from '../utils.js';\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_tenant_usage_metrics',\n api: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class TenantUsageMetric extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId()\n tenantId?: string;\n\n /**\n * Discriminator for which subscriber identity recorded this usage.\n * `'tenant'` (default) preserves the legacy shape; `'external'` indicates\n * the subscriber is `subscriberExternalId` under the issuing `tenantId`.\n */\n subscriberKind: SubscriberKind = 'tenant';\n\n /**\n * Opaque caller-namespaced subscriber id when `subscriberKind === 'external'`.\n * Empty string when kind is `'tenant'`.\n */\n subscriberExternalId: string = '';\n\n metricKey: string = '';\n quantity: number = 0.0;\n windowStart: Date = new Date();\n windowEnd: Date = new Date();\n source: string = '';\n sourceId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n provider: string = '';\n dimensions: string = '{}';\n\n constructor(options: TenantUsageMetricOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.subscriberKind !== undefined)\n this.subscriberKind = options.subscriberKind;\n if (options.subscriberExternalId !== undefined)\n this.subscriberExternalId = options.subscriberExternalId;\n // Construction-time guard; the same invariant is re-checked in\n // `validateBeforeSave` so the generated update path can't bypass it.\n assertSubscriberInvariant('TenantUsageMetric', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (options.metricKey !== undefined) this.metricKey = options.metricKey;\n if (options.quantity !== undefined) this.quantity = options.quantity;\n if (options.windowStart !== undefined)\n this.windowStart = options.windowStart;\n if (options.windowEnd !== undefined) this.windowEnd = options.windowEnd;\n if (options.source !== undefined) this.source = options.source;\n if (options.sourceId !== undefined) this.sourceId = options.sourceId;\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.workRefType !== undefined)\n this.workRefType = options.workRefType;\n if (options.workRefId !== undefined) this.workRefId = options.workRefId;\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.dimensions !== undefined) this.dimensions = options.dimensions;\n }\n\n /** See `TenantSubscription.validateBeforeSave` for the rationale. */\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n assertSubscriberInvariant('TenantUsageMetric', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (this.id) {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n const persisted = [\n row.tenant_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.metric_key,\n row.quantity,\n row.window_start,\n row.window_end,\n row.source,\n row.source_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.dimensions,\n ];\n const current = [\n this.tenantId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.metricKey,\n this.quantity,\n this.windowStart,\n this.windowEnd,\n this.source,\n this.sourceId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.dimensions,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeEvidence(value) !== normalizeEvidence(current[index]),\n )\n ) {\n throw new Error(\n 'Usage events are immutable; record a new event instead.',\n );\n }\n }\n }\n }\n\n /**\n * Project this row's polymorphic subscriber columns onto the\n * {@link Subscriber} discriminated union.\n */\n getSubscriber(): Subscriber | null {\n if (!this.tenantId) {\n return null;\n }\n if (this.subscriberKind === 'external') {\n if (!this.subscriberExternalId) {\n return null;\n }\n return {\n kind: 'external',\n tenantId: this.tenantId,\n externalId: this.subscriberExternalId,\n };\n }\n return { kind: 'tenant', tenantId: this.tenantId };\n }\n\n getDimensions(): JsonObject {\n return parseJsonObject(this.dimensions, {});\n }\n\n setDimensions(dimensions: JsonObject): void {\n this.dimensions = stringifyJson(dimensions);\n }\n}\n\nexport default TenantUsageMetric;\n\nfunction normalizeEvidence(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') {\n const timestamp = Date.parse(value);\n if (/^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value) && Number.isFinite(timestamp)) {\n return new Date(timestamp).toISOString();\n }\n }\n return String(value ?? '');\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { TenantUsageMetric } from '../models/TenantUsageMetric.js';\nimport type {\n AiUsageSummary,\n RecordUsageOptions,\n SummarizeAiUsageOptions,\n SummarizeUsageBatchOptions,\n SummarizeUsageOptions,\n UsageSummary,\n} from '../types.js';\nimport {\n deterministicUuid,\n normalizeSubscriber,\n stringifyJson,\n subscriberToColumns,\n} from '../utils.js';\n\nexport class TenantUsageMetricCollection extends SmrtCollection<TenantUsageMetric> {\n static readonly _itemClass = TenantUsageMetric;\n\n async recordUsage(options: RecordUsageOptions): Promise<TenantUsageMetric> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n const sourcedId =\n options.source && options.sourceId\n ? await deterministicUuid([\n 'tenant-usage',\n columns.tenantId,\n columns.subscriberKind,\n columns.subscriberExternalId,\n options.metricKey,\n options.source,\n options.sourceId,\n ])\n : null;\n if (options.source && options.sourceId) {\n const existing = await this.get(sourcedId as string);\n if (existing) return existing;\n }\n try {\n return await this.create({\n ...(sourcedId ? { id: sourcedId } : {}),\n tenantId: columns.tenantId,\n subscriberKind: columns.subscriberKind,\n subscriberExternalId: columns.subscriberExternalId,\n metricKey: options.metricKey,\n quantity: options.quantity,\n windowStart: options.windowStart,\n windowEnd: options.windowEnd,\n source: options.source ?? '',\n sourceId: options.sourceId ?? '',\n projectId: options.projectId ?? '',\n workRefType: options.workRefType ?? '',\n workRefId: options.workRefId ?? '',\n provider: options.provider ?? '',\n dimensions: stringifyJson(options.dimensions ?? {}),\n _insertOnly: Boolean(sourcedId),\n });\n } catch (error) {\n if (sourcedId) {\n const existing = await this.get(sourcedId);\n if (existing) return existing;\n }\n throw error;\n }\n }\n\n /**\n * Legacy accessor — finds metrics for `subscriberKind = 'tenant'` under the\n * given tenant. External-kind rows scoped to the same tenant are excluded.\n */\n async findByTenantAndMetric(\n tenantId: string,\n metricKey: string,\n ): Promise<TenantUsageMetric[]> {\n return this.list({\n where: { tenantId, metricKey, subscriberKind: 'tenant' },\n orderBy: 'windowStart DESC',\n });\n }\n\n async summarizeUsage(options: SummarizeUsageOptions): Promise<UsageSummary> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n\n const where: Record<string, unknown> = {\n tenantId: columns.tenantId,\n subscriberKind: columns.subscriberKind,\n metricKey: options.metricKey,\n 'windowStart <': options.window.end.toISOString(),\n 'windowEnd >': options.window.start.toISOString(),\n };\n if (subscriber.kind === 'external') {\n where.subscriberExternalId = columns.subscriberExternalId;\n }\n\n const metrics = await this.list({ where });\n\n const baseSummary: UsageSummary = {\n tenantId: columns.tenantId,\n metricKey: options.metricKey,\n quantity: metrics.reduce((sum, metric) => sum + metric.quantity, 0),\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...baseSummary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return baseSummary;\n }\n\n async summarizeUsageBatch(\n options: SummarizeUsageBatchOptions,\n ): Promise<UsageSummary[]> {\n const metricKeys = Array.from(new Set(options.metricKeys));\n if (metricKeys.length === 0) {\n return [];\n }\n\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n\n const metricPlaceholders = metricKeys.map(() => '?').join(', ');\n const params: unknown[] = [\n columns.tenantId,\n columns.subscriberKind,\n ...metricKeys,\n options.window.end.toISOString(),\n options.window.start.toISOString(),\n ];\n let subscriberSql = '';\n if (subscriber.kind === 'external') {\n subscriberSql = 'AND subscriber_external_id = ?';\n params.splice(2, 0, columns.subscriberExternalId);\n }\n\n const result = await this.db.query(\n `SELECT\n metric_key,\n COALESCE(SUM(quantity), 0) AS quantity\n FROM _smrt_tenant_usage_metrics\n WHERE tenant_id = ?\n AND subscriber_kind = ?\n ${subscriberSql}\n AND metric_key IN (${metricPlaceholders})\n AND window_start < ?\n AND window_end > ?\n GROUP BY metric_key`,\n ...params,\n );\n\n const quantityByMetric = new Map<string, number>();\n for (const row of resultRows(result)) {\n const metricKey = String(row.metric_key ?? row.metricKey ?? '');\n if (metricKey) {\n quantityByMetric.set(metricKey, numberFromRow(row, 'quantity'));\n }\n }\n\n return metricKeys.map((metricKey) => {\n const baseSummary: UsageSummary = {\n tenantId: columns.tenantId,\n metricKey,\n quantity: quantityByMetric.get(metricKey) ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...baseSummary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return baseSummary;\n });\n }\n\n /**\n * Summarize persisted AI usage for a tenant within a window.\n *\n * Reads the framework `_smrt_ai_usage` system table via a raw aggregate\n * query. This deliberately uses `this.db.query` rather than the inherited\n * `query()`: those rows are framework usage records, not `TenantUsageMetric`\n * instances, so model hydration would discard the aggregate columns. Tenant\n * scoping is applied explicitly through the `tenant_id` filter.\n *\n * Named distinctly from the inherited `SmrtClass.summarizeAiUsage` (which\n * returns grouped stats across all tenants) to avoid overriding it.\n */\n async summarizeTenantAiUsage(\n options: SummarizeAiUsageOptions,\n ): Promise<AiUsageSummary> {\n const result = await this.db.query(\n `SELECT\n COALESCE(SUM(prompt_tokens), 0) AS prompt_tokens,\n COALESCE(SUM(completion_tokens), 0) AS completion_tokens,\n COALESCE(SUM(total_tokens), 0) AS total_tokens,\n COALESCE(SUM(estimated_cost), 0) AS estimated_cost,\n COUNT(*) AS request_count\n FROM _smrt_ai_usage\n WHERE tenant_id = ?\n AND operation <> 'blocked'\n AND NOT (operation = 'external-agent' AND id LIKE 'external-agent:%')\n AND created_at >= ?\n AND created_at < ?`,\n options.tenantId,\n options.window.start.toISOString(),\n options.window.end.toISOString(),\n );\n const row = firstRow(result);\n\n return {\n tenantId: options.tenantId,\n promptTokens: numberFromRow(row, 'prompt_tokens'),\n completionTokens: numberFromRow(row, 'completion_tokens'),\n totalTokens: numberFromRow(row, 'total_tokens'),\n estimatedCost: numberFromRow(row, 'estimated_cost'),\n requestCount: numberFromRow(row, 'request_count'),\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n }\n}\n\nfunction firstRow(result: unknown): Record<string, unknown> {\n const rows = resultRows(result);\n return (rows[0] ?? {}) as Record<string, unknown>;\n}\n\nfunction resultRows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : ((result as { rows?: Record<string, unknown>[] })?.rows ?? []);\n}\n\nfunction numberFromRow(row: Record<string, unknown>, key: string): number {\n const value = row[key];\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'bigint') {\n return Number(value);\n }\n if (typeof value === 'string') {\n return Number.parseFloat(value) || 0;\n }\n return 0;\n}\n","/**\n * Subscriptions money columns: floating-point major units → integer minor units.\n *\n * Ships as an explicit, opt-in migration rather than a schema-differ upgrade\n * because REAL→INTEGER is not information-preserving: an automatic\n * `ALTER … TYPE integer` would truncate `19.99` to `19`. The values have to be\n * rescaled by the currency's minor-unit factor during the type change (#2401).\n *\n * ```ts\n * console.log((await preflightSubscriptionsMoneyMinorUnits(db)).summary);\n * await migrateSubscriptionsMoneyToMinorUnits(db);\n * ```\n *\n * On SQLite the values are rescaled but the declared type cannot change in\n * place; those columns come back in `declaredTypeChangePending` and need the\n * table-rebuild path (#2370).\n *\n * **Pricing rules are not migrated.** `PricingRule.terms` is a JSON blob whose\n * `unitPrice` / `overageUnitPrice` / `amount` / tier prices are now read as\n * *minor units per unit of usage*. They are deliberately left fractional (a\n * per-token rate is routinely a fraction of a cent), so there is no type to\n * change — but every existing rule's terms are in major units and must be\n * rescaled by the operator, who alone knows which keys in a given rule are\n * prices and which are quantities or ratios.\n */\n\nimport {\n type DatabaseInterface,\n type MinorUnitsPreflightResult,\n type MinorUnitsRescaleResult,\n type MoneyColumnTarget,\n preflightMinorUnitsRescale,\n rescaleMoneyColumnsToMinorUnits,\n} from '@happyvertical/smrt-core/migrations';\n\n/** Marker recorded in `_smrt_backfills` once the rescale has run. */\nexport const SUBSCRIPTIONS_MONEY_MINOR_UNITS_BACKFILL =\n '@happyvertical/smrt-subscriptions:money-minor-units:v1';\n\n/**\n * Every subscriptions money column that held major units before #2401.\n *\n * `quantity` columns are absent on purpose: metered quantities are genuinely\n * fractional and stay DECIMAL.\n */\nexport const SUBSCRIPTIONS_MONEY_COLUMNS: MoneyColumnTarget[] = [\n { table: '_smrt_subscription_plans', columns: ['price_amount'] },\n { table: '_smrt_client_charges', columns: ['amount'] },\n { table: '_smrt_billing_adjustments', columns: ['amount'] },\n { table: '_smrt_spending_policies', columns: ['limit_amount'] },\n];\n\n/**\n * Report what {@link migrateSubscriptionsMoneyToMinorUnits} would do, without\n * writing anything.\n */\nexport function preflightSubscriptionsMoneyMinorUnits(\n db: DatabaseInterface,\n options: { scale?: number; engineHint?: string } = {},\n): Promise<MinorUnitsPreflightResult> {\n return preflightMinorUnitsRescale(db, SUBSCRIPTIONS_MONEY_COLUMNS, options);\n}\n\n/**\n * Convert every subscriptions money column from floating-point major units to\n * integer minor units. Idempotent via a `_smrt_backfills` marker.\n *\n * @throws `MinorUnitsPreflightError` when a row would be rounded or would\n * overflow `int4` and `force` was not set.\n */\nexport function migrateSubscriptionsMoneyToMinorUnits(\n db: DatabaseInterface,\n options: { scale?: number; engineHint?: string; force?: boolean } = {},\n): Promise<MinorUnitsRescaleResult> {\n return rescaleMoneyColumnsToMinorUnits(db, SUBSCRIPTIONS_MONEY_COLUMNS, {\n ...options,\n backfillName: SUBSCRIPTIONS_MONEY_MINOR_UNITS_BACKFILL,\n packageName: '@happyvertical/smrt-subscriptions',\n });\n}\n","/**\n * Backfill effective-dated plan versions for data written before #4032.\n *\n * Run once after the manifest migration (`smrt db:migrate`) has created\n * `_smrt_subscription_plan_versions` and the `plan_version_*` columns on\n * `_smrt_tenant_subscriptions`:\n *\n * ```ts\n * const report = await migrateSubscriptionPlanVersions(db);\n * if (report.failed.length) console.error(report.failed);\n * ```\n *\n * - Every plan without versions gets version 1: its current terms, effective\n * from the plan's `created_at`. Nothing on the plan row changes.\n * - Every subscription without a pin is pinned to the version in force at its\n * period start (`currentPeriodStart ?? startedAt`) with\n * `planVersionPinReason: 'migration'`. With only version 1 present that is\n * always version 1, so no subscriber's entitlements change.\n *\n * Idempotent: plans with versions and pinned subscriptions are skipped. Runs\n * in system context across all tenants. A subscription whose existing row no\n * longer passes validation is reported in `failed` and left unpinned (it keeps\n * resolving through the live plan's version 1); the run continues.\n */\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport { snapshotLegacyPlanVersion } from '../plan-versioning.js';\n\nexport interface SubscriptionPlanVersionsMigrationReport {\n /** Plans that received their version 1. */\n plansVersioned: number;\n /** Subscriptions that received a pin. */\n subscriptionsPinned: number;\n /** Subscriptions that could not be pinned, with the validation error. */\n failed: Array<{ subscriptionId: string; error: string }>;\n}\n\nexport async function migrateSubscriptionPlanVersions(\n db: DatabaseInterface,\n options: { pageSize?: number } = {},\n): Promise<SubscriptionPlanVersionsMigrationReport> {\n const pageSize = options.pageSize ?? 200;\n return withSystemContext(async () => {\n const report: SubscriptionPlanVersionsMigrationReport = {\n plansVersioned: 0,\n subscriptionsPinned: 0,\n failed: [],\n };\n const plans = await SubscriptionPlanCollection.create({ db });\n for (let offset = 0; ; offset += pageSize) {\n const page = await plans.list({\n orderBy: 'id ASC',\n limit: pageSize,\n offset,\n });\n for (const plan of page) {\n if (await snapshotLegacyPlanVersion(plan)) report.plansVersioned += 1;\n }\n if (page.length < pageSize) break;\n }\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n for (let offset = 0; ; offset += pageSize) {\n const page = await subscriptions.list({\n orderBy: 'id ASC',\n limit: pageSize,\n offset,\n });\n for (const subscription of page) {\n if (subscription.planVersionId || !subscription.planId) continue;\n try {\n await subscription.save();\n if (subscription.planVersionId) report.subscriptionsPinned += 1;\n } catch (error) {\n report.failed.push({\n subscriptionId: String(subscription.id),\n error: rootMessage(error),\n });\n }\n }\n if (page.length < pageSize) break;\n }\n return report;\n });\n}\n\nfunction rootMessage(error: unknown): string {\n let current: unknown = error;\n while (current instanceof Error && current.cause instanceof Error) {\n current = current.cause;\n }\n return current instanceof Error ? current.message : String(current);\n}\n","import {\n crossPackageRef,\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\n\nexport type PricingStrategy =\n | 'fixed_unit'\n | 'cost_plus'\n | 'multiplier'\n | 'tiered'\n | 'included_overage'\n | 'flat'\n | 'custom';\nexport type SpendingPolicyBehavior =\n | 'observe'\n | 'warn'\n | 'block'\n | 'approval_required';\n/**\n * `balance` is a prepaid credit balance: the policy's limit is the sum of its\n * {@link CreditGrant}s and spend accumulates from `balanceFrom` onward.\n */\nexport type SpendingPeriod =\n | 'day'\n | 'week'\n | 'month'\n | 'year'\n | 'rolling'\n | 'balance';\n/**\n * Which charges a spending policy counts (#3059).\n *\n * - `billed`: provider charges payable by the policy tenant (`ClientCharge`\n * rows whose `tenantId` is the tenant) — the pre-#3059 behavior.\n * - `retail`: what the tenant owes its reseller (`RetailCharge` rows).\n * - `wholesale`: what the policy's parent (`setByTenantId`) pays the provider\n * for this tenant's usage (`ClientCharge` rows billed to the parent with\n * `usageTenantId` = the tenant). Requires a delegated policy.\n */\nexport type SpendingBasis = 'billed' | 'retail' | 'wholesale';\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_pricing_rules',\n api: true,\n cli: true,\n mcp: true,\n})\nexport class PricingRule extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n ruleKey: string = '';\n metricKey: string = '';\n serviceKey: string = '';\n strategy: PricingStrategy = 'fixed_unit';\n currency: string = 'USD';\n effectiveFrom: Date = new Date();\n effectiveTo: Date | null = null;\n priority: number = 0;\n terms: string = '{}';\n active: boolean = true;\n /**\n * The price book this rule belongs to (#3059), or empty for a tenant's\n * direct pricing. Book rules are priced only through\n * `CommercialUsageService.rateUsage()`; `price()` ignores them.\n */\n @foreignKey('PriceBook')\n priceBookId: string = '';\n\n getTerms(): Record<string, unknown> {\n try {\n return JSON.parse(this.terms) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n setTerms(value: Record<string, unknown>): void {\n this.terms = JSON.stringify(value);\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_client_charges',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n conflictColumns: ['usage_event_id'],\n})\nexport class ClientCharge extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The payer: the usage tenant, or its billing owner when parent-billed. */\n @tenantId() tenantId?: string;\n @foreignKey('TenantUsageMetric')\n usageEventId: string = '';\n /** The tenant whose usage was charged; differs from `tenantId` for wholesale. */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n usageTenantId: string = '';\n subscriberKind: string = 'tenant';\n subscriberExternalId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n @field({ description: 'Who supplied the service that was used.' })\n provider: string = '';\n @field({ description: 'The service that was used.' })\n serviceKey: string = '';\n @field({\n description: 'What was used, such as messages sent or minutes of audio.',\n })\n metricKey: string = '';\n /**\n * Metered quantity — genuinely fractional (`duration.seconds`, token counts\n * scaled by a rate), so it stays DECIMAL.\n */\n @field({ description: 'How much of it was used.' })\n quantity: number = 0.0;\n /**\n * Charge in **integer minor units** of {@link currency} (#2401).\n *\n * Summed against {@link BillingAdjustment.amount} and compared against\n * {@link SpendingPolicy.limitAmount}, so all three carry the same unit —\n * `CommercialService.calculateAmount()` rounds to a whole minor unit at the\n * one boundary where the fractional pricing terms meet money.\n */\n @field({ description: 'What it cost, in cents.' })\n amount: number = 0;\n @field({ description: 'The currency the amount is in, such as USD.' })\n currency: string = 'USD';\n @foreignKey('PricingRule')\n pricingRuleId: string = '';\n /** Wholesale book that priced this charge, or empty for direct pricing. */\n @foreignKey('PriceBook')\n priceBookId: string = '';\n pricingSnapshot: string = '{}';\n @field({\n description: 'Where the charge stands: draft, approved or adjusted.',\n })\n status: 'draft' | 'approved' | 'adjusted' = 'draft';\n @field({ description: 'When the charge was approved.' })\n approvedAt: Date | null = null;\n\n getPricingSnapshot(): Record<string, unknown> {\n try {\n return JSON.parse(this.pricingSnapshot) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.getCanonicalPersistedRow({ id: this.id });\n if (!row || (row.status !== 'approved' && row.status !== 'adjusted'))\n return;\n if (\n (row.status === 'approved' &&\n this.status !== 'approved' &&\n this.status !== 'adjusted') ||\n (row.status === 'adjusted' && this.status !== 'adjusted')\n ) {\n throw new Error(\n 'Approved client charges cannot be reverted to an editable status.',\n );\n }\n const persisted = [\n row.tenant_id,\n row.usage_event_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.service_key,\n row.metric_key,\n row.quantity,\n row.amount,\n row.currency,\n row.pricing_rule_id,\n row.pricing_snapshot,\n row.approved_at,\n row.usage_tenant_id,\n row.price_book_id,\n ];\n const current = [\n this.tenantId,\n this.usageEventId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.serviceKey,\n this.metricKey,\n this.quantity,\n this.amount,\n this.currency,\n this.pricingRuleId,\n this.pricingSnapshot,\n this.approvedAt,\n this.usageTenantId,\n this.priceBookId,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeSnapshot(value) !== normalizeSnapshot(current[index]),\n )\n ) {\n throw new Error(\n 'Approved client charges are immutable; append a BillingAdjustment instead.',\n );\n }\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_billing_adjustments',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class BillingAdjustment extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n @foreignKey('ClientCharge')\n clientChargeId: string = '';\n /**\n * Signed correction in **integer minor units**, same unit as\n * {@link ClientCharge.amount} it adjusts. Negative values are legitimate\n * (a credit) — that is why the non-negative guard in\n * `CommercialService.calculateAmount()` does not apply here (#2401).\n */\n amount: number = 0;\n currency: string = 'USD';\n reason: string = '';\n source: string = '';\n sourceId: string = '';\n createdBy: string = '';\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n throw new Error(\n 'Billing adjustments are append-only; create a new adjustment instead.',\n );\n }\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_spending_policies',\n conflictColumns: [\n 'tenant_id',\n 'subscriber_kind',\n 'subscriber_external_id',\n 'project_id',\n 'service_key',\n 'metric_key',\n 'period',\n 'name',\n ],\n api: true,\n cli: true,\n mcp: true,\n hooks: { beforeDelete: 'assertDelegationAuthority' },\n})\nexport class SpendingPolicy extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n name: string = '';\n subscriberKind: string = '';\n subscriberExternalId: string = '';\n projectId: string = '';\n serviceKey: string = '';\n metricKey: string = '';\n period: SpendingPeriod = 'month';\n rollingSeconds: number = 0;\n /**\n * Spending cap in **integer minor units** of {@link currency}. Compared\n * directly against the sum of `ClientCharge.amount` + `BillingAdjustment`s\n * plus the caller's estimate, so it must carry the same unit (#2401).\n * Must be zero for a `balance` policy, whose limit is its credit grants.\n */\n limitAmount: number = 0;\n currency: string = 'USD';\n behavior: SpendingPolicyBehavior = 'observe';\n priority: number = 0;\n active: boolean = true;\n /** Which charges count toward the policy; see {@link SpendingBasis}. */\n basis: SpendingBasis = 'billed';\n /**\n * The parent tenant that set this policy on its child (#3059), or empty for\n * a tenant's own policy. A delegated policy can be changed or deleted only\n * by that parent, a system context, or a super-admin bypass.\n */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n setByTenantId: string = '';\n /** Start of the spend window for a `balance` policy; defaults to creation. */\n balanceFrom: Date | null = null;\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (this.subscriberExternalId && !this.subscriberKind) {\n throw new Error(\n 'Spending policies with subscriberExternalId require subscriberKind.',\n );\n }\n if (\n this.period === 'rolling' &&\n (!Number.isFinite(this.rollingSeconds) || this.rollingSeconds <= 0)\n ) {\n throw new Error(\n 'Rolling spending policies require rollingSeconds greater than zero.',\n );\n }\n if (\n this.basis !== 'billed' &&\n this.basis !== 'retail' &&\n this.basis !== 'wholesale'\n ) {\n throw new Error(\n 'Spending policy basis must be billed, retail, or wholesale.',\n );\n }\n if (this.basis === 'wholesale' && !this.setByTenantId) {\n throw new Error(\n 'Wholesale spending policies must be delegated by a parent (setByTenantId).',\n );\n }\n if (this.period === 'balance') {\n if (this.limitAmount !== 0) {\n throw new Error(\n 'Balance spending policies take their limit from credit grants; limitAmount must be 0.',\n );\n }\n if (!this.balanceFrom) this.balanceFrom = new Date();\n }\n const targets = await this.persistedTargets();\n await this.assertBalanceLedgerStable(targets);\n await this.assertDelegationAuthority(targets);\n }\n\n /**\n * A balance policy's credit grants are scoped to its currency and period;\n * changing either would silently detach the ledger, so create a new\n * balance instead.\n */\n protected async assertBalanceLedgerStable(\n rows: Array<Record<string, unknown> | null>,\n ): Promise<void> {\n for (const row of rows) {\n if (row?.period !== 'balance') continue;\n if (this.period !== 'balance' || row.currency !== this.currency) {\n throw new Error(\n 'A balance policy cannot change currency or period; create a new balance policy.',\n );\n }\n }\n }\n\n /**\n * The rows this save can overwrite: by id and, because a new object may\n * already carry a generated id, by conflict key (an upsert target).\n */\n protected async persistedTargets(): Promise<\n Array<Record<string, unknown> | null>\n > {\n const byId = this.id\n ? await this.getCanonicalPersistedRow({ id: this.id })\n : null;\n const byKey = this.tenantId\n ? await this.getCanonicalPersistedRow({\n tenant_id: this.tenantId,\n subscriber_kind: this.subscriberKind,\n subscriber_external_id: this.subscriberExternalId,\n project_id: this.projectId,\n service_key: this.serviceKey,\n metric_key: this.metricKey,\n period: this.period,\n name: this.name,\n })\n : null;\n return [byId, byKey];\n }\n\n /**\n * A delegated policy belongs to the parent that set it: the constrained\n * child cannot create one in a parent's name, loosen it, or delete it.\n * The parent's-own-context allowance applies only where no tenancy\n * interceptor is registered; with one, the interceptor refuses a parent\n * writing the child's row, so parents change delegated policies through\n * `ResellerBillingService.setDelegatedSpendingPolicy()` (set\n * `active: false` to retire one).\n * Checks both the persisted row (by id, or by conflict key for an upsert)\n * and the incoming value.\n */\n protected async assertDelegationAuthority(\n targets?: Array<Record<string, unknown> | null>,\n ): Promise<void> {\n const [byId, byKey] = targets ?? (await this.persistedTargets());\n const owners = new Set(\n [byId?.set_by_tenant_id, byKey?.set_by_tenant_id, this.setByTenantId]\n .filter((value): value is string => Boolean(value))\n .map((value) => String(value).toLowerCase()),\n );\n if (owners.size === 0) return;\n if (isSystemContext() || isSuperAdminBypass()) return;\n const current = getTenantId()?.toLowerCase();\n if (owners.size === 1 && current && owners.has(current)) return;\n throw new TenantIsolationError(\n 'Delegated spending policies can be changed only by the parent that set them.',\n );\n }\n}\n\nexport class PricingRuleCollection extends SmrtCollection<PricingRule> {\n static readonly _itemClass = PricingRule;\n}\nexport class ClientChargeCollection extends SmrtCollection<ClientCharge> {\n static readonly _itemClass = ClientCharge;\n}\nexport class BillingAdjustmentCollection extends SmrtCollection<BillingAdjustment> {\n static readonly _itemClass = BillingAdjustment;\n}\nexport class SpendingPolicyCollection extends SmrtCollection<SpendingPolicy> {\n static readonly _itemClass = SpendingPolicy;\n}\n\nfunction normalizeSnapshot(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value)) {\n const timestamp = Date.parse(value);\n if (Number.isFinite(timestamp)) return new Date(timestamp).toISOString();\n }\n return String(value ?? '');\n}\n","/**\n * Reseller billing records (#3059): price books, their per-relationship\n * assignment, the reseller's retail ledger, and prepaid credit grants.\n *\n * Money is integer minor units throughout, exactly as in `commercial.ts`.\n */\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport { tenantKey } from '../utils.js';\n\n/**\n * `wholesale` books price what a service provider charges a reseller for its\n * children's usage; `retail` books price what a reseller charges its children.\n */\nexport type PriceBookKind = 'wholesale' | 'retail';\n\nconst PRICE_BOOK_KINDS: readonly PriceBookKind[] = ['wholesale', 'retail'];\nconst CURRENCY_PATTERN = /^[A-Z]{3}$/;\n\nexport function isPriceBookKind(value: unknown): value is PriceBookKind {\n return PRICE_BOOK_KINDS.includes(value as PriceBookKind);\n}\n\n/** ISO 4217-shaped (three upper-case letters) currency code check. */\nexport function isCurrencyCode(value: unknown): value is string {\n return typeof value === 'string' && CURRENCY_PATTERN.test(value);\n}\n\n/**\n * A named set of prices published by one seller tenant. Its prices are\n * ordinary {@link PricingRule} rows that carry this book's id and the same\n * tenant; one rule per currency gives a price in several currencies.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_price_books',\n conflictColumns: ['tenant_id', 'book_key'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class PriceBook extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The seller that publishes and owns the book. */\n @tenantId() tenantId?: string;\n bookKey: string = '';\n name: string = '';\n kind: PriceBookKind = 'retail';\n active: boolean = true;\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.bookKey.trim()) {\n throw new Error('Price books require a bookKey.');\n }\n if (!isPriceBookKind(this.kind)) {\n throw new Error('Price book kind must be wholesale or retail.');\n }\n }\n}\n\n/**\n * Which price books rate one child tenant's usage, keyed like the tenancy\n * billing relationship it belongs to (one row per child). The reseller is\n * recorded so an assignment made under one relationship never prices usage\n * after the child moves to a different reseller.\n *\n * A system table managed through `ResellerBillingService`, like\n * `_smrt_billing_relationships`; it has no generated API surface.\n */\n@smrt({\n tableName: '_smrt_price_book_assignments',\n conflictColumns: ['child_tenant_id'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class PriceBookAssignment extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n @field({ required: true })\n childTenantId: string = '';\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n @field({ required: true })\n resellerTenantId: string = '';\n @foreignKey('PriceBook')\n wholesalePriceBookId: string = '';\n wholesaleCurrency: string = '';\n @foreignKey('PriceBook')\n retailPriceBookId: string = '';\n retailCurrency: string = '';\n}\n\n/**\n * What a reseller charges one child for one usage event, priced from the\n * reseller's retail book. The provider's charge for the same event is the\n * {@link ClientCharge} in `clientChargeId`, payable by the billing owner.\n *\n * `tenantId` is always the payer (the child), so tenant-scoped reads and the\n * child's `retail`-basis spending policies see exactly what it owes.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_retail_charges',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n conflictColumns: ['usage_event_id'],\n})\nexport class RetailCharge extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n resellerTenantId: string = '';\n @foreignKey('TenantUsageMetric')\n usageEventId: string = '';\n @foreignKey('ClientCharge')\n clientChargeId: string = '';\n subscriberKind: string = 'tenant';\n subscriberExternalId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n provider: string = '';\n serviceKey: string = '';\n metricKey: string = '';\n /** Metered quantity; fractional, like `ClientCharge.quantity`. */\n quantity: number = 0.0;\n /** Charge in integer minor units of {@link currency}. */\n amount: number = 0;\n currency: string = 'USD';\n @foreignKey('PriceBook')\n priceBookId: string = '';\n @foreignKey('PricingRule')\n pricingRuleId: string = '';\n pricingSnapshot: string = '{}';\n status: 'draft' | 'approved' = 'draft';\n approvedAt: Date | null = null;\n\n getPricingSnapshot(): Record<string, unknown> {\n try {\n return JSON.parse(this.pricingSnapshot) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.getCanonicalPersistedRow({ id: this.id });\n if (row?.status !== 'approved') return;\n const persisted = [\n row.tenant_id,\n row.reseller_tenant_id,\n row.usage_event_id,\n row.client_charge_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.service_key,\n row.metric_key,\n row.quantity,\n row.amount,\n row.currency,\n row.price_book_id,\n row.pricing_rule_id,\n row.pricing_snapshot,\n row.status,\n row.approved_at,\n ];\n const current = [\n this.tenantId,\n this.resellerTenantId,\n this.usageEventId,\n this.clientChargeId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.serviceKey,\n this.metricKey,\n this.quantity,\n this.amount,\n this.currency,\n this.priceBookId,\n this.pricingRuleId,\n this.pricingSnapshot,\n this.status,\n this.approvedAt,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeLedgerValue(value) !== normalizeLedgerValue(current[index]),\n )\n ) {\n throw new Error('Approved retail charges are immutable.');\n }\n }\n}\n\n/**\n * An append-only credit on a prepaid (`period: 'balance'`) spending policy.\n * Positive amounts add credit; a negative amount reverses an earlier grant.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_credit_grants',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n hooks: { beforeDelete: 'refuseDelete' },\n})\nexport class CreditGrant extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The tenant whose balance is credited (the policy's tenant). */\n @tenantId() tenantId?: string;\n @foreignKey('SpendingPolicy')\n spendingPolicyId: string = '';\n /** Signed credit in integer minor units of {@link currency}. */\n amount: number = 0;\n currency: string = 'USD';\n reason: string = '';\n source: string = '';\n sourceId: string = '';\n /** A parent tenant that granted the credit, or empty when self-granted. */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n grantedByTenantId: string = '';\n\n /** Append-only: history is corrected by a reversing grant, never removed. */\n protected refuseDelete(): void {\n throw new Error(\n 'Credit grants are append-only; record a reversing grant instead of deleting.',\n );\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!Number.isSafeInteger(this.amount) || this.amount === 0) {\n throw new Error(\n 'Credit grant amounts must be nonzero integer minor units (cents).',\n );\n }\n if (this.id) {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n throw new Error(\n 'Credit grants are append-only; record a reversing grant instead.',\n );\n }\n }\n const policy = this.spendingPolicyId\n ? ((await this.db.get('_smrt_spending_policies', {\n id: this.spendingPolicyId,\n })) as Record<string, unknown> | null)\n : null;\n if (\n policy?.period !== 'balance' ||\n tenantKey(policy.tenant_id as string) !== tenantKey(this.tenantId) ||\n policy.currency !== this.currency\n ) {\n throw new Error(\n 'Credit grants must credit a balance policy of the same tenant and currency.',\n );\n }\n // A parent's delegated balance is funded only by that parent.\n const setBy = tenantKey(policy.set_by_tenant_id as string);\n if (!setBy) return;\n if (tenantKey(this.grantedByTenantId) !== setBy) {\n throw new TenantIsolationError(\n 'Delegated balance credit must be granted by the parent that set it.',\n );\n }\n if (\n !isSystemContext() &&\n !isSuperAdminBypass() &&\n tenantKey(getTenantId()) !== setBy\n ) {\n throw new TenantIsolationError(\n 'Only the parent that set a delegated policy can grant it credit.',\n );\n }\n }\n}\n\nexport class PriceBookCollection extends SmrtCollection<PriceBook> {\n static readonly _itemClass = PriceBook;\n}\nexport class PriceBookAssignmentCollection extends SmrtCollection<PriceBookAssignment> {\n static readonly _itemClass = PriceBookAssignment;\n}\nexport class RetailChargeCollection extends SmrtCollection<RetailCharge> {\n static readonly _itemClass = RetailCharge;\n}\nexport class CreditGrantCollection extends SmrtCollection<CreditGrant> {\n static readonly _itemClass = CreditGrant;\n}\n\nfunction normalizeLedgerValue(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value)) {\n const timestamp = Date.parse(value);\n if (Number.isFinite(timestamp)) return new Date(timestamp).toISOString();\n }\n if (typeof value === 'boolean') return value ? '1' : '0';\n return String(value ?? '');\n}\n","/**\n * Declared recipes for smrt-subscriptions (#4409): user-facing units of\n * functionality an app or agent can pick instead of the whole package.\n * The scanner reads these statics into the `recipes` array of `manifest.json`\n * and `smrt-knowledge.json`; nothing here runs at that point.\n *\n * @packageDocumentation\n */\n\nimport { SmrtRecipe } from '@happyvertical/smrt-core';\nimport { ClientCharge } from './models/commercial.js';\nimport { SubscriptionPlan } from './models/SubscriptionPlan.js';\nimport { SubscriptionPlanVersion } from './models/SubscriptionPlanVersion.js';\nimport { TenantSubscription } from './models/TenantSubscription.js';\n\n/**\n * Subscriptions: the plans you sell, who is subscribed to which, the terms\n * each paid period is held to, and what usage was charged. Reseller pricing\n * (price books, pricing rules, credits) stays out: it is a wholesale concern,\n * not something a person opens day to day.\n */\nexport class SubscriptionPlansRecipe extends SmrtRecipe {\n static id = 'subscriptions.plans';\n static help = './plans.recipe.md';\n static label = 'Subscriptions';\n static summary =\n 'Sell plans that renew, see who is subscribed to which, and what their usage cost.';\n static synonyms = [\n 'subscriptions',\n 'subscription plans',\n 'plans',\n 'memberships',\n 'recurring billing',\n 'pricing tiers',\n ];\n static section = {\n id: 'sales',\n label: 'Sales',\n icon: 'shoppingBag',\n description: 'Customers, orders and quotes: everything you sell.',\n };\n static models = [\n SubscriptionPlan,\n SubscriptionPlanVersion,\n TenantSubscription,\n ClientCharge,\n ];\n static nav = [\n {\n label: 'Plans',\n model: SubscriptionPlan,\n icon: 'tag',\n description:\n 'The plans you sell, with their price and how often they bill.',\n noun: 'plan',\n },\n {\n label: 'Subscriptions',\n model: TenantSubscription,\n icon: 'repeat',\n description:\n 'Who is subscribed to which plan, and where each one stands.',\n noun: 'subscription',\n },\n {\n label: 'Plan versions',\n model: SubscriptionPlanVersion,\n icon: 'fileText',\n description:\n 'Every set of terms a plan has had, and from when each applied.',\n noun: 'plan version',\n },\n {\n label: 'Charges',\n model: ClientCharge,\n icon: 'receipt',\n description: 'What each subscriber used and what it cost them.',\n noun: 'charge',\n },\n ];\n static options = {\n SubscriptionPlan: {\n fields: {\n name: { order: 1 },\n planKey: { label: 'Plan code', order: 2 },\n description: { order: 3 },\n status: { order: 4 },\n priceAmount: { label: 'Price (in cents)', order: 5 },\n currency: { order: 6 },\n billingInterval: { label: 'Billed every', order: 7 },\n pricingMode: { label: 'How it is priced', order: 8 },\n minimumAmount: {\n label: 'Minimum (in cents)',\n visibility: 'advanced',\n },\n suggestedAmount: {\n label: 'Suggested (in cents)',\n visibility: 'advanced',\n },\n sortOrder: { label: 'Position in list', visibility: 'advanced' },\n tenantId: { visibility: 'hidden' },\n features: { visibility: 'hidden' },\n thresholds: { visibility: 'hidden' },\n externalProvider: { visibility: 'hidden' },\n providerProductId: { visibility: 'hidden' },\n providerPriceId: { visibility: 'hidden' },\n stripeProductId: { visibility: 'hidden' },\n stripePriceId: { visibility: 'hidden' },\n metadata: { visibility: 'hidden' },\n },\n },\n SubscriptionPlanVersion: {\n fields: {\n planId: { label: 'Plan', order: 1 },\n version: { label: 'Version number', order: 2 },\n effectiveFrom: { label: 'In force from', order: 3 },\n name: { order: 4 },\n status: { order: 5 },\n priceAmount: { label: 'Price (in cents)', order: 6 },\n currency: { order: 7 },\n billingInterval: { label: 'Billed every', order: 8 },\n planKey: { label: 'Plan code', visibility: 'advanced' },\n pricingMode: { label: 'How it is priced', visibility: 'advanced' },\n minimumAmount: {\n label: 'Minimum (in cents)',\n visibility: 'advanced',\n },\n suggestedAmount: {\n label: 'Suggested (in cents)',\n visibility: 'advanced',\n },\n tenantId: { visibility: 'hidden' },\n features: { visibility: 'hidden' },\n thresholds: { visibility: 'hidden' },\n },\n },\n TenantSubscription: {\n fields: {\n planId: { label: 'Plan', order: 1 },\n status: { order: 2 },\n startedAt: { label: 'Started on', order: 3 },\n currentPeriodStart: { label: 'Current period starts', order: 4 },\n currentPeriodEnd: { label: 'Current period ends', order: 5 },\n trialEndsAt: { label: 'Trial ends', order: 6 },\n cancelAtPeriodEnd: { label: 'Cancel at end of period', order: 7 },\n canceledAt: { label: 'Cancelled on', visibility: 'advanced' },\n agreedAmount: {\n label: 'Agreed amount (in cents)',\n visibility: 'advanced',\n },\n subscriberKind: { label: 'Subscriber type', visibility: 'advanced' },\n subscriberExternalId: {\n label: 'Outside subscriber',\n visibility: 'advanced',\n },\n planVersionId: {\n label: 'Plan version',\n visibility: 'advanced',\n locked: true,\n },\n tenantId: { visibility: 'hidden' },\n planVersionPinnedAt: { visibility: 'hidden' },\n planVersionPinReason: { visibility: 'hidden' },\n planVersionPinNote: { visibility: 'hidden' },\n retainsPaidPeriod: { visibility: 'hidden' },\n externalProvider: { visibility: 'hidden' },\n stripeCustomerId: { visibility: 'hidden' },\n stripeSubscriptionId: { visibility: 'hidden' },\n stripeCheckoutSessionId: { visibility: 'hidden' },\n metadata: { visibility: 'hidden' },\n },\n },\n ClientCharge: {\n fields: {\n metricKey: { label: 'What was used', order: 1 },\n quantity: { label: 'How much', order: 2 },\n amount: { label: 'Amount (in cents)', order: 3 },\n currency: { order: 4 },\n status: { order: 5 },\n approvedAt: { label: 'Approved on', order: 6 },\n serviceKey: { label: 'Service', visibility: 'advanced' },\n provider: { visibility: 'advanced' },\n tenantId: { visibility: 'hidden' },\n usageEventId: { visibility: 'hidden' },\n usageTenantId: { visibility: 'hidden' },\n subscriberKind: { visibility: 'hidden' },\n subscriberExternalId: { visibility: 'hidden' },\n projectId: { visibility: 'hidden' },\n workRefType: { visibility: 'hidden' },\n workRefId: { visibility: 'hidden' },\n pricingRuleId: { visibility: 'hidden' },\n priceBookId: { visibility: 'hidden' },\n pricingSnapshot: { visibility: 'hidden' },\n },\n },\n } as const;\n}\n","export type ResellerBillingErrorCode =\n | 'INVALID_TENANT'\n | 'INVALID_CURRENCY'\n | 'INVALID_AMOUNT'\n | 'PRICE_BOOK_NOT_FOUND'\n | 'PRICE_BOOK_INACTIVE'\n | 'PRICE_BOOK_KIND_MISMATCH'\n | 'PRICE_BOOK_OWNER_MISMATCH'\n | 'PRICE_BOOK_NOT_ASSIGNED'\n | 'NO_EFFECTIVE_PRICE'\n | 'RELATIONSHIP_REQUIRED'\n | 'POLICY_NOT_FOUND'\n | 'POLICY_NOT_BALANCE'\n | 'POLICY_CONFLICT'\n | 'ASSIGNMENT_CONFLICT';\n\n/** A reseller price book, rating, or delegated-spending rule was violated. */\nexport class ResellerBillingError extends Error {\n constructor(\n message: string,\n public readonly code: ResellerBillingErrorCode,\n ) {\n super(message);\n this.name = 'ResellerBillingError';\n }\n}\n","import {\n type DatabaseConfig,\n isDatabaseInterface,\n isEmbeddedDatabase,\n type SmrtClassOptions,\n withEmbeddedWriteTransaction,\n} from '@happyvertical/smrt-core';\nimport {\n type BillingRelationshipService,\n type BillingRelationshipView,\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport type { SqlAdapterType } from '@happyvertical/sql';\nimport { TenantUsageMetricCollection } from '../collections/TenantUsageMetricCollection.js';\nimport {\n BillingAdjustmentCollection,\n type ClientCharge,\n ClientChargeCollection,\n type PricingRule,\n PricingRuleCollection,\n type PricingStrategy,\n type SpendingBasis,\n type SpendingPolicy,\n SpendingPolicyCollection,\n} from '../models/commercial.js';\nimport {\n type CreditGrant,\n CreditGrantCollection,\n type PriceBook,\n PriceBookAssignmentCollection,\n PriceBookCollection,\n type PriceBookKind,\n type RetailCharge,\n RetailChargeCollection,\n} from '../models/reseller.js';\nimport type { TenantUsageMetric } from '../models/TenantUsageMetric.js';\nimport type { RecordUsageOptions, SubscriberKind } from '../types.js';\nimport {\n deterministicUuid,\n normalizeSubscriber,\n subscriberToColumns,\n tenantKey,\n} from '../utils.js';\nimport { ResellerBillingError } from './reseller-errors.js';\n\nexport interface PriceUsageOptions {\n usageEventId: string;\n approved?: boolean;\n at?: Date;\n}\n\n/** The released smrt-tenancy billing-owner read this package depends on. */\nexport type BillingRelationshipReader = Pick<\n BillingRelationshipService,\n 'getRelationship'\n>;\n\nexport interface RateUsageOptions extends PriceUsageOptions {\n /** Resolves the usage tenant's reseller relationship and billing owner. */\n billingRelationships: BillingRelationshipReader;\n}\n\n/**\n * The outcome of rating one usage event (#3059). A usage event is rated\n * exactly once: the first rating fixes the payer and price books, and later\n * calls return the same records even if the billing owner has since changed.\n */\nexport interface UsageRating {\n /** The tenant that produced the usage. */\n usageTenantId: string;\n /** Who pays the provider: the usage tenant, or its reseller. */\n billingOwnerTenantId: string;\n /** `direct` for self-billed usage, `wholesale` for reseller-billed usage. */\n mode: 'direct' | 'wholesale';\n /** The provider's charge, payable by {@link billingOwnerTenantId}. */\n charge: ClientCharge;\n /** The reseller's retail charge to the child, when a retail book applies. */\n retailCharge: RetailCharge | null;\n}\nexport interface CustomPricingContext {\n usage: { quantity: number; dimensions: Record<string, unknown> };\n rule: PricingRule;\n terms: Record<string, unknown>;\n}\nexport type CustomPricingStrategy = (\n context: CustomPricingContext,\n) => number | Promise<number>;\n\nexport interface CommercialBillingStorage {\n adapterType: SqlAdapterType;\n writeStrategy?: 'immediate' | 'manual' | 'none';\n}\n\nexport interface CommercialUsageServiceOptions extends SmrtClassOptions {\n /**\n * Required when `db` is an already-resolved database handle, whose public\n * interface does not expose its adapter/write-back configuration.\n */\n billingStorage?: CommercialBillingStorage;\n}\n\nconst embeddedAdjustmentLocks = new Map<string | object, Promise<void>>();\n\nasync function withEmbeddedSourcedAdjustmentLock<T>(\n db: { url?: string },\n storage: CommercialBillingStorage,\n sourced: boolean,\n operation: () => Promise<T>,\n): Promise<T> {\n if (!sourced || storage.adapterType === 'postgres') return operation();\n\n const key = db.url ? `${storage.adapterType}:${db.url}` : (db as object);\n const previous = embeddedAdjustmentLocks.get(key) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const queued = previous.then(() => current);\n embeddedAdjustmentLocks.set(key, queued);\n await previous;\n try {\n return await operation();\n } finally {\n release();\n if (embeddedAdjustmentLocks.get(key) === queued) {\n embeddedAdjustmentLocks.delete(key);\n }\n }\n}\n\nexport class UnsupportedCommercialBillingStorageError extends Error {\n readonly code = 'UNSUPPORTED_COMMERCIAL_BILLING_STORAGE';\n\n constructor(storage: CommercialBillingStorage) {\n super(\n `Commercial billing does not support ${storage.adapterType} ` +\n `with immediate JSON write-back because exported files are not ` +\n `transactionally rolled back. Use PostgreSQL, SQLite, ordinary ` +\n `DuckDB, or a non-immediate write strategy.`,\n );\n this.name = 'UnsupportedCommercialBillingStorageError';\n }\n}\n\nexport class CommercialBillingStorageConfigurationError extends Error {\n readonly code = 'COMMERCIAL_BILLING_STORAGE_CONFIGURATION_REQUIRED';\n\n constructor(message?: string) {\n super(\n message ??\n 'Commercial billing requires billingStorage when db is an already-resolved handle because adapter write-back capabilities are not public on that interface.',\n );\n this.name = 'CommercialBillingStorageConfigurationError';\n }\n}\n\nfunction assertValidCommercialBillingWriteStrategy(\n writeStrategy: unknown,\n): asserts writeStrategy is CommercialBillingStorage['writeStrategy'] {\n if (\n writeStrategy !== undefined &&\n writeStrategy !== 'immediate' &&\n writeStrategy !== 'manual' &&\n writeStrategy !== 'none'\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing database writeStrategy must be immediate, manual, or none.',\n );\n }\n}\n\nfunction snapshotCommercialBillingStorage(\n storage: CommercialBillingStorage,\n): CommercialBillingStorage {\n const adapterType: unknown = storage.adapterType;\n if (\n adapterType !== 'sqlite' &&\n adapterType !== 'postgres' &&\n adapterType !== 'duckdb' &&\n adapterType !== 'json'\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing storage adapterType must be sqlite, postgres, duckdb, or json.',\n );\n }\n const writeStrategy: unknown = storage.writeStrategy;\n assertValidCommercialBillingWriteStrategy(writeStrategy);\n return { adapterType, writeStrategy };\n}\n\nfunction snapshotCommercialUsageServiceOptions(\n options: CommercialUsageServiceOptions,\n): CommercialUsageServiceOptions {\n const snapshot = { ...options };\n if (snapshot.billingStorage) {\n snapshot.billingStorage = snapshotCommercialBillingStorage(\n snapshot.billingStorage,\n );\n }\n for (const key of ['db', 'persistence'] as const) {\n const database = snapshot[key];\n if (\n database &&\n typeof database !== 'string' &&\n !isDatabaseInterface(database)\n ) {\n snapshot[key] = { ...database };\n }\n }\n return snapshot;\n}\n\nexport function assertCommercialBillingStorageSupported(\n storage: CommercialBillingStorage,\n): void {\n const snapshot = snapshotCommercialBillingStorage(storage);\n const writeStrategy =\n snapshot.adapterType === 'json'\n ? (snapshot.writeStrategy ?? 'immediate')\n : snapshot.writeStrategy;\n if (\n (snapshot.adapterType === 'json' || snapshot.adapterType === 'duckdb') &&\n writeStrategy === 'immediate'\n ) {\n throw new UnsupportedCommercialBillingStorageError({\n ...snapshot,\n writeStrategy,\n });\n }\n}\n\nfunction inferAdapterType(url: string): SqlAdapterType | undefined {\n if (/^postgres(?:ql)?:/iu.test(url)) return 'postgres';\n if (/^(?:https?|libsql):\\/\\//iu.test(url)) return 'sqlite';\n if (/\\.duckdb(?:$|\\?)/iu.test(url)) return 'duckdb';\n if (url === ':memory:' || url.startsWith('file:')) return 'sqlite';\n return undefined;\n}\n\nfunction environmentAdapterType(): SqlAdapterType | undefined {\n const type = process.env.HAVE_SQL_TYPE;\n if (type === undefined || type === '') return undefined;\n if (\n type === 'sqlite' ||\n type === 'postgres' ||\n type === 'duckdb' ||\n type === 'json'\n ) {\n return type;\n }\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing HAVE_SQL_TYPE must be sqlite, postgres, duckdb, or json.',\n );\n}\n\nfunction environmentWriteStrategy(): CommercialBillingStorage['writeStrategy'] {\n const strategy = process.env.HAVE_SQL_WRITE_STRATEGY;\n if (strategy === undefined || strategy === '') return undefined;\n if (\n strategy === 'immediate' ||\n strategy === 'manual' ||\n strategy === 'none'\n ) {\n return strategy;\n }\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing HAVE_SQL_WRITE_STRATEGY must be immediate, manual, or none.',\n );\n}\n\nfunction billingStorageFromConfig(\n config: DatabaseConfig | undefined,\n declared?: CommercialBillingStorage,\n): CommercialBillingStorage {\n // Validate a configured environment value even when an explicit config type\n // wins adapter precedence. Otherwise normalization below could hide an SDK\n // configuration error by replacing the invalid environment value.\n const environmentType = environmentAdapterType();\n if (config === undefined) {\n if (environmentType)\n return {\n adapterType: environmentType,\n writeStrategy: environmentWriteStrategy(),\n };\n return { adapterType: 'sqlite' };\n }\n if (isDatabaseInterface(config)) {\n throw new CommercialBillingStorageConfigurationError();\n }\n if (typeof config === 'string') {\n const adapterType =\n environmentType ?? inferAdapterType(config) ?? declared?.adapterType;\n if (adapterType)\n return {\n adapterType,\n writeStrategy: environmentWriteStrategy() ?? declared?.writeStrategy,\n };\n throw new Error(\n 'Commercial billing requires an explicit billingStorage adapter contract for ambiguous database URLs.',\n );\n }\n const adapterType =\n config.type ??\n environmentType ??\n inferAdapterType(String(config.url ?? '')) ??\n declared?.adapterType;\n if (!adapterType) {\n throw new Error(\n 'Commercial billing requires an explicit database type or billingStorage adapter contract.',\n );\n }\n const configuredWriteStrategy = config.writeStrategy;\n assertValidCommercialBillingWriteStrategy(configuredWriteStrategy);\n const writeStrategy =\n configuredWriteStrategy === 'immediate' ||\n configuredWriteStrategy === 'manual' ||\n configuredWriteStrategy === 'none'\n ? configuredWriteStrategy\n : (environmentWriteStrategy() ?? declared?.writeStrategy);\n return { adapterType, writeStrategy };\n}\n\nfunction effectiveWriteStrategy(\n storage: CommercialBillingStorage,\n): CommercialBillingStorage['writeStrategy'] {\n if (storage.writeStrategy) return storage.writeStrategy;\n if (storage.adapterType === 'json') return 'immediate';\n if (storage.adapterType === 'duckdb') return 'none';\n return undefined;\n}\n\nfunction resolveCommercialBillingStorage(\n options: CommercialUsageServiceOptions,\n): CommercialBillingStorage {\n // Environment declarations are configuration contracts, even when explicit\n // options win precedence. Reject invalid nonempty values before setup.\n environmentAdapterType();\n environmentWriteStrategy();\n const configuredDatabase = options.db ?? options.persistence;\n if (isDatabaseInterface(configuredDatabase)) {\n if (!options.billingStorage) {\n throw new CommercialBillingStorageConfigurationError();\n }\n return options.billingStorage;\n }\n const configured = billingStorageFromConfig(\n configuredDatabase,\n options.billingStorage,\n );\n if (\n options.billingStorage &&\n (options.billingStorage.adapterType !== configured.adapterType ||\n effectiveWriteStrategy(options.billingStorage) !==\n effectiveWriteStrategy(configured))\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billingStorage must match the configured database adapter and write strategy.',\n );\n }\n return configured;\n}\n\nfunction normalizedCommercialClassOptions(\n options: CommercialUsageServiceOptions,\n billingStorage: CommercialBillingStorage,\n): SmrtClassOptions {\n const { billingStorage: _billingStorage, ...classOptions } = options;\n const configuredDatabase = options.db ?? options.persistence;\n if (configuredDatabase && !isDatabaseInterface(configuredDatabase)) {\n const normalizedDatabase =\n typeof configuredDatabase === 'string'\n ? {\n type: billingStorage.adapterType,\n url: configuredDatabase,\n writeStrategy: billingStorage.writeStrategy,\n }\n : {\n ...configuredDatabase,\n type: billingStorage.adapterType,\n writeStrategy: billingStorage.writeStrategy,\n };\n if (options.db !== undefined) classOptions.db = normalizedDatabase;\n else classOptions.persistence = normalizedDatabase;\n }\n return classOptions;\n}\n\ninterface ResellerCollections {\n books: PriceBookCollection;\n assignments: PriceBookAssignmentCollection;\n retailCharges: RetailChargeCollection;\n}\n\nexport class CommercialUsageService {\n private readonly customStrategies = new Map<string, CustomPricingStrategy>();\n private resellerCollections?: Promise<ResellerCollections>;\n constructor(\n private readonly usage: TenantUsageMetricCollection,\n private readonly rules: PricingRuleCollection,\n private readonly charges: ClientChargeCollection,\n private readonly adjustments: BillingAdjustmentCollection,\n private readonly billingStorage: CommercialBillingStorage,\n ) {\n if (!billingStorage) {\n throw new CommercialBillingStorageConfigurationError();\n }\n assertCommercialBillingStorageSupported(billingStorage);\n }\n\n static async create(\n options: CommercialUsageServiceOptions = {},\n ): Promise<CommercialUsageService> {\n const optionSnapshot = snapshotCommercialUsageServiceOptions(options);\n const billingStorage = resolveCommercialBillingStorage(optionSnapshot);\n assertCommercialBillingStorageSupported(billingStorage);\n const classOptions = normalizedCommercialClassOptions(\n optionSnapshot,\n billingStorage,\n );\n const usage = await TenantUsageMetricCollection.create(classOptions);\n const sharedOptions = { ...classOptions, db: usage.db };\n return new CommercialUsageService(\n usage,\n await PricingRuleCollection.create(sharedOptions),\n await ClientChargeCollection.create(sharedOptions),\n await BillingAdjustmentCollection.create(sharedOptions),\n billingStorage,\n );\n }\n\n registerCustomStrategy(key: string, strategy: CustomPricingStrategy): void {\n this.customStrategies.set(key, strategy);\n }\n\n async record(options: RecordUsageOptions) {\n return this.usage.recordUsage(options);\n }\n\n async price(options: PriceUsageOptions): Promise<ClientCharge> {\n const existing = await this.charges.list({\n where: { usageEventId: options.usageEventId },\n limit: 1,\n });\n if (existing[0]) {\n return this.approveCharge(existing[0], options.approved);\n }\n const usage = await this.usage.get(options.usageEventId);\n if (!usage)\n throw new Error(`Usage event ${options.usageEventId} was not found.`);\n const at = options.at ?? usage.windowStart;\n const dimensions = usage.getDimensions();\n const rules = await this.rules.list({\n where: {\n tenantId: usage.tenantId,\n metricKey: usage.metricKey,\n active: true,\n },\n });\n // Price-book rules are published by a seller for rateUsage(); they are\n // never a tenant's own direct pricing.\n const rule = selectRule(\n rules.filter((candidate) => !candidate.priceBookId),\n at,\n String(dimensions.serviceKey ?? ''),\n );\n if (!rule)\n throw new Error(\n `No effective pricing rule for metric '${usage.metricKey}'.`,\n );\n if (!usage.id)\n throw new Error(\n `Usage event ${options.usageEventId} has no persisted id.`,\n );\n if (!rule.id)\n throw new Error(`Pricing rule '${rule.ruleKey}' has no persisted id.`);\n const amount = await this.calculateAmount(rule, usage.quantity, dimensions);\n const chargeId = await deterministicUuid([\n 'client-charge',\n String(usage.tenantId),\n String(usage.id),\n ]);\n try {\n return await this.charges.create({\n id: chargeId,\n tenantId: usage.tenantId,\n usageEventId: String(usage.id),\n usageTenantId: usage.tenantId,\n subscriberKind: usage.subscriberKind,\n subscriberExternalId: usage.subscriberExternalId,\n projectId: usage.projectId,\n workRefType: usage.workRefType,\n workRefId: usage.workRefId,\n provider: usage.provider,\n serviceKey: String(dimensions.serviceKey ?? ''),\n metricKey: usage.metricKey,\n quantity: usage.quantity,\n amount,\n currency: rule.currency,\n pricingRuleId: String(rule.id),\n pricingSnapshot: JSON.stringify({\n ruleKey: rule.ruleKey,\n strategy: rule.strategy,\n terms: rule.getTerms(),\n effectiveFrom: rule.effectiveFrom,\n }),\n status: options.approved ? 'approved' : 'draft',\n approvedAt: options.approved ? new Date() : null,\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent = await this.charges.get(chargeId);\n if (!concurrent) throw error;\n return this.approveCharge(concurrent, options.approved);\n }\n }\n\n /**\n * Rate one usage event under its billing owner's price books (#3059).\n *\n * - No reseller relationship, or a `self`-billed one: the usage tenant pays\n * the provider directly, priced exactly as {@link price} prices it.\n * - `reseller`-billed: the reseller pays the provider from the child's\n * assigned wholesale book (a {@link ClientCharge} with `tenantId` = the\n * reseller and `usageTenantId` = the child) and, when the child has a\n * retail book assigned, the child owes the reseller a\n * {@link RetailCharge}. Both records commit in one transaction.\n *\n * Rating is idempotent per usage event and frozen at first rating: a later\n * billing-owner change never re-prices or double-charges an event that\n * already has a provider charge, because `ClientCharge` holds exactly one\n * row per usage event.\n *\n * Rating reads the seller's books across tenants; run it where the host's\n * tenancy rules allow that (typically a system context).\n */\n async rateUsage(options: RateUsageOptions): Promise<UsageRating> {\n const { retailCharges } = await this.getResellerCollections();\n const existing = await this.charges.list({\n where: { usageEventId: options.usageEventId },\n limit: 1,\n });\n if (existing[0]) {\n return this.frozenRating(existing[0], retailCharges, options.approved);\n }\n const usage = await this.usage.get(options.usageEventId);\n if (!usage)\n throw new Error(`Usage event ${options.usageEventId} was not found.`);\n if (!usage.id || !usage.tenantId)\n throw new Error(\n `Usage event ${options.usageEventId} has no persisted tenant id.`,\n );\n const relationship = await options.billingRelationships.getRelationship(\n usage.tenantId,\n );\n if (relationship?.billingOwnerMode !== 'reseller') {\n const charge = await this.price(options);\n return this.frozenRating(charge, retailCharges, options.approved);\n }\n let failure: unknown;\n try {\n await this.rateResellerBilled(usage, relationship, options);\n } catch (error) {\n failure = error;\n }\n // Return root-bound records (never the committed transaction's handles).\n // After a failure, a concurrent rating of the same event may have won the\n // one-row-per-event insert; its transaction wrote the complete rating.\n const rated = await this.charges.list({\n where: { usageEventId: String(usage.id) },\n limit: 1,\n });\n if (!rated[0]) throw failure ?? new Error('Rating was not persisted.');\n return this.frozenRating(rated[0], retailCharges, options.approved);\n }\n\n private async rateResellerBilled(\n usage: TenantUsageMetric,\n relationship: BillingRelationshipView,\n options: RateUsageOptions,\n ): Promise<UsageRating> {\n const { books, assignments } = await this.getResellerCollections();\n const childTenantId = relationship.childTenantId;\n const resellerTenantId = relationship.resellerTenantId;\n const assignment = await assignments.get({ childTenantId });\n if (\n !assignment?.wholesalePriceBookId ||\n tenantKey(assignment.resellerTenantId) !== resellerTenantId\n ) {\n throw new ResellerBillingError(\n `No wholesale price book is assigned to tenant ${childTenantId} under reseller ${resellerTenantId}.`,\n 'PRICE_BOOK_NOT_ASSIGNED',\n );\n }\n const at = options.at ?? usage.windowStart;\n const dimensions = usage.getDimensions();\n const serviceKey = String(dimensions.serviceKey ?? '');\n const wholesaleBook = await loadBook(\n books,\n assignment.wholesalePriceBookId,\n 'wholesale',\n );\n assertWholesalePublisher(wholesaleBook, resellerTenantId, childTenantId);\n const wholesaleRule = await this.selectBookRule(\n wholesaleBook,\n usage.metricKey,\n serviceKey,\n assignment.wholesaleCurrency,\n at,\n );\n let retail: { book: PriceBook; rule: PricingRule } | null = null;\n if (assignment.retailPriceBookId) {\n const retailBook = await loadBook(\n books,\n assignment.retailPriceBookId,\n 'retail',\n );\n if (tenantKey(retailBook.tenantId) !== resellerTenantId) {\n throw new ResellerBillingError(\n `Retail price book '${retailBook.bookKey}' is not published by reseller ${resellerTenantId}.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n retail = {\n book: retailBook,\n rule: await this.selectBookRule(\n retailBook,\n usage.metricKey,\n serviceKey,\n assignment.retailCurrency,\n at,\n ),\n };\n }\n const wholesaleAmount = await this.calculateAmount(\n wholesaleRule,\n usage.quantity,\n dimensions,\n );\n const retailAmount = retail\n ? await this.calculateAmount(retail.rule, usage.quantity, dimensions)\n : 0;\n const usageEventId = String(usage.id);\n const chargeId = await deterministicUuid([\n 'client-charge',\n String(usage.tenantId),\n usageEventId,\n ]);\n const retailChargeId = await deterministicUuid([\n 'retail-charge',\n String(usage.tenantId),\n usageEventId,\n ]);\n const approvedAt = options.approved ? new Date() : null;\n const status = options.approved ? 'approved' : 'draft';\n const usageColumns = {\n usageEventId,\n subscriberKind: usage.subscriberKind,\n subscriberExternalId: usage.subscriberExternalId,\n projectId: usage.projectId,\n workRefType: usage.workRefType,\n workRefId: usage.workRefId,\n provider: usage.provider,\n serviceKey,\n metricKey: usage.metricKey,\n quantity: usage.quantity,\n };\n const snapshot = (book: PriceBook, rule: PricingRule) =>\n JSON.stringify({\n ruleKey: rule.ruleKey,\n strategy: rule.strategy,\n terms: rule.getTerms(),\n effectiveFrom: rule.effectiveFrom,\n priceBookKey: book.bookKey,\n priceBookKind: book.kind,\n usageTenantId: childTenantId,\n billingOwnerTenantId: resellerTenantId,\n });\n const db = this.charges.db;\n return withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const charges = await ClientChargeCollection.create({\n db: transaction,\n });\n const retailCharges = await RetailChargeCollection.create({\n db: transaction,\n });\n const charge = await charges.create({\n id: chargeId,\n tenantId: resellerTenantId,\n usageTenantId: childTenantId,\n ...usageColumns,\n amount: wholesaleAmount,\n currency: wholesaleRule.currency,\n pricingRuleId: String(wholesaleRule.id),\n priceBookId: String(wholesaleBook.id),\n pricingSnapshot: snapshot(wholesaleBook, wholesaleRule),\n status,\n approvedAt,\n _insertOnly: true,\n });\n const retailCharge = retail\n ? await retailCharges.create({\n id: retailChargeId,\n tenantId: childTenantId,\n resellerTenantId,\n clientChargeId: chargeId,\n ...usageColumns,\n amount: retailAmount,\n currency: retail.rule.currency,\n priceBookId: String(retail.book.id),\n pricingRuleId: String(retail.rule.id),\n pricingSnapshot: snapshot(retail.book, retail.rule),\n status,\n approvedAt,\n _insertOnly: true,\n })\n : null;\n return {\n usageTenantId: childTenantId,\n billingOwnerTenantId: resellerTenantId,\n mode: 'wholesale' as const,\n charge,\n retailCharge,\n };\n },\n );\n }\n\n private async selectBookRule(\n book: PriceBook,\n metricKey: string,\n serviceKey: string,\n currency: string,\n at: Date,\n ): Promise<PricingRule> {\n const rules = await this.rules.list({\n where: {\n tenantId: book.tenantId,\n priceBookId: book.id,\n metricKey,\n currency,\n active: true,\n },\n });\n const rule = selectRule(\n // The owner check keeps a rule filed under someone else's book (the\n // rules API is tenant-writable) from pricing that book.\n rules.filter(\n (candidate) =>\n candidate.priceBookId === book.id &&\n candidate.tenantId === book.tenantId &&\n candidate.currency === currency,\n ),\n at,\n serviceKey,\n );\n if (!rule?.id) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' has no effective ${currency} price for metric '${metricKey}'.`,\n 'NO_EFFECTIVE_PRICE',\n );\n }\n return rule;\n }\n\n private async frozenRating(\n charge: ClientCharge,\n retailCharges: RetailChargeCollection,\n approved = false,\n ): Promise<UsageRating> {\n const retail = await retailCharges.list({\n where: { usageEventId: charge.usageEventId },\n limit: 1,\n });\n let providerCharge = charge;\n let retailCharge: RetailCharge | null = retail[0] ?? null;\n if (\n approved &&\n (providerCharge.status === 'draft' || retailCharge?.status === 'draft')\n ) {\n // Approve both legs in one transaction so they never disagree.\n const db = this.charges.db;\n [providerCharge, retailCharge] = await withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const charges = await ClientChargeCollection.create({\n db: transaction,\n });\n const retails = await RetailChargeCollection.create({\n db: transaction,\n });\n const provider = await charges.get(String(charge.id));\n if (!provider) {\n throw new Error(`Client charge ${charge.id} was not found.`);\n }\n const leg = retailCharge\n ? await retails.get(String(retailCharge.id))\n : null;\n const approvedAt = new Date();\n if (provider.status === 'draft') {\n provider.status = 'approved';\n provider.approvedAt = approvedAt;\n await provider.save();\n }\n if (leg?.status === 'draft') {\n leg.status = 'approved';\n leg.approvedAt = approvedAt;\n await leg.save();\n }\n return [provider, leg ?? null] as const;\n },\n );\n // Hand back root-bound records, not the committed transaction's.\n providerCharge = (await this.charges.get(String(charge.id))) ?? charge;\n retailCharge = retailCharge?.id\n ? ((await retailCharges.get(String(retailCharge.id))) ?? null)\n : null;\n }\n return {\n usageTenantId:\n tenantKey(providerCharge.usageTenantId) ||\n tenantKey(providerCharge.tenantId),\n billingOwnerTenantId: tenantKey(providerCharge.tenantId),\n mode: providerCharge.priceBookId ? 'wholesale' : 'direct',\n charge: providerCharge,\n retailCharge,\n };\n }\n\n private getResellerCollections(): Promise<ResellerCollections> {\n this.resellerCollections ??= (async () => {\n const options = { db: this.charges.db };\n return {\n books: await PriceBookCollection.create(options),\n assignments: await PriceBookAssignmentCollection.create(options),\n retailCharges: await RetailChargeCollection.create(options),\n };\n })();\n this.resellerCollections.catch(() => {\n this.resellerCollections = undefined;\n });\n return this.resellerCollections;\n }\n\n private async approveCharge(\n charge: ClientCharge,\n approved = false,\n ): Promise<ClientCharge> {\n if (approved && charge.status === 'draft') {\n charge.status = 'approved';\n charge.approvedAt = new Date();\n await charge.save();\n }\n return charge;\n }\n\n /**\n * Append a signed correction to an approved charge.\n *\n * @param amount - Signed correction in **integer minor units**, same unit as\n * the charge (#2401). Negative is legitimate — that is a credit. A\n * fractional value is rejected rather than silently rounded, because it\n * almost always means the caller passed major units.\n */\n async adjust(\n chargeId: string,\n amount: number,\n reason: string,\n source = '',\n sourceId = '',\n ) {\n if (!Number.isInteger(amount)) {\n throw new Error(\n `Billing adjustment amount must be an integer number of minor units ` +\n `(cents) — got ${amount}. Money is exact: -$0.25 is -25, not -0.25.`,\n );\n }\n const sourced = Boolean(source && sourceId);\n return withEmbeddedSourcedAdjustmentLock(\n this.charges.db,\n this.billingStorage,\n sourced,\n () => this.adjustWithinLock(chargeId, amount, reason, source, sourceId),\n );\n }\n\n private async adjustWithinLock(\n chargeId: string,\n amount: number,\n reason: string,\n source: string,\n sourceId: string,\n ) {\n const initialCharge = await this.charges.get(chargeId);\n if (!initialCharge)\n throw new Error(`Client charge ${chargeId} was not found.`);\n if (\n initialCharge.status !== 'approved' &&\n initialCharge.status !== 'adjusted'\n ) {\n throw new Error(\n `Client charge ${chargeId} must be approved before it can be adjusted.`,\n );\n }\n const sourcedId =\n source && sourceId\n ? await deterministicUuid([\n 'billing-adjustment',\n String(initialCharge.tenantId),\n chargeId,\n source,\n sourceId,\n ])\n : null;\n const db = this.charges.db;\n if (!db.transaction) {\n throw new Error('Atomic billing adjustment requires transaction support');\n }\n try {\n return await withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const options = { db: transaction };\n const charges = await ClientChargeCollection.create(options);\n const adjustments = await BillingAdjustmentCollection.create(options);\n const charge = await charges.get(chargeId);\n if (!charge)\n throw new Error(`Client charge ${chargeId} was not found.`);\n if (charge.status !== 'approved' && charge.status !== 'adjusted') {\n throw new Error(\n `Client charge ${chargeId} must be approved before it can be adjusted.`,\n );\n }\n let adjustment = sourcedId\n ? await adjustments.get(sourcedId)\n : undefined;\n if (!adjustment) {\n adjustment = await adjustments.create({\n ...(sourcedId ? { id: sourcedId } : {}),\n tenantId: charge.tenantId,\n clientChargeId: chargeId,\n amount,\n currency: charge.currency,\n reason,\n source,\n sourceId,\n _insertOnly: Boolean(sourcedId),\n });\n }\n if (charge.status === 'approved') {\n charge.status = 'adjusted';\n await charge.save();\n }\n return adjustment;\n },\n );\n } catch (error) {\n // A concurrent sourced adjustment may win the deterministic insert. Its\n // transaction also owns the charge-state transition, so it is safe to\n // return only after both durable records are visible.\n if (sourcedId) {\n // Embedded adapters multiplex one native handle. Keep recovery reads\n // sequential just like the transaction flow protected above.\n const adjustment = await this.adjustments.get(sourcedId);\n const charge = await this.charges.get(chargeId);\n if (adjustment && charge?.status === 'adjusted') return adjustment;\n }\n throw error;\n }\n }\n\n /**\n * Price one usage event, in **integer minor units** (#2401).\n *\n * The pricing terms stay fractional on purpose — a per-token rate is\n * routinely a fraction of a cent, and an integer `unitPrice` would truncate\n * it to zero — so terms are read as *minor units per unit of usage* and only\n * the result is rounded. This is the single boundary in the package where a\n * rate meets money, which is what lets `evaluateSpending()` compare sums\n * against `SpendingPolicy.limitAmount` exactly.\n *\n * Replaces the old micro-unit rounding (`Math.round(amount * 1e6) / 1e6`),\n * which kept six sub-cent digits in a column that is now integral.\n */\n async calculateAmount(\n rule: PricingRule,\n quantity: number,\n dimensions: Record<string, unknown> = {},\n ): Promise<number> {\n const terms = rule.getTerms();\n const number = (key: string, fallback = 0) =>\n Number(terms[key] ?? fallback);\n let amount: number;\n switch (rule.strategy as PricingStrategy) {\n case 'fixed_unit':\n amount = quantity * number('unitPrice');\n break;\n case 'cost_plus':\n amount =\n Number(dimensions.providerCost ?? 0) +\n number('fixedMarkup') +\n Number(dimensions.providerCost ?? 0) * number('markupRatio');\n break;\n case 'multiplier':\n amount =\n Number(dimensions.providerCost ?? quantity) * number('multiplier', 1);\n break;\n case 'flat':\n amount = number('amount');\n break;\n case 'included_overage':\n amount =\n Math.max(0, quantity - number('includedQuantity')) *\n number('overageUnitPrice');\n break;\n case 'tiered':\n amount = priceTiers(\n quantity,\n Array.isArray(terms.tiers) ? terms.tiers : [],\n );\n break;\n case 'custom': {\n const custom = this.customStrategies.get(\n String(terms.strategyKey ?? ''),\n );\n if (!custom)\n throw new Error(\n `Custom pricing strategy '${String(terms.strategyKey ?? '')}' is not registered.`,\n );\n amount = await custom({ usage: { quantity, dimensions }, rule, terms });\n break;\n }\n }\n if (!Number.isFinite(amount) || amount < 0)\n throw new Error('Pricing produced an invalid amount.');\n return Math.round(amount);\n }\n}\n\nexport interface SpendingDecision {\n allowed: boolean;\n approvalRequired: boolean;\n state: 'ok' | 'observed' | 'warned' | 'blocked' | 'approval_required';\n /**\n * Already-spent plus estimated, in **integer minor units** — the same unit as\n * `SpendingPolicy.limitAmount` it is compared against (#2401).\n */\n projectedAmount: number;\n matchedPolicyId: string | null;\n /**\n * For a prepaid `balance` policy: credit remaining before this estimate\n * (grants minus spend), in integer minor units. Absent for other periods.\n */\n balanceAmount?: number;\n}\n\nexport interface SpendingEvaluationInput {\n tenantId: string;\n subscriberKind?: SubscriberKind;\n subscriberExternalId?: string;\n projectId?: string;\n serviceKey?: string;\n metricKey: string;\n /** Estimated cost of the pending call, in integer minor units (#2401). */\n estimatedAmount: number;\n /**\n * Per-basis estimates, in integer minor units, for policies whose basis\n * prices the call differently (a retail estimate for `retail` policies, a\n * wholesale estimate for `wholesale` ones). Falls back to\n * {@link estimatedAmount}.\n */\n estimatedAmounts?: Partial<Record<SpendingBasis, number>>;\n currency: string;\n at?: Date;\n}\n\n/** Context handed to an {@link AutoTopUpHook} when a balance would run out. */\nexport interface AutoTopUpRequest {\n policyId: string;\n tenantId: string;\n /** The parent that set the policy, or empty for the tenant's own policy. */\n setByTenantId: string;\n currency: string;\n /** Credit remaining before the estimate, in integer minor units. */\n balanceAmount: number;\n estimatedAmount: number;\n /** How far the estimate overshoots the balance, in integer minor units. */\n shortfall: number;\n /**\n * Recompute the shortfall against the credit and spend recorded now. A\n * hook that secures funds asynchronously calls it before charging: a\n * concurrent evaluation may have topped the balance up since this one read\n * it, and the evaluator re-reads the credit after the hook returns.\n */\n currentShortfall?: () => Promise<number>;\n}\n\n/**\n * A top-up the hook has secured. `sourceId` makes it idempotent: the same\n * `source`/`sourceId` pair is credited once however often it is returned.\n */\nexport interface AutoTopUpGrant {\n amount: number;\n sourceId: string;\n source?: string;\n reason?: string;\n}\n\n/**\n * Host hook for prepaid balances. Called when a pending charge would exhaust a\n * `balance` policy; return a grant to credit it (after the host has secured\n * the funds) or nothing to let the policy's behavior apply. The evaluator\n * never calls a payment provider itself, and re-reads the balance after the\n * hook returns either way, so credit granted meanwhile by another path counts.\n */\nexport type AutoTopUpHook = (\n request: AutoTopUpRequest,\n) =>\n | AutoTopUpGrant\n | null\n | undefined\n | Promise<AutoTopUpGrant | null | undefined>;\n\nexport interface SpendingPolicyEvaluatorOptions extends SmrtClassOptions {\n autoTopUp?: AutoTopUpHook;\n /**\n * The smrt-tenancy relationship reader. When supplied, a delegated policy\n * applies only while its `setByTenantId` is the tenant's current reseller;\n * without it every delegated policy applies (fail closed).\n */\n billingRelationships?: BillingRelationshipReader;\n}\n\nexport interface GrantCreditInput {\n spendingPolicyId: string;\n /** Signed, nonzero credit in integer minor units of the policy currency. */\n amount: number;\n reason?: string;\n /** With `sourceId`, makes the grant idempotent (a payment or order id). */\n source?: string;\n sourceId?: string;\n /** The parent granting credit on its child's delegated policy. */\n grantedByTenantId?: string;\n}\n\nexport interface SpendingPolicyEvaluatorExtensions {\n retailCharges?: RetailChargeCollection;\n credits?: CreditGrantCollection;\n autoTopUp?: AutoTopUpHook;\n billingRelationships?: BillingRelationshipReader;\n}\n\ninterface LedgerRow {\n id?: string | null;\n amount: number;\n status: string;\n projectId: string;\n serviceKey: string;\n metricKey: string;\n subscriberKind: string;\n subscriberExternalId: string;\n}\n\nexport class SpendingPolicyEvaluator {\n private ledgers?: Promise<{\n retailCharges: RetailChargeCollection;\n credits: CreditGrantCollection;\n }>;\n constructor(\n private readonly policies: SpendingPolicyCollection,\n private readonly charges: ClientChargeCollection,\n private readonly adjustments: BillingAdjustmentCollection,\n private readonly extensions: SpendingPolicyEvaluatorExtensions = {},\n ) {}\n static async create(options: SpendingPolicyEvaluatorOptions = {}) {\n const { autoTopUp, billingRelationships, ...classOptions } = options;\n const policies = await SpendingPolicyCollection.create(classOptions);\n const sharedOptions = { ...classOptions, db: policies.db };\n return new SpendingPolicyEvaluator(\n policies,\n await ClientChargeCollection.create(sharedOptions),\n await BillingAdjustmentCollection.create(sharedOptions),\n {\n retailCharges: await RetailChargeCollection.create(sharedOptions),\n credits: await CreditGrantCollection.create(sharedOptions),\n autoTopUp,\n billingRelationships,\n },\n );\n }\n\n async evaluate(input: SpendingEvaluationInput): Promise<SpendingDecision> {\n const at = input.at ?? new Date();\n const normalizedInput = {\n ...input,\n ...subscriberToColumns(\n normalizeSubscriber({\n tenantId: input.tenantId,\n subscriberKind: input.subscriberKind,\n subscriberExternalId: input.subscriberExternalId,\n }),\n ),\n };\n const candidates = await this.policies.list({\n where: {\n tenantId: input.tenantId,\n currency: input.currency,\n active: true,\n },\n });\n const matchingPolicies = await this.withoutStaleDelegations(\n input.tenantId,\n selectPolicies(candidates, normalizedInput),\n );\n if (matchingPolicies.length === 0)\n return {\n allowed: true,\n approvalRequired: false,\n state: 'ok',\n projectedAmount: input.estimatedAmount,\n matchedPolicyId: null,\n };\n const decisions = await Promise.all(\n matchingPolicies.map((policy) =>\n this.evaluatePolicy(policy, normalizedInput, at),\n ),\n );\n return decisions.reduce((mostRestrictive, decision) =>\n decisionRank(decision) > decisionRank(mostRestrictive)\n ? decision\n : mostRestrictive,\n );\n }\n\n /**\n * Drop delegated policies whose parent is no longer the tenant's reseller,\n * when a relationship reader is configured.\n */\n private async withoutStaleDelegations(\n tenantId: string,\n policies: SpendingPolicy[],\n ): Promise<SpendingPolicy[]> {\n const reader = this.extensions.billingRelationships;\n if (!reader || !policies.some((policy) => tenantKey(policy.setByTenantId)))\n return policies;\n const relationship = await reader.getRelationship(tenantId);\n const currentParent = tenantKey(relationship?.resellerTenantId);\n return policies.filter((policy) => {\n const setBy = tenantKey(policy.setByTenantId);\n return !setBy || setBy === currentParent;\n });\n }\n\n /**\n * Credit a prepaid `balance` policy. A delegated policy accepts grants only\n * from the parent that set it (or a system context / super-admin bypass).\n */\n async grantCredit(input: GrantCreditInput): Promise<CreditGrant> {\n const policy = await this.policies.get(input.spendingPolicyId);\n if (!policy?.id) {\n throw new ResellerBillingError(\n `Spending policy ${input.spendingPolicyId} was not found.`,\n 'POLICY_NOT_FOUND',\n );\n }\n const setBy = tenantKey(policy.setByTenantId);\n if (\n setBy &&\n !isSystemContext() &&\n !isSuperAdminBypass() &&\n getTenantId()?.toLowerCase() !== setBy\n ) {\n throw new TenantIsolationError(\n 'Only the parent that set a delegated policy can grant it credit.',\n );\n }\n if (\n input.grantedByTenantId &&\n setBy &&\n tenantKey(input.grantedByTenantId) !== setBy\n ) {\n throw new TenantIsolationError(\n 'Delegated policy credit must be granted by the parent that set it.',\n );\n }\n return this.recordGrant(policy, {\n ...input,\n grantedByTenantId: input.grantedByTenantId || setBy,\n });\n }\n\n private async recordGrant(\n policy: SpendingPolicy,\n input: GrantCreditInput,\n ): Promise<CreditGrant> {\n if (policy.period !== 'balance') {\n throw new ResellerBillingError(\n `Spending policy '${policy.name}' is not a balance policy.`,\n 'POLICY_NOT_BALANCE',\n );\n }\n if (!Number.isSafeInteger(input.amount) || input.amount === 0) {\n throw new ResellerBillingError(\n `Credit amount must be a nonzero integer number of minor units — got ${input.amount}.`,\n 'INVALID_AMOUNT',\n );\n }\n const { credits } = await this.getLedgers();\n const source = input.source ?? '';\n const sourceId = input.sourceId ?? '';\n const id =\n source && sourceId\n ? await deterministicUuid([\n 'credit-grant',\n String(policy.tenantId),\n String(policy.id),\n source,\n sourceId,\n ])\n : undefined;\n if (id) {\n const existing = await credits.get(id);\n if (existing) return existing;\n }\n try {\n return await credits.create({\n ...(id ? { id } : {}),\n tenantId: policy.tenantId,\n spendingPolicyId: String(policy.id),\n amount: input.amount,\n currency: policy.currency,\n reason: input.reason ?? '',\n source,\n sourceId,\n grantedByTenantId: input.grantedByTenantId ?? '',\n _insertOnly: Boolean(id),\n });\n } catch (error) {\n const concurrent = id ? await credits.get(id) : undefined;\n if (concurrent) return concurrent;\n throw error;\n }\n }\n\n private async evaluatePolicy(\n policy: SpendingPolicy,\n input: SpendingEvaluationInput,\n at: Date,\n ): Promise<SpendingDecision> {\n const estimatedAmount =\n input.estimatedAmounts?.[policy.basis] ?? input.estimatedAmount;\n const [start, end] = policyWindow(policy, at);\n const spent = await this.spentFor(policy, input.tenantId, start, end);\n if (policy.period !== 'balance') {\n return decide(policy, spent + estimatedAmount, policy.limitAmount);\n }\n let credit = await this.creditFor(policy);\n const projectedAmount = spent + estimatedAmount;\n const policyId = policy.id;\n if (projectedAmount > credit && this.extensions.autoTopUp && policyId) {\n const grant = await this.extensions.autoTopUp({\n policyId,\n tenantId: String(policy.tenantId),\n setByTenantId: tenantKey(policy.setByTenantId),\n currency: policy.currency,\n balanceAmount: credit - spent,\n estimatedAmount,\n shortfall: projectedAmount - credit,\n currentShortfall: async () =>\n (await this.spentFor(policy, input.tenantId, start, end)) +\n estimatedAmount -\n (await this.creditFor(policy)),\n });\n if (grant) {\n // The hook is host code configured on this evaluator; its grant is\n // recorded with the policy's own grantor even when evaluation runs in\n // the constrained child's tenant context.\n await withSystemContext(() =>\n this.recordGrant(policy, {\n spendingPolicyId: policyId,\n amount: grant.amount,\n reason: grant.reason ?? 'auto top-up',\n source: grant.source ?? 'auto_top_up',\n sourceId: grant.sourceId,\n grantedByTenantId: tenantKey(policy.setByTenantId),\n }),\n );\n }\n // Re-read either way: a concurrent top-up may have landed.\n credit = await this.creditFor(policy);\n }\n return {\n ...decide(policy, projectedAmount, credit),\n balanceAmount: credit - spent,\n };\n }\n\n /** Approved spend in the policy's window, currency, scope, and basis. */\n private async spentFor(\n policy: SpendingPolicy,\n tenantId: string,\n start: Date,\n end: Date,\n ): Promise<number> {\n const scope: Record<string, unknown> = {\n currency: policy.currency,\n 'approvedAt >=': start.toISOString(),\n 'approvedAt <': end.toISOString(),\n };\n if (policy.metricKey) scope.metricKey = policy.metricKey;\n if (policy.projectId) scope.projectId = policy.projectId;\n if (policy.serviceKey) scope.serviceKey = policy.serviceKey;\n if (policy.subscriberKind) scope.subscriberKind = policy.subscriberKind;\n if (policy.subscriberExternalId)\n scope.subscriberExternalId = policy.subscriberExternalId;\n\n const setBy = tenantKey(policy.setByTenantId);\n if (policy.basis === 'retail') {\n const { retailCharges } = await this.getLedgers();\n const where: Record<string, unknown> = {\n ...scope,\n tenantId,\n status: 'approved',\n };\n // A parent's cap counts only what the child owes that parent.\n if (setBy) where.resellerTenantId = setBy;\n const rows = await retailCharges.list({ where });\n return sumScoped(\n policy,\n rows.filter(\n (row) => !setBy || tenantKey(row.resellerTenantId) === setBy,\n ),\n ['approved'],\n );\n }\n\n if (policy.basis === 'wholesale') {\n if (!setBy) return 0;\n // Reviewed cross-tenant read: the parent's provider charges for this\n // child's usage, bounded to (payer = setBy, usageTenantId = tenant) and\n // reduced to a sum, so a child-context evaluation can enforce its\n // parent's wholesale cap without reading the parent's other rows.\n return withSystemContext(() =>\n this.sumProviderCharges(policy, scope, setBy, tenantId),\n );\n }\n return this.sumProviderCharges(policy, scope, tenantId);\n }\n\n private async sumProviderCharges(\n policy: SpendingPolicy,\n scope: Record<string, unknown>,\n payer: string,\n usageTenantId?: string,\n ): Promise<number> {\n const where: Record<string, unknown> = {\n ...scope,\n tenantId: payer,\n status: ['approved', 'adjusted'],\n };\n if (usageTenantId) where.usageTenantId = usageTenantId;\n const rows = await this.charges.list({ where });\n const scopedCharges = rows.filter(\n (charge) =>\n (!usageTenantId ||\n tenantKey(charge.usageTenantId) === tenantKey(usageTenantId)) &&\n (charge.status === 'approved' || charge.status === 'adjusted') &&\n matchesChargeScope(policy, charge),\n );\n const chargeIds = scopedCharges\n .map((charge) => charge.id)\n .filter((id): id is string => Boolean(id));\n const chargeIdSet = new Set(chargeIds);\n const adjustmentRows =\n chargeIds.length > 0\n ? await this.adjustments.list({\n where: {\n tenantId: payer,\n currency: policy.currency,\n clientChargeId: chargeIds,\n },\n })\n : [];\n const spent = scopedCharges.reduce((sum, charge) => sum + charge.amount, 0);\n return (\n spent +\n adjustmentRows\n .filter((adjustment) => chargeIdSet.has(adjustment.clientChargeId))\n .reduce((sum, adjustment) => sum + adjustment.amount, 0)\n );\n }\n\n private async creditFor(policy: SpendingPolicy): Promise<number> {\n const { credits } = await this.getLedgers();\n const grants = await credits.list({\n where: {\n tenantId: policy.tenantId,\n spendingPolicyId: policy.id,\n currency: policy.currency,\n },\n });\n // A delegated balance holds only credit its current parent granted: when\n // a new parent takes over the policy, a former parent's grants stay with\n // that former relationship instead of funding the new one.\n const setBy = tenantKey(policy.setByTenantId);\n return grants\n .filter(\n (grant) =>\n grant.spendingPolicyId === policy.id &&\n (!setBy || tenantKey(grant.grantedByTenantId) === setBy),\n )\n .reduce((sum, grant) => sum + grant.amount, 0);\n }\n\n private getLedgers(): Promise<{\n retailCharges: RetailChargeCollection;\n credits: CreditGrantCollection;\n }> {\n this.ledgers ??= (async () => {\n const options = { db: this.policies.db };\n return {\n retailCharges:\n this.extensions.retailCharges ??\n (await RetailChargeCollection.create(options)),\n credits:\n this.extensions.credits ??\n (await CreditGrantCollection.create(options)),\n };\n })();\n this.ledgers.catch(() => {\n this.ledgers = undefined;\n });\n return this.ledgers;\n }\n}\n\nfunction decide(\n policy: SpendingPolicy,\n projectedAmount: number,\n limitAmount: number,\n): SpendingDecision {\n const exceeded = projectedAmount > limitAmount;\n const matchedPolicyId = policy.id ?? null;\n if (!exceeded || policy.behavior === 'observe')\n return {\n allowed: true,\n approvalRequired: false,\n state: exceeded ? 'observed' : 'ok',\n projectedAmount,\n matchedPolicyId,\n };\n if (policy.behavior === 'warn')\n return {\n allowed: true,\n approvalRequired: false,\n state: 'warned',\n projectedAmount,\n matchedPolicyId,\n };\n if (policy.behavior === 'approval_required')\n return {\n allowed: false,\n approvalRequired: true,\n state: 'approval_required',\n projectedAmount,\n matchedPolicyId,\n };\n return {\n allowed: false,\n approvalRequired: false,\n state: 'blocked',\n projectedAmount,\n matchedPolicyId,\n };\n}\n\nfunction sumScoped(\n policy: SpendingPolicy,\n rows: LedgerRow[],\n statuses: string[],\n): number {\n return rows\n .filter(\n (row) => statuses.includes(row.status) && matchesChargeScope(policy, row),\n )\n .reduce((sum, row) => sum + row.amount, 0);\n}\n\n/**\n * The provider leg must be priced by someone other than the payer: a reseller\n * (or its child) never publishes the wholesale book it is charged from.\n */\nexport function assertWholesalePublisher(\n book: PriceBook,\n resellerTenantId: string,\n childTenantId: string,\n): void {\n const publisher = tenantKey(book.tenantId);\n if (publisher === resellerTenantId || publisher === childTenantId) {\n throw new ResellerBillingError(\n `Wholesale price book '${book.bookKey}' is published by the tenant it would charge.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n}\n\nasync function loadBook(\n books: PriceBookCollection,\n id: string,\n kind: PriceBookKind,\n): Promise<PriceBook> {\n const book = await books.get(id);\n if (!book?.id) {\n throw new ResellerBillingError(\n `Price book ${id} was not found.`,\n 'PRICE_BOOK_NOT_FOUND',\n );\n }\n if (book.kind !== kind) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is a ${book.kind} book, not ${kind}.`,\n 'PRICE_BOOK_KIND_MISMATCH',\n );\n }\n if (!book.active) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is inactive.`,\n 'PRICE_BOOK_INACTIVE',\n );\n }\n return book;\n}\n\nfunction selectRule(\n rules: PricingRule[],\n at: Date,\n serviceKey: string,\n): PricingRule | undefined {\n return rules\n .filter(\n (rule) =>\n rule.effectiveFrom <= at &&\n (!rule.effectiveTo || rule.effectiveTo > at) &&\n (!rule.serviceKey || rule.serviceKey === serviceKey),\n )\n .sort(\n (a, b) =>\n Number(Boolean(b.serviceKey)) - Number(Boolean(a.serviceKey)) ||\n b.priority - a.priority ||\n b.effectiveFrom.getTime() - a.effectiveFrom.getTime(),\n )[0];\n}\nfunction priceTiers(quantity: number, tiers: unknown[]): number {\n let remaining = quantity,\n prior = 0,\n amount = 0;\n for (const raw of tiers as Array<Record<string, unknown>>) {\n const upTo = raw.upTo == null ? Infinity : Number(raw.upTo);\n const units = Math.max(0, Math.min(remaining, upTo - prior));\n amount += units * Number(raw.unitPrice ?? 0);\n remaining -= units;\n prior = upTo;\n if (remaining <= 0) break;\n }\n return amount;\n}\nfunction selectPolicies(\n policies: SpendingPolicy[],\n input: Record<string, unknown>,\n): SpendingPolicy[] {\n return policies\n .filter(\n (p) =>\n hasValidSubscriberScope(p) &&\n (!p.metricKey || p.metricKey === input.metricKey) &&\n p.currency === input.currency &&\n (!p.projectId || p.projectId === input.projectId) &&\n (!p.serviceKey || p.serviceKey === input.serviceKey) &&\n (!p.subscriberKind ||\n (p.subscriberKind === (input.subscriberKind ?? 'tenant') &&\n (!p.subscriberExternalId ||\n p.subscriberExternalId === input.subscriberExternalId))),\n )\n .sort((a, b) => scopeScore(b) - scopeScore(a) || b.priority - a.priority);\n}\n\nfunction decisionRank(decision: SpendingDecision): number {\n return {\n ok: 0,\n observed: 1,\n warned: 2,\n approval_required: 3,\n blocked: 4,\n }[decision.state];\n}\nfunction scopeScore(p: SpendingPolicy): number {\n return (\n Number(Boolean(p.subscriberKind)) +\n Number(Boolean(p.subscriberExternalId)) +\n Number(Boolean(p.projectId)) +\n Number(Boolean(p.serviceKey)) +\n Number(Boolean(p.metricKey))\n );\n}\nfunction matchesChargeScope(p: SpendingPolicy, c: LedgerRow): boolean {\n return (\n hasValidSubscriberScope(p) &&\n (!p.projectId || p.projectId === c.projectId) &&\n (!p.serviceKey || p.serviceKey === c.serviceKey) &&\n (!p.metricKey || p.metricKey === c.metricKey) &&\n (!p.subscriberKind ||\n (p.subscriberKind === c.subscriberKind &&\n (!p.subscriberExternalId ||\n p.subscriberExternalId === c.subscriberExternalId)))\n );\n}\nfunction hasValidSubscriberScope(p: SpendingPolicy): boolean {\n return !p.subscriberExternalId || Boolean(p.subscriberKind);\n}\nfunction policyWindow(policy: SpendingPolicy, at: Date): [Date, Date] {\n const end = new Date(at);\n const start = new Date(at);\n if (policy.period === 'balance')\n start.setTime(\n new Date(policy.balanceFrom ?? policy.created_at ?? 0).getTime(),\n );\n else if (policy.period === 'rolling')\n start.setTime(at.getTime() - policy.rollingSeconds * 1000);\n else if (policy.period === 'day') start.setUTCHours(0, 0, 0, 0);\n else if (policy.period === 'week') {\n start.setUTCHours(0, 0, 0, 0);\n start.setUTCDate(start.getUTCDate() - ((start.getUTCDay() + 6) % 7));\n } else if (policy.period === 'month') {\n start.setUTCDate(1);\n start.setUTCHours(0, 0, 0, 0);\n } else {\n start.setUTCMonth(0, 1);\n start.setUTCHours(0, 0, 0, 0);\n }\n return [start, end];\n}\n","import type {\n PlanThreshold,\n ThresholdEvaluation,\n UsageSummary,\n} from '../types.js';\n\nexport function evaluateThreshold(\n threshold: PlanThreshold,\n usage: UsageSummary,\n): ThresholdEvaluation {\n const ratio =\n threshold.limit === 0\n ? usage.quantity > 0\n ? Infinity\n : 0\n : usage.quantity / threshold.limit;\n const warningRatio = threshold.warningRatio ?? 0.8;\n const blocked =\n threshold.enforcement === 'block' &&\n (threshold.limit === 0\n ? usage.quantity > 0\n : usage.quantity >= threshold.limit);\n const warned = !blocked && ratio >= warningRatio;\n\n return {\n threshold,\n usage,\n ratio,\n state: blocked ? 'blocked' : warned ? 'warn' : 'ok',\n allowed: !blocked,\n remaining: Math.max(0, threshold.limit - usage.quantity),\n };\n}\n\nexport function evaluateThresholds(\n thresholds: PlanThreshold[],\n usage: UsageSummary[],\n): ThresholdEvaluation[] {\n const usageByMetric = new Map(\n usage.map((summary) => [summary.metricKey, summary]),\n );\n\n return thresholds.map((threshold) => {\n const summary =\n usageByMetric.get(threshold.metricKey) ??\n emptyUsageSummary(threshold.metricKey);\n return evaluateThreshold(threshold, summary);\n });\n}\n\nfunction emptyUsageSummary(metricKey: string): UsageSummary {\n const now = new Date();\n return {\n tenantId: '',\n metricKey,\n quantity: 0,\n windowStart: now,\n windowEnd: now,\n };\n}\n","import type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { TenantUsageMetricCollection } from '../collections/TenantUsageMetricCollection.js';\nimport type {\n AiUsageSummary,\n RecordUsageOptions,\n SummarizeAiUsageOptions,\n SummarizeUsageBatchOptions,\n SummarizeUsageOptions,\n UsageSummary,\n} from '../types.js';\nimport { normalizeSubscriber } from '../utils.js';\n\nexport class TenantUsageMeter {\n constructor(\n private readonly metrics: TenantUsageMetricCollection,\n private readonly classOptions: SmrtClassOptions = {},\n ) {}\n\n static async create(\n classOptions: SmrtClassOptions = {},\n ): Promise<TenantUsageMeter> {\n const metrics = await TenantUsageMetricCollection.create(classOptions);\n return new TenantUsageMeter(metrics, classOptions);\n }\n\n /**\n * Record one usage row.\n *\n * Accepts the polymorphic subscriber fields directly on the options object\n * (`subscriberKind`/`subscriberExternalId`); when omitted defaults to a\n * `'tenant'`-kind row keyed off `tenantId`. The collection layer enforces\n * the XOR invariant — passing `subscriberKind: 'external'` without a\n * non-empty `subscriberExternalId` throws.\n */\n async record(options: RecordUsageOptions): Promise<void> {\n await this.metrics.recordUsage(options);\n }\n\n /**\n * Summarize usage over a window for a given subscriber.\n *\n * The `ai.*` short-circuit only fires for `'tenant'`-kind subscribers since\n * the `_smrt_ai_usage` system table is tenant-scoped; external subscribers\n * fall through to the normal `_smrt_tenant_usage_metrics` aggregation.\n */\n async summarize(options: SummarizeUsageOptions): Promise<UsageSummary> {\n // Normalize at the boundary so the `ai.*` short-circuit and the standard\n // `summarizeUsage` path both refuse the same XOR violations (e.g. caller\n // passes subscriberExternalId without subscriberKind: 'external'). Without\n // this, the AI short-circuit would silently re-scope to tenant-wide\n // _smrt_ai_usage totals.\n normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n\n const aiSummary = await this.trySummarizeAiMetric(options);\n if (aiSummary) {\n return aiSummary;\n }\n\n return this.metrics.summarizeUsage(options);\n }\n\n async summarizeBatch(\n options: SummarizeUsageBatchOptions,\n ): Promise<UsageSummary[]> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const metricKeys = Array.from(new Set(options.metricKeys));\n if (metricKeys.length === 0) {\n return [];\n }\n\n const useTenantAiSummary = subscriber.kind === 'tenant';\n const aiMetricKeys = useTenantAiSummary\n ? metricKeys.filter((metricKey) => metricKey.startsWith('ai.'))\n : [];\n const persistedMetricKeys = useTenantAiSummary\n ? metricKeys.filter((metricKey) => !metricKey.startsWith('ai.'))\n : metricKeys;\n\n const summaries = new Map<string, UsageSummary>();\n let fallbackAiMetricKeys: string[] = [];\n if (aiMetricKeys.length > 0) {\n if (!(await this.hasAiUsageTable())) {\n fallbackAiMetricKeys = aiMetricKeys;\n } else {\n try {\n const aiSummary = await this.summarizeAiUsage({\n tenantId: options.tenantId,\n window: options.window,\n });\n const quantityByMetric = aiQuantityByMetric(aiSummary);\n for (const metricKey of aiMetricKeys) {\n summaries.set(metricKey, {\n tenantId: options.tenantId,\n metricKey,\n quantity: quantityByMetric[metricKey] ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n });\n }\n } catch (error) {\n if (!isMissingAiUsageTableError(error)) {\n throw error;\n }\n fallbackAiMetricKeys = aiMetricKeys;\n }\n }\n }\n\n const persistedSummaries = await this.metrics.summarizeUsageBatch({\n ...options,\n metricKeys: [...persistedMetricKeys, ...fallbackAiMetricKeys],\n });\n for (const summary of persistedSummaries) {\n summaries.set(summary.metricKey, summary);\n }\n\n return metricKeys.map(\n (metricKey) =>\n summaries.get(metricKey) ??\n emptyUsageSummary(subscriber, metricKey, options.window),\n );\n }\n\n async summarizeAiUsage(\n options: SummarizeAiUsageOptions,\n ): Promise<AiUsageSummary> {\n return this.metrics.summarizeTenantAiUsage(options);\n }\n\n getOptions(): SmrtClassOptions {\n return this.classOptions;\n }\n\n private async trySummarizeAiMetric(\n options: SummarizeUsageOptions,\n ): Promise<UsageSummary | null> {\n if (!options.metricKey.startsWith('ai.')) {\n return null;\n }\n // _smrt_ai_usage is tenant-scoped only; external subscribers must use the\n // standard usage path. Skip the short-circuit so the caller's recorded\n // usage rows are summed instead.\n const kind = options.subscriberKind ?? 'tenant';\n if (kind !== 'tenant') {\n return null;\n }\n if (!(await this.hasAiUsageTable())) {\n return null;\n }\n\n let summary: AiUsageSummary;\n try {\n summary = await this.summarizeAiUsage({\n tenantId: options.tenantId,\n window: options.window,\n });\n } catch (error) {\n if (isMissingAiUsageTableError(error)) {\n return null;\n }\n throw error;\n }\n\n const quantityByMetric: Record<string, number> = {\n ...aiQuantityByMetric(summary),\n };\n\n return {\n tenantId: options.tenantId,\n metricKey: options.metricKey,\n quantity: quantityByMetric[options.metricKey] ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n }\n\n private async hasAiUsageTable(): Promise<boolean> {\n return this.metrics.db.tableExists('_smrt_ai_usage');\n }\n}\n\nfunction aiQuantityByMetric(summary: AiUsageSummary): Record<string, number> {\n return {\n 'ai.tokens.prompt': summary.promptTokens,\n 'ai.tokens.completion': summary.completionTokens,\n 'ai.tokens.total': summary.totalTokens,\n 'ai.cost.estimated': summary.estimatedCost,\n 'ai.requests': summary.requestCount,\n };\n}\n\nfunction isMissingAiUsageTableError(\n error: unknown,\n seen = new Set<unknown>(),\n): boolean {\n if (!error) {\n return false;\n }\n if (typeof error !== 'object') {\n return isMissingAiUsageTableMessage(String(error));\n }\n if (seen.has(error)) {\n return false;\n }\n seen.add(error);\n\n const err = error as {\n code?: unknown;\n message?: unknown;\n cause?: unknown;\n context?: Record<string, unknown>;\n };\n const codes = [err?.code, err?.context?.code, err?.context?.errorCode];\n if (codes.some((code) => code === '42P01')) {\n return true;\n }\n\n const messages = [\n err?.message,\n err?.context?.originalError,\n err?.context?.error,\n err?.context?.details,\n ];\n for (const candidate of messages) {\n if (\n candidate &&\n typeof candidate === 'object' &&\n isMissingAiUsageTableError(candidate, seen)\n ) {\n return true;\n }\n if (isMissingAiUsageTableMessage(String(candidate ?? ''))) {\n return true;\n }\n }\n\n return err?.cause ? isMissingAiUsageTableError(err.cause, seen) : false;\n}\n\nfunction isMissingAiUsageTableMessage(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes('_smrt_ai_usage') &&\n (normalized.includes('no such table') ||\n normalized.includes('does not exist') ||\n normalized.includes('undefined table'))\n );\n}\n\nfunction emptyUsageSummary(\n subscriber: ReturnType<typeof normalizeSubscriber>,\n metricKey: string,\n window: SummarizeUsageBatchOptions['window'],\n): UsageSummary {\n const summary: UsageSummary = {\n tenantId: subscriber.tenantId,\n metricKey,\n quantity: 0,\n windowStart: window.start,\n windowEnd: window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...summary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return summary;\n}\n","import { isSystemContext } from '@happyvertical/smrt-tenancy';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport { SubscriptionPlanVersionCollection } from '../collections/SubscriptionPlanVersionCollection.js';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport type { SubscriptionPlanVersion } from '../models/SubscriptionPlanVersion.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport type {\n EntitlementResolution,\n EntitlementResolutionContext,\n PlanFeatureGrant,\n PlanThreshold,\n SmrtClassOptions,\n Subscriber,\n SubscriptionResolverOptions,\n ThresholdEvaluation,\n UsageSummary,\n UsageWindow,\n} from '../types.js';\nimport {\n getWindowForThreshold,\n getWindowKey,\n isValidThreshold,\n} from '../utils.js';\nimport { evaluateThreshold } from './threshold-evaluator.js';\nimport { TenantUsageMeter } from './usage-meter.js';\n\nexport interface SubscriptionPlanReader {\n get(criteria: { id: string }): Promise<SubscriptionPlan | null>;\n}\n\n/**\n * Reader for effective-dated plan versions (#4032). `findInForce` resolves\n * subscriptions that have no pinned version yet (rows written before\n * versioning and not yet migrated).\n */\nexport interface SubscriptionPlanVersionReader {\n get(criteria: { id: string }): Promise<SubscriptionPlanVersion | null>;\n findInForce?(\n planId: string,\n at: Date,\n ): Promise<SubscriptionPlanVersion | null>;\n}\n\n/**\n * Reader contract for finding the current subscription for a subscriber.\n *\n * The legacy `findCurrentForTenant(tenantId)` signature stays for backward\n * compatibility with the original tenant-only resolver. New implementations\n * should provide `findCurrentForSubscriber(subscriber)` — it's preferred when\n * present and lets the resolver work with both `'tenant'` and `'external'`\n * subscribers without callers having to pre-narrow the discriminator.\n */\nexport interface TenantSubscriptionReader {\n findCurrentForTenant(\n tenantId: string,\n now?: Date,\n ): Promise<TenantSubscription | null>;\n findCurrentForSubscriber?(\n subscriber: Subscriber,\n now?: Date,\n ): Promise<TenantSubscription | null>;\n}\n\n/**\n * Reader contract for summarizing usage.\n *\n * `summarize(options)` already accepts the polymorphic\n * `subscriberKind`/`subscriberExternalId` fields. When omitted the reader\n * defaults to `'tenant'`, which is what existing callers got before this\n * change — no behavior shift for them. The discriminator type is derived\n * from `Subscriber['kind']` rather than inlined so any future additions to\n * the union stay consistent across the package.\n */\nexport interface UsageSummaryReader {\n summarize(options: {\n tenantId: string;\n subscriberKind?: Subscriber['kind'];\n subscriberExternalId?: string;\n metricKey: string;\n window: UsageWindow;\n }): Promise<UsageSummary>;\n summarizeBatch?(options: {\n tenantId: string;\n subscriberKind?: Subscriber['kind'];\n subscriberExternalId?: string;\n metricKeys: string[];\n window: UsageWindow;\n }): Promise<UsageSummary[]>;\n}\n\nexport interface SubscriptionResolverReaders {\n plans: SubscriptionPlanReader;\n subscriptions: TenantSubscriptionReader;\n usage: UsageSummaryReader;\n /**\n * Plan versions. When present, entitlements come from the version frozen\n * for the subscription's current period instead of the live plan row.\n * Omitting it keeps the pre-#4032 live-plan behavior.\n */\n planVersions?: SubscriptionPlanVersionReader;\n}\n\nexport class SubscriptionResolver {\n constructor(private readonly readers: SubscriptionResolverReaders) {}\n\n /**\n * Build the default resolver readers once for a request or app lifecycle and\n * reuse the returned resolver across entitlement checks.\n */\n static async create(\n classOptions: SmrtClassOptions = {},\n ): Promise<SubscriptionResolver> {\n const [plans, subscriptions, usage, planVersions] = await Promise.all([\n SubscriptionPlanCollection.create(classOptions),\n TenantSubscriptionCollection.create(classOptions),\n TenantUsageMeter.create(classOptions),\n SubscriptionPlanVersionCollection.create(classOptions),\n ]);\n return new SubscriptionResolver({\n plans,\n subscriptions,\n usage,\n // Pinned versions of legacy global plans stay readable under a tenant\n // context through the collection's bounded global fallback.\n planVersions: {\n get: ({ id }) => planVersions.findVisibleById(id),\n findInForce: (planId, at) => planVersions.findInForce(planId, at),\n },\n });\n }\n\n /**\n * Load the subscription/plan pair used by entitlement resolution. Callers\n * that need both the entitlement snapshot and the backing records can load\n * this once, then pass it back via `options.context`.\n */\n async loadEntitlementContext(\n subscriberOrTenantId: Subscriber | string,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolutionContext> {\n const subscriber = toSubscriber(subscriberOrTenantId);\n const now = options.now ?? new Date();\n const subscription = await this.resolveSubscription(\n subscriber,\n now,\n options.context,\n );\n const plan = await this.resolvePlan(subscription, options.context);\n const planVersion = await this.resolvePlanVersion(\n subscription,\n options.context,\n );\n return { subscription, plan, planVersion };\n }\n\n /**\n * Feature keys the subscriber's entitled terms grant, without evaluating\n * usage thresholds (#4761). Same subscription, plan-version and entitlement\n * rules as {@link resolveEntitlements}; used by `SubscriptionFeatureSource`\n * so a flag check never reads usage meters.\n */\n async resolveFeatureGrants(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<{\n featureKeys: string[];\n /** The entitled terms' grants with their `metadata` (#4759). */\n grants: PlanFeatureGrant[];\n planId: string | null;\n planKey: string | null;\n }> {\n const now = options.now ?? new Date();\n const { identity, terms } = await this.resolveEntitledTerms(\n subscriber,\n now,\n options,\n );\n return {\n featureKeys: terms ? terms.getFeatureKeys() : [],\n grants: terms ? terms.getFeatureGrants() : [],\n planId: identity?.planId ?? null,\n planKey: identity?.planKey ?? null,\n };\n }\n\n /**\n * The entitled plan terms' thresholds, without reading any usage meter\n * (#4760). Same subscription, plan-version and entitlement rules as\n * {@link resolveEntitlements}; `entitled` is false when there is no\n * current subscription or it does not entitle now (thresholds are then\n * empty). The hosted inference gate reads its spend caps from here and\n * meters `_smrt_ai_usage` itself. Thresholds are returned as stored, valid\n * or not (the models' `getThresholds()` drops invalid entries), so a caller\n * can refuse a malformed cap instead of skipping it; thresholds JSON that\n * is not an array throws.\n */\n async resolvePlanThresholds(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<{\n entitled: boolean;\n thresholds: PlanThreshold[];\n planId: string | null;\n planKey: string | null;\n planVersionId: string | null;\n subscriptionId: string | null;\n }> {\n const now = options.now ?? new Date();\n const { identity, terms } = await this.resolveEntitledTerms(\n subscriber,\n now,\n options,\n );\n return {\n entitled: terms !== null,\n thresholds: terms ? rawThresholds(terms.thresholds) : [],\n planId: identity?.planId ?? null,\n planKey: identity?.planKey ?? null,\n planVersionId: identity?.planVersionId ?? null,\n subscriptionId: identity?.subscriptionId ?? null,\n };\n }\n\n private async resolveEntitledTerms(\n subscriber: Subscriber,\n now: Date,\n options: SubscriptionResolverOptions,\n ): Promise<{\n identity: EntitlementIdentity | null;\n terms: SubscriptionPlan | SubscriptionPlanVersion | null;\n }> {\n const { subscription, plan, planVersion } =\n await this.loadEntitlementContext(subscriber, { ...options, now });\n\n if (!subscription) {\n return { identity: null, terms: null };\n }\n\n // With versioning the frozen version is authoritative: a later edit,\n // archive or entitlement removal on the live plan never reaches a paid\n // period. A pinned version that cannot be found fails closed; only an\n // unpinned subscription to a plan with no versions (unmigrated legacy\n // data) falls back to the live plan.\n // Without a version reader or context (custom pre-#4032 readers) the\n // live plan stays authoritative.\n const terms =\n planVersion === undefined\n ? plan\n : (planVersion ?? (subscription.planVersionId ? null : plan));\n const identity = {\n planId: plan?.id ?? planVersion?.planId ?? subscription.planId ?? null,\n planKey: plan?.planKey ?? planVersion?.planKey ?? null,\n planVersionId: terms === planVersion ? (planVersion?.id ?? null) : null,\n planVersion:\n terms === planVersion ? (planVersion?.version ?? null) : null,\n subscriptionId: subscription.id ?? null,\n status: subscription.status,\n };\n\n if (!terms?.isActive() || !subscription.isEntitled(now)) {\n return { identity, terms: null };\n }\n return { identity, terms };\n }\n\n /**\n * Polymorphic entitlement resolution. Works for both `'tenant'`-kind and\n * `'external'`-kind subscribers and is the preferred surface — the\n * `resolveTenantEntitlements(tenantId)` method below is a thin wrapper.\n */\n async resolveEntitlements(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolution> {\n const now = options.now ?? new Date();\n const entitled = await this.resolveEntitledTerms(subscriber, now, options);\n\n if (!entitled.identity) {\n return emptyResolution(subscriber);\n }\n const { identity, terms } = entitled;\n if (!terms) {\n return { ...emptyResolution(subscriber), ...identity };\n }\n\n const thresholds = terms.getThresholds().filter(isValidThreshold);\n const thresholdEvaluations = await this.resolveThresholdEvaluations(\n subscriber,\n thresholds,\n now,\n options,\n );\n\n return {\n tenantId: subscriber.tenantId,\n subscriber,\n ...identity,\n featureKeys: terms.getFeatureKeys(),\n thresholds,\n thresholdEvaluations,\n allowed: thresholdEvaluations.every((evaluation) => evaluation.allowed),\n };\n }\n\n /**\n * Legacy single-tenant wrapper around {@link resolveEntitlements}. Kept so\n * existing tenant-only callers don't need to update their call sites.\n */\n async resolveTenantEntitlements(\n tenantId: string,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolution> {\n return this.resolveEntitlements({ kind: 'tenant', tenantId }, options);\n }\n\n async isFeatureEnabled(\n subscriberOrTenantId: Subscriber | string,\n featureKey: string,\n options: SubscriptionResolverOptions = {},\n ): Promise<boolean> {\n const resolution = await this.resolveEntitlements(\n toSubscriber(subscriberOrTenantId),\n options,\n );\n return resolution.featureKeys.includes(featureKey);\n }\n\n async assertWithinThresholds(\n subscriberOrTenantId: Subscriber | string,\n options: SubscriptionResolverOptions = {},\n ): Promise<void> {\n const subscriber = toSubscriber(subscriberOrTenantId);\n const resolution = await this.resolveEntitlements(subscriber, options);\n const blocked = resolution.thresholdEvaluations.find(\n (evaluation) => !evaluation.allowed,\n );\n\n if (blocked) {\n const subject =\n subscriber.kind === 'external'\n ? `external:${subscriber.externalId}`\n : `Tenant ${subscriber.tenantId}`;\n throw new Error(\n `${subject} exceeded subscription threshold ${blocked.threshold.metricKey}`,\n );\n }\n }\n\n private async resolveSubscription(\n subscriber: Subscriber,\n now: Date,\n context?: EntitlementResolutionContext,\n ): Promise<TenantSubscription | null> {\n if (hasContextValue(context, 'subscription')) {\n const subscription = context?.subscription ?? null;\n assertSubscriptionMatchesSubscriber(subscription, subscriber);\n return subscription;\n }\n return this.findCurrentSubscription(subscriber, now);\n }\n\n private async resolvePlan(\n subscription: TenantSubscription | null,\n context?: EntitlementResolutionContext,\n ): Promise<SubscriptionPlan | null> {\n if (!subscription?.planId) {\n return null;\n }\n if (hasContextValue(context, 'plan')) {\n const plan = context?.plan ?? null;\n assertPlanMatchesSubscription(plan, subscription);\n return plan;\n }\n const plan = await this.readers.plans.get({ id: subscription.planId });\n assertPlanMatchesSubscription(plan, subscription);\n return plan;\n }\n\n /**\n * The version frozen for the subscription's current period: its pinned\n * `planVersionId`, or — for rows not yet pinned — the version in force at\n * its period start. Null when the subscription has no plan or a pinned\n * version is missing (the resolver then fails closed); undefined when no\n * version reader or context is available.\n */\n private async resolvePlanVersion(\n subscription: TenantSubscription | null,\n context?: EntitlementResolutionContext,\n ): Promise<SubscriptionPlanVersion | null | undefined> {\n if (!subscription?.planId) {\n return null;\n }\n if (hasContextValue(context, 'planVersion')) {\n const planVersion = context?.planVersion ?? null;\n assertPlanVersionMatchesSubscription(planVersion, subscription);\n return planVersion;\n }\n const reader = this.readers.planVersions;\n if (!reader) {\n return undefined;\n }\n const planVersion = subscription.planVersionId\n ? await reader.get({ id: subscription.planVersionId })\n : ((await reader.findInForce?.(\n subscription.planId,\n new Date(subscription.currentPeriodStart ?? subscription.startedAt),\n )) ?? null);\n assertPlanVersionMatchesSubscription(planVersion, subscription);\n return planVersion;\n }\n\n /**\n * Bridge the legacy and polymorphic reader contracts.\n *\n * Prefers `findCurrentForSubscriber` when the reader provides it (the\n * preferred shape). For `'tenant'` subscribers we fall back to the legacy\n * `findCurrentForTenant`. For `'external'` subscribers the reader MUST\n * implement `findCurrentForSubscriber` — otherwise we have no way to scope\n * the lookup and we throw rather than silently returning the tenant's\n * primary subscription.\n */\n private async findCurrentSubscription(\n subscriber: Subscriber,\n now: Date,\n ): Promise<TenantSubscription | null> {\n if (this.readers.subscriptions.findCurrentForSubscriber) {\n return this.readers.subscriptions.findCurrentForSubscriber(\n subscriber,\n now,\n );\n }\n if (subscriber.kind === 'tenant') {\n return this.readers.subscriptions.findCurrentForTenant(\n subscriber.tenantId,\n now,\n );\n }\n throw new Error(\n 'External-subscriber resolution requires a TenantSubscriptionReader ' +\n 'that implements findCurrentForSubscriber()',\n );\n }\n\n private async resolveThresholdEvaluations(\n subscriber: Subscriber,\n thresholds: PlanThreshold[],\n now: Date,\n options: SubscriptionResolverOptions,\n ): Promise<ThresholdEvaluation[]> {\n if (thresholds.length === 0) {\n return [];\n }\n\n if (!this.readers.usage.summarizeBatch) {\n const evaluations: ThresholdEvaluation[] = [];\n for (const threshold of thresholds) {\n const window =\n options.usageWindows?.[threshold.window] ??\n getWindowForThreshold(threshold.window, now);\n const usage = await this.readers.usage.summarize({\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n subscriberExternalId:\n subscriber.kind === 'external' ? subscriber.externalId : undefined,\n metricKey: threshold.metricKey,\n window,\n });\n evaluations.push(evaluateThreshold(threshold, usage));\n }\n return evaluations;\n }\n\n const groups = new Map<\n string,\n {\n window: UsageWindow;\n entries: Array<{ index: number; threshold: PlanThreshold }>;\n }\n >();\n\n thresholds.forEach((threshold, index) => {\n const window =\n options.usageWindows?.[threshold.window] ??\n getWindowForThreshold(threshold.window, now);\n const key = getWindowKey(window);\n const group = groups.get(key) ?? { window, entries: [] };\n group.entries.push({ index, threshold });\n groups.set(key, group);\n });\n\n const evaluations: ThresholdEvaluation[] = new Array(thresholds.length);\n await Promise.all(\n Array.from(groups.values()).map(async ({ window, entries }) => {\n const metricKeys = uniqueMetricKeys(\n entries.map((entry) => entry.threshold.metricKey),\n );\n const summaries = await this.readers.usage.summarizeBatch?.({\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n subscriberExternalId:\n subscriber.kind === 'external' ? subscriber.externalId : undefined,\n metricKeys,\n window,\n });\n const summaryByMetric = new Map(\n (summaries ?? []).map((summary) => [summary.metricKey, summary]),\n );\n\n for (const { index, threshold } of entries) {\n const usage =\n summaryByMetric.get(threshold.metricKey) ??\n emptyUsageSummary(subscriber, threshold.metricKey, window);\n evaluations[index] = evaluateThreshold(threshold, usage);\n }\n }),\n );\n\n return evaluations;\n }\n}\n\ntype EntitlementIdentity = Pick<\n EntitlementResolution,\n | 'planId'\n | 'planKey'\n | 'planVersionId'\n | 'planVersion'\n | 'subscriptionId'\n | 'status'\n>;\n\nfunction toSubscriber(input: Subscriber | string): Subscriber {\n if (typeof input === 'string') {\n return { kind: 'tenant', tenantId: input };\n }\n return input;\n}\n\nfunction emptyResolution(subscriber: Subscriber): EntitlementResolution {\n return {\n tenantId: subscriber.tenantId,\n subscriber,\n planId: null,\n planKey: null,\n planVersionId: null,\n planVersion: null,\n subscriptionId: null,\n status: 'none',\n featureKeys: [],\n thresholds: [],\n thresholdEvaluations: [],\n allowed: false,\n };\n}\n\nfunction hasContextValue<K extends keyof EntitlementResolutionContext>(\n context: EntitlementResolutionContext | undefined,\n key: K,\n): boolean {\n return context?.[key] !== undefined;\n}\n\nfunction assertSubscriptionMatchesSubscriber(\n subscription: TenantSubscription | null,\n subscriber: Subscriber,\n): void {\n if (!subscription) {\n return;\n }\n const subscriptionSubscriber = subscription.getSubscriber();\n if (\n !subscriptionSubscriber ||\n !sameSubscriber(subscriptionSubscriber, subscriber)\n ) {\n throw new Error(\n 'Provided entitlement context subscription does not match requested subscriber',\n );\n }\n}\n\nfunction assertPlanMatchesSubscription(\n plan: SubscriptionPlan | null,\n subscription: TenantSubscription,\n): void {\n if (!plan) {\n return;\n }\n if (\n !isSystemContext() &&\n plan.tenantId !== null &&\n plan.tenantId !== subscription.tenantId\n ) {\n throw new Error('Entitlement plan does not belong to subscription tenant');\n }\n if (!plan.id || plan.id !== subscription.planId) {\n throw new Error(\n 'Provided entitlement context plan does not match subscription.planId',\n );\n }\n}\n\nfunction assertPlanVersionMatchesSubscription(\n planVersion: SubscriptionPlanVersion | null,\n subscription: TenantSubscription,\n): void {\n if (!planVersion) {\n return;\n }\n if (\n !isSystemContext() &&\n planVersion.tenantId !== null &&\n planVersion.tenantId !== subscription.tenantId\n ) {\n throw new Error(\n 'Entitlement plan version does not belong to subscription tenant',\n );\n }\n if (\n !planVersion.id ||\n planVersion.planId !== subscription.planId ||\n (subscription.planVersionId !== null &&\n planVersion.id !== subscription.planVersionId)\n ) {\n throw new Error(\n 'Provided entitlement plan version does not match the subscription',\n );\n }\n}\n\nfunction sameSubscriber(left: Subscriber, right: Subscriber): boolean {\n if (left.kind !== right.kind || left.tenantId !== right.tenantId) {\n return false;\n }\n if (left.kind === 'tenant') {\n return true;\n }\n return right.kind === 'external' && left.externalId === right.externalId;\n}\n\nfunction uniqueMetricKeys(metricKeys: string[]): string[] {\n return Array.from(new Set(metricKeys));\n}\n\nfunction emptyUsageSummary(\n subscriber: Subscriber,\n metricKey: string,\n window: UsageWindow,\n): UsageSummary {\n const summary: UsageSummary = {\n tenantId: subscriber.tenantId,\n metricKey,\n quantity: 0,\n windowStart: window.start,\n windowEnd: window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...summary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return summary;\n}\n\nexport type { PlanThreshold };\n\n/**\n * Every stored threshold object, without the validity filter the plan\n * models apply (#4760). Unparseable or non-array JSON throws: a broken\n * plan must never read as \"no caps\".\n */\nfunction rawThresholds(value: string | null | undefined): PlanThreshold[] {\n if (value === null || value === undefined || value.trim() === '') return [];\n const parsed: unknown = JSON.parse(value);\n if (!Array.isArray(parsed)) {\n throw new Error('Plan thresholds are not a JSON array.');\n }\n return parsed.filter(\n (entry): entry is PlanThreshold =>\n entry !== null && typeof entry === 'object' && !Array.isArray(entry),\n );\n}\n","/**\n * Plan feature grants as `smrt-features` flags (#4761).\n *\n * `SubscriptionFeatureSource` implements `smrt-features`' `FeatureGrantSource`\n * structurally, so this package does not depend on `smrt-features` and\n * `smrt-features` never depends on this one. Hosts either pass a per-request\n * source as `grantSource` in the feature resolution context, or register an\n * app-wide one with {@link registerSubscriptionFeatureSource}, which writes the\n * `Symbol.for('@happyvertical/smrt-features:grant-source')` slot that\n * `FeatureResolver` reads.\n *\n * Local installs: when the subscription tables do not exist, or the tenant has\n * no entitled subscription, the source reports no grants and logs nothing, so\n * paid keys stay at their (off) defaults. Every other failure propagates: a\n * database outage must not silently look like \"no plan\".\n */\nimport {\n classifyDatabaseError,\n type SmrtClassOptions,\n} from '@happyvertical/smrt-core';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport { SubscriptionResolver } from './subscription-resolver.js';\n\n/** Structural mirror of `smrt-features`' `FeatureGrantSnapshot`. */\nexport interface SubscriptionFeatureGrants {\n featureKeys: readonly string[];\n planId: string | null;\n planKey: string | null;\n}\n\n/** Structural mirror of `smrt-features`' `FeatureGrantingPlan`. */\nexport interface SubscriptionGrantingPlan {\n planKey: string;\n planId: string | null;\n name: string | null;\n}\n\n/** Reader for the plan catalog an upgrade response searches. */\nexport interface GrantingPlanReader {\n findActive(): Promise<SubscriptionPlan[]>;\n}\n\nexport interface SubscriptionFeatureSourceOptions {\n /** One resolver for the request (or app lifetime); never built per flag. */\n resolver: SubscriptionResolver;\n /** Plan catalog for `findGrantingPlan()`; omitted means no plan is named. */\n plans?: GrantingPlanReader;\n /**\n * Memoize grants per tenant for this instance's lifetime (default `true`).\n * Keep it on for a request-scoped source; a process-wide source registered\n * with {@link registerSubscriptionFeatureSource} turns it off so a plan\n * change is visible on the next check.\n */\n memoize?: boolean;\n /** Clock for entitlement checks; defaults to the current time. */\n now?: () => Date;\n}\n\n/** `Symbol.for()` key `smrt-features` reads its global grant source from. */\nexport const FEATURE_GRANT_SOURCE_SLOT_KEY =\n '@happyvertical/smrt-features:grant-source';\n\nconst SUBSCRIPTION_TABLES = new Set([\n '_smrt_tenant_subscriptions',\n '_smrt_subscription_plans',\n '_smrt_subscription_plan_versions',\n]);\n\nexport class SubscriptionFeatureSource {\n private readonly resolver: SubscriptionResolver;\n private readonly plans: GrantingPlanReader | undefined;\n private readonly memoize: boolean;\n private readonly now: () => Date;\n private readonly grants = new Map<\n string,\n Promise<SubscriptionFeatureGrants | null>\n >();\n private catalog: Promise<SubscriptionPlan[] | null> | null = null;\n\n constructor(options: SubscriptionFeatureSourceOptions) {\n this.resolver = options.resolver;\n this.plans = options.plans;\n this.memoize = options.memoize ?? true;\n this.now = options.now ?? (() => new Date());\n }\n\n /**\n * Build one source with its own resolver and plan catalog. Call once per\n * request (or once at setup with `memoize: false` for a global source).\n */\n static async create(\n classOptions: SmrtClassOptions = {},\n options: Omit<SubscriptionFeatureSourceOptions, 'resolver' | 'plans'> = {},\n ): Promise<SubscriptionFeatureSource> {\n const [resolver, plans] = await Promise.all([\n SubscriptionResolver.create(classOptions),\n SubscriptionPlanCollection.create(classOptions),\n ]);\n return new SubscriptionFeatureSource({ ...options, resolver, plans });\n }\n\n /** Feature keys the tenant's entitled plan grants, or `null` for none. */\n getGrants(tenantId: string): Promise<SubscriptionFeatureGrants | null> {\n if (!this.memoize) {\n return this.loadGrants(tenantId);\n }\n let pending = this.grants.get(tenantId);\n if (!pending) {\n pending = this.loadGrants(tenantId);\n this.grants.set(tenantId, pending);\n // A failed lookup is not cached; the next check retries.\n pending.catch(() => this.grants.delete(tenantId));\n }\n return pending;\n }\n\n /**\n * The first active plan (by `sortOrder`) visible in the current context\n * that grants `featureKey`, for an upgrade response.\n */\n async findGrantingPlan(\n featureKey: string,\n _tenantId: string | null,\n ): Promise<SubscriptionGrantingPlan | null> {\n const catalog = await this.loadCatalog();\n const plan = catalog?.find((candidate) =>\n candidate.getFeatureKeys().includes(featureKey),\n );\n if (!plan) {\n return null;\n }\n return {\n planKey: plan.planKey,\n planId: plan.id ? String(plan.id) : null,\n name: plan.name || null,\n };\n }\n\n private async loadGrants(\n tenantId: string,\n ): Promise<SubscriptionFeatureGrants | null> {\n try {\n const grants = await this.resolver.resolveFeatureGrants(\n { kind: 'tenant', tenantId },\n { now: this.now() },\n );\n return grants.featureKeys.length > 0\n ? {\n featureKeys: grants.featureKeys,\n planId: grants.planId,\n planKey: grants.planKey,\n }\n : null;\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return null;\n }\n throw error;\n }\n }\n\n private loadCatalog(): Promise<SubscriptionPlan[] | null> {\n if (!this.plans) {\n return Promise.resolve(null);\n }\n const load = async () => {\n try {\n return (await this.plans?.findActive()) ?? null;\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return null;\n }\n throw error;\n }\n };\n if (!this.memoize) {\n return load();\n }\n if (!this.catalog) {\n this.catalog = load();\n this.catalog.catch(() => {\n this.catalog = null;\n });\n }\n return this.catalog;\n }\n}\n\n/**\n * Register `source` as `smrt-features`' process-wide grant source, or clear it\n * with `undefined`. Equivalent to `setFeatureGrantSource()` from\n * `smrt-features`, without importing that package. Register a source built\n * with `memoize: false`; pass request-scoped sources per call instead.\n */\nexport function registerSubscriptionFeatureSource(\n source: SubscriptionFeatureSource | undefined,\n): void {\n (globalThis as unknown as Record<symbol, unknown>)[\n Symbol.for(FEATURE_GRANT_SOURCE_SLOT_KEY)\n ] = source;\n}\n\n/**\n * True when `error` reports that one of this package's tables does not exist\n * — core's `DB_SCHEMA_MISSING` or a raw \"no such table\" / \"relation does not\n * exist\" driver error naming a subscription table.\n */\nexport function isMissingSubscriptionTableError(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; current && depth < 8; depth++) {\n const candidate = current as {\n code?: unknown;\n details?: { tableName?: unknown };\n cause?: unknown;\n };\n if (\n candidate.code === 'DB_SCHEMA_MISSING' &&\n typeof candidate.details?.tableName === 'string' &&\n SUBSCRIPTION_TABLES.has(candidate.details.tableName)\n ) {\n return true;\n }\n current = candidate.cause;\n }\n\n const classification = classifyDatabaseError(error);\n if (classification.kind !== 'undefined_object') {\n return false;\n }\n if (classification.driverCodes.includes('42703')) {\n // Undefined column: schema drift, not a missing table.\n return false;\n }\n return classification.driverMessages.some((message) => {\n const lower = message.toLowerCase();\n return (\n (lower.includes('no such table') || lower.includes('does not exist')) &&\n Array.from(SUBSCRIPTION_TABLES).some((table) => lower.includes(table))\n );\n });\n}\n","/**\n * Entitlement change hook (#4759).\n *\n * A plan change arrives through the host's billing webhook (Stripe in\n * smrt-saas-starter, #4667): the host writes the new `TenantSubscription`\n * state. Code that must react to a feature key being gained or lost (hosted\n * inference provisioning, #4759) registers a listener here; the host wraps\n * its webhook write in {@link trackEntitlementChange}, which snapshots the\n * tenant's feature grants before and after and notifies listeners with the\n * difference.\n *\n * Listeners run after the write has been applied (and committed, when the\n * host's write commits inside `apply`). A listener failure never undoes the\n * write: it is collected in the outcome's `failures` so the host can log it,\n * alert, or retry the reaction (listeners are expected to be idempotent;\n * hosted provisioning is, through `runOnce()`). This package stays free of\n * any listener's dependencies: listeners satisfy the structural\n * {@link EntitlementChangeListener} type.\n */\nimport type { PlanFeatureGrant } from '../types.js';\nimport { isMissingSubscriptionTableError } from './subscription-feature-source.js';\nimport type { SubscriptionResolver } from './subscription-resolver.js';\n\n/** A tenant's entitled grants at one moment. */\nexport interface EntitlementSnapshot {\n planId: string | null;\n planKey: string | null;\n /** Enabled feature keys, sorted. */\n featureKeys: string[];\n /** Enabled grants (with their `metadata`), sorted by key. */\n grants: PlanFeatureGrant[];\n}\n\n/** The difference between two snapshots of one tenant. */\nexport interface EntitlementChange {\n tenantId: string;\n /** Keys granted after but not before. */\n gained: string[];\n /** Keys granted before but not after. */\n lost: string[];\n /**\n * Keys granted both before and after whose grant `metadata` changed (a\n * plan's budget for `inference.hosted`, for instance).\n */\n changed: string[];\n before: EntitlementSnapshot;\n after: EntitlementSnapshot;\n}\n\n/** Reacts to an {@link EntitlementChange}; may be async. */\nexport type EntitlementChangeListener = (\n change: EntitlementChange,\n) => void | Promise<void>;\n\n/** One listener that threw. */\nexport interface EntitlementChangeFailure {\n error: unknown;\n}\n\n/** What {@link notifyEntitlementChange} reports. */\nexport interface EntitlementChangeOutcome {\n change: EntitlementChange;\n /** Listeners that threw, in registration order. Empty when all succeeded. */\n failures: EntitlementChangeFailure[];\n}\n\n/** `Symbol.for()` key of the process-wide listener set. */\nexport const ENTITLEMENT_CHANGE_LISTENERS_SLOT_KEY =\n '@happyvertical/smrt-subscriptions:entitlement-change-listeners';\n\nfunction listenerSet(): Set<EntitlementChangeListener> {\n const slot = globalThis as unknown as Record<symbol, unknown>;\n const key = Symbol.for(ENTITLEMENT_CHANGE_LISTENERS_SLOT_KEY);\n let set = slot[key] as Set<EntitlementChangeListener> | undefined;\n if (!set) {\n set = new Set();\n slot[key] = set;\n }\n return set;\n}\n\n/**\n * Register a process-wide listener. Returns a function that unregisters it.\n * Registering the same function twice keeps one registration.\n */\nexport function registerEntitlementChangeListener(\n listener: EntitlementChangeListener,\n): () => void {\n const set = listenerSet();\n set.add(listener);\n return () => {\n set.delete(listener);\n };\n}\n\n/** The registered listeners, in registration order. */\nexport function getEntitlementChangeListeners(): EntitlementChangeListener[] {\n return [...listenerSet()];\n}\n\n/** An empty snapshot: no entitled subscription. */\nexport function emptyEntitlementSnapshot(): EntitlementSnapshot {\n return { planId: null, planKey: null, featureKeys: [], grants: [] };\n}\n\nfunction canonicalJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;\n if (value && typeof value === 'object') {\n return `{${Object.keys(value as Record<string, unknown>)\n .sort()\n .map(\n (key) =>\n `${JSON.stringify(key)}:${canonicalJson((value as Record<string, unknown>)[key])}`,\n )\n .join(',')}}`;\n }\n return JSON.stringify(value ?? null);\n}\n\n/**\n * Snapshot the tenant's entitled grants through `resolver` (no usage\n * meters are read). Missing subscription tables read as no plan, like\n * `SubscriptionFeatureSource`; every other error propagates.\n */\nexport async function snapshotEntitlements(\n resolver: Pick<SubscriptionResolver, 'resolveFeatureGrants'>,\n tenantId: string,\n options: { now?: Date } = {},\n): Promise<EntitlementSnapshot> {\n try {\n const resolved = await resolver.resolveFeatureGrants(\n { kind: 'tenant', tenantId },\n options.now ? { now: options.now } : {},\n );\n const grants = (resolved.grants ?? [])\n .filter((grant) => grant.enabled !== false)\n .sort((a, b) => a.featureKey.localeCompare(b.featureKey));\n return {\n planId: resolved.planId,\n planKey: resolved.planKey,\n featureKeys: [...new Set(resolved.featureKeys)].sort(),\n grants,\n };\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return emptyEntitlementSnapshot();\n }\n throw error;\n }\n}\n\n/** Compute the {@link EntitlementChange} between two snapshots. */\nexport function diffEntitlements(\n tenantId: string,\n before: EntitlementSnapshot,\n after: EntitlementSnapshot,\n): EntitlementChange {\n const was = new Set(before.featureKeys);\n const now = new Set(after.featureKeys);\n const metadataOf = (snapshot: EntitlementSnapshot, key: string) =>\n canonicalJson(\n snapshot.grants.find((grant) => grant.featureKey === key)?.metadata ??\n null,\n );\n return {\n tenantId,\n gained: after.featureKeys.filter((key) => !was.has(key)),\n lost: before.featureKeys.filter((key) => !now.has(key)),\n changed: after.featureKeys.filter(\n (key) =>\n was.has(key) && metadataOf(before, key) !== metadataOf(after, key),\n ),\n before,\n after,\n };\n}\n\n/** True when the change gains, loses or changes at least one key. */\nexport function hasEntitlementChange(change: EntitlementChange): boolean {\n return (\n change.gained.length > 0 ||\n change.lost.length > 0 ||\n change.changed.length > 0\n );\n}\n\n/**\n * Notify `listeners` (default: the registered ones) of `change`, one after\n * another. A change with nothing gained, lost or changed notifies nobody.\n * Never throws for a listener: failures are returned.\n */\nexport async function notifyEntitlementChange(\n change: EntitlementChange,\n options: { listeners?: readonly EntitlementChangeListener[] } = {},\n): Promise<EntitlementChangeOutcome> {\n const failures: EntitlementChangeFailure[] = [];\n if (!hasEntitlementChange(change)) return { change, failures };\n for (const listener of options.listeners ?? getEntitlementChangeListeners()) {\n try {\n await listener(change);\n } catch (error) {\n failures.push({ error });\n }\n }\n return { change, failures };\n}\n\n/** Options for {@link trackEntitlementChange}. */\nexport interface TrackEntitlementChangeOptions {\n tenantId: string;\n /** Resolver used for both snapshots (build one per webhook delivery). */\n resolver: Pick<SubscriptionResolver, 'resolveFeatureGrants'>;\n /** Listeners to notify instead of the registered ones. */\n listeners?: readonly EntitlementChangeListener[];\n /** Clock for both snapshots; defaults to the current time at each. */\n now?: () => Date;\n}\n\n/**\n * Snapshot the tenant's grants, run `apply` (the webhook's subscription\n * write), snapshot again, and notify listeners of the difference. `apply`'s\n * error propagates and notifies nobody. Listener failures are returned in\n * `failures`, never thrown.\n *\n * ```ts\n * const { failures } = await trackEntitlementChange(\n * { tenantId, resolver: await SubscriptionResolver.create({ db }) },\n * () => applyStripeSubscriptionUpdate(event),\n * );\n * ```\n */\nexport async function trackEntitlementChange<T>(\n options: TrackEntitlementChangeOptions,\n apply: () => Promise<T>,\n): Promise<EntitlementChangeOutcome & { result: T }> {\n const at = () => (options.now ? { now: options.now() } : {});\n const before = await snapshotEntitlements(\n options.resolver,\n options.tenantId,\n at(),\n );\n const result = await apply();\n const after = await snapshotEntitlements(\n options.resolver,\n options.tenantId,\n at(),\n );\n const outcome = await notifyEntitlementChange(\n diffEntitlements(options.tenantId, before, after),\n options.listeners ? { listeners: options.listeners } : {},\n );\n return { ...outcome, result };\n}\n","/**\n * Hosted AI spend policy (#4760, epic #4667).\n *\n * A plan caps platform-paid (`source: hosted`) inference with ordinary\n * `PlanThreshold`s on two reserved metric keys, so the window, amount and\n * enforcement come from the plan (and its pinned version) like every other\n * threshold:\n *\n * - {@link AI_HOSTED_SPEND_METRIC}: the tenant's hosted spend per window.\n * - {@link AI_HOSTED_USER_SPEND_METRIC}: each user's hosted spend per window\n * (the per-user cap within the tenant's plan).\n *\n * `limit` is **integer micro-dollars** (1 USD = 1,000,000): the repo's\n * integer-minor-unit money rule at the precision per-call AI costs need.\n * `enforcement: 'block'` blocks at or over the cap; `'warn'` only warns;\n * `'observe'` never affects a call. `warningRatio` (default 0.8) warns\n * before the cap. A cap of 0 blocks every hosted call.\n *\n * Spend is read from `_smrt_ai_usage.estimated_cost` (USD, summed and\n * rounded to micro-dollars) for rows of the tenant in the threshold's\n * window whose `tags` record `source: hosted` (and, for the per-user cap,\n * the `userId` tag), matched as case-sensitive exact JSON fragments. Blocked rows (`operation: 'blocked'`) and\n * external-agent measurements never count. Rows without a cost rate add\n * nothing; give hosted models a cost rate.\n *\n * These keys are evaluated by {@link HostedAiSpendEvaluator} only:\n * `resolveEntitlements()` reports them with quantity 0 (the tenant usage\n * meter has no hosted or per-user meter).\n */\n\nimport { usesPostgresDialect } from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type {\n PlanThreshold,\n SmrtClassOptions,\n SubscriptionResolverOptions,\n UsageWindow,\n} from '../types.js';\nimport { getWindowForThreshold, isValidThreshold } from '../utils.js';\nimport { SubscriptionResolver } from './subscription-resolver.js';\n\n/** Plan threshold key: the tenant's hosted AI spend, micro-dollars. */\nexport const AI_HOSTED_SPEND_METRIC = 'ai.hosted.spend_micros';\n/** Plan threshold key: each user's hosted AI spend, micro-dollars. */\nexport const AI_HOSTED_USER_SPEND_METRIC = 'ai.hosted.user_spend_micros';\n\n/** Micro-dollars per US dollar. */\nexport const MICROS_PER_USD = 1_000_000;\n\n/** Length of a `rolling` threshold window (as `getWindowForThreshold`). */\nconst ROLLING_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;\n\n/** The cap a decision names: tenant or per-user. */\nexport type HostedAiSpendPolicy = 'tenant-cap' | 'user-cap';\n\n/** One evaluated hosted spend threshold. */\nexport interface HostedAiSpendEvaluation {\n policy: HostedAiSpendPolicy;\n threshold: PlanThreshold;\n /** The cap, integer micro-dollars. */\n cap: number;\n /** Metered hosted spend in the window, integer micro-dollars. */\n spend: number;\n window: UsageWindow;\n /**\n * When the cap lifts: the calendar window's end; for a blocked `rolling`\n * cap, the moment enough counted spend has left the 30-day window to bring\n * the total below the cap (null when no expiry can, e.g. a 0 cap, or the\n * cap is not blocked).\n */\n resetsAt: Date | null;\n state: 'ok' | 'warn' | 'blocked';\n}\n\n/** The most restrictive outcome over every hosted spend threshold. */\nexport interface HostedAiSpendDecision {\n state: 'ok' | 'warn' | 'blocked';\n /** False when the tenant has no current entitled subscription. */\n entitled: boolean;\n planId: string | null;\n planKey: string | null;\n /**\n * The deciding evaluation: for `blocked`, the blocking cap that lifts\n * last (the call runs again only when every blocking cap has lifted);\n * for `warn`, the warning cap closest to its limit.\n */\n decidedBy: HostedAiSpendEvaluation | null;\n evaluations: HostedAiSpendEvaluation[];\n}\n\n/** Hosted spend totals for one window. */\nexport interface HostedAiSpendSummary {\n /** Integer micro-dollars. */\n spend: number;\n}\n\n/** The scope of one spend read. */\nexport interface HostedAiSpendScope {\n tenantId: string;\n /** Only this user's rows (the `userId` tag); omitted: the whole tenant. */\n userId?: string;\n window: UsageWindow;\n}\n\n/** Reads hosted spend; the default reads `_smrt_ai_usage`. */\nexport interface HostedAiSpendReader {\n summarize(options: HostedAiSpendScope): Promise<HostedAiSpendSummary>;\n /**\n * For a rolling window: the earliest moment the counted rows, expiring\n * oldest first after `windowMs`, bring the scope's spend below `cap`;\n * null when no expiry can. Optional: without it a blocked rolling cap\n * reports no reset time.\n */\n liftsAt?(\n options: HostedAiSpendScope & { cap: number; windowMs: number },\n ): Promise<Date | null>;\n}\n\n/** A plan cap the gate cannot evaluate: the caller must fail closed. */\nexport class HostedAiSpendPolicyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HostedAiSpendPolicyError';\n }\n}\n\nfunction rows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : ((result as { rows?: Record<string, unknown>[] })?.rows ?? []);\n}\n\nfunction numberOf(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0;\n if (typeof value === 'bigint') return Number(value);\n if (typeof value === 'string') return Number.parseFloat(value) || 0;\n return 0;\n}\n\nfunction dateOf(value: unknown): Date | null {\n if (value === null || value === undefined) return null;\n const date = value instanceof Date ? value : new Date(String(value));\n return Number.isNaN(date.getTime()) ? null : date;\n}\n\n/**\n * The exact fragment one tag leaves in `_smrt_ai_usage.tags` as\n * `JSON.stringify` writes it (core's persistence handler): `\"key\":\"value\"`.\n * The value is JSON-encoded, so a quote inside it cannot end the match\n * early, and the closing quote anchors it, so `u1` never matches `u10`.\n */\nexport function hostedAiTagFragment(key: string, value: string): string {\n return `${JSON.stringify(key)}:${JSON.stringify(value)}`;\n}\n\n/**\n * A case-sensitive substring test: `LIKE` folds ASCII case on SQLite, which\n * would merge users `Alice` and `alice`.\n */\nfunction containsSql(db: DatabaseInterface): string {\n return usesPostgresDialect(db) ? 'strpos(tags, ?) > 0' : 'instr(tags, ?) > 0';\n}\n\nfunction scopeSql(\n db: DatabaseInterface,\n { tenantId, userId, window }: HostedAiSpendScope,\n): { where: string; params: unknown[] } {\n const contains = containsSql(db);\n const params: unknown[] = [\n tenantId,\n window.start.toISOString(),\n window.end.toISOString(),\n hostedAiTagFragment('source', 'hosted'),\n ];\n let where = `tenant_id = ?\n AND created_at >= ?\n AND created_at < ?\n AND operation <> 'blocked'\n AND NOT (operation = 'external-agent' AND id LIKE 'external-agent:%')\n AND ${contains}`;\n if (userId !== undefined) {\n params.push(hostedAiTagFragment('userId', userId));\n where += `\\n AND ${contains}`;\n }\n return { where, params };\n}\n\n/**\n * The default {@link HostedAiSpendReader}: one aggregate query over\n * `_smrt_ai_usage` by `tenant_id` and `created_at` (served by\n * `idx_smrt_ai_usage_tenant_created`), filtered on the `source` and\n * `userId` tag fragments (`strpos` on PostgreSQL, `instr` on SQLite and\n * DuckDB). A fragment can only over-count (a row whose tags contain it\n * elsewhere), never miss a row core wrote, so the error is always toward\n * the cap.\n */\nexport function createHostedAiSpendReader(\n db: DatabaseInterface,\n): HostedAiSpendReader {\n return {\n async summarize(scope) {\n const { where, params } = scopeSql(db, scope);\n const result = await db.query(\n `SELECT COALESCE(SUM(estimated_cost), 0) AS cost\n FROM _smrt_ai_usage\n WHERE ${where}`,\n ...params,\n );\n const row = rows(result)[0] ?? {};\n return { spend: Math.round(numberOf(row.cost) * MICROS_PER_USD) };\n },\n async liftsAt({ cap, windowMs, ...scope }) {\n // Nothing lifts a 0 cap: spend can never drop below it.\n if (cap <= 0) return null;\n const { where, params } = scopeSql(db, scope);\n // Rows expire oldest first, so the cap lifts when the newest row whose\n // newest-first running total reaches the cap leaves the window. The\n // running total is the raw USD sum, compared with the same rounding\n // `summarize()` applies (Math.round(x) >= cap <=> x >= cap - 0.5); the\n // database computes it, so only that one row is returned.\n const result = await db.query(\n `SELECT created_at\n FROM (\n SELECT created_at, id,\n SUM(estimated_cost) OVER (\n ORDER BY created_at DESC, id DESC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS running\n FROM _smrt_ai_usage\n WHERE ${where}\n AND estimated_cost IS NOT NULL\n ) counted\n WHERE running * ${MICROS_PER_USD} >= ?\n ORDER BY created_at DESC, id DESC\n LIMIT 1`,\n ...params,\n cap - 0.5,\n );\n const at = dateOf(rows(result)[0]?.created_at);\n return at ? new Date(at.getTime() + windowMs) : null;\n },\n };\n}\n\nfunction policyFor(threshold: PlanThreshold): HostedAiSpendPolicy | null {\n if (threshold.metricKey === AI_HOSTED_SPEND_METRIC) return 'tenant-cap';\n if (threshold.metricKey === AI_HOSTED_USER_SPEND_METRIC) return 'user-cap';\n return null;\n}\n\n/**\n * The hosted spend thresholds of a plan. A hosted key whose threshold is\n * malformed (unknown window or enforcement, or a limit that is not a\n * non-negative safe integer of micro-dollars) throws\n * {@link HostedAiSpendPolicyError}: a broken cap must never read as \"no cap\".\n */\nexport function hostedAiSpendThresholds(\n thresholds: readonly PlanThreshold[],\n): Array<{ policy: HostedAiSpendPolicy; threshold: PlanThreshold }> {\n const result: Array<{\n policy: HostedAiSpendPolicy;\n threshold: PlanThreshold;\n }> = [];\n for (const threshold of thresholds) {\n const policy = policyFor(threshold);\n if (!policy) continue;\n if (\n !isValidThreshold(threshold) ||\n !Number.isSafeInteger(threshold.limit)\n ) {\n throw new HostedAiSpendPolicyError(\n `Plan threshold ${threshold.metricKey} is not a valid hosted AI cap (limit must be a non-negative integer of micro-dollars).`,\n );\n }\n result.push({ policy, threshold });\n }\n return result;\n}\n\n/** Evaluate one cap against its metered spend. */\nexport function evaluateHostedAiSpendThreshold(\n policy: HostedAiSpendPolicy,\n threshold: PlanThreshold,\n summary: HostedAiSpendSummary,\n window: UsageWindow,\n): HostedAiSpendEvaluation {\n const cap = threshold.limit;\n const spend = summary.spend;\n const over = spend >= cap;\n const warningRatio = threshold.warningRatio ?? 0.8;\n const nearing = cap === 0 ? over : spend >= cap * warningRatio;\n let state: HostedAiSpendEvaluation['state'] = 'ok';\n if (threshold.enforcement === 'block' && over) state = 'blocked';\n else if (threshold.enforcement !== 'observe' && nearing) state = 'warn';\n // A rolling cap's reset is computed from the rows by the evaluator, and\n // only when it blocks (`HostedAiSpendReader.liftsAt`).\n const resetsAt = threshold.window === 'rolling' ? null : window.end;\n return { policy, threshold, cap, spend, window, resetsAt, state };\n}\n\nfunction laterReset(\n a: HostedAiSpendEvaluation,\n b: HostedAiSpendEvaluation,\n): HostedAiSpendEvaluation {\n // An unknown reset (null) sorts last: it lifts no earlier than any other.\n if (!a.resetsAt) return a;\n if (!b.resetsAt) return b;\n return b.resetsAt.getTime() > a.resetsAt.getTime() ? b : a;\n}\n\nfunction closerToCap(\n a: HostedAiSpendEvaluation,\n b: HostedAiSpendEvaluation,\n): HostedAiSpendEvaluation {\n const ratio = (e: HostedAiSpendEvaluation) =>\n e.cap === 0 ? Number.POSITIVE_INFINITY : e.spend / e.cap;\n return ratio(b) > ratio(a) ? b : a;\n}\n\n/** Fold evaluations into the most restrictive decision. */\nexport function decideHostedAiSpend(\n evaluations: HostedAiSpendEvaluation[],\n plan: { entitled: boolean; planId: string | null; planKey: string | null },\n): HostedAiSpendDecision {\n const blocked = evaluations.filter((e) => e.state === 'blocked');\n const warned = evaluations.filter((e) => e.state === 'warn');\n const decidedBy =\n blocked.length > 0\n ? blocked.reduce(laterReset)\n : warned.length > 0\n ? warned.reduce(closerToCap)\n : null;\n return {\n state: blocked.length > 0 ? 'blocked' : warned.length > 0 ? 'warn' : 'ok',\n entitled: plan.entitled,\n planId: plan.planId,\n planKey: plan.planKey,\n decidedBy,\n evaluations,\n };\n}\n\n/** Options for {@link HostedAiSpendEvaluator}. */\nexport interface HostedAiSpendEvaluatorOptions {\n resolver: Pick<SubscriptionResolver, 'resolvePlanThresholds'>;\n spend: HostedAiSpendReader;\n /**\n * How long a tenant's plan thresholds are reused, in ms (default 30 000):\n * entitlements resolve once per request burst, while spend is always read\n * fresh. 0 disables the memo.\n */\n termsTtlMs?: number;\n now?: () => Date;\n}\n\ntype PlanThresholds = Awaited<\n ReturnType<SubscriptionResolver['resolvePlanThresholds']>\n>;\n\n/**\n * Evaluates a tenant's (and one user's) hosted AI spend against the plan's\n * caps. Plan thresholds come from `SubscriptionResolver` (memoized per\n * tenant for `termsTtlMs`); spend is read on every call. Errors (a resolver\n * or database outage, missing tables, a malformed cap) propagate: the gate\n * turns them into a fail-closed block.\n */\nexport class HostedAiSpendEvaluator {\n private readonly terms = new Map<\n string,\n { at: number; value: Promise<PlanThresholds> }\n >();\n private readonly termsTtlMs: number;\n private readonly now: () => Date;\n\n constructor(private readonly options: HostedAiSpendEvaluatorOptions) {\n this.termsTtlMs = options.termsTtlMs ?? 30_000;\n this.now = options.now ?? (() => new Date());\n }\n\n /** Build the default resolver and `_smrt_ai_usage` reader over one db. */\n static async create(\n classOptions: SmrtClassOptions & { db: DatabaseInterface },\n options: Omit<HostedAiSpendEvaluatorOptions, 'resolver' | 'spend'> = {},\n ): Promise<HostedAiSpendEvaluator> {\n return new HostedAiSpendEvaluator({\n ...options,\n resolver: await SubscriptionResolver.create(classOptions),\n spend: createHostedAiSpendReader(classOptions.db),\n });\n }\n\n /** Drop memoized plan thresholds (all tenants, or one). */\n invalidate(tenantId?: string): void {\n if (tenantId === undefined) this.terms.clear();\n else this.terms.delete(tenantId);\n }\n\n private planThresholds(\n tenantId: string,\n resolverOptions: SubscriptionResolverOptions,\n ): Promise<PlanThresholds> {\n const at = Date.now();\n const cached = this.terms.get(tenantId);\n if (cached && this.termsTtlMs > 0 && at - cached.at < this.termsTtlMs) {\n return cached.value;\n }\n const value = this.options.resolver.resolvePlanThresholds(\n { kind: 'tenant', tenantId },\n resolverOptions,\n );\n if (this.termsTtlMs > 0) {\n this.terms.set(tenantId, { at, value });\n value.catch(() => {\n if (this.terms.get(tenantId)?.value === value) {\n this.terms.delete(tenantId);\n }\n });\n }\n return value;\n }\n\n /**\n * Evaluate the plan's hosted caps for `tenantId` and, when given, the\n * per-user caps for `userId`. Without a `userId` the per-user caps are\n * skipped (no user to meter: jobs, shared agent clients).\n */\n async evaluate(input: {\n tenantId: string;\n userId?: string;\n resolverOptions?: SubscriptionResolverOptions;\n }): Promise<HostedAiSpendDecision> {\n const now = this.now();\n const plan = await this.planThresholds(input.tenantId, {\n ...(input.resolverOptions ?? {}),\n now,\n });\n const caps = hostedAiSpendThresholds(plan.thresholds).filter(\n ({ policy }) => policy === 'tenant-cap' || input.userId !== undefined,\n );\n const evaluations = await Promise.all(\n caps.map(async ({ policy, threshold }) => {\n const window = getWindowForThreshold(threshold.window, now);\n const scope = {\n tenantId: input.tenantId,\n ...(policy === 'user-cap' ? { userId: input.userId } : {}),\n window,\n };\n const summary = await this.options.spend.summarize(scope);\n const evaluation = evaluateHostedAiSpendThreshold(\n policy,\n threshold,\n summary,\n window,\n );\n if (\n evaluation.state === 'blocked' &&\n threshold.window === 'rolling' &&\n this.options.spend.liftsAt\n ) {\n evaluation.resetsAt = await this.options.spend.liftsAt({\n ...scope,\n cap: evaluation.cap,\n windowMs: ROLLING_WINDOW_MS,\n });\n }\n return evaluation;\n }),\n );\n return decideHostedAiSpend(evaluations, plan);\n }\n}\n","/**\n * Reseller price books and parent-delegated spending (#3059).\n *\n * Billing ownership comes from the released smrt-tenancy\n * `BillingRelationshipService`; this service never re-derives it. Rating lives\n * on `CommercialUsageService.rateUsage()`, enforcement on\n * `SpendingPolicyEvaluator` — this service manages the records they read.\n */\nimport {\n isEmbeddedDatabase,\n isPostgresDatabase,\n type SmrtClassOptions,\n withEmbeddedWriteTransaction,\n} from '@happyvertical/smrt-core';\nimport {\n type BillingRelationshipView,\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport {\n BillingAdjustmentCollection,\n ClientChargeCollection,\n type PricingRule,\n PricingRuleCollection,\n type PricingStrategy,\n type SpendingBasis,\n type SpendingPeriod,\n type SpendingPolicy,\n type SpendingPolicyBehavior,\n SpendingPolicyCollection,\n} from '../models/commercial.js';\nimport {\n type CreditGrant,\n CreditGrantCollection,\n isCurrencyCode,\n type PriceBook,\n type PriceBookAssignment,\n PriceBookAssignmentCollection,\n PriceBookCollection,\n type PriceBookKind,\n RetailChargeCollection,\n} from '../models/reseller.js';\nimport type { SubscriberKind } from '../types.js';\nimport { deterministicUuid, tenantKey } from '../utils.js';\nimport {\n assertWholesalePublisher,\n type BillingRelationshipReader,\n SpendingPolicyEvaluator,\n} from './commercial.js';\nimport { ResellerBillingError } from './reseller-errors.js';\n\nexport type ResellerBillingAction =\n | 'define_prices'\n | 'assign_wholesale_price_book'\n | 'assign_retail_price_book'\n | 'manage_child_spending';\n\nexport interface ResellerBillingServiceOptions extends SmrtClassOptions {\n /** The released smrt-tenancy billing relationship reader. */\n billingRelationships: BillingRelationshipReader;\n /**\n * Optional host permission check. Without it, only a system context or a\n * super-admin bypass may mutate reseller billing records, mirroring\n * `BillingRelationshipService`. Once it (or the context) authorizes a call,\n * the service performs that call's writes in a system context, because\n * they span tenants (a parent writes rows owned by its child).\n */\n authorize?: (request: {\n action: ResellerBillingAction;\n /**\n * The tenant whose authority the action exercises: the book's seller for\n * `define_prices` and `assign_wholesale_price_book`, the parent for\n * `assign_retail_price_book` and `manage_child_spending`.\n */\n tenantId: string;\n childTenantId?: string;\n /**\n * For price-book assignments and child spending: the child's current\n * reseller, which pays the wholesale leg. A host must confirm the caller\n * holds `tenantId`'s authority and, for `assign_wholesale_price_book`,\n * that the publisher is a legitimate provider for this reseller — the\n * package can refuse only a payer-published book.\n */\n resellerTenantId?: string;\n }) => Promise<boolean>;\n}\n\nexport interface DefinePriceBookPriceInput {\n priceBookId: string;\n ruleKey: string;\n metricKey: string;\n serviceKey?: string;\n strategy: PricingStrategy;\n effectiveFrom?: Date;\n effectiveTo?: Date | null;\n priority?: number;\n /**\n * One entry per currency. Terms use the same *minor units per unit of usage*\n * convention as any `PricingRule` (#2401).\n */\n prices: Array<{ currency: string; terms: Record<string, unknown> }>;\n}\n\nexport interface PriceBookLeg {\n priceBookId: string;\n /** Currency the leg is charged in; the book needs a price in it. */\n currency: string;\n}\n\nexport interface AssignPriceBooksInput {\n childTenantId: string;\n /** `undefined` keeps the current leg; `null` clears it. */\n wholesale?: PriceBookLeg | null;\n retail?: PriceBookLeg | null;\n}\n\nexport interface PriceBookAssignmentView {\n childTenantId: string;\n resellerTenantId: string;\n wholesale: PriceBookLeg | null;\n retail: PriceBookLeg | null;\n}\n\nexport interface DelegatedSpendingPolicyInput {\n parentTenantId: string;\n childTenantId: string;\n name: string;\n basis: SpendingBasis;\n currency: string;\n behavior: SpendingPolicyBehavior;\n period?: SpendingPeriod;\n rollingSeconds?: number;\n /** Integer minor units; must be 0 (the default) for a `balance` policy. */\n limitAmount?: number;\n metricKey?: string;\n serviceKey?: string;\n projectId?: string;\n subscriberKind?: SubscriberKind | '';\n subscriberExternalId?: string;\n priority?: number;\n active?: boolean;\n balanceFrom?: Date;\n}\n\nexport interface GrantChildCreditInput {\n parentTenantId: string;\n childTenantId: string;\n spendingPolicyId: string;\n /** Signed, nonzero integer minor units of the policy currency. */\n amount: number;\n reason?: string;\n source?: string;\n sourceId?: string;\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction canonicalTenantId(id: string): string {\n if (typeof id !== 'string' || !UUID_PATTERN.test(id)) {\n throw new ResellerBillingError(\n 'Tenant IDs must be UUIDs.',\n 'INVALID_TENANT',\n );\n }\n return id.toLowerCase();\n}\n\nfunction assertCurrency(currency: string): void {\n if (!isCurrencyCode(currency)) {\n throw new ResellerBillingError(\n `Currency '${currency}' must be a three-letter upper-case code.`,\n 'INVALID_CURRENCY',\n );\n }\n}\n\nfunction legView(\n priceBookId: string | null | undefined,\n currency: string,\n): PriceBookLeg | null {\n return priceBookId ? { priceBookId: String(priceBookId), currency } : null;\n}\n\nfunction assignmentView(row: PriceBookAssignment): PriceBookAssignmentView {\n return {\n childTenantId: tenantKey(row.childTenantId),\n resellerTenantId: tenantKey(row.resellerTenantId),\n wholesale: legView(row.wholesalePriceBookId, row.wholesaleCurrency),\n retail: legView(row.retailPriceBookId, row.retailCurrency),\n };\n}\n\n/**\n * Run an already-authorized operation in a system context. Only called after\n * `assertManage()` (or for a book metadata read that precedes it).\n */\nfunction authorized<T>(operation: () => Promise<T>): Promise<T> {\n return withSystemContext(operation);\n}\n\n/**\n * Manages price books, their per-relationship assignment, and the spending\n * policies and credits a parent tenant sets on its children.\n */\nexport class ResellerBillingService {\n private constructor(\n private readonly options: ResellerBillingServiceOptions,\n private readonly books: PriceBookCollection,\n private readonly assignments: PriceBookAssignmentCollection,\n private readonly rules: PricingRuleCollection,\n private readonly policies: SpendingPolicyCollection,\n private readonly evaluator: SpendingPolicyEvaluator,\n ) {}\n\n static async create(\n options: ResellerBillingServiceOptions,\n ): Promise<ResellerBillingService> {\n if (typeof options.billingRelationships?.getRelationship !== 'function') {\n throw new Error(\n 'Reseller billing requires a billingRelationships reader from smrt-tenancy.',\n );\n }\n const {\n billingRelationships: _reader,\n authorize: _authorize,\n ...rest\n } = options;\n const books = await PriceBookCollection.create(rest);\n const shared = { ...rest, db: books.db };\n const policies = await SpendingPolicyCollection.create(shared);\n const evaluator = new SpendingPolicyEvaluator(\n policies,\n await ClientChargeCollection.create(shared),\n await BillingAdjustmentCollection.create(shared),\n {\n retailCharges: await RetailChargeCollection.create(shared),\n credits: await CreditGrantCollection.create(shared),\n },\n );\n return new ResellerBillingService(\n options,\n books,\n await PriceBookAssignmentCollection.create(shared),\n await PricingRuleCollection.create(shared),\n policies,\n evaluator,\n );\n }\n\n /**\n * Publish one price in a book, in one or more currencies. Each currency is\n * a `PricingRule` owned by the book's seller; re-defining the same rule key,\n * currency, and effective date replaces that rule's terms.\n */\n async definePrice(input: DefinePriceBookPriceInput): Promise<PricingRule[]> {\n const book = await this.readBook(input.priceBookId);\n const sellerTenantId = canonicalTenantId(String(book.tenantId));\n await this.assertManage('define_prices', sellerTenantId, undefined, true);\n if (!input.ruleKey.trim() || !input.metricKey.trim()) {\n throw new Error('Price book prices require a ruleKey and metricKey.');\n }\n if (input.prices.length === 0) {\n throw new ResellerBillingError(\n 'A price needs at least one currency.',\n 'INVALID_CURRENCY',\n );\n }\n const currencies = new Set<string>();\n for (const { currency } of input.prices) {\n assertCurrency(currency);\n if (currencies.has(currency)) {\n throw new ResellerBillingError(\n `Currency ${currency} is listed twice for one price.`,\n 'INVALID_CURRENCY',\n );\n }\n currencies.add(currency);\n }\n const effectiveFrom = input.effectiveFrom ?? new Date();\n return authorized(async () => {\n const saved: PricingRule[] = [];\n for (const { currency, terms } of input.prices) {\n const id = await deterministicUuid([\n 'price-book-rule',\n String(book.id),\n input.ruleKey,\n input.metricKey,\n input.serviceKey ?? '',\n currency,\n effectiveFrom.toISOString(),\n ]);\n const values = {\n tenantId: book.tenantId,\n priceBookId: String(book.id),\n ruleKey: input.ruleKey,\n metricKey: input.metricKey,\n serviceKey: input.serviceKey ?? '',\n strategy: input.strategy,\n currency,\n effectiveFrom,\n effectiveTo: input.effectiveTo ?? null,\n priority: input.priority ?? 0,\n terms: JSON.stringify(terms),\n active: true,\n };\n const existing = await this.rules.get(id);\n if (existing) {\n Object.assign(existing, values);\n await existing.save();\n saved.push(existing);\n } else {\n saved.push(await this.rules.create({ id, ...values }));\n }\n }\n return saved;\n });\n }\n\n /**\n * Select the wholesale and/or retail book that rates a child's usage under\n * its current reseller relationship. The retail book must be published by\n * that reseller; the wholesale book must be published by someone other\n * than the reseller or child it charges. Each leg is authorized separately:\n * the wholesale leg by its publisher (`assign_wholesale_price_book`), the\n * retail leg by the reseller (`assign_retail_price_book`).\n */\n async assignPriceBooks(\n input: AssignPriceBooksInput,\n ): Promise<PriceBookAssignmentView> {\n const relationship = await this.requireRelationship(input.childTenantId);\n const { childTenantId, resellerTenantId } = relationship;\n const existing = await authorized(() =>\n this.assignments.get({ childTenantId }),\n );\n // An assignment made under a previous reseller does not carry over.\n const current =\n existing && tenantKey(existing.resellerTenantId) === resellerTenantId\n ? assignmentView(existing)\n : null;\n\n if (input.wholesale !== undefined) {\n let publisher = resellerTenantId;\n if (input.wholesale) {\n const book = await this.requireLeg(input.wholesale, 'wholesale');\n assertWholesalePublisher(book, resellerTenantId, childTenantId);\n publisher = tenantKey(book.tenantId);\n } else if (current?.wholesale) {\n publisher = tenantKey(\n (await this.readBook(current.wholesale.priceBookId)).tenantId,\n );\n }\n await this.assertManage(\n 'assign_wholesale_price_book',\n publisher,\n childTenantId,\n false,\n resellerTenantId,\n );\n }\n if (input.retail) {\n const book = await this.requireLeg(input.retail, 'retail');\n if (tenantKey(book.tenantId) !== resellerTenantId) {\n throw new ResellerBillingError(\n `Retail price book '${book.bookKey}' is not published by the child's reseller.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n }\n if (input.retail !== undefined || input.wholesale === undefined) {\n await this.assertManage(\n 'assign_retail_price_book',\n resellerTenantId,\n childTenantId,\n false,\n resellerTenantId,\n );\n }\n\n // Read-merge-write under one lock so concurrent single-leg updates\n // cannot overwrite each other's leg.\n const db = this.assignments.db;\n return authorized(() =>\n withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n if (isPostgresDatabase(transaction)) {\n await transaction.query(\n \"SELECT pg_advisory_xact_lock(hashtext('smrt-price-book-assignments'))\",\n );\n }\n const assignments = await PriceBookAssignmentCollection.create({\n db: transaction,\n });\n const row = await assignments.get({ childTenantId });\n const fresh =\n row && tenantKey(row.resellerTenantId) === resellerTenantId\n ? assignmentView(row)\n : null;\n if (\n input.wholesale === null &&\n fresh?.wholesale?.priceBookId !== current?.wholesale?.priceBookId\n ) {\n // The clear was authorized against a different wholesale book.\n throw new ResellerBillingError(\n 'The wholesale assignment changed concurrently; retry.',\n 'ASSIGNMENT_CONFLICT',\n );\n }\n const wholesale =\n input.wholesale === undefined\n ? (fresh?.wholesale ?? null)\n : input.wholesale;\n const retail =\n input.retail === undefined ? (fresh?.retail ?? null) : input.retail;\n const values = {\n childTenantId,\n resellerTenantId,\n wholesalePriceBookId: wholesale?.priceBookId ?? '',\n wholesaleCurrency: wholesale?.currency ?? '',\n retailPriceBookId: retail?.priceBookId ?? '',\n retailCurrency: retail?.currency ?? '',\n };\n if (row) {\n Object.assign(row, values);\n await row.save();\n return assignmentView(row);\n }\n return assignmentView(await assignments.create(values));\n },\n ),\n );\n }\n\n /** The child's assignment under its current reseller, if any. */\n async getPriceBookAssignment(\n childTenantId: string,\n ): Promise<PriceBookAssignmentView | null> {\n const relationship =\n await this.options.billingRelationships.getRelationship(\n canonicalTenantId(childTenantId),\n );\n if (!relationship) return null;\n const row = await this.assignments.get({\n childTenantId: relationship.childTenantId,\n });\n if (\n !row ||\n tenantKey(row.resellerTenantId) !== relationship.resellerTenantId\n ) {\n return null;\n }\n return assignmentView(row);\n }\n\n /**\n * Create or replace a spending policy that a parent sets on its child. The\n * row belongs to the child (so the ordinary evaluator enforces it for the\n * child) and records the parent in `setByTenantId`, which locks it against\n * changes by the child. A delegated limit left by a former parent may be\n * replaced (not a former parent's prepaid balance, which keeps its credit\n * ledger); one the child set for itself may not. Use `period: 'balance'`\n * for a prepaid credit balance and fund it with {@link grantChildCredit}.\n */\n async setDelegatedSpendingPolicy(\n input: DelegatedSpendingPolicyInput,\n ): Promise<SpendingPolicy> {\n const parentTenantId = canonicalTenantId(input.parentTenantId);\n const relationship = await this.requireChildOf(\n input.childTenantId,\n parentTenantId,\n );\n await this.assertManage(\n 'manage_child_spending',\n parentTenantId,\n relationship.childTenantId,\n false,\n relationship.resellerTenantId,\n );\n assertCurrency(input.currency);\n if (\n input.limitAmount !== undefined &&\n !Number.isSafeInteger(input.limitAmount)\n ) {\n throw new ResellerBillingError(\n `Spending limits must be integer minor units — got ${input.limitAmount}.`,\n 'INVALID_AMOUNT',\n );\n }\n const values = {\n tenantId: relationship.childTenantId,\n name: input.name,\n subscriberKind: input.subscriberKind ?? '',\n subscriberExternalId: input.subscriberExternalId ?? '',\n projectId: input.projectId ?? '',\n serviceKey: input.serviceKey ?? '',\n metricKey: input.metricKey ?? '',\n period: input.period ?? 'month',\n rollingSeconds: input.rollingSeconds ?? 0,\n limitAmount: input.limitAmount ?? 0,\n currency: input.currency,\n behavior: input.behavior,\n priority: input.priority ?? 0,\n active: input.active ?? true,\n basis: input.basis,\n setByTenantId: parentTenantId,\n ...(input.balanceFrom ? { balanceFrom: input.balanceFrom } : {}),\n };\n // Authorized above; the row belongs to the child, so write it outside\n // the parent's own tenant scope.\n return authorized(async () => {\n const existing = (\n await this.policies.list({\n where: {\n tenantId: values.tenantId,\n subscriberKind: values.subscriberKind,\n subscriberExternalId: values.subscriberExternalId,\n projectId: values.projectId,\n serviceKey: values.serviceKey,\n metricKey: values.metricKey,\n period: values.period,\n name: values.name,\n },\n limit: 1,\n })\n )[0];\n if (existing) {\n const owner = tenantKey(existing.setByTenantId);\n if (!owner) {\n throw new ResellerBillingError(\n `Spending policy '${input.name}' already exists for this child and was set by the child.`,\n 'POLICY_CONFLICT',\n );\n }\n // A former parent's prepaid balance keeps its credit ledger: taking\n // it over would strand that credit (or revive it if the child\n // returns), so the new parent must use a different name.\n if (owner !== parentTenantId && existing.period === 'balance') {\n throw new ResellerBillingError(\n `Balance policy '${input.name}' belongs to a former parent; choose another name.`,\n 'POLICY_CONFLICT',\n );\n }\n Object.assign(existing, values);\n await existing.save();\n return existing;\n }\n return this.policies.create(values);\n });\n }\n\n /** Credit a prepaid balance policy the parent set on its child. */\n async grantChildCredit(input: GrantChildCreditInput): Promise<CreditGrant> {\n const parentTenantId = canonicalTenantId(input.parentTenantId);\n const relationship = await this.requireChildOf(\n input.childTenantId,\n parentTenantId,\n );\n await this.assertManage(\n 'manage_child_spending',\n parentTenantId,\n relationship.childTenantId,\n false,\n relationship.resellerTenantId,\n );\n return authorized(async () => {\n const policy = await this.policies.get(input.spendingPolicyId);\n if (\n !policy ||\n tenantKey(policy.tenantId) !== relationship.childTenantId ||\n tenantKey(policy.setByTenantId) !== parentTenantId\n ) {\n throw new ResellerBillingError(\n `Spending policy ${input.spendingPolicyId} is not a policy this parent set on the child.`,\n 'POLICY_NOT_FOUND',\n );\n }\n return this.evaluator.grantCredit({\n spendingPolicyId: input.spendingPolicyId,\n amount: input.amount,\n reason: input.reason,\n source: input.source,\n sourceId: input.sourceId,\n grantedByTenantId: parentTenantId,\n });\n });\n }\n\n private async requireRelationship(\n childTenantId: string,\n ): Promise<BillingRelationshipView> {\n const relationship =\n await this.options.billingRelationships.getRelationship(\n canonicalTenantId(childTenantId),\n );\n if (!relationship) {\n throw new ResellerBillingError(\n `Tenant ${childTenantId} has no reseller relationship.`,\n 'RELATIONSHIP_REQUIRED',\n );\n }\n return relationship;\n }\n\n private async requireChildOf(\n childTenantId: string,\n parentTenantId: string,\n ): Promise<BillingRelationshipView> {\n const relationship = await this.requireRelationship(childTenantId);\n if (relationship.resellerTenantId !== parentTenantId) {\n throw new ResellerBillingError(\n `Tenant ${childTenantId} is not a child of ${parentTenantId}.`,\n 'RELATIONSHIP_REQUIRED',\n );\n }\n return relationship;\n }\n\n /**\n * Read a book's metadata to learn its publisher and kind before deciding\n * authorization. Books belong to their seller, so the read is not scoped to\n * the caller; nothing beyond a validation error is returned on denial.\n */\n private async readBook(id: string): Promise<PriceBook> {\n const book = await authorized(() => this.books.get(id));\n if (!book?.id) {\n throw new ResellerBillingError(\n `Price book ${id} was not found.`,\n 'PRICE_BOOK_NOT_FOUND',\n );\n }\n return book;\n }\n\n private async requireLeg(\n leg: PriceBookLeg,\n kind: PriceBookKind,\n ): Promise<PriceBook> {\n assertCurrency(leg.currency);\n const book = await this.readBook(leg.priceBookId);\n if (book.kind !== kind) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is a ${book.kind} book, not ${kind}.`,\n 'PRICE_BOOK_KIND_MISMATCH',\n );\n }\n return book;\n }\n\n private async assertManage(\n action: ResellerBillingAction,\n tenantId: string,\n childTenantId?: string,\n allowOwnTenant = false,\n resellerTenantId?: string,\n ): Promise<void> {\n if (\n isSystemContext() ||\n isSuperAdminBypass() ||\n (allowOwnTenant && getTenantId()?.toLowerCase() === tenantId) ||\n (await this.options.authorize?.({\n action,\n tenantId,\n childTenantId,\n ...(resellerTenantId ? { resellerTenantId } : {}),\n }))\n ) {\n return;\n }\n throw new TenantIsolationError('Reseller billing mutation denied.');\n }\n}\n","import { StepUpRequiredError } from '@happyvertical/smrt-users/step-up';\n\nexport { StepUpRequiredError };\n\n/** Stable machine code of {@link NotOwnerError}. */\nexport const NOT_OWNER_CODE = 'not_owner';\n\n/**\n * The caller is not the owner of the tenant that holds the account: a member,\n * a device-only or layered session, no session, or another tenant's account.\n * One message and code for all of them, so nothing about the account or the\n * tenant leaks.\n */\nexport class NotOwnerError extends Error {\n readonly code = NOT_OWNER_CODE;\n\n constructor(message = 'Only the account owner may do this.') {\n super(message);\n this.name = 'NotOwnerError';\n }\n}\n\n/** A refusal after both checks passed (the relay or directory said no). */\nexport class VaultAccountAdminError extends Error {\n readonly code: string;\n\n constructor(code: string, message = 'The vault account action failed.') {\n super(message);\n this.name = 'VaultAccountAdminError';\n this.code = code;\n }\n}\n","/**\n * Hosted vault-account admin actions (#4841): replace (supersede), un-replace\n * and provision the replacement of a family's vault account.\n *\n * The relay's admin token can silence or redirect any account, and the local\n * restart calls cannot tell the owner from someone holding an unlocked\n * device, so this layer is the only gate on a takeover of the backup line.\n * Each action therefore, in order:\n *\n * 1. requires the caller to be the tenant OWNER on a first-class session\n * (`not_owner` otherwise: a member, a device-only session, no session, or\n * an account of another tenant),\n * 2. requires a step-up: the owner proved a password or passkey on the\n * hosted account within `stepUpMaxAgeSeconds` (`step_up_required`),\n * 3. records `authorized` in the audit sink, and only then\n * 4. calls the relay, exactly once, and records the outcome.\n *\n * A refusal is audited (`denied`, with the reason code) and throws; the relay\n * is never called. Nothing here reads a request, a cookie or a secret.\n */\nimport {\n DEFAULT_STEP_UP_MAX_AGE_SECONDS,\n isTenantOwnerSession,\n requireRecentAuthentication,\n type StepUpSession,\n} from '@happyvertical/smrt-users/step-up';\nimport {\n NotOwnerError,\n StepUpRequiredError,\n VaultAccountAdminError,\n} from './errors.js';\nimport type {\n ProvisionRestartAccountInput,\n ProvisionRestartAccountResult,\n SupersedeVaultAccountInput,\n UnsupersedeVaultAccountInput,\n VaultAccountAction,\n VaultAccountAdminDeps,\n VaultAccountAuditEntry,\n} from './types.js';\n\n/** The relay's account and device id grammar. */\nconst IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;\n\ntype Subject = Pick<\n VaultAccountAuditEntry,\n 'oldAccountId' | 'newAccountId' | 'deviceId'\n>;\n\nfunction errorCode(error: unknown): string {\n if (error && typeof error === 'object') {\n const code = (error as { code?: unknown }).code;\n if (typeof code === 'string' && /^[\\w.:-]{1,64}$/.test(code)) return code;\n const name = (error as { name?: unknown }).name;\n if (typeof name === 'string') return name.slice(0, 64);\n }\n return 'unknown';\n}\n\nclass Gate {\n private readonly now: () => Date;\n\n constructor(\n private readonly deps: VaultAccountAdminDeps,\n private readonly action: VaultAccountAction,\n private readonly session: StepUpSession | null | undefined,\n private readonly subject: Subject,\n ) {\n this.now = deps.now ?? (() => new Date());\n }\n\n private entry(\n outcome: VaultAccountAuditEntry['outcome'],\n extra: Partial<VaultAccountAuditEntry> = {},\n ): VaultAccountAuditEntry {\n const entry: VaultAccountAuditEntry = {\n at: this.now().toISOString(),\n action: this.action,\n outcome,\n actorUserId: this.session?.user?.id ?? null,\n tenantId: this.session?.tenantId ?? null,\n ...extra,\n };\n for (const [key, value] of Object.entries(this.subject)) {\n if (typeof value === 'string') {\n (entry as unknown as Record<string, unknown>)[key] = value;\n }\n }\n return entry;\n }\n\n private async deny(\n error: NotOwnerError | StepUpRequiredError,\n ): Promise<never> {\n // A broken sink never turns a refusal into anything else.\n await this.recordQuietly(this.entry('denied', { denial: error.code }));\n throw error;\n }\n\n /**\n * Run both checks, then the audit-before-act record. Throws\n * {@link NotOwnerError} or {@link StepUpRequiredError}; resolves with the\n * verified tenant id.\n */\n async authorize(\n accounts: readonly string[],\n validate?: (tenantId: string) => void | Promise<void>,\n ): Promise<string> {\n const session = this.session;\n const isOwner = this.deps.isOwner ?? isTenantOwnerSession;\n let owner = false;\n try {\n owner = Boolean(session && isOwner(session));\n } catch {\n owner = false;\n }\n if (!session || !owner || !session.tenantId || !session.user?.id) {\n return this.deny(new NotOwnerError());\n }\n const tenantId = session.tenantId;\n const userId = session.user.id;\n\n // The accounts must be this tenant's: an owner of one tenant never moves\n // another's. Unknown and foreign accounts are refused alike.\n for (const accountId of accounts) {\n let owningTenant: string | null = null;\n if (IDENTIFIER.test(accountId)) {\n try {\n owningTenant = await this.deps.directory.tenantForAccount(accountId);\n } catch {\n owningTenant = null;\n }\n }\n if (owningTenant !== tenantId) return this.deny(new NotOwnerError());\n }\n\n try {\n requireRecentAuthentication(session, {\n maxAgeSeconds:\n this.deps.stepUpMaxAgeSeconds ?? DEFAULT_STEP_UP_MAX_AGE_SECONDS,\n now: this.now,\n expectedSessionId: session.sessionId,\n expectedUserId: userId,\n });\n } catch {\n return this.deny(new StepUpRequiredError());\n }\n\n // Malformed input from an authorized caller: refused, not audited as\n // authorized, and still before any relay call.\n try {\n await validate?.(tenantId);\n } catch (error) {\n // A foreign account named by the caller is a denied attempt: audited.\n if (error instanceof NotOwnerError) return this.deny(error);\n throw error;\n }\n\n // Audit before acting: if the record cannot be written, nothing happens.\n try {\n await this.deps.audit.record(this.entry('authorized'));\n } catch {\n throw new VaultAccountAdminError(\n 'audit_unavailable',\n 'The action could not be recorded, so it was not performed.',\n );\n }\n return tenantId;\n }\n\n /** Record the relay call's outcome; a sink failure never undoes the call. */\n async finish(\n outcome: 'succeeded' | 'failed',\n extra: Partial<VaultAccountAuditEntry> = {},\n ): Promise<void> {\n await this.recordQuietly(this.entry(outcome, extra));\n }\n\n private async recordQuietly(entry: VaultAccountAuditEntry): Promise<void> {\n try {\n await this.deps.audit.record(entry);\n } catch {\n // Observability only: never changes what the caller is told or does.\n }\n }\n\n /** Run the single relay call and audit its outcome. */\n async perform<T extends string | boolean>(\n call: () => Promise<T>,\n update: Partial<VaultAccountAuditEntry> = {},\n ): Promise<T> {\n let result: T;\n try {\n result = await call();\n } catch (error) {\n await this.finish('failed', { ...update, errorCode: errorCode(error) });\n throw error;\n }\n await this.finish('succeeded', { ...update, result: String(result) });\n return result;\n }\n}\n\nfunction invalid(field: string): VaultAccountAdminError {\n return new VaultAccountAdminError(\n 'invalid_request',\n `Invalid request: ${field}.`,\n );\n}\n\n/**\n * Replace `oldAccount` by `newAccount` (relay admin `PUT\n * .../superseded-by`). The new account must already hold an active device\n * (see {@link provisionRestartAccount}); the relay enforces that, and no\n * chains or loops. Idempotent for the same target.\n */\nexport async function supersedeVaultAccount(\n input: SupersedeVaultAccountInput,\n): Promise<'superseded' | 'unchanged'> {\n const { oldAccount, newAccount } = input;\n const gate = new Gate(input, 'supersede', input.session, {\n oldAccountId: oldAccount,\n newAccountId: newAccount,\n });\n await gate.authorize([oldAccount, newAccount], () => {\n if (oldAccount === newAccount) throw invalid('newAccount');\n });\n return gate.perform(() =>\n input.relay.supersedeAccount(oldAccount, newAccount),\n );\n}\n\n/**\n * Undo a supersession (relay admin `DELETE .../superseded-by`), for an\n * operator mistake or a restart that never reached the working device. Returns\n * false when `oldAccount` was not superseded.\n */\nexport async function unsupersedeVaultAccount(\n input: UnsupersedeVaultAccountInput,\n): Promise<boolean> {\n const { oldAccount } = input;\n const gate = new Gate(input, 'unsupersede', input.session, {\n oldAccountId: oldAccount,\n });\n await gate.authorize([oldAccount]);\n return gate.perform(() => input.relay.clearSupersession(oldAccount));\n}\n\n/**\n * Step 1 of the restart flow (app-runtime README, \"Restarting when the\n * recovery secret is lost\"), before the supersede: allocate a fresh vault\n * account id, link it to the caller's tenant (so `backup.vault` resolves for\n * it), and register the working device's relay signing key in it (relay admin\n * `PUT .../devices/:device`). The id is minted per call, so a retry after a\n * crash makes another empty account unless `newAccountId` is pinned.\n */\nexport async function provisionRestartAccount(\n input: ProvisionRestartAccountInput,\n): Promise<ProvisionRestartAccountResult> {\n const { oldAccount, deviceId, devicePublicKey } = input;\n const subject: Subject = { oldAccountId: oldAccount, deviceId };\n const gate = new Gate(\n input,\n 'provision_restart_account',\n input.session,\n subject,\n );\n let accountId = '';\n const tenantId = await gate.authorize([oldAccount], async (tenantId) => {\n if (!IDENTIFIER.test(deviceId)) throw invalid('deviceId');\n if (typeof devicePublicKey !== 'string' || !devicePublicKey) {\n throw invalid('devicePublicKey');\n }\n accountId = await (input.newAccountId ?? (() => crypto.randomUUID()))();\n if (!IDENTIFIER.test(accountId) || accountId === oldAccount) {\n throw invalid('newAccountId');\n }\n subject.newAccountId = accountId;\n // A pinned or retried id must not name another tenant's account: linking\n // it and registering a device key there would take over that backup line.\n let owningTenant: string | null;\n try {\n owningTenant = await input.directory.tenantForAccount(accountId);\n } catch {\n owningTenant = null;\n }\n if (owningTenant !== null && owningTenant !== tenantId) {\n throw new NotOwnerError();\n }\n });\n const device = await gate.perform(async () => {\n await input.directory.linkAccount(tenantId, accountId);\n const registered = await input.relay.registerDevice(\n accountId,\n deviceId,\n devicePublicKey,\n );\n if (registered === 'conflict') {\n throw new VaultAccountAdminError('device_conflict');\n }\n return registered;\n });\n return { accountId, deviceId, device };\n}\n","/**\n * {@link VaultRelayAdminPort} over the relay's admin HTTP API (private\n * listener, bearer token): `PUT /admin/v1/accounts/:account/devices/:device`,\n * `PUT` and `DELETE /admin/v1/accounts/:account/superseded-by`. The token is\n * sent as a header and never appears in an error, a message or a log.\n */\nimport { VaultAccountAdminError } from './errors.js';\nimport type { VaultRelayAdminPort } from './types.js';\n\nexport interface VaultRelayAdminClientOptions {\n /** Admin listener origin, e.g. `http://vault-relay-admin:8081`. */\n baseUrl: string;\n /** `VAULT_RELAY_ADMIN_TOKEN`. */\n adminToken: string;\n fetch?: typeof fetch;\n}\n\nconst SEGMENT = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;\n\nfunction segment(value: string): string {\n if (!SEGMENT.test(value)) {\n throw new VaultAccountAdminError('invalid_request');\n }\n return value;\n}\n\nexport function createVaultRelayAdminClient(\n options: VaultRelayAdminClientOptions,\n): VaultRelayAdminPort {\n if (!options.adminToken || options.adminToken.length < 32) {\n throw new Error('vault relay admin client: the admin token is required');\n }\n const base = new URL(options.baseUrl);\n const token = options.adminToken;\n const doFetch = options.fetch ?? fetch;\n\n async function call(\n method: 'PUT' | 'DELETE',\n path: string,\n body?: Record<string, string>,\n ): Promise<{ status: number; code: string | null }> {\n const response = await doFetch(new URL(path, base), {\n method,\n redirect: 'error',\n headers: {\n authorization: `Bearer ${token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n let code: string | null = null;\n if (response.status >= 400) {\n try {\n const parsed = (await response.json()) as { error?: unknown };\n if (\n typeof parsed.error === 'string' &&\n /^\\w{1,64}$/.test(parsed.error)\n ) {\n code = parsed.error;\n }\n } catch {\n code = null;\n }\n }\n return { status: response.status, code };\n }\n\n const fail = (status: number, code: string | null): never => {\n throw new VaultAccountAdminError(\n code ?? `relay_${status}`,\n `The vault relay refused the request (${status}).`,\n );\n };\n\n return {\n async registerDevice(accountId, deviceId, publicKey) {\n const { status, code } = await call(\n 'PUT',\n `/admin/v1/accounts/${segment(accountId)}/devices/${segment(deviceId)}`,\n { publicKey },\n );\n if (status === 201) return 'registered';\n if (status === 200) return 'unchanged';\n if (status === 409) return 'conflict';\n return fail(status, code);\n },\n async supersedeAccount(accountId, supersededBy) {\n const { status, code } = await call(\n 'PUT',\n `/admin/v1/accounts/${segment(accountId)}/superseded-by`,\n { supersededBy: segment(supersededBy) },\n );\n if (status === 201) return 'superseded';\n if (status === 200) return 'unchanged';\n return fail(status, code);\n },\n async clearSupersession(accountId) {\n const { status, code } = await call(\n 'DELETE',\n `/admin/v1/accounts/${segment(accountId)}/superseded-by`,\n );\n if (status === 204) return true;\n if (status === 404 && code === 'no_supersession') return false;\n return fail(status, code);\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["options","adapterType","plan","planVersion","evaluations","tenantId"],"sources":["../src/__smrt-register__.ts","../src/billing/config.ts","../src/models/TenantSubscription.ts","../src/collections/TenantSubscriptionCollection.ts","../src/models/BillingCheckoutSession.ts","../src/billing/events.ts","../src/billing/plans.ts","../src/billing/apply.ts","../src/billing/checkout-sessions.ts","../src/billing/signing.ts","../src/billing/types.ts","../src/billing/host.ts","../src/models/TenantUsageMetric.ts","../src/collections/TenantUsageMetricCollection.ts","../src/migrations/moneyMinorUnits.ts","../src/migrations/planVersions.ts","../src/models/commercial.ts","../src/models/reseller.ts","../src/recipes.ts","../src/services/reseller-errors.ts","../src/services/commercial.ts","../src/services/threshold-evaluator.ts","../src/services/usage-meter.ts","../src/services/subscription-resolver.ts","../src/services/subscription-feature-source.ts","../src/services/entitlement-changes.ts","../src/services/hosted-ai-spend.ts","../src/services/reseller.ts","../src/vault-account/errors.ts","../src/vault-account/actions.ts","../src/vault-account/relay-admin-client.ts"],"sourcesContent":["// Generated by @happyvertical/smrt-core smrtPlugin at library build time.\n// The package manifest is inlined so self-registration cannot miss when a\n// downstream bundler relocates this module away from dist/manifest.json\n// (https://github.com/happyvertical/smrt/issues/1506,\n// https://github.com/happyvertical/smrt/issues/1507).\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(JSON.parse(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":0,\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"packageVersion\\\":\\\"0.61.1\\\",\\\"objects\\\":{\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanCollection\\\":{\\\"name\\\":\\\"subscriptionplancollection\\\",\\\"className\\\":\\\"SubscriptionPlanCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanCollection\\\",\\\"collection\\\":\\\"subscriptionplans\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/SubscriptionPlanCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByPlanKey\\\":{\\\"name\\\":\\\"findByPlanKey\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":false,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]},{\\\"name\\\":\\\"planKey\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findActive\\\":{\\\"name\\\":\\\"findActive\\\",\\\"async\\\":true,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Promise<SubscriptionPlan[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByProviderPriceId\\\":{\\\"name\\\":\\\"findByProviderPriceId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"providerPriceId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByStripePriceId\\\":{\\\"name\\\":\\\"findByStripePriceId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"stripePriceId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlan | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SubscriptionPlan\\\",\\\"exportName\\\":\\\"SubscriptionPlanCollection\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plans\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"sort_order\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"provider_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"provider_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"sort_order\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_plan_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plans_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"458e59be\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersionCollection\\\":{\\\"name\\\":\\\"subscriptionplanversioncollection\\\",\\\"className\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersionCollection\\\",\\\"collection\\\":\\\"subscriptionplanversions\\\",\\\"description\\\":\\\"Effective-dated plan versions (#4032).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/SubscriptionPlanVersionCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findVisibleById\\\":{\\\"name\\\":\\\"findVisibleById\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"id\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"listForPlan\\\":{\\\"name\\\":\\\"listForPlan\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findLatest\\\":{\\\"name\\\":\\\"findLatest\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string | null\\\",\\\"optional\\\":true,\\\"unionBranches\\\":[{\\\"type\\\":\\\"string\\\"},{\\\"type\\\":\\\"null\\\"}]}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findInForce\\\":{\\\"name\\\":\\\"findInForce\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"planId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"at\\\",\\\"type\\\":\\\"Date\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SubscriptionPlanVersion\\\",\\\"exportName\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanVersionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plan_versions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plan_versions_plan_id_version_idx\\\",\\\"columns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"f42156f9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantSubscriptionCollection\\\":{\\\"name\\\":\\\"tenantsubscriptioncollection\\\",\\\"className\\\":\\\"TenantSubscriptionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscriptionCollection\\\",\\\"collection\\\":\\\"tenantsubscriptions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/TenantSubscriptionCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"findByTenant\\\":{\\\"name\\\":\\\"findByTenant\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantSubscription[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findCurrentForTenant\\\":{\\\"name\\\":\\\"findCurrentForTenant\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findCurrentForSubscriber\\\":{\\\"name\\\":\\\"findCurrentForSubscriber\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"subscriber\\\",\\\"type\\\":\\\"Subscriber\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByStripeSubscriptionId\\\":{\\\"name\\\":\\\"findByStripeSubscriptionId\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"stripeSubscriptionId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantSubscription | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantSubscription\\\",\\\"exportName\\\":\\\"TenantSubscriptionCollection\\\",\\\"collectionExportName\\\":\\\"TenantSubscriptionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_subscriptions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'incomplete',\\\\n \\\\\\\"started_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"trial_ends_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"cancel_at_period_end\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"canceled_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"agreed_amount\\\\\\\" INTEGER,\\\\n \\\\\\\"plan_version_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_version_pinned_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"plan_version_pin_reason\\\\\\\" TEXT,\\\\n \\\\\\\"plan_version_pin_note\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retains_paid_period\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_customer_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_subscription_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_checkout_session_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"incomplete\\\"},\\\"started_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"trial_ends_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"cancel_at_period_end\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"canceled_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"agreed_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_version_pinned_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_note\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retains_paid_period\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_customer_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_subscription_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_checkout_session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_id_idx\\\",\\\"columns\\\":[\\\"plan_id\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_version_id_idx\\\",\\\"columns\\\":[\\\"plan_version_id\\\"]}],\\\"version\\\":\\\"c281741d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantUsageMetricCollection\\\":{\\\"name\\\":\\\"tenantusagemetriccollection\\\",\\\"className\\\":\\\"TenantUsageMetricCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetricCollection\\\",\\\"collection\\\":\\\"tenantusagemetrics\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/collections/TenantUsageMetricCollection.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{\\\"recordUsage\\\":{\\\"name\\\":\\\"recordUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"RecordUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantUsageMetric>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"findByTenantAndMetric\\\":{\\\"name\\\":\\\"findByTenantAndMetric\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"tenantId\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false},{\\\"name\\\":\\\"metricKey\\\",\\\"type\\\":\\\"string\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<TenantUsageMetric[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeUsage\\\":{\\\"name\\\":\\\"summarizeUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<UsageSummary>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeUsageBatch\\\":{\\\"name\\\":\\\"summarizeUsageBatch\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeUsageBatchOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<UsageSummary[]>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"summarizeTenantAiUsage\\\":{\\\"name\\\":\\\"summarizeTenantAiUsage\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SummarizeAiUsageOptions\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"Promise<AiUsageSummary>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"TenantUsageMetric\\\",\\\"exportName\\\":\\\"TenantUsageMetricCollection\\\",\\\"collectionExportName\\\":\\\"TenantUsageMetricCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_usage_metrics\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"window_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"window_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"dimensions\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"window_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"window_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"4884a70d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\":{\\\"name\\\":\\\"billingcheckoutsession\\\",\\\"className\\\":\\\"BillingCheckoutSession\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\",\\\"collection\\\":\\\"billingcheckoutsessions\\\",\\\"description\\\":\\\"One Checkout session created by the billing host, recorded when the host creates it and required when the paid session completes, so signed metadata copied onto another integration's session is never…\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/BillingCheckoutSession.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"sessionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"default\\\":\\\"\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"targetTenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The tenant the host created the session for.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The tenant the host created the session for.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"pending\\\",\\\"enum\\\":[\\\"pending\\\",\\\"completed\\\",\\\"needs_reconciliation\\\",\\\"dismissed\\\"]},\\\"expiresAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"completedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"conflictColumns\\\":[\\\"session_id\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"BillingCheckoutSession\\\",\\\"collectionExportName\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"validationRules\\\":[{\\\"field\\\":\\\"sessionId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"text\\\"}],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_checkout_sessions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"session_id\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"target_tenant_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'pending',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"completed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"detail\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"target_tenant_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"pending\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"completed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_session_id_idx\\\",\\\"columns\\\":[\\\"session_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"c1924881\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSessionCollection\\\":{\\\"name\\\":\\\"billingcheckoutsessioncollection\\\",\\\"className\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSessionCollection\\\",\\\"collection\\\":\\\"billingcheckoutsessions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/BillingCheckoutSession.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"BillingCheckoutSession\\\",\\\"exportName\\\":\\\"BillingCheckoutSessionCollection\\\",\\\"collectionExportName\\\":\\\"BillingCheckoutSessionCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:BillingCheckoutSession\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_checkout_sessions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_checkout_sessions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"session_id\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"target_tenant_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'pending',\\\\n \\\\\\\"expires_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"completed_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"detail\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"target_tenant_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"pending\\\"},\\\"expires_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"completed_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"detail\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_session_id_idx\\\",\\\"columns\\\":[\\\"session_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_billing_checkout_sessions_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]}],\\\"version\\\":\\\"c1924881\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\":{\\\"name\\\":\\\"subscriptionplan\\\",\\\"className\\\":\\\"SubscriptionPlan\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"collection\\\":\\\"subscriptionplans\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/SubscriptionPlan.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"nullable\\\":true,\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":false,\\\"autoPopulate\\\":true,\\\"nullable\\\":true,\\\"mode\\\":\\\"optional\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"planKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"A short code that identifies the plan, such as starter or pro.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"A short code that identifies the plan, such as starter or pro.\\\"}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What the plan is called, as customers see it.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan is called, as customers see it.\\\"}},\\\"description\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"A sentence or two about what the plan offers.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"A sentence or two about what the plan offers.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"description\\\":\\\"Whether the plan is a draft, on sale (active) or archived.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan is a draft, on sale (active) or archived.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"archived\\\",\\\"draft\\\"]},\\\"sortOrder\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"Where the plan sits when plans are listed; lower numbers come first.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the plan sits when plans are listed; lower numbers come first.\\\"}},\\\"priceAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What the plan costs each billing period, in cents, as a whole number.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan costs each billing period, in cents, as a whole number.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the price is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the price is in, such as USD.\\\"}},\\\"billingInterval\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"description\\\":\\\"How often the subscriber is billed: every day, week, month or year.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How often the subscriber is billed: every day, week, month or year.\\\"},\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\"]},\\\"pricingMode\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed\\\",\\\"description\\\":\\\"Whether the plan is free, has a fixed price, or lets the subscriber choose what to pay. It cannot change once the plan is saved.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan is free, has a fixed price, or lets the subscriber choose what to pay. It cannot change once the plan is saved.\\\"},\\\"enum\\\":[\\\"free\\\",\\\"fixed\\\",\\\"pay_what_you_can\\\"]},\\\"minimumAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber may pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber may pay, in cents.\\\"}},\\\"suggestedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\"}},\\\"externalProvider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"providerProductId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"providerPriceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripeProductId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripePriceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"features\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanTerms\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"save\\\":{\\\"name\\\":\\\"save\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"SmrtSaveOptions\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<this>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"publishTerms\\\":{\\\"name\\\":\\\"publishTerms\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"object\\\",\\\"optional\\\":true,\\\"memberTypes\\\":[\\\"Date\\\"]}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getVersionInForce\\\":{\\\"name\\\":\\\"getVersionInForce\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"at\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"Promise<SubscriptionPlanVersion | null>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureGrants\\\":{\\\"name\\\":\\\"getFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanFeatureGrant[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setFeatureGrants\\\":{\\\"name\\\":\\\"setFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"grants\\\",\\\"type\\\":\\\"Array<string | PlanFeatureGrant>\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureKeys\\\":{\\\"name\\\":\\\"getFeatureKeys\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"string[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getThresholds\\\":{\\\"name\\\":\\\"getThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanThreshold[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setThresholds\\\":{\\\"name\\\":\\\"setThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"thresholds\\\",\\\"type\\\":\\\"PlanThreshold[]\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getMetadata\\\":{\\\"name\\\":\\\"getMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setMetadata\\\":{\\\"name\\\":\\\"setMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"metadata\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"cli\\\":{\\\"skipApiCheck\\\":true},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"optional\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SubscriptionPlan\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plans\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plans\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"description\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"sort_order\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"provider_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"provider_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_product_id\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_price_id\\\\\\\" TEXT,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"description\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"sort_order\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"provider_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_product_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_price_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_plan_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"plan_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plans_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plans_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"458e59be\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\":{\\\"name\\\":\\\"subscriptionplanversion\\\",\\\"className\\\":\\\"SubscriptionPlanVersion\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"collection\\\":\\\"subscriptionplanversions\\\",\\\"description\\\":\\\"An immutable, effective-dated snapshot of a plan's terms (#4032).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/SubscriptionPlanVersion.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"nullable\\\":true,\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":false,\\\"autoPopulate\\\":true,\\\"nullable\\\":true,\\\"mode\\\":\\\"optional\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"planId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlan\\\",\\\"description\\\":\\\"The plan this version belongs to.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan this version belongs to.\\\"}},\\\"planKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The plan code at the time this version was published.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan code at the time this version was published.\\\"}},\\\"version\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"Which version of the plan this is, counting from 1.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Which version of the plan this is, counting from 1.\\\"}},\\\"effectiveFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"The date and time from which these terms apply.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The date and time from which these terms apply.\\\"}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What the plan was called when this version was published.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan was called when this version was published.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"active\\\",\\\"description\\\":\\\"Whether the plan was a draft, on sale (active) or archived under this version.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan was a draft, on sale (active) or archived under this version.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"archived\\\",\\\"draft\\\"]},\\\"priceAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What the plan cost each billing period under this version, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What the plan cost each billing period under this version, in cents.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the price is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the price is in, such as USD.\\\"}},\\\"billingInterval\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"description\\\":\\\"How often the subscriber was billed: every day, week, month or year.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How often the subscriber was billed: every day, week, month or year.\\\"},\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\"]},\\\"pricingMode\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed\\\",\\\"description\\\":\\\"Whether the plan was free, had a fixed price, or let the subscriber choose what to pay.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the plan was free, had a fixed price, or let the subscriber choose what to pay.\\\"},\\\"enum\\\":[\\\"free\\\",\\\"fixed\\\",\\\"pay_what_you_can\\\"]},\\\"minimumAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber could pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the least a subscriber could pay, in cents.\\\"}},\\\"suggestedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount suggested to the subscriber, in cents.\\\"}},\\\"features\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"methods\\\":{\\\"isActive\\\":{\\\"name\\\":\\\"isActive\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanTerms\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureGrants\\\":{\\\"name\\\":\\\"getFeatureGrants\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanFeatureGrant[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getFeatureKeys\\\":{\\\"name\\\":\\\"getFeatureKeys\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"string[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getThresholds\\\":{\\\"name\\\":\\\"getThresholds\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"PlanThreshold[]\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"refuseDelete\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"optional\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SubscriptionPlanVersion\\\",\\\"collectionExportName\\\":\\\"SubscriptionPlanVersionCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_subscription_plan_versions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"version\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'active',\\\\n \\\\\\\"price_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"billing_interval\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"pricing_mode\\\\\\\" TEXT DEFAULT 'fixed',\\\\n \\\\\\\"minimum_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"suggested_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"features\\\\\\\" TEXT DEFAULT '[]',\\\\n \\\\\\\"thresholds\\\\\\\" TEXT DEFAULT '[]'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"version\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"active\\\"},\\\"price_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"billing_interval\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"pricing_mode\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed\\\"},\\\"minimum_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"suggested_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"features\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"},\\\"thresholds\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"[]\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_subscription_plan_versions_plan_id_version_idx\\\",\\\"columns\\\":[\\\"plan_id\\\",\\\"version\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_subscription_plan_versions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"f42156f9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\":{\\\"name\\\":\\\"tenantsubscription\\\",\\\"className\\\":\\\"TenantSubscription\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"collection\\\":\\\"tenantsubscriptions\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/TenantSubscription.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\",\\\"description\\\":\\\"Whether the subscriber is your own workspace (tenant) or an outside customer (external).\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Whether the subscriber is your own workspace (tenant) or an outside customer (external).\\\"},\\\"enum\\\":[\\\"tenant\\\",\\\"external\\\"]},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"Who the outside subscriber is, when the subscriber type is external.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Who the outside subscriber is, when the subscriber type is external.\\\"}},\\\"planId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlan\\\",\\\"description\\\":\\\"The plan this subscription is for.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The plan this subscription is for.\\\"}},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"incomplete\\\",\\\"description\\\":\\\"Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.\\\"},\\\"enum\\\":[\\\"active\\\",\\\"canceled\\\",\\\"incomplete\\\",\\\"past_due\\\",\\\"trialing\\\",\\\"unpaid\\\"]},\\\"startedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"The day the subscription began.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The day the subscription began.\\\"}},\\\"currentPeriodStart\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the current billing period began.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the current billing period began.\\\"}},\\\"currentPeriodEnd\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the current billing period ends and the next one is due.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the current billing period ends and the next one is due.\\\"}},\\\"trialEndsAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the free trial ends, if there is one.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the free trial ends, if there is one.\\\"}},\\\"cancelAtPeriodEnd\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":false,\\\"description\\\":\\\"Tick to let the subscription run out at the end of the current period instead of renewing.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Tick to let the subscription run out at the end of the current period instead of renewing.\\\"}},\\\"canceledAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the subscription was cancelled.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the subscription was cancelled.\\\"}},\\\"agreedAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"description\\\":\\\"For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.\\\"}},\\\"planVersionId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SubscriptionPlanVersion\\\",\\\"description\\\":\\\"The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.\\\"}},\\\"planVersionPinnedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"planVersionPinReason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"enum\\\":[\\\"period_start\\\",\\\"renewal\\\",\\\"upgrade\\\",\\\"authorized\\\",\\\"migration\\\"]},\\\"planVersionPinNote\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"retainsPaidPeriod\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":false},\\\"externalProvider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false},\\\"stripeCustomerId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripeSubscriptionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripeCheckoutSessionId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"replacePlanVersion\\\":{\\\"name\\\":\\\"replacePlanVersion\\\",\\\"async\\\":true,\\\"parameters\\\":[{\\\"name\\\":\\\"options\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":false,\\\"typeUnresolved\\\":true}],\\\"returnType\\\":\\\"Promise<this>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"isEntitled\\\":{\\\"name\\\":\\\"isEntitled\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"now\\\",\\\"type\\\":\\\"any\\\",\\\"optional\\\":true}],\\\"returnType\\\":\\\"boolean\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getSubscriber\\\":{\\\"name\\\":\\\"getSubscriber\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Subscriber | null\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getMetadata\\\":{\\\"name\\\":\\\"getMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setMetadata\\\":{\\\"name\\\":\\\"setMetadata\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"metadata\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\",\\\"update\\\"]},\\\"cli\\\":{\\\"skipApiCheck\\\":true},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantSubscription\\\",\\\"collectionExportName\\\":\\\"TenantSubscriptionCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_subscriptions\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_subscriptions\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"plan_id\\\\\\\" UUID,\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'incomplete',\\\\n \\\\\\\"started_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"current_period_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"trial_ends_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"cancel_at_period_end\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"canceled_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"agreed_amount\\\\\\\" INTEGER,\\\\n \\\\\\\"plan_version_id\\\\\\\" UUID,\\\\n \\\\\\\"plan_version_pinned_at\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"plan_version_pin_reason\\\\\\\" TEXT,\\\\n \\\\\\\"plan_version_pin_note\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retains_paid_period\\\\\\\" BOOLEAN DEFAULT FALSE,\\\\n \\\\\\\"external_provider\\\\\\\" TEXT,\\\\n \\\\\\\"stripe_customer_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_subscription_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"stripe_checkout_session_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metadata\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"plan_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plans\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"incomplete\\\"},\\\"started_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"current_period_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"trial_ends_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"cancel_at_period_end\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"canceled_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"agreed_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_subscription_plan_versions\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"plan_version_pinned_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"plan_version_pin_note\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retains_paid_period\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":false},\\\"external_provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"stripe_customer_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_subscription_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"stripe_checkout_session_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metadata\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_id_idx\\\",\\\"columns\\\":[\\\"plan_id\\\"]},{\\\"name\\\":\\\"_smrt_tenant_subscriptions_plan_version_id_idx\\\",\\\"columns\\\":[\\\"plan_version_id\\\"]}],\\\"version\\\":\\\"c281741d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\":{\\\"name\\\":\\\"tenantusagemetric\\\",\\\"className\\\":\\\"TenantUsageMetric\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:TenantUsageMetric\\\",\\\"collection\\\":\\\"tenantusagemetrics\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/TenantUsageMetric.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\",\\\"enum\\\":[\\\"tenant\\\",\\\"external\\\"]},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"windowStart\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"windowEnd\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"methods\\\":{\\\"getSubscriber\\\":{\\\"name\\\":\\\"getSubscriber\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Subscriber | null\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"getDimensions\\\":{\\\"name\\\":\\\"getDimensions\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"JsonObject\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setDimensions\\\":{\\\"name\\\":\\\"setDimensions\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"dimensions\\\",\\\"type\\\":\\\"JsonObject\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\",\\\"create\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"TenantUsageMetric\\\",\\\"collectionExportName\\\":\\\"TenantUsageMetricCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_tenant_usage_metrics\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"window_start\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"window_end\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"dimensions\\\\\\\" TEXT DEFAULT '{}'\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"window_start\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"window_end\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"dimensions\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_tenant_usage_metrics_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"4884a70d\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PricingRule\\\":{\\\"name\\\":\\\"pricingrule\\\",\\\"className\\\":\\\"PricingRule\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PricingRule\\\",\\\"collection\\\":\\\"pricingrules\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"ruleKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"fixed_unit\\\",\\\"enum\\\":[\\\"fixed_unit\\\",\\\"cost_plus\\\",\\\"multiplier\\\",\\\"tiered\\\",\\\"included_overage\\\",\\\"flat\\\",\\\"custom\\\"]},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effectiveFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"effectiveTo\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"}},\\\"methods\\\":{\\\"getTerms\\\":{\\\"name\\\":\\\"getTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true},\\\"setTerms\\\":{\\\"name\\\":\\\"setTerms\\\",\\\"async\\\":false,\\\"parameters\\\":[{\\\"name\\\":\\\"value\\\",\\\"type\\\":\\\"Record<string, unknown>\\\",\\\"optional\\\":false}],\\\"returnType\\\":\\\"void\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"api\\\":true,\\\"cli\\\":true,\\\"mcp\\\":true,\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PricingRule\\\",\\\"collectionExportName\\\":\\\"PricingRuleCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_pricing_rules\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"rule_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"strategy\\\\\\\" TEXT DEFAULT 'fixed_unit',\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"effective_to\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"terms\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"rule_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed_unit\\\"},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"effective_to\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_pricing_rules_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_pricing_rules_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_pricing_rules_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"37fd6ea9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\":{\\\"name\\\":\\\"clientcharge\\\",\\\"className\\\":\\\"ClientCharge\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"collection\\\":\\\"clientcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"usageEventId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"TenantUsageMetric\\\"},\\\"usageTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"Who supplied the service that was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Who supplied the service that was used.\\\"}},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"The service that was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The service that was used.\\\"}},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"What was used, such as messages sent or minutes of audio.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What was used, such as messages sent or minutes of audio.\\\"}},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"How much of it was used.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"How much of it was used.\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0,\\\"description\\\":\\\"What it cost, in cents.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"What it cost, in cents.\\\"}},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\",\\\"description\\\":\\\"The currency the amount is in, such as USD.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"The currency the amount is in, such as USD.\\\"}},\\\"pricingRuleId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PricingRule\\\"},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"pricingSnapshot\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"draft\\\",\\\"description\\\":\\\"Where the charge stands: draft, approved or adjusted.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"Where the charge stands: draft, approved or adjusted.\\\"},\\\"enum\\\":[\\\"draft\\\",\\\"approved\\\",\\\"adjusted\\\"]},\\\"approvedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false,\\\"description\\\":\\\"When the charge was approved.\\\",\\\"_meta\\\":{\\\"description\\\":\\\"When the charge was approved.\\\"}}},\\\"methods\\\":{\\\"getPricingSnapshot\\\":{\\\"name\\\":\\\"getPricingSnapshot\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"usage_event_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"ClientCharge\\\",\\\"collectionExportName\\\":\\\"ClientChargeCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_client_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"usage_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_client_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_client_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_usage_tenant_id_idx\\\",\\\"columns\\\":[\\\"usage_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"92fb8003\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\":{\\\"name\\\":\\\"billingadjustment\\\",\\\"className\\\":\\\"BillingAdjustment\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\",\\\"collection\\\":\\\"billingadjustments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"clientChargeId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"ClientCharge\\\"},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"createdBy\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"BillingAdjustment\\\",\\\"collectionExportName\\\":\\\"BillingAdjustmentCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_adjustments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"created_by\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"created_by\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_adjustments_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_adjustments_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_billing_adjustments_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]}],\\\"version\\\":\\\"cfbd2832\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\":{\\\"name\\\":\\\"spendingpolicy\\\",\\\"className\\\":\\\"SpendingPolicy\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\",\\\"collection\\\":\\\"spendingpolicies\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"month\\\",\\\"enum\\\":[\\\"day\\\",\\\"week\\\",\\\"month\\\",\\\"year\\\",\\\"rolling\\\",\\\"balance\\\"]},\\\"rollingSeconds\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"limitAmount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"observe\\\",\\\"enum\\\":[\\\"observe\\\",\\\"warn\\\",\\\"block\\\",\\\"approval_required\\\"]},\\\"priority\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"billed\\\",\\\"enum\\\":[\\\"billed\\\",\\\"retail\\\",\\\"wholesale\\\"]},\\\"setByTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"balanceFrom\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"api\\\":true,\\\"cli\\\":true,\\\"mcp\\\":true,\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"assertDelegationAuthority\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"SpendingPolicy\\\",\\\"collectionExportName\\\":\\\"SpendingPolicyCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_spending_policies\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"period\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"rolling_seconds\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"limit_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"behavior\\\\\\\" TEXT DEFAULT 'observe',\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"basis\\\\\\\" TEXT DEFAULT 'billed',\\\\n \\\\\\\"set_by_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"balance_from\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"rolling_seconds\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"limit_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"observe\\\"},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"billed\\\"},\\\"set_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"balance_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_spending_policies_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_set_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"set_by_tenant_id\\\"]}],\\\"version\\\":\\\"21fbbb20\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PricingRuleCollection\\\":{\\\"name\\\":\\\"pricingrulecollection\\\",\\\"className\\\":\\\"PricingRuleCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PricingRuleCollection\\\",\\\"collection\\\":\\\"pricingrules\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\"},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PricingRule\\\",\\\"exportName\\\":\\\"PricingRuleCollection\\\",\\\"collectionExportName\\\":\\\"PricingRuleCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PricingRule\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_pricing_rules\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_pricing_rules\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"rule_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"strategy\\\\\\\" TEXT DEFAULT 'fixed_unit',\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"effective_from\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"effective_to\\\\\\\" TIMESTAMP,\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"terms\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"rule_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"strategy\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"fixed_unit\\\"},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"effective_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"effective_to\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"terms\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_pricing_rules_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_pricing_rules_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_pricing_rules_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"37fd6ea9\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:ClientChargeCollection\\\":{\\\"name\\\":\\\"clientchargecollection\\\",\\\"className\\\":\\\"ClientChargeCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:ClientChargeCollection\\\",\\\"collection\\\":\\\"clientcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"ClientCharge\\\",\\\"exportName\\\":\\\"ClientChargeCollection\\\",\\\"collectionExportName\\\":\\\"ClientChargeCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_client_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_client_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"usage_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_client_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_client_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_usage_tenant_id_idx\\\",\\\"columns\\\":[\\\"usage_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]},{\\\"name\\\":\\\"_smrt_client_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]}],\\\"version\\\":\\\"92fb8003\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:BillingAdjustmentCollection\\\":{\\\"name\\\":\\\"billingadjustmentcollection\\\",\\\"className\\\":\\\"BillingAdjustmentCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustmentCollection\\\",\\\"collection\\\":\\\"billingadjustments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"BillingAdjustment\\\",\\\"exportName\\\":\\\"BillingAdjustmentCollection\\\",\\\"collectionExportName\\\":\\\"BillingAdjustmentCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:BillingAdjustment\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_billing_adjustments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_billing_adjustments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"created_by\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"created_by\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_billing_adjustments_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_billing_adjustments_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_billing_adjustments_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]}],\\\"version\\\":\\\"cfbd2832\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:SpendingPolicyCollection\\\":{\\\"name\\\":\\\"spendingpolicycollection\\\",\\\"className\\\":\\\"SpendingPolicyCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicyCollection\\\",\\\"collection\\\":\\\"spendingpolicies\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/commercial.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\"},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"SpendingPolicy\\\",\\\"exportName\\\":\\\"SpendingPolicyCollection\\\",\\\"collectionExportName\\\":\\\"SpendingPolicyCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:SpendingPolicy\\\",\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_spending_policies\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_spending_policies\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"period\\\\\\\" TEXT DEFAULT 'month',\\\\n \\\\\\\"rolling_seconds\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"limit_amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"behavior\\\\\\\" TEXT DEFAULT 'observe',\\\\n \\\\\\\"priority\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE,\\\\n \\\\\\\"basis\\\\\\\" TEXT DEFAULT 'billed',\\\\n \\\\\\\"set_by_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"balance_from\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"period\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"month\\\"},\\\"rolling_seconds\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"limit_amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"behavior\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"observe\\\"},\\\"priority\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true},\\\"basis\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"billed\\\"},\\\"set_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"balance_from\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_subscriber_kind_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"subscriber_kind\\\",\\\"subscriber_external_id\\\",\\\"project_id\\\",\\\"service_key\\\",\\\"metric_key\\\",\\\"period\\\",\\\"name\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_spending_policies_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_spending_policies_set_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"set_by_tenant_id\\\"]}],\\\"version\\\":\\\"21fbbb20\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBook\\\":{\\\"name\\\":\\\"pricebook\\\",\\\"className\\\":\\\"PriceBook\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBook\\\",\\\"collection\\\":\\\"pricebooks\\\",\\\"description\\\":\\\"A named set of prices published by one seller tenant. Its prices are ordinary PricingRule rows that carry this book's id and the same tenant; one rule per currency gives a price in several currencies.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"bookKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"retail\\\",\\\"enum\\\":[\\\"wholesale\\\",\\\"retail\\\"]},\\\"active\\\":{\\\"type\\\":\\\"boolean\\\",\\\"required\\\":false,\\\"default\\\":true}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false,\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PriceBook\\\",\\\"collectionExportName\\\":\\\"PriceBookCollection\\\",\\\"displayLabelField\\\":\\\"name\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_books\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"book_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"kind\\\\\\\" TEXT DEFAULT 'retail',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"book_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"retail\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_books_tenant_id_book_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_price_books_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_books_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"56296d2f\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\":{\\\"name\\\":\\\"pricebookassignment\\\",\\\"className\\\":\\\"PriceBookAssignment\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\",\\\"collection\\\":\\\"pricebookassignments\\\",\\\"description\\\":\\\"Which price books rate one child tenant's usage, keyed like the tenancy billing relationship it belongs to (one row per child).\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"childTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":true,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"resellerTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":true,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\",\\\"_meta\\\":{\\\"required\\\":true}},\\\"wholesalePriceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"wholesaleCurrency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"retailPriceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"retailCurrency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"conflictColumns\\\":[\\\"child_tenant_id\\\"],\\\"api\\\":false,\\\"cli\\\":false,\\\"mcp\\\":false},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"PriceBookAssignment\\\",\\\"collectionExportName\\\":\\\"PriceBookAssignmentCollection\\\",\\\"validationRules\\\":[{\\\"field\\\":\\\"childTenantId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"crossPackageRef\\\"},{\\\"field\\\":\\\"resellerTenantId\\\",\\\"rule\\\":\\\"required\\\",\\\"fieldType\\\":\\\"crossPackageRef\\\"}],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_book_assignments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"child_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"wholesale_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"wholesale_currency\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retail_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"retail_currency\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"child_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"wholesale_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"wholesale_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retail_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"retail_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_book_assignments_child_tenant_id_idx\\\",\\\"columns\\\":[\\\"child_tenant_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_price_book_assignments_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_wholesale_price_book_id_idx\\\",\\\"columns\\\":[\\\"wholesale_price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_retail_price_book_id_idx\\\",\\\"columns\\\":[\\\"retail_price_book_id\\\"]}],\\\"version\\\":\\\"990da9b7\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\":{\\\"name\\\":\\\"retailcharge\\\",\\\"className\\\":\\\"RetailCharge\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\",\\\"collection\\\":\\\"retailcharges\\\",\\\"description\\\":\\\"What a reseller charges one child for one usage event, priced from the reseller's retail book.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"resellerTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"},\\\"usageEventId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"TenantUsageMetric\\\"},\\\"clientChargeId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"ClientCharge\\\"},\\\"subscriberKind\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriberExternalId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"projectId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefType\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"workRefId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"serviceKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"metricKey\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"decimal\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"priceBookId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PriceBook\\\"},\\\"pricingRuleId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"PricingRule\\\"},\\\"pricingSnapshot\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"draft\\\",\\\"enum\\\":[\\\"draft\\\",\\\"approved\\\"]},\\\"approvedAt\\\":{\\\"type\\\":\\\"datetime\\\",\\\"required\\\":false}},\\\"methods\\\":{\\\"getPricingSnapshot\\\":{\\\"name\\\":\\\"getPricingSnapshot\\\",\\\"async\\\":false,\\\"parameters\\\":[],\\\"returnType\\\":\\\"Record<string, unknown>\\\",\\\"isStatic\\\":false,\\\"isPublic\\\":true}},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"conflictColumns\\\":[\\\"usage_event_id\\\"],\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"}},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"RetailCharge\\\",\\\"collectionExportName\\\":\\\"RetailChargeCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_retail_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_retail_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_retail_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]}],\\\"version\\\":\\\"ad6930a8\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\":{\\\"name\\\":\\\"creditgrant\\\",\\\"className\\\":\\\"CreditGrant\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\",\\\"collection\\\":\\\"creditgrants\\\",\\\"description\\\":\\\"An append-only credit on a prepaid (period: 'balance') spending policy. Positive amounts add credit; a negative amount reverses an earlier grant.\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{\\\"tenantId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":true,\\\"_meta\\\":{\\\"sqlType\\\":\\\"UUID\\\",\\\"__tenancy\\\":{\\\"isTenantIdField\\\":true,\\\"autoFilter\\\":true,\\\"required\\\":true,\\\"autoPopulate\\\":true,\\\"nullable\\\":false,\\\"mode\\\":\\\"required\\\",\\\"field\\\":\\\"tenantId\\\",\\\"allowSuperAdminBypass\\\":false}}},\\\"spendingPolicyId\\\":{\\\"type\\\":\\\"foreignKey\\\",\\\"required\\\":false,\\\"related\\\":\\\"SpendingPolicy\\\"},\\\"amount\\\":{\\\"type\\\":\\\"integer\\\",\\\"required\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"sourceId\\\":{\\\"type\\\":\\\"text\\\",\\\"required\\\":false,\\\"default\\\":\\\"\\\"},\\\"grantedByTenantId\\\":{\\\"type\\\":\\\"crossPackageRef\\\",\\\"required\\\":false,\\\"related\\\":\\\"@happyvertical/smrt-users:Tenant\\\"}},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"hooks\\\":{\\\"beforeDelete\\\":\\\"refuseDelete\\\"},\\\"tenantScoped\\\":{\\\"mode\\\":\\\"required\\\"},\\\"conflictColumns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"]},\\\"extends\\\":\\\"SmrtObject\\\",\\\"exportName\\\":\\\"CreditGrant\\\",\\\"collectionExportName\\\":\\\"CreditGrantCollection\\\",\\\"validationRules\\\":[],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_credit_grants\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"spending_policy_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"granted_by_tenant_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"spending_policy_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_spending_policies\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"granted_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_credit_grants_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_credit_grants_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_spending_policy_id_idx\\\",\\\"columns\\\":[\\\"spending_policy_id\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_granted_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"granted_by_tenant_id\\\"]}],\\\"version\\\":\\\"e11305fc\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookCollection\\\":{\\\"name\\\":\\\"pricebookcollection\\\",\\\"className\\\":\\\"PriceBookCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookCollection\\\",\\\"collection\\\":\\\"pricebooks\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PriceBook\\\",\\\"exportName\\\":\\\"PriceBookCollection\\\",\\\"collectionExportName\\\":\\\"PriceBookCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PriceBook\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_books\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_books\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"book_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"name\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"kind\\\\\\\" TEXT DEFAULT 'retail',\\\\n \\\\\\\"active\\\\\\\" BOOLEAN DEFAULT TRUE\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"book_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"name\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"retail\\\"},\\\"active\\\":{\\\"type\\\":\\\"BOOLEAN\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":true}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_books_tenant_id_book_key_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"book_key\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_price_books_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_books_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]}],\\\"version\\\":\\\"56296d2f\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:PriceBookAssignmentCollection\\\":{\\\"name\\\":\\\"pricebookassignmentcollection\\\",\\\"className\\\":\\\"PriceBookAssignmentCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignmentCollection\\\",\\\"collection\\\":\\\"pricebookassignments\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"api\\\":false,\\\"mcp\\\":false,\\\"cli\\\":false},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"PriceBookAssignment\\\",\\\"exportName\\\":\\\"PriceBookAssignmentCollection\\\",\\\"collectionExportName\\\":\\\"PriceBookAssignmentCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:PriceBookAssignment\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_price_book_assignments\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_price_book_assignments\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"child_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"wholesale_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"wholesale_currency\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"retail_price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"retail_currency\\\\\\\" TEXT DEFAULT ''\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"child_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"wholesale_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"wholesale_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"retail_price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"retail_currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_price_book_assignments_child_tenant_id_idx\\\",\\\"columns\\\":[\\\"child_tenant_id\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_price_book_assignments_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_created_at_idx\\\",\\\"columns\\\":[\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_wholesale_price_book_id_idx\\\",\\\"columns\\\":[\\\"wholesale_price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_price_book_assignments_retail_price_book_id_idx\\\",\\\"columns\\\":[\\\"retail_price_book_id\\\"]}],\\\"version\\\":\\\"990da9b7\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:RetailChargeCollection\\\":{\\\"name\\\":\\\"retailchargecollection\\\",\\\"className\\\":\\\"RetailChargeCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:RetailChargeCollection\\\",\\\"collection\\\":\\\"retailcharges\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"RetailCharge\\\",\\\"exportName\\\":\\\"RetailChargeCollection\\\",\\\"collectionExportName\\\":\\\"RetailChargeCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:RetailCharge\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_retail_charges\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_retail_charges\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"reseller_tenant_id\\\\\\\" UUID,\\\\n \\\\\\\"usage_event_id\\\\\\\" UUID,\\\\n \\\\\\\"client_charge_id\\\\\\\" UUID,\\\\n \\\\\\\"subscriber_kind\\\\\\\" TEXT DEFAULT 'tenant',\\\\n \\\\\\\"subscriber_external_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"project_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_type\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"work_ref_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"provider\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"service_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"metric_key\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"quantity\\\\\\\" REAL DEFAULT 0,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"price_book_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_rule_id\\\\\\\" UUID,\\\\n \\\\\\\"pricing_snapshot\\\\\\\" TEXT DEFAULT '{}',\\\\n \\\\\\\"status\\\\\\\" TEXT DEFAULT 'draft',\\\\n \\\\\\\"approved_at\\\\\\\" TIMESTAMP\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"reseller_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false},\\\"usage_event_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_tenant_usage_metrics\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"CASCADE\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"client_charge_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_client_charges\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"subscriber_kind\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"tenant\\\"},\\\"subscriber_external_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"project_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_type\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"work_ref_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"provider\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"service_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"metric_key\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"quantity\\\":{\\\"type\\\":\\\"REAL\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"price_book_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_price_books\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_rule_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_pricing_rules\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"pricing_snapshot\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"{}\\\"},\\\"status\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"draft\\\"},\\\"approved_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_retail_charges_usage_event_id_idx\\\",\\\"columns\\\":[\\\"usage_event_id\\\"],\\\"unique\\\":true,\\\"nullsNotDistinct\\\":true},{\\\"name\\\":\\\"_smrt_retail_charges_slug_context_idx\\\",\\\"columns\\\":[\\\"slug\\\",\\\"context\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_reseller_tenant_id_idx\\\",\\\"columns\\\":[\\\"reseller_tenant_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_client_charge_id_idx\\\",\\\"columns\\\":[\\\"client_charge_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_price_book_id_idx\\\",\\\"columns\\\":[\\\"price_book_id\\\"]},{\\\"name\\\":\\\"_smrt_retail_charges_pricing_rule_id_idx\\\",\\\"columns\\\":[\\\"pricing_rule_id\\\"]}],\\\"version\\\":\\\"ad6930a8\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"},\\\"@happyvertical/smrt-subscriptions:CreditGrantCollection\\\":{\\\"name\\\":\\\"creditgrantcollection\\\",\\\"className\\\":\\\"CreditGrantCollection\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrantCollection\\\",\\\"collection\\\":\\\"creditgrants\\\",\\\"filePath\\\":\\\"/home/runner/work/smrt/smrt/packages/subscriptions/src/models/reseller.ts\\\",\\\"packageName\\\":\\\"@happyvertical/smrt-subscriptions\\\",\\\"fields\\\":{},\\\"methods\\\":{},\\\"decoratorConfig\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"api\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"mcp\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]},\\\"cli\\\":{\\\"include\\\":[\\\"list\\\",\\\"get\\\"]}},\\\"extends\\\":\\\"SmrtCollection\\\",\\\"extendsTypeArg\\\":\\\"CreditGrant\\\",\\\"exportName\\\":\\\"CreditGrantCollection\\\",\\\"collectionExportName\\\":\\\"CreditGrantCollectionCollection\\\",\\\"collectionOf\\\":\\\"@happyvertical/smrt-subscriptions:CreditGrant\\\",\\\"inheritedExposure\\\":[\\\"api\\\",\\\"mcp\\\",\\\"cli\\\"],\\\"schema\\\":{\\\"tableName\\\":\\\"_smrt_credit_grants\\\",\\\"ddl\\\":\\\"CREATE TABLE IF NOT EXISTS \\\\\\\"_smrt_credit_grants\\\\\\\" (\\\\n \\\\\\\"_sync_origin_device_id\\\\\\\" TEXT,\\\\n \\\\\\\"_sync_revision\\\\\\\" INTEGER,\\\\n \\\\\\\"id\\\\\\\" UUID PRIMARY KEY NOT NULL,\\\\n \\\\\\\"slug\\\\\\\" TEXT NOT NULL,\\\\n \\\\\\\"context\\\\\\\" TEXT NOT NULL DEFAULT '',\\\\n \\\\\\\"created_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"updated_at\\\\\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\\\n \\\\\\\"tenant_id\\\\\\\" UUID NOT NULL,\\\\n \\\\\\\"spending_policy_id\\\\\\\" UUID,\\\\n \\\\\\\"amount\\\\\\\" INTEGER DEFAULT 0,\\\\n \\\\\\\"currency\\\\\\\" TEXT DEFAULT 'USD',\\\\n \\\\\\\"reason\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"source_id\\\\\\\" TEXT DEFAULT '',\\\\n \\\\\\\"granted_by_tenant_id\\\\\\\" UUID\\\\n);\\\",\\\"columns\\\":{\\\"_sync_origin_device_id\\\":{\\\"type\\\":\\\"TEXT\\\"},\\\"_sync_revision\\\":{\\\"type\\\":\\\"INTEGER\\\"},\\\"id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"primaryKey\\\":true,\\\"referenceKind\\\":\\\"id\\\",\\\"notNull\\\":true},\\\"slug\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true},\\\"context\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"\\\"},\\\"created_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"updated_at\\\":{\\\"type\\\":\\\"TIMESTAMP\\\",\\\"notNull\\\":true,\\\"default\\\":\\\"current_timestamp\\\"},\\\"tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"tenantId\\\",\\\"notNull\\\":true,\\\"unique\\\":false},\\\"spending_policy_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"foreignKey\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"foreignKey\\\":{\\\"table\\\":\\\"_smrt_spending_policies\\\",\\\"column\\\":\\\"id\\\",\\\"onDelete\\\":\\\"NO ACTION\\\",\\\"onUpdate\\\":\\\"CASCADE\\\"}},\\\"amount\\\":{\\\"type\\\":\\\"INTEGER\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":0},\\\"currency\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"USD\\\"},\\\"reason\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"source_id\\\":{\\\"type\\\":\\\"TEXT\\\",\\\"notNull\\\":false,\\\"unique\\\":false,\\\"default\\\":\\\"\\\"},\\\"granted_by_tenant_id\\\":{\\\"type\\\":\\\"UUID\\\",\\\"referenceKind\\\":\\\"crossPackageRef\\\",\\\"notNull\\\":false,\\\"unique\\\":false}},\\\"indexes\\\":[{\\\"name\\\":\\\"_smrt_credit_grants_slug_context_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"slug\\\",\\\"context\\\"],\\\"unique\\\":true},{\\\"name\\\":\\\"_smrt_credit_grants_tenant_id_created_at_idx\\\",\\\"columns\\\":[\\\"tenant_id\\\",\\\"created_at\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_spending_policy_id_idx\\\",\\\"columns\\\":[\\\"spending_policy_id\\\"]},{\\\"name\\\":\\\"_smrt_credit_grants_granted_by_tenant_id_idx\\\",\\\"columns\\\":[\\\"granted_by_tenant_id\\\"]}],\\\"version\\\":\\\"e11305fc\\\"},\\\"importPath\\\":\\\"@happyvertical/smrt-subscriptions\\\"}},\\\"moduleType\\\":\\\"smrt\\\",\\\"recipes\\\":[{\\\"id\\\":\\\"subscriptions.plans\\\",\\\"className\\\":\\\"SubscriptionPlansRecipe\\\",\\\"label\\\":\\\"Subscriptions\\\",\\\"summary\\\":\\\"Sell plans that renew, see who is subscribed to which, and what their usage cost.\\\",\\\"synonyms\\\":[\\\"subscriptions\\\",\\\"subscription plans\\\",\\\"plans\\\",\\\"memberships\\\",\\\"recurring billing\\\",\\\"pricing tiers\\\"],\\\"models\\\":[\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\"],\\\"nav\\\":[{\\\"label\\\":\\\"Plans\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\",\\\"icon\\\":\\\"tag\\\",\\\"description\\\":\\\"The plans you sell, with their price and how often they bill.\\\",\\\"noun\\\":\\\"plan\\\"},{\\\"label\\\":\\\"Subscriptions\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\",\\\"icon\\\":\\\"repeat\\\",\\\"description\\\":\\\"Who is subscribed to which plan, and where each one stands.\\\",\\\"noun\\\":\\\"subscription\\\"},{\\\"label\\\":\\\"Plan versions\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\",\\\"icon\\\":\\\"fileText\\\",\\\"description\\\":\\\"Every set of terms a plan has had, and from when each applied.\\\",\\\"noun\\\":\\\"plan version\\\"},{\\\"label\\\":\\\"Charges\\\",\\\"model\\\":\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\",\\\"icon\\\":\\\"receipt\\\",\\\"description\\\":\\\"What each subscriber used and what it cost them.\\\",\\\"noun\\\":\\\"charge\\\"}],\\\"requires\\\":[],\\\"section\\\":{\\\"id\\\":\\\"sales\\\",\\\"label\\\":\\\"Sales\\\",\\\"icon\\\":\\\"shoppingBag\\\",\\\"description\\\":\\\"Customers, orders and quotes: everything you sell.\\\"},\\\"options\\\":{\\\"@happyvertical/smrt-subscriptions:SubscriptionPlan\\\":{\\\"fields\\\":{\\\"name\\\":{\\\"order\\\":1},\\\"planKey\\\":{\\\"label\\\":\\\"Plan code\\\",\\\"order\\\":2},\\\"description\\\":{\\\"order\\\":3},\\\"status\\\":{\\\"order\\\":4},\\\"priceAmount\\\":{\\\"label\\\":\\\"Price (in cents)\\\",\\\"order\\\":5},\\\"currency\\\":{\\\"order\\\":6},\\\"billingInterval\\\":{\\\"label\\\":\\\"Billed every\\\",\\\"order\\\":7},\\\"pricingMode\\\":{\\\"label\\\":\\\"How it is priced\\\",\\\"order\\\":8},\\\"minimumAmount\\\":{\\\"label\\\":\\\"Minimum (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"suggestedAmount\\\":{\\\"label\\\":\\\"Suggested (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"sortOrder\\\":{\\\"label\\\":\\\"Position in list\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"features\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"thresholds\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"externalProvider\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"providerProductId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"providerPriceId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeProductId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripePriceId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"metadata\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:SubscriptionPlanVersion\\\":{\\\"fields\\\":{\\\"planId\\\":{\\\"label\\\":\\\"Plan\\\",\\\"order\\\":1},\\\"version\\\":{\\\"label\\\":\\\"Version number\\\",\\\"order\\\":2},\\\"effectiveFrom\\\":{\\\"label\\\":\\\"In force from\\\",\\\"order\\\":3},\\\"name\\\":{\\\"order\\\":4},\\\"status\\\":{\\\"order\\\":5},\\\"priceAmount\\\":{\\\"label\\\":\\\"Price (in cents)\\\",\\\"order\\\":6},\\\"currency\\\":{\\\"order\\\":7},\\\"billingInterval\\\":{\\\"label\\\":\\\"Billed every\\\",\\\"order\\\":8},\\\"planKey\\\":{\\\"label\\\":\\\"Plan code\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"pricingMode\\\":{\\\"label\\\":\\\"How it is priced\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"minimumAmount\\\":{\\\"label\\\":\\\"Minimum (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"suggestedAmount\\\":{\\\"label\\\":\\\"Suggested (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"features\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"thresholds\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:TenantSubscription\\\":{\\\"fields\\\":{\\\"planId\\\":{\\\"label\\\":\\\"Plan\\\",\\\"order\\\":1},\\\"status\\\":{\\\"order\\\":2},\\\"startedAt\\\":{\\\"label\\\":\\\"Started on\\\",\\\"order\\\":3},\\\"currentPeriodStart\\\":{\\\"label\\\":\\\"Current period starts\\\",\\\"order\\\":4},\\\"currentPeriodEnd\\\":{\\\"label\\\":\\\"Current period ends\\\",\\\"order\\\":5},\\\"trialEndsAt\\\":{\\\"label\\\":\\\"Trial ends\\\",\\\"order\\\":6},\\\"cancelAtPeriodEnd\\\":{\\\"label\\\":\\\"Cancel at end of period\\\",\\\"order\\\":7},\\\"canceledAt\\\":{\\\"label\\\":\\\"Cancelled on\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"agreedAmount\\\":{\\\"label\\\":\\\"Agreed amount (in cents)\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"subscriberKind\\\":{\\\"label\\\":\\\"Subscriber type\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"subscriberExternalId\\\":{\\\"label\\\":\\\"Outside subscriber\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"planVersionId\\\":{\\\"label\\\":\\\"Plan version\\\",\\\"visibility\\\":\\\"advanced\\\",\\\"locked\\\":true},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinnedAt\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinReason\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"planVersionPinNote\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"retainsPaidPeriod\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"externalProvider\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeCustomerId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeSubscriptionId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"stripeCheckoutSessionId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"metadata\\\":{\\\"visibility\\\":\\\"hidden\\\"}}},\\\"@happyvertical/smrt-subscriptions:ClientCharge\\\":{\\\"fields\\\":{\\\"metricKey\\\":{\\\"label\\\":\\\"What was used\\\",\\\"order\\\":1},\\\"quantity\\\":{\\\"label\\\":\\\"How much\\\",\\\"order\\\":2},\\\"amount\\\":{\\\"label\\\":\\\"Amount (in cents)\\\",\\\"order\\\":3},\\\"currency\\\":{\\\"order\\\":4},\\\"status\\\":{\\\"order\\\":5},\\\"approvedAt\\\":{\\\"label\\\":\\\"Approved on\\\",\\\"order\\\":6},\\\"serviceKey\\\":{\\\"label\\\":\\\"Service\\\",\\\"visibility\\\":\\\"advanced\\\"},\\\"provider\\\":{\\\"visibility\\\":\\\"advanced\\\"},\\\"tenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"usageEventId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"usageTenantId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"subscriberKind\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"subscriberExternalId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"projectId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"workRefType\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"workRefId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"pricingRuleId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"priceBookId\\\":{\\\"visibility\\\":\\\"hidden\\\"},\\\"pricingSnapshot\\\":{\\\"visibility\\\":\\\"hidden\\\"}}}},\\\"help\\\":{\\\"markdown\\\":\\\"## Overview\\\\n\\\\nSubscriptions is where you sell plans that renew. A plan says what it costs,\\\\nhow often it bills and whether it is free, a fixed price or pay what you can.\\\\nA subscription joins a subscriber to a plan and shows where it stands, from\\\\ntrial to active to cancelled. Every time you change a plan's terms, the\\\\nearlier terms are kept as a plan version, so a subscriber who already paid for\\\\na period keeps what they paid for until it renews. Charges show what each\\\\nsubscriber used and what it cost them.\\\\n\\\\nAll amounts are whole numbers of cents, with no decimal point.\\\\n\\\\n## Tasks\\\\n\\\\n### Set up a plan\\\\n\\\\n1. Open the plans and choose **New**.\\\\n2. Type the **{field:SubscriptionPlan.name}** customers will see and a short **{field:SubscriptionPlan.planKey}** such as \\\\\\\"starter\\\\\\\".\\\\n3. Choose **{field:SubscriptionPlan.pricingMode}**: free, a fixed price, or pay what you can. This cannot change once the plan is saved; make a new plan instead.\\\\n4. For a fixed price, enter the **{field:SubscriptionPlan.priceAmount}** in cents and the **{field:SubscriptionPlan.currency}**.\\\\n5. Set how often it bills in **{field:SubscriptionPlan.billingInterval}**.\\\\n6. Set the **{field:SubscriptionPlan.status}** to active when it is ready to sell.\\\\n7. Save.\\\\n\\\\n### Change a plan's price or terms\\\\n\\\\n1. Open the plan and edit the **{field:SubscriptionPlan.priceAmount}**, **{field:SubscriptionPlan.billingInterval}** or **{field:SubscriptionPlan.status}**.\\\\n2. Save. The new terms apply to new subscribers and to existing ones from their next renewal; a period already paid for keeps its old terms.\\\\n\\\\n### Retire a plan\\\\n\\\\n1. Open the plan and set its **{field:SubscriptionPlan.status}** to archived.\\\\n2. Save. No one new can subscribe to it; existing subscribers keep going until they cancel.\\\\n\\\\n### Subscribe someone to a plan\\\\n\\\\n1. Open the subscriptions and choose **New**.\\\\n2. Pick the **{field:TenantSubscription.planId}**.\\\\n3. Enter the day it **{field:TenantSubscription.startedAt}** and, if there is a free trial, when the **{field:TenantSubscription.trialEndsAt}**.\\\\n4. Save. The **{field:TenantSubscription.status}** shows where the subscription stands once it has been paid for.\\\\n\\\\n### See where a subscription stands\\\\n\\\\n1. Open the subscriptions and find the one you want.\\\\n2. The **{field:TenantSubscription.status}** shows whether it is still incomplete, on trial, active, past due, unpaid or cancelled.\\\\n3. **{field:TenantSubscription.currentPeriodStart}** and **{field:TenantSubscription.currentPeriodEnd}** show the period that has been paid for.\\\\n\\\\n### Cancel a subscription\\\\n\\\\n1. Open the subscription.\\\\n2. Tick **{field:TenantSubscription.cancelAtPeriodEnd}** so it runs out when the current period ends instead of renewing.\\\\n3. Save.\\\\n\\\\n### Look up the terms a subscriber was sold\\\\n\\\\nPlan versions are written automatically whenever a plan is saved with changed\\\\nterms; you cannot add or edit them here.\\\\n\\\\n1. Open the plan versions and find the **{field:SubscriptionPlanVersion.planId}** you are interested in.\\\\n2. Each row shows the **{field:SubscriptionPlanVersion.version}** and the date it was **{field:SubscriptionPlanVersion.effectiveFrom}**.\\\\n3. Read the **{field:SubscriptionPlanVersion.priceAmount}**, **{field:SubscriptionPlanVersion.currency}** and **{field:SubscriptionPlanVersion.billingInterval}** that applied under it.\\\\n\\\\n### See what a subscriber was charged\\\\n\\\\nCharges are created by the usage and billing service as usage is recorded;\\\\nyou cannot add or edit them here.\\\\n\\\\n1. Open the charges.\\\\n2. Each row shows **{field:ClientCharge.metricKey}**, **{field:ClientCharge.quantity}** and the **{field:ClientCharge.amount}** in cents.\\\\n3. The **{field:ClientCharge.status}** shows whether the charge is still a draft, approved or adjusted.\\\\n\\\",\\\"fieldRefs\\\":[\\\"ClientCharge.amount\\\",\\\"ClientCharge.metricKey\\\",\\\"ClientCharge.quantity\\\",\\\"ClientCharge.status\\\",\\\"SubscriptionPlan.billingInterval\\\",\\\"SubscriptionPlan.currency\\\",\\\"SubscriptionPlan.name\\\",\\\"SubscriptionPlan.planKey\\\",\\\"SubscriptionPlan.priceAmount\\\",\\\"SubscriptionPlan.pricingMode\\\",\\\"SubscriptionPlan.status\\\",\\\"SubscriptionPlanVersion.billingInterval\\\",\\\"SubscriptionPlanVersion.currency\\\",\\\"SubscriptionPlanVersion.effectiveFrom\\\",\\\"SubscriptionPlanVersion.planId\\\",\\\"SubscriptionPlanVersion.priceAmount\\\",\\\"SubscriptionPlanVersion.version\\\",\\\"TenantSubscription.cancelAtPeriodEnd\\\",\\\"TenantSubscription.currentPeriodEnd\\\",\\\"TenantSubscription.currentPeriodStart\\\",\\\"TenantSubscription.planId\\\",\\\"TenantSubscription.startedAt\\\",\\\"TenantSubscription.status\\\",\\\"TenantSubscription.trialEndsAt\\\"]},\\\"demo\\\":{\\\"mode\\\":\\\"server\\\",\\\"reasons\\\":[\\\"Needs a server because its package does not build for a browser: core migrations (node:crypto, node:os); and its package depends on @happyvertical/smrt-profiles, @happyvertical/smrt-tenancy, @happyvertical/smrt-users, which do not build for a browser (#3617, #3624, #3626).\\\"]}}],\\\"smrtDependencies\\\":[\\\"@happyvertical/smrt-core\\\",\\\"@happyvertical/smrt-features\\\",\\\"@happyvertical/smrt-tenancy\\\",\\\"@happyvertical/smrt-users\\\"],\\\"browser\\\":{\\\"status\\\":\\\"server-only\\\",\\\"issues\\\":[\\\"#3617\\\",\\\"#3624\\\",\\\"#3626\\\"],\\\"reason\\\":\\\"core migrations (node:crypto, node:os)\\\",\\\"via\\\":[\\\"@happyvertical/smrt-profiles\\\",\\\"@happyvertical/smrt-tenancy\\\",\\\"@happyvertical/smrt-users\\\"]},\\\"stampsConstructors\\\":true}\"));\n","/**\n * Host configuration surface for the billing glue (#4786).\n *\n * Environment variables, with the secrets held in non-enumerable properties so\n * a stray `JSON.stringify(config)` or `console.log(config)` cannot print them.\n * Error messages name the variable and never its value.\n */\nimport type { BillingUrls } from './types.js';\n\nexport const BILLING_ENV = {\n secretKey: 'STRIPE_SECRET_KEY',\n webhookSecret: 'STRIPE_WEBHOOK_SECRET',\n webhookTolerance: 'STRIPE_WEBHOOK_TOLERANCE',\n metadataSecret: 'BILLING_METADATA_SECRET',\n metadataPreviousSecrets: 'BILLING_METADATA_PREVIOUS_SECRETS',\n successUrl: 'BILLING_SUCCESS_URL',\n cancelUrl: 'BILLING_CANCEL_URL',\n portalReturnUrl: 'BILLING_PORTAL_RETURN_URL',\n} as const;\n\nexport const DEFAULT_WEBHOOK_TOLERANCE_SECONDS = 300;\nexport const MAX_WEBHOOK_TOLERANCE_SECONDS = 900;\n\n/** The env var holding the provider price id for a plan key. */\nexport function priceEnvName(planKey: string): string {\n return `STRIPE_PRICE_${planKey.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}`;\n}\n\nexport interface BillingEnvOptions {\n /** Plan keys whose `STRIPE_PRICE_<KEY>` variables should be read. */\n planKeys: readonly string[];\n}\n\nexport interface BillingEnvConfig {\n /**\n * Provider credentials for `getAccountingProvider({ type: 'stripe', … })`.\n * `secretKey` and `webhookSecret` are non-enumerable (they do not survive\n * a spread, `JSON.stringify` or `console.log`), so read them by name.\n */\n stripe: {\n readonly secretKey: string;\n readonly webhookSecret: string;\n webhookTolerance: number;\n };\n /**\n * Checkout-metadata signing (#4786). `signingSecret` is unset unless\n * `BILLING_METADATA_SECRET` is configured (the host then falls back to the\n * webhook secret). `previousSecrets` (comma-separated\n * `BILLING_METADATA_PREVIOUS_SECRETS`) are still accepted when a completed\n * checkout is verified, so rotating a secret does not drop sessions created\n * before the rotation. Both are non-enumerable.\n */\n metadata: {\n readonly signingSecret: string | undefined;\n readonly previousSecrets: readonly string[];\n };\n urls: BillingUrls;\n /** Plan key to price id for every plan whose variable is set. */\n prices: Record<string, string>;\n}\n\ntype Env = Record<string, string | undefined>;\n\nfunction read(env: Env, name: string): string | undefined {\n const value = env[name]?.trim();\n return value ? value : undefined;\n}\n\nfunction required(env: Env, name: string): string {\n const value = read(env, name);\n if (!value) throw new Error(`${name} is required.`);\n return value;\n}\n\n/**\n * Validate a redirect destination: absolute, no embedded credentials, and\n * https (plain http only for loopback development hosts).\n */\nexport function assertBillingUrl(name: string, value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(`${name} must be an absolute URL.`);\n }\n const loopback =\n url.hostname === 'localhost' ||\n url.hostname === '127.0.0.1' ||\n url.hostname === '[::1]' ||\n url.hostname.endsWith('.localhost');\n if (url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback)) {\n throw new Error(`${name} must use https.`);\n }\n if (url.username || url.password) {\n throw new Error(`${name} must not contain credentials.`);\n }\n // Returned as given: Checkout expands a literal `{CHECKOUT_SESSION_ID}`\n // placeholder that URL normalisation would percent-encode.\n return value;\n}\n\nexport function assertWebhookTolerance(seconds: number): number {\n if (\n !Number.isInteger(seconds) ||\n seconds < 1 ||\n seconds > MAX_WEBHOOK_TOLERANCE_SECONDS\n ) {\n throw new Error(\n `The webhook tolerance must be a whole number of seconds from 1 to ${MAX_WEBHOOK_TOLERANCE_SECONDS}.`,\n );\n }\n return seconds;\n}\n\n/** Read and validate billing configuration from an environment map. */\nexport function readBillingEnv(\n env: Env,\n options: BillingEnvOptions,\n): BillingEnvConfig {\n const secretKey = required(env, BILLING_ENV.secretKey);\n if (!/^(sk|rk)_/.test(secretKey)) {\n throw new Error(\n `${BILLING_ENV.secretKey} must be a secret key (sk_ or rk_).`,\n );\n }\n const webhookSecret = required(env, BILLING_ENV.webhookSecret);\n if (!webhookSecret.startsWith('whsec_')) {\n throw new Error(\n `${BILLING_ENV.webhookSecret} must be a webhook signing secret (whsec_).`,\n );\n }\n const toleranceText = read(env, BILLING_ENV.webhookTolerance);\n const tolerance = toleranceText\n ? Number(toleranceText)\n : DEFAULT_WEBHOOK_TOLERANCE_SECONDS;\n try {\n assertWebhookTolerance(tolerance);\n } catch {\n throw new Error(\n `${BILLING_ENV.webhookTolerance} must be a whole number of seconds from 1 to ${MAX_WEBHOOK_TOLERANCE_SECONDS}.`,\n );\n }\n\n const prices: Record<string, string> = {};\n for (const planKey of options.planKeys) {\n const price = read(env, priceEnvName(planKey));\n if (price) prices[planKey] = price;\n }\n\n const stripe = { webhookTolerance: tolerance } as BillingEnvConfig['stripe'];\n Object.defineProperty(stripe, 'secretKey', {\n value: secretKey,\n enumerable: false,\n });\n Object.defineProperty(stripe, 'webhookSecret', {\n value: webhookSecret,\n enumerable: false,\n });\n\n const metadata = {} as BillingEnvConfig['metadata'];\n Object.defineProperty(metadata, 'signingSecret', {\n value: read(env, BILLING_ENV.metadataSecret),\n enumerable: false,\n });\n Object.defineProperty(metadata, 'previousSecrets', {\n value: (read(env, BILLING_ENV.metadataPreviousSecrets) ?? '')\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean),\n enumerable: false,\n });\n\n return {\n stripe,\n metadata,\n prices,\n urls: {\n successUrl: assertBillingUrl(\n BILLING_ENV.successUrl,\n required(env, BILLING_ENV.successUrl),\n ),\n cancelUrl: assertBillingUrl(\n BILLING_ENV.cancelUrl,\n required(env, BILLING_ENV.cancelUrl),\n ),\n portalReturnUrl: assertBillingUrl(\n BILLING_ENV.portalReturnUrl,\n required(env, BILLING_ENV.portalReturnUrl),\n ),\n },\n };\n}\n","import { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSystemContext,\n TenantScoped,\n tenantId,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport {\n type PlanVersionReplacement,\n pinSubscriptionPlanVersion,\n} from '../plan-versioning.js';\nimport type {\n JsonObject,\n PlanVersionPinReason,\n Subscriber,\n SubscriberKind,\n SubscriptionStatus,\n TenantSubscriptionOptions,\n} from '../types.js';\nimport {\n assertSubscriberInvariant,\n parseJsonObject,\n stringifyJson,\n} from '../utils.js';\n\n/** In-period replacements requested through `replacePlanVersion()`. */\nconst pendingReplacements = new WeakMap<\n TenantSubscription,\n PlanVersionReplacement\n>();\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_tenant_subscriptions',\n api: { include: ['list', 'get', 'create', 'update'] },\n cli: { skipApiCheck: true },\n mcp: { include: ['list', 'get'] },\n // The conflict key includes the subscriber discriminator so an issuing tenant\n // can host many distinct external subscribers without collisions on the\n // unique index:\n // - tenant-kind rows always have subscriber_external_id = '' → uniqueness\n // reduces to (tenant_id, 'tenant', '') = at most one tenant-kind row per\n // tenant (preserves the pre-polymorphic invariant).\n // - external-kind rows are unique on (tenant_id, 'external', externalId) =\n // at most one active subscription per (issuer, external subscriber).\n //\n // UPGRADE NOTE: databases created against the pre-#1454 conflict key\n // ['tenant_id'] still carry the legacy `_smrt_tenant_subscriptions_tenant_id_idx`.\n // `smrt db:migrate` does not sweep orphan indexes by default, so the legacy\n // index persists and continues to reject external subscriptions until it's\n // dropped. Run scripts/migrate-1454-drop-legacy-conflict-index.ts once on\n // upgrade, or pass `--drop-indexes` to `db:migrate`. Fresh databases need\n // neither — the generated schema already reflects the new key.\n conflictColumns: ['tenant_id', 'subscriber_kind', 'subscriber_external_id'],\n})\nexport class TenantSubscription extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId()\n tenantId?: string;\n\n /**\n * Discriminator for the subscriber identity.\n *\n * - `'tenant'` (default): the subscriber IS the owning `tenantId` — the\n * pre-polymorphic shape. All existing rows continue to behave this way.\n * - `'external'`: the subscriber is `subscriberExternalId`, scoped under the\n * issuing `tenantId`. Used for B2C buyers, anonymous-email subscribers,\n * agent identities, and any other caller-defined identity.\n */\n @field({\n description:\n 'Whether the subscriber is your own workspace (tenant) or an outside customer (external).',\n })\n subscriberKind: SubscriberKind = 'tenant';\n\n /**\n * Caller-namespaced opaque identifier for the subscriber when\n * `subscriberKind === 'external'`. Empty string when kind is `'tenant'`.\n *\n * The package treats this as opaque — no FK, no inferred semantics. Callers\n * are expected to namespace (e.g. `buyer-contact:abc123`,\n * `agent:hermes-7`, `email:foo@example.com`).\n */\n @field({\n description:\n 'Who the outside subscriber is, when the subscriber type is external.',\n })\n subscriberExternalId: string = '';\n\n @field({ description: 'The plan this subscription is for.' })\n @foreignKey('SubscriptionPlan')\n planId: string = '';\n\n @field({\n description:\n 'Where the subscription stands: incomplete, trialing, active, past due, unpaid or cancelled.',\n })\n status: SubscriptionStatus = 'incomplete';\n @field({ description: 'The day the subscription began.' })\n startedAt: Date = new Date();\n @field({ description: 'When the current billing period began.' })\n currentPeriodStart: Date | null = null;\n @field({\n description:\n 'When the current billing period ends and the next one is due.',\n })\n currentPeriodEnd: Date | null = null;\n @field({ description: 'When the free trial ends, if there is one.' })\n trialEndsAt: Date | null = null;\n @field({\n description:\n 'Tick to let the subscription run out at the end of the current period instead of renewing.',\n })\n cancelAtPeriodEnd: boolean = false;\n @field({ description: 'When the subscription was cancelled.' })\n canceledAt: Date | null = null;\n /** Amount selected for this subscription, in integer minor units. */\n @field({\n description:\n 'For a pay-what-you-can plan, the amount the subscriber chose to pay, in cents.',\n })\n agreedAmount: number | null = null;\n /**\n * The immutable `SubscriptionPlanVersion` frozen for the current period\n * (#4032). Maintained on save: pinned at period start, re-pinned when\n * `currentPeriodStart` moves (renewal), and replaced mid-period only by an\n * entitlement upgrade or an authorized {@link replacePlanVersion}. Null\n * only for subscriptions to unmigrated legacy plans with no versions.\n */\n @field({\n description:\n 'The version of the plan terms this subscription is held to for the current period. It is kept up to date automatically.',\n })\n @foreignKey('SubscriptionPlanVersion')\n planVersionId: string | null = null;\n /** When {@link planVersionId} was last set. */\n planVersionPinnedAt: Date | null = null;\n /** Why {@link planVersionId} was last set (audit). */\n planVersionPinReason: PlanVersionPinReason | null = null;\n /** Caller-supplied reason for an `upgrade`/`authorized` replacement. */\n planVersionPinNote: string = '';\n /**\n * Set when the row was canceled while it entitled (`active`/`trialing`\n * within its period), so the paid period runs to `currentPeriodEnd`.\n * Derived on save from the stored row and never taken from the caller: a\n * subscription canceled while `incomplete`, `past_due` or `unpaid` (for\n * example a provider's `incomplete_expired`) entitles nothing.\n */\n retainsPaidPeriod: boolean = false;\n externalProvider: string | null = null;\n stripeCustomerId: string = '';\n stripeSubscriptionId: string = '';\n stripeCheckoutSessionId: string = '';\n metadata: string = '{}';\n\n constructor(options: TenantSubscriptionOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.subscriberKind !== undefined)\n this.subscriberKind = options.subscriberKind;\n if (options.subscriberExternalId !== undefined)\n this.subscriberExternalId = options.subscriberExternalId;\n // Enforce the subscriber XOR invariant at construction time so callers\n // catch mistakes early. The same check also runs in `validateBeforeSave`\n // below so the generated PUT/PATCH update path — which mutates an existing\n // instance via `Object.assign()` and bypasses this constructor — can't\n // sneak a malformed row past us either.\n assertSubscriberInvariant('TenantSubscription', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (options.planId !== undefined) this.planId = options.planId;\n if (options.status !== undefined) this.status = options.status;\n if (options.startedAt !== undefined) this.startedAt = options.startedAt;\n if (options.currentPeriodStart !== undefined) {\n this.currentPeriodStart = options.currentPeriodStart;\n }\n if (options.currentPeriodEnd !== undefined) {\n this.currentPeriodEnd = options.currentPeriodEnd;\n }\n if (options.trialEndsAt !== undefined)\n this.trialEndsAt = options.trialEndsAt;\n if (options.cancelAtPeriodEnd !== undefined) {\n this.cancelAtPeriodEnd = options.cancelAtPeriodEnd;\n }\n if (options.canceledAt !== undefined) this.canceledAt = options.canceledAt;\n if (options.agreedAmount !== undefined)\n this.agreedAmount = options.agreedAmount;\n if (options.planVersionId !== undefined)\n this.planVersionId = options.planVersionId;\n if (options.planVersionPinnedAt !== undefined)\n this.planVersionPinnedAt = options.planVersionPinnedAt;\n if (options.planVersionPinReason !== undefined)\n this.planVersionPinReason = options.planVersionPinReason;\n if (options.planVersionPinNote !== undefined)\n this.planVersionPinNote = options.planVersionPinNote;\n if (options.retainsPaidPeriod !== undefined)\n this.retainsPaidPeriod = options.retainsPaidPeriod;\n if (options.externalProvider !== undefined) {\n this.externalProvider = options.externalProvider;\n }\n if (options.stripeCustomerId !== undefined) {\n this.stripeCustomerId = options.stripeCustomerId;\n }\n if (options.stripeSubscriptionId !== undefined) {\n this.stripeSubscriptionId = options.stripeSubscriptionId;\n }\n if (options.stripeCheckoutSessionId !== undefined) {\n this.stripeCheckoutSessionId = options.stripeCheckoutSessionId;\n }\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Validates the subscriber XOR invariant before every save. Critical for the\n * generated update path: `SmrtCollection.update()` mutates the existing\n * instance via `Object.assign()` and calls `save()` directly — the\n * constructor never re-runs, so without this hook a partial update like\n * `{ subscriberExternalId: 'buyer:alice' }` on a tenant-kind row would\n * persist a malformed conflict key and let two tenant-kind rows coexist\n * under the same tenant.\n */\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n assertSubscriberInvariant('TenantSubscription', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (\n this.agreedAmount !== null &&\n (!Number.isSafeInteger(this.agreedAmount) || this.agreedAmount < 0)\n ) {\n throw new Error(\n 'agreedAmount must be a non-negative integer minor-unit amount',\n );\n }\n const plans = await SubscriptionPlanCollection.create({ db: this.db });\n // Ordinary reads inherit the caller's tenancy. The bounded global fallback\n // permits legacy public plans without exposing any other tenant's plan.\n const scopedPlan = await plans.get({ id: this.planId }, { cache: false });\n const plan =\n scopedPlan ??\n (await withSystemContext(() =>\n plans.get({ id: this.planId, tenantId: null }, { cache: false }),\n ));\n if (\n !plan ||\n (!isSystemContext() &&\n plan.tenantId !== null &&\n plan.tenantId !== (this.tenantId ?? getTenantId() ?? null))\n ) {\n throw new Error('Subscription plan is unavailable');\n }\n if (plan.pricingMode === 'pay_what_you_can') {\n if (\n this.agreedAmount === null ||\n this.agreedAmount < plan.minimumAmount\n ) {\n throw new Error('agreedAmount must meet the plan minimumAmount');\n }\n } else if (this.agreedAmount !== null) {\n throw new Error('agreedAmount requires a pay_what_you_can plan');\n }\n const replacement = pendingReplacements.get(this);\n pendingReplacements.delete(this);\n const { TenantSubscriptionCollection } = await import(\n '../collections/TenantSubscriptionCollection.js'\n );\n // The row this save replaces: by id, or — for a create that will\n // upsert onto an existing subscriber row — by the natural key, so a\n // re-create cannot bypass the paid-period rules.\n const subscriptions = await TenantSubscriptionCollection.create({\n db: this.db,\n });\n const persisted =\n (this.id\n ? await subscriptions.get({ id: String(this.id) }, { cache: false })\n : null) ??\n (this.isPersisted\n ? null\n : ((\n await subscriptions.list({\n where: {\n tenantId: this.tenantId ?? getTenantId() ?? null,\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n },\n limit: 1,\n })\n )[0] ?? null));\n if (this.status !== 'canceled') {\n this.retainsPaidPeriod = false;\n } else if (persisted?.status === 'canceled') {\n this.retainsPaidPeriod = persisted.retainsPaidPeriod;\n } else {\n this.retainsPaidPeriod =\n persisted !== null &&\n (persisted.status === 'active' || persisted.status === 'trialing') &&\n persisted.isEntitled();\n }\n await pinSubscriptionPlanVersion(this, persisted, replacement);\n }\n\n /**\n * Replace the plan version frozen for the current period and save (#4032).\n *\n * - `policy: 'upgrade'` succeeds only when the target's entitlements cover\n * the frozen version's (see `isEntitlementUpgrade`); otherwise the save\n * is rejected and the paid period keeps its terms.\n * - `policy: 'authorized'` accepts any target and requires a `reason`,\n * recorded with `planVersionPinReason: 'authorized'` for audit — use it\n * for an operator-approved downgrade, refund, or correction.\n *\n * The target is `planVersionId`, else the version of `planId` (as set on\n * this instance) in force now. A plain `planId` change in the same period\n * is treated as `policy: 'upgrade'`.\n */\n async replacePlanVersion(\n options: PlanVersionReplacement & { planId?: string },\n ): Promise<this> {\n const { planId, ...replacement } = options;\n if (planId !== undefined) this.planId = planId;\n pendingReplacements.set(this, replacement);\n try {\n return await this.save();\n } finally {\n pendingReplacements.delete(this);\n }\n }\n\n /**\n * Whether the subscription grants entitlements at `now`. Active and\n * trialing subscriptions entitle until `currentPeriodEnd`. A subscription\n * canceled while it entitled keeps its paid period ({@link\n * retainsPaidPeriod}) until `currentPeriodEnd`, never without one (#4032).\n * For an immediate cancellation (for example with a refund) set\n * `currentPeriodEnd` to the cancellation time.\n */\n isEntitled(now = new Date()): boolean {\n const end = this.currentPeriodEnd\n ? new Date(this.currentPeriodEnd).getTime()\n : null;\n if (this.status === 'canceled') {\n return this.retainsPaidPeriod && end !== null && now.getTime() <= end;\n }\n if (this.status !== 'active' && this.status !== 'trialing') {\n return false;\n }\n if (end !== null && end < now.getTime()) {\n return false;\n }\n return true;\n }\n\n /**\n * Project this row's polymorphic subscriber columns onto the\n * {@link Subscriber} discriminated union. Returns `null` when the owning\n * tenant is absent — that's an invalid row that should not be acted on.\n */\n getSubscriber(): Subscriber | null {\n if (!this.tenantId) {\n return null;\n }\n if (this.subscriberKind === 'external') {\n if (!this.subscriberExternalId) {\n return null;\n }\n return {\n kind: 'external',\n tenantId: this.tenantId,\n externalId: this.subscriberExternalId,\n };\n }\n return { kind: 'tenant', tenantId: this.tenantId };\n }\n\n getMetadata(): JsonObject {\n return parseJsonObject(this.metadata, {});\n }\n\n setMetadata(metadata: JsonObject): void {\n this.metadata = stringifyJson(metadata);\n }\n}\n\nexport default TenantSubscription;\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { TenantSubscription } from '../models/TenantSubscription.js';\nimport type { Subscriber } from '../types.js';\n\nexport class TenantSubscriptionCollection extends SmrtCollection<TenantSubscription> {\n static readonly _itemClass = TenantSubscription;\n\n /**\n * List subscriptions whose owning tenant scope is `tenantId`. Includes both\n * `'tenant'`-kind (subscriber == owner) and `'external'`-kind (subscriber is\n * an external identity scoped under this tenant) rows.\n */\n async findByTenant(tenantId: string): Promise<TenantSubscription[]> {\n return this.list({\n where: { tenantId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Legacy single-tenant accessor: returns the current subscription where the\n * tenant IS the subscriber (`subscriberKind = 'tenant'`). External-kind rows\n * scoped under this tenant are intentionally excluded so existing callers\n * are not surprised by buyer/agent subscriptions.\n */\n async findCurrentForTenant(\n tenantId: string,\n now = new Date(),\n ): Promise<TenantSubscription | null> {\n return this.findCurrentForSubscriber({ kind: 'tenant', tenantId }, now);\n }\n\n /**\n * Polymorphic current-subscription accessor.\n *\n * For `'tenant'` subscribers we match rows with `subscriberKind = 'tenant'`\n * under the same `tenantId`. For `'external'` subscribers we match by\n * `(tenantId, subscriberExternalId)` with `subscriberKind = 'external'`.\n */\n async findCurrentForSubscriber(\n subscriber: Subscriber,\n now = new Date(),\n ): Promise<TenantSubscription | null> {\n const where: Record<string, unknown> = {\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n };\n if (subscriber.kind === 'external') {\n where.subscriberExternalId = subscriber.externalId;\n }\n\n const subscriptions = await this.list({\n where,\n orderBy: 'created_at DESC',\n });\n return (\n subscriptions.find((subscription) => subscription.isEntitled(now)) ??\n subscriptions[0] ??\n null\n );\n }\n\n async findByStripeSubscriptionId(\n stripeSubscriptionId: string,\n ): Promise<TenantSubscription | null> {\n const subscriptions = await this.list({\n where: { stripeSubscriptionId },\n limit: 1,\n });\n return subscriptions[0] ?? null;\n }\n}\n","import {\n field,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\n\n/**\n * Where a Checkout session the billing host created stands (#4814).\n *\n * - `pending`: created by the host, not yet completed.\n * - `completed`: the paid session was linked to its tenant (single use).\n * - `needs_reconciliation`: a paid session whose record was missing, expired\n * or did not match. It is not linked; an operator links it on purpose with\n * `BillingHost.reconcileCheckout()`.\n */\nexport type BillingCheckoutSessionStatus =\n | 'pending'\n | 'completed'\n | 'needs_reconciliation'\n | 'dismissed';\n\n/**\n * One Checkout session created by the billing host, recorded when the host\n * creates it and required when the paid session completes, so signed\n * metadata copied onto another integration's session is never trusted.\n * `sessionId` is the provider's unguessable, unique id and doubles as the\n * single-use nonce.\n *\n * A system table managed through `createBillingHost()`, like\n * `_smrt_price_book_assignments`; it has no generated API surface. It is a\n * root export because the published manifest advertises it. `tenantId` is the\n * tenant the host created the session for (`''` on a row opened for a session\n * the host never recorded).\n */\n@smrt({\n tableName: '_smrt_billing_checkout_sessions',\n conflictColumns: ['session_id'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class BillingCheckoutSession extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @field({ required: true })\n sessionId: string = '';\n @field({ description: 'The tenant the host created the session for.' })\n targetTenantId: string = '';\n status: BillingCheckoutSessionStatus = 'pending';\n expiresAt: Date = new Date(0);\n completedAt: Date | null = null;\n /** Why the row needs reconciliation (a code, never provider text). */\n reason: string = '';\n /** JSON ids needed to reconcile: event, subscription, customer, plan. */\n detail: string = '{}';\n}\n\nexport class BillingCheckoutSessionCollection extends SmrtCollection<BillingCheckoutSession> {\n static readonly _itemClass = BillingCheckoutSession;\n}\n","/**\n * Normalise verified Stripe webhook payloads into the facts this module acts\n * on (#4786). Pure: no I/O, no trust decisions beyond reading shapes.\n */\nimport type { SubscriptionStatus } from '../types.js';\nimport type { BillingSubscriptionState } from './types.js';\n\nexport const SUBSCRIPTION_EVENT_TYPES = new Set([\n 'customer.subscription.created',\n 'customer.subscription.updated',\n 'customer.subscription.deleted',\n 'customer.subscription.paused',\n 'customer.subscription.resumed',\n]);\n\nexport const CHECKOUT_COMPLETED = 'checkout.session.completed';\nexport const SUBSCRIPTION_DELETED = 'customer.subscription.deleted';\n\n/** What the provider says about one subscription at a point in time. */\nexport interface SubscriptionSnapshot {\n subscriptionId: string;\n customerId: string;\n status: SubscriptionStatus;\n priceId?: string;\n startedAt?: Date | null;\n currentPeriodStart?: Date | null;\n currentPeriodEnd?: Date | null;\n trialEndsAt?: Date | null;\n cancelAtPeriodEnd?: boolean;\n canceledAt?: Date | null;\n endedAt?: Date | null;\n}\n\nexport interface CheckoutCompletedFacts {\n sessionId: string;\n mode: string | undefined;\n paymentStatus: string | undefined;\n customerId: string | undefined;\n subscriptionId: string | undefined;\n metadata: Record<string, string>;\n}\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport function asRecord(value: unknown): UnknownRecord | null {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nexport function asString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\n/** A Stripe id that is either a string or an expanded `{ id }` object. */\nexport function externalId(value: unknown): string | undefined {\n return asString(value) ?? asString(asRecord(value)?.id);\n}\n\nexport function stripeObject(payload: unknown): UnknownRecord | null {\n return asRecord(asRecord(asRecord(payload)?.data)?.object);\n}\n\nexport function toDate(value: unknown): Date | null {\n if (value instanceof Date) {\n return Number.isFinite(value.getTime()) ? value : null;\n }\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) {\n return new Date(value * 1000);\n }\n return null;\n}\n\nconst STATUS_MAP: Record<string, SubscriptionStatus> = {\n active: 'active',\n trialing: 'trialing',\n past_due: 'past_due',\n unpaid: 'unpaid',\n canceled: 'canceled',\n incomplete: 'incomplete',\n // An abandoned first payment never entitled anything.\n incomplete_expired: 'canceled',\n // Paused subscriptions do not entitle.\n paused: 'unpaid',\n};\n\n/** Unknown provider statuses fail closed to a non-entitling status. */\nexport function mapSubscriptionStatus(\n value: string | undefined,\n): SubscriptionStatus {\n return (value && STATUS_MAP[value]) || 'incomplete';\n}\n\nfunction stringMap(value: unknown): Record<string, string> {\n const result: Record<string, string> = {};\n const record = asRecord(value);\n if (!record) return result;\n for (const [key, entry] of Object.entries(record)) {\n if (typeof entry === 'string') result[key] = entry;\n }\n return result;\n}\n\nfunction itemList(object: UnknownRecord): UnknownRecord[] {\n const data = asRecord(object.items)?.data;\n return Array.isArray(data)\n ? data.map(asRecord).filter((item): item is UnknownRecord => item !== null)\n : [];\n}\n\n/** The first line-item price id: what the provider actually bills. */\nexport function subscriptionPriceId(object: UnknownRecord): string | undefined {\n for (const item of itemList(object)) {\n const price = externalId(asRecord(item.price)?.id ?? item.price);\n if (price) return price;\n }\n return undefined;\n}\n\n/**\n * Billing periods live on the subscription in older API versions and on its\n * items in newer ones; read either.\n */\nfunction periodDate(\n object: UnknownRecord,\n key: 'current_period_start' | 'current_period_end',\n): Date | null | undefined {\n if (key in object) return toDate(object[key]);\n for (const item of itemList(object)) {\n if (key in item) return toDate(item[key]);\n }\n return undefined;\n}\n\n/** Facts from a `customer.subscription.*` event object. */\nexport function subscriptionSnapshotFromObject(\n object: UnknownRecord,\n eventType: string,\n): SubscriptionSnapshot | null {\n const subscriptionId = asString(object.id);\n const customerId = externalId(object.customer);\n if (!subscriptionId || !customerId) return null;\n return {\n subscriptionId,\n customerId,\n status:\n eventType === SUBSCRIPTION_DELETED\n ? 'canceled'\n : mapSubscriptionStatus(asString(object.status)),\n priceId: subscriptionPriceId(object),\n startedAt: toDate(object.start_date),\n currentPeriodStart: periodDate(object, 'current_period_start'),\n currentPeriodEnd: periodDate(object, 'current_period_end'),\n trialEndsAt: 'trial_end' in object ? toDate(object.trial_end) : undefined,\n cancelAtPeriodEnd:\n typeof object.cancel_at_period_end === 'boolean'\n ? object.cancel_at_period_end\n : undefined,\n canceledAt:\n 'canceled_at' in object ? toDate(object.canceled_at) : undefined,\n endedAt: 'ended_at' in object ? toDate(object.ended_at) : undefined,\n };\n}\n\n/** Facts from a provider subscription read back through the SDK. */\nexport function subscriptionSnapshotFromState(\n state: BillingSubscriptionState,\n): SubscriptionSnapshot {\n const raw = asRecord(state.raw);\n return {\n subscriptionId: state.externalId,\n customerId: state.customerExternalId,\n status: mapSubscriptionStatus(state.status),\n priceId: raw ? subscriptionPriceId(raw) : undefined,\n startedAt: raw && 'start_date' in raw ? toDate(raw.start_date) : undefined,\n currentPeriodStart:\n state.currentPeriodStart ??\n (raw ? periodDate(raw, 'current_period_start') : undefined),\n currentPeriodEnd:\n state.currentPeriodEnd ??\n (raw ? periodDate(raw, 'current_period_end') : undefined),\n trialEndsAt: state.trialEnd ?? null,\n cancelAtPeriodEnd: state.cancelAtPeriodEnd,\n canceledAt: state.canceledAt ?? null,\n endedAt: raw && 'ended_at' in raw ? toDate(raw.ended_at) : undefined,\n };\n}\n\nexport function checkoutFactsFromObject(\n object: UnknownRecord,\n): CheckoutCompletedFacts | null {\n const sessionId = asString(object.id);\n if (!sessionId) return null;\n return {\n sessionId,\n mode: asString(object.mode),\n paymentStatus: asString(object.payment_status),\n customerId: externalId(object.customer),\n subscriptionId: externalId(object.subscription),\n metadata: stringMap(object.metadata),\n };\n}\n","/**\n * Plan lookup, price mapping and purchasability for the billing glue (#4786).\n *\n * Plans are read in a system context and then checked explicitly: a plan is\n * visible to a tenant only when it is the tenant's own or a global\n * (`tenantId: null`) plan. The provider price always comes from server\n * configuration or the plan's own binding, never from a request.\n */\n\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\n\nexport function planVisibleToTenant(\n plan: SubscriptionPlan,\n tenantId: string,\n): boolean {\n return plan.tenantId === null || plan.tenantId === tenantId;\n}\n\nfunction providerIsStripe(plan: SubscriptionPlan): boolean {\n return !plan.externalProvider || plan.externalProvider === 'stripe';\n}\n\n/** The provider price id a plan is sold under, or undefined when unset. */\nexport function priceIdForPlan(\n plan: SubscriptionPlan,\n prices: Record<string, string> | undefined,\n): string | undefined {\n const configured = prices?.[plan.planKey]?.trim();\n if (configured) return configured;\n if (!providerIsStripe(plan)) return undefined;\n return (\n plan.providerPriceId?.trim() || plan.stripePriceId?.trim() || undefined\n );\n}\n\n/**\n * Whose plans may be sold and resolved from a provider price. `deny` (the\n * default) is operator plans only: a tenant that can write its own\n * `SubscriptionPlan` rows (for example through a mounted generated API) cannot\n * mint a plan, or shadow a global plan key, and buy the entitlements it wrote.\n */\nexport type TenantPlanPolicy = 'deny' | 'allow';\n\nexport class PlanDirectory {\n constructor(\n private readonly db: DatabaseInterface,\n private readonly prices: Record<string, string> | undefined,\n private readonly tenantPlans: TenantPlanPolicy = 'deny',\n ) {}\n\n private sellable(plan: SubscriptionPlan, tenantId: string): boolean {\n return this.tenantPlans === 'allow'\n ? planVisibleToTenant(plan, tenantId)\n : plan.tenantId === null;\n }\n\n /**\n * The plan a subscription row already points at, for status-only updates:\n * visibility only, so a row on a legacy tenant plan keeps resolving.\n */\n async findExisting(\n tenantId: string,\n planId: string,\n ): Promise<SubscriptionPlan | null> {\n return withSystemContext(async () => {\n const plan = await (await this.collection()).get(\n { id: planId },\n { cache: false },\n );\n return plan && planVisibleToTenant(plan, tenantId) ? plan : null;\n });\n }\n\n private collection(): Promise<SubscriptionPlanCollection> {\n return SubscriptionPlanCollection.create({ db: this.db });\n }\n\n /** A plan `tenantId` may buy, by key (own plan first if allowed) or by id. */\n async find(\n tenantId: string,\n ref: { planKey?: string; planId?: string },\n ): Promise<SubscriptionPlan | null> {\n return withSystemContext(async () => {\n const plans = await this.collection();\n if (ref.planId) {\n const plan = await plans.get({ id: ref.planId }, { cache: false });\n return plan && this.sellable(plan, tenantId) ? plan : null;\n }\n if (ref.planKey) {\n const own =\n this.tenantPlans === 'allow'\n ? await plans.findByPlanKey(tenantId, ref.planKey)\n : null;\n return own ?? (await plans.findByPlanKey(null, ref.planKey));\n }\n return null;\n });\n }\n\n /**\n * The plan a provider price id is sold as, for `tenantId`: configured\n * price map first, then plan price bindings. The tenant's own plan beats a\n * global one.\n */\n async findByPriceId(\n tenantId: string,\n priceId: string,\n ): Promise<SubscriptionPlan | null> {\n const mappedKeys = Object.entries(this.prices ?? {})\n .filter(([, price]) => price === priceId)\n .map(([planKey]) => planKey);\n return withSystemContext(async () => {\n const plans = await this.collection();\n const candidates: SubscriptionPlan[] = [];\n for (const planKey of mappedKeys) {\n const own =\n this.tenantPlans === 'allow'\n ? await plans.findByPlanKey(tenantId, planKey)\n : null;\n const global = await plans.findByPlanKey(null, planKey);\n if (own) candidates.push(own);\n if (global) candidates.push(global);\n }\n if (candidates.length === 0) {\n candidates.push(\n ...(await plans.list({ where: { providerPriceId: priceId } })),\n ...(await plans.list({ where: { stripePriceId: priceId } })),\n );\n }\n const visible = candidates\n .filter(\n (plan) => this.sellable(plan, tenantId) && providerIsStripe(plan),\n )\n .sort(\n (a, b) =>\n Number(b.tenantId === tenantId) - Number(a.tenantId === tenantId),\n );\n return visible[0] ?? null;\n });\n }\n}\n","/**\n * Apply verified provider facts to `TenantSubscription` (#4786).\n *\n * Runs inside the idempotency transaction, so every read and write here uses\n * the transaction handle it is given. Provider ids link a subscription to\n * exactly one tenant; an event that disagrees with an existing link is\n * refused (and reported), never merged.\n *\n * Out-of-order delivery converges because each applied event records its\n * provider `created` time on the row and an older event is skipped; a\n * cancellation also wins a same-second tie. A plan change is applied as an\n * authorised plan-version replacement so a downgrade made in the provider is\n * honoured mid-period (the provider, which billed it, is the authority) while\n * the pinning audit trail records why.\n */\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport type { JsonObject, SubscriptionStatus } from '../types.js';\nimport { CHECKOUT_COMPLETED, type SubscriptionSnapshot } from './events.js';\nimport { PlanDirectory } from './plans.js';\nimport type { BillingLogger } from './types.js';\n\n/** JSON-safe result stored with the idempotency claim and replayed. */\nexport interface AppliedOutcome {\n action: 'applied' | 'ignored' | 'needs_reconciliation';\n reason?: string;\n}\n\nexport interface ApplyContext {\n db: DatabaseInterface;\n tenantPlans: 'deny' | 'allow';\n /** PostgreSQL: serialize concurrent events for one subscription or tenant. */\n postgres: boolean;\n prices: Record<string, string> | undefined;\n logger: BillingLogger | undefined;\n}\n\ninterface EventFacts {\n eventId: string;\n eventType: string;\n /** The provider's own event time (whole seconds). */\n eventCreated: Date;\n /** When the snapshot was read, if it was read rather than delivered. */\n observedAt?: Date;\n}\n\nconst ENTITLEMENT_CLAIMING = new Set([\n 'active',\n 'trialing',\n 'past_due',\n 'unpaid',\n]);\n\n/**\n * Serialize applies that touch the same provider subscription or tenant on\n * PostgreSQL, where two transactions can otherwise both read the row before\n * either writes and let an older event overwrite a newer one. Transaction-\n * scoped, taken in sorted order. Embedded engines already have one writer.\n */\nexport async function lockBillingKeys(\n ctx: Pick<ApplyContext, 'db' | 'postgres'>,\n keys: string[],\n): Promise<void> {\n if (!ctx.postgres) return;\n for (const key of [...new Set(keys)].sort()) {\n await ctx.db.query(\n 'SELECT pg_advisory_xact_lock(hashtextextended($1, 0))',\n `smrt-subscriptions:billing:${key}`,\n );\n }\n}\n\nfunction ignored(\n ctx: ApplyContext,\n facts: EventFacts,\n reason: string,\n fields: Record<string, unknown> = {},\n): AppliedOutcome {\n ctx.logger?.warn?.('billing.event.ignored', {\n eventId: facts.eventId,\n eventType: facts.eventType,\n reason,\n ...fields,\n });\n return { action: 'ignored', reason };\n}\n\ninterface LastApplied {\n eventId?: string;\n at?: Date;\n terminal: boolean;\n}\n\nfunction readLastApplied(row: TenantSubscription): LastApplied {\n const stripe = row.getMetadata().stripe;\n if (!stripe || typeof stripe !== 'object' || Array.isArray(stripe)) {\n return { terminal: false };\n }\n const block = stripe as JsonObject;\n const at =\n typeof block.lastEventAt === 'string' ? new Date(block.lastEventAt) : null;\n return {\n eventId:\n typeof block.lastEventId === 'string' ? block.lastEventId : undefined,\n at: at && Number.isFinite(at.getTime()) ? at : undefined,\n terminal: block.terminal === true,\n };\n}\n\n/** The price the row was last granted for (`metadata.stripe.priceId`). */\nfunction readRecordedPrice(row: TenantSubscription): string | undefined {\n const stripe = row.getMetadata().stripe;\n if (!stripe || typeof stripe !== 'object' || Array.isArray(stripe)) {\n return undefined;\n }\n const price = (stripe as JsonObject).priceId;\n return typeof price === 'string' && price ? price : undefined;\n}\n\n/**\n * A row held for an unmapped price still has a live provider subscription\n * (`metadata.stripe.held`): checkout must not sell a second one over it.\n */\nexport function isHeldSubscription(row: TenantSubscription): boolean {\n const stripe = row.getMetadata().stripe;\n return (\n row.status !== 'canceled' &&\n !!stripe &&\n typeof stripe === 'object' &&\n !Array.isArray(stripe) &&\n (stripe as JsonObject).held === HELD_PRICE_UNMAPPED\n );\n}\n\nconst HELD_PRICE_UNMAPPED = 'price_unmapped';\n\n/** Entitling statuses become `incomplete` while an unmapped price is held. */\nconst HELD_STATUS: Partial<Record<SubscriptionStatus, SubscriptionStatus>> = {\n active: 'incomplete',\n trialing: 'incomplete',\n past_due: 'incomplete',\n};\n\nfunction isStale(last: LastApplied, facts: EventFacts): boolean {\n if (last.eventId && last.eventId === facts.eventId) return true;\n if (!last.at) return false;\n const delta = facts.eventCreated.getTime() - last.at.getTime();\n if (delta < 0) return true;\n // Events carry whole-second times; a cancellation wins a same-second tie.\n return delta === 0 && last.terminal && facts.eventType !== CHECKOUT_COMPLETED;\n}\n\nfunction stripeMetadata(\n row: TenantSubscription | null,\n facts: EventFacts,\n snapshot: SubscriptionSnapshot,\n planKey: string,\n resetProvider: boolean,\n held = false,\n): JsonObject {\n const base = row ? row.getMetadata() : {};\n // A different provider subscription starts its own event history.\n const prior =\n !resetProvider &&\n base.stripe &&\n typeof base.stripe === 'object' &&\n !Array.isArray(base.stripe)\n ? (base.stripe as JsonObject)\n : {};\n const observed = facts.observedAt\n ? new Date(Math.floor(facts.observedAt.getTime() / 1000) * 1000)\n : undefined;\n const at =\n observed && observed.getTime() > facts.eventCreated.getTime()\n ? observed\n : facts.eventCreated;\n const { held: _previouslyHeld, ...carried } = prior;\n return {\n ...base,\n planKey,\n stripe: {\n ...carried,\n ...(held ? { held: HELD_PRICE_UNMAPPED } : {}),\n lastEventId: facts.eventId,\n lastEventType: facts.eventType,\n lastEventAt: at.toISOString(),\n priceId:\n snapshot.priceId ?? (prior.priceId as string | undefined) ?? null,\n terminal: snapshot.status === 'canceled',\n },\n };\n}\n\nasync function listRows(\n db: DatabaseInterface,\n where: Record<string, unknown>,\n): Promise<TenantSubscription[]> {\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n return subscriptions.list({ where, limit: 3 });\n}\n\nfunction dateOrKeep(\n next: Date | null | undefined,\n current: Date | null | undefined,\n): Date | null {\n return next !== undefined ? next : (current ?? null);\n}\n\ninterface RowWrite {\n tenantId: string;\n existing: TenantSubscription | null;\n plan: SubscriptionPlan;\n snapshot: SubscriptionSnapshot;\n facts: EventFacts;\n checkoutSessionId?: string;\n /** The row is held for an unmapped price (see `isHeldSubscription`). */\n held?: boolean;\n}\n\nasync function writeRow(\n ctx: ApplyContext,\n write: RowWrite,\n): Promise<AppliedOutcome> {\n const { existing, plan, snapshot, facts } = write;\n const planId = String(plan.id);\n const newSubscription =\n !existing || existing.stripeSubscriptionId !== snapshot.subscriptionId;\n const base = newSubscription ? null : existing;\n\n let periodEnd = dateOrKeep(snapshot.currentPeriodEnd, base?.currentPeriodEnd);\n if (snapshot.status === 'canceled') {\n // Cancellation ends access when it happened, not at the paid-through date\n // of an immediately cancelled subscription, and never later than now (a\n // provider timestamp ahead of this clock must not extend access).\n const endedAt = new Date(\n Math.min(\n (\n snapshot.endedAt ??\n snapshot.canceledAt ??\n facts.eventCreated\n ).getTime(),\n Date.now(),\n ),\n );\n if (!periodEnd || periodEnd.getTime() > endedAt.getTime()) {\n periodEnd = endedAt;\n }\n }\n const fields = {\n status: snapshot.status,\n startedAt: snapshot.startedAt ?? base?.startedAt ?? facts.eventCreated,\n currentPeriodStart: dateOrKeep(\n snapshot.currentPeriodStart,\n base?.currentPeriodStart,\n ),\n currentPeriodEnd: periodEnd,\n trialEndsAt: dateOrKeep(snapshot.trialEndsAt, base?.trialEndsAt),\n cancelAtPeriodEnd:\n snapshot.cancelAtPeriodEnd ?? base?.cancelAtPeriodEnd ?? false,\n canceledAt:\n snapshot.canceledAt !== undefined\n ? snapshot.canceledAt\n : snapshot.status === 'canceled'\n ? (base?.canceledAt ?? facts.eventCreated)\n : (base?.canceledAt ?? null),\n externalProvider: 'stripe',\n stripeCustomerId: snapshot.customerId,\n stripeSubscriptionId: snapshot.subscriptionId,\n stripeCheckoutSessionId:\n write.checkoutSessionId ?? base?.stripeCheckoutSessionId ?? '',\n };\n\n const subscriptions = await TenantSubscriptionCollection.create({\n db: ctx.db,\n });\n let row: TenantSubscription;\n if (existing) {\n Object.assign(existing, fields);\n existing.setMetadata(\n stripeMetadata(\n existing,\n facts,\n snapshot,\n plan.planKey,\n newSubscription,\n write.held,\n ),\n );\n if (existing.planId !== planId) {\n await existing.replacePlanVersion({\n planId,\n policy: 'authorized',\n reason: `stripe:${facts.eventId}`,\n });\n } else {\n await existing.save();\n }\n row = existing;\n } else {\n row = await subscriptions.create({\n tenantId: write.tenantId,\n subscriberKind: 'tenant',\n subscriberExternalId: '',\n planId,\n ...fields,\n metadata: JSON.stringify(\n stripeMetadata(null, facts, snapshot, plan.planKey, true),\n ),\n });\n }\n ctx.logger?.info?.('billing.subscription.applied', {\n eventId: facts.eventId,\n eventType: facts.eventType,\n tenantId: write.tenantId,\n subscriptionRowId: String(row.id),\n planKey: plan.planKey,\n status: snapshot.status,\n });\n return { action: 'applied' };\n}\n\n/** A `customer.subscription.*` event for an already-linked subscription. */\nexport async function applySubscriptionEvent(\n ctx: ApplyContext,\n facts: EventFacts,\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n return withSystemContext(async () => {\n await lockBillingKeys(ctx, [`subscription:${snapshot.subscriptionId}`]);\n const linked = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n if (linked.length === 0) {\n // Not ours (or its checkout has not landed; the checkout event reads\n // the subscription back, so nothing is lost by not guessing here).\n return ignored(ctx, facts, 'unlinked_subscription');\n }\n if (linked.length > 1) return ignored(ctx, facts, 'ambiguous_subscription');\n const tenantId = String((linked[0] as TenantSubscription).tenantId);\n // A checkout for the same tenant locks the tenant too; take it, then read\n // the row again so the staleness decision sees the committed state.\n await lockBillingKeys(ctx, [\n `subscription:${snapshot.subscriptionId}`,\n `tenant:${tenantId}`,\n ]);\n const current = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n if (current.length !== 1 || current[0]?.tenantId !== tenantId) {\n return ignored(ctx, facts, 'unlinked_subscription');\n }\n const row = current[0] as TenantSubscription;\n if (row.stripeCustomerId && row.stripeCustomerId !== snapshot.customerId) {\n return ignored(ctx, facts, 'customer_mismatch', { tenantId });\n }\n if (isStale(readLastApplied(row), facts)) {\n return ignored(ctx, facts, 'stale_event', { tenantId });\n }\n\n const directory = new PlanDirectory(ctx.db, ctx.prices, ctx.tenantPlans);\n const priced = snapshot.priceId\n ? await directory.findByPriceId(tenantId, snapshot.priceId)\n : null;\n const plan = priced ?? (await directory.findExisting(tenantId, row.planId));\n if (!plan) throw new Error('The subscription plan could not be resolved.');\n if (!priced && snapshot.priceId) {\n const recorded = readRecordedPrice(row);\n if (snapshot.priceId !== recorded) {\n // The provider bills a price this host cannot map and it is not the\n // one the row was granted for: the previous plan's entitlements must\n // not carry over to an unknown product. Hold (non-entitling status,\n // plan and recorded price untouched) until the mapping is fixed or\n // the price returns, so every later event is held too.\n ctx.logger?.error?.('billing.price.unmapped_held', {\n eventId: facts.eventId,\n tenantId,\n providerStatus: snapshot.status,\n });\n return writeRow(ctx, {\n tenantId,\n existing: row,\n plan,\n snapshot: {\n ...snapshot,\n status: HELD_STATUS[snapshot.status] ?? snapshot.status,\n priceId: recorded,\n },\n facts,\n // A cancelled subscription is not billing: nothing left to protect.\n held: snapshot.status !== 'canceled',\n });\n }\n ctx.logger?.warn?.('billing.price.unmapped', {\n eventId: facts.eventId,\n tenantId,\n });\n }\n return writeRow(ctx, { tenantId, existing: row, plan, snapshot, facts });\n });\n}\n\nexport interface CheckoutLink {\n tenantId: string;\n planId: string;\n checkoutSessionId: string;\n}\n\n/**\n * A completed Checkout whose signed metadata names the tenant and plan. The\n * snapshot is the subscription read back from the provider after the event,\n * so the row reflects current state however the events were ordered.\n */\nexport async function applyCheckoutCompleted(\n ctx: ApplyContext,\n facts: EventFacts,\n link: CheckoutLink,\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n return withSystemContext(async () => {\n const { tenantId } = link;\n await lockBillingKeys(ctx, [\n `subscription:${snapshot.subscriptionId}`,\n `tenant:${tenantId}`,\n ]);\n const bySubscription = await listRows(ctx.db, {\n stripeSubscriptionId: snapshot.subscriptionId,\n });\n const byCustomer = await listRows(ctx.db, {\n stripeCustomerId: snapshot.customerId,\n });\n const foreign = [...bySubscription, ...byCustomer].some(\n (row) => row.tenantId !== tenantId,\n );\n if (foreign) {\n return ignored(ctx, facts, 'tenant_mismatch', { tenantId });\n }\n if (bySubscription.length > 1) {\n return ignored(ctx, facts, 'ambiguous_subscription', { tenantId });\n }\n const ownRows = await listRows(ctx.db, {\n tenantId,\n subscriberKind: 'tenant',\n });\n const existing = bySubscription[0] ?? ownRows[0] ?? null;\n if (\n existing?.stripeSubscriptionId &&\n existing.stripeSubscriptionId !== snapshot.subscriptionId &&\n (ENTITLEMENT_CLAIMING.has(existing.status) ||\n isHeldSubscription(existing))\n ) {\n // The buyer paid for a second subscription that is not tracked. Cancel\n // or refund it at the provider: this is an operator alert, not noise.\n if (ENTITLEMENT_CLAIMING.has(snapshot.status)) {\n ctx.logger?.error?.('billing.checkout.orphaned_subscription', {\n eventId: facts.eventId,\n tenantId,\n subscriptionId: snapshot.subscriptionId,\n });\n }\n return ignored(ctx, facts, 'already_subscribed', { tenantId });\n }\n if (\n existing &&\n existing.stripeSubscriptionId === snapshot.subscriptionId &&\n isStale(readLastApplied(existing), facts)\n ) {\n return ignored(ctx, facts, 'stale_event', { tenantId });\n }\n\n const directory = new PlanDirectory(ctx.db, ctx.prices, ctx.tenantPlans);\n const priced = snapshot.priceId\n ? await directory.findByPriceId(tenantId, snapshot.priceId)\n : null;\n const named = await directory.find(tenantId, { planId: link.planId });\n if (priced && named && priced.id !== named.id) {\n ctx.logger?.warn?.('billing.checkout.plan_price_disagree', {\n eventId: facts.eventId,\n tenantId,\n });\n }\n // What the provider bills is what the tenant has; the signed metadata\n // names the intent and covers a price the host never mapped.\n const plan = priced ?? named;\n if (!plan) throw new Error('The checkout plan could not be resolved.');\n return writeRow(ctx, {\n tenantId,\n existing,\n plan,\n snapshot,\n facts,\n checkoutSessionId: link.checkoutSessionId,\n });\n });\n}\n","/**\n * Binding a completed Checkout to the session the host created (#4814).\n *\n * The signed metadata alone is copyable: another integration on the same\n * Stripe account can put it on its own session and pay first. So the host\n * records each session id when it creates the session, and a paid session\n * links a tenant only when a pending record for exactly that id names the\n * same tenant and the signed expiry has not passed at the event time.\n * Anything else is never linked and never dropped: the paid session is\n * recorded as `needs_reconciliation` for an operator.\n */\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n type BillingCheckoutSession,\n BillingCheckoutSessionCollection,\n} from '../models/BillingCheckoutSession.js';\nimport {\n type AppliedOutcome,\n type ApplyContext,\n applyCheckoutCompleted,\n lockBillingKeys,\n} from './apply.js';\nimport { CHECKOUT_COMPLETED, type SubscriptionSnapshot } from './events.js';\n\n/** Signed metadata key holding the expiry, in whole epoch seconds. */\nexport const METADATA_EXPIRY_KEY = 'smrt_exp';\n/**\n * Stripe expires a Checkout session after 24 hours; the host allows an hour\n * more. The expiry is checked against the event time, not the delivery time,\n * so a late webhook retry of an in-time payment still completes.\n */\nexport const CHECKOUT_SESSION_TTL_MS = 25 * 60 * 60 * 1000;\n\nexport type CheckoutRefusal =\n | 'session_record_missing'\n | 'session_record_mismatch'\n | 'session_expired';\n\ntype Verdict =\n | { kind: 'bound' }\n | { kind: 'replay'; reason: string }\n | { kind: 'reconcile'; reason: CheckoutRefusal };\n\n/** The binding rules, in order. Pure: no I/O. */\nexport function checkBinding(\n record: BillingCheckoutSession | null,\n input: { tenantId: string; exp: string | undefined; eventTime: Date },\n): Verdict {\n if (!record) return { kind: 'reconcile', reason: 'session_record_missing' };\n if (record.status === 'completed') {\n return { kind: 'replay', reason: 'session_already_completed' };\n }\n if (record.status === 'needs_reconciliation') {\n return { kind: 'replay', reason: 'session_needs_reconciliation' };\n }\n if (record.targetTenantId !== input.tenantId) {\n return { kind: 'reconcile', reason: 'session_record_mismatch' };\n }\n if (!input.exp || !/^\\d{1,12}$/.test(input.exp)) {\n return { kind: 'reconcile', reason: 'session_record_mismatch' };\n }\n const at = input.eventTime.getTime();\n if (\n at > Number.parseInt(input.exp, 10) * 1000 ||\n at > new Date(record.expiresAt).getTime()\n ) {\n return { kind: 'reconcile', reason: 'session_expired' };\n }\n return { kind: 'bound' };\n}\n\n/** Record a session the host just created. Idempotent per session id. */\nexport async function recordCheckoutSession(\n db: DatabaseInterface,\n input: { sessionId: string; tenantId: string; expiresAt: Date },\n): Promise<void> {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n if (await sessions.get({ sessionId: input.sessionId })) return;\n try {\n await sessions.create({\n sessionId: input.sessionId,\n targetTenantId: input.tenantId,\n status: 'pending',\n expiresAt: input.expiresAt,\n });\n } catch (error) {\n // A concurrent identical request recorded it first.\n if (!(await sessions.get({ sessionId: input.sessionId }))) throw error;\n }\n}\n\nexport interface ReconcileContext {\n eventId: string;\n eventCreated: string;\n subscriptionId: string;\n customerId: string;\n planId: string;\n claimedTenantId: string;\n}\n\nexport function parseReconcileContext(\n record: BillingCheckoutSession,\n): ReconcileContext | null {\n try {\n const value = JSON.parse(record.detail) as Record<string, unknown>;\n const text = (key: string) =>\n typeof value[key] === 'string' ? (value[key] as string) : '';\n const parsed = {\n eventId: text('eventId'),\n eventCreated: text('eventCreated'),\n subscriptionId: text('subscriptionId'),\n customerId: text('customerId'),\n planId: text('planId'),\n claimedTenantId: text('claimedTenantId'),\n };\n return parsed.subscriptionId &&\n parsed.customerId &&\n Number.isFinite(Date.parse(parsed.eventCreated))\n ? parsed\n : null;\n } catch {\n return null;\n }\n}\n\nexport interface BoundCompletion {\n sessionId: string;\n /** From the verified signed metadata. */\n tenantId: string;\n planId: string;\n exp: string | undefined;\n eventId: string;\n eventTime: Date;\n}\n\n/**\n * Inside the idempotency transaction: bind the paid session to its record,\n * then link the tenant. `ctx.db` is the transaction handle.\n */\nexport async function completeBoundCheckout(\n ctx: ApplyContext,\n input: BoundCompletion,\n facts: Parameters<typeof applyCheckoutCompleted>[1],\n snapshot: SubscriptionSnapshot,\n): Promise<AppliedOutcome> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const sessions = await BillingCheckoutSessionCollection.create({\n db: ctx.db,\n });\n const record = await sessions.get({ sessionId: input.sessionId });\n const verdict = checkBinding(record, input);\n\n if (verdict.kind === 'replay') {\n ctx.logger?.warn?.('billing.checkout.not_relinked', {\n eventId: input.eventId,\n sessionId: input.sessionId,\n reason: verdict.reason,\n });\n return { action: 'ignored', reason: verdict.reason };\n }\n if (verdict.kind === 'reconcile') {\n const context: ReconcileContext = {\n eventId: input.eventId,\n eventCreated: input.eventTime.toISOString(),\n subscriptionId: snapshot.subscriptionId,\n customerId: snapshot.customerId,\n planId: input.planId,\n claimedTenantId: input.tenantId,\n };\n if (record) {\n record.status = 'needs_reconciliation';\n record.reason = verdict.reason;\n record.detail = JSON.stringify(context);\n await record.save();\n } else {\n await sessions.create({\n sessionId: input.sessionId,\n targetTenantId: '',\n status: 'needs_reconciliation',\n expiresAt: input.eventTime,\n reason: verdict.reason,\n detail: JSON.stringify(context),\n });\n }\n // A paid purchase nobody has linked: loud, with codes and ids only.\n ctx.logger?.error?.('billing.checkout.needs_reconciliation', {\n eventId: input.eventId,\n sessionId: input.sessionId,\n reason: verdict.reason,\n claimedTenantId: input.tenantId,\n subscriptionId: snapshot.subscriptionId,\n });\n return { action: 'needs_reconciliation', reason: verdict.reason };\n }\n\n const outcome = await applyCheckoutCompleted(\n ctx,\n facts,\n {\n tenantId: input.tenantId,\n planId: input.planId,\n checkoutSessionId: input.sessionId,\n },\n snapshot,\n );\n if (outcome.action === 'applied' && record) {\n record.status = 'completed';\n record.completedAt = new Date();\n await record.save();\n }\n return outcome;\n}\n\n/** A flagged session and the ids captured when it was flagged. */\nexport async function loadFlaggedCheckout(\n db: DatabaseInterface,\n sessionId: string,\n): Promise<{\n record: BillingCheckoutSession;\n flagged: ReconcileContext;\n} | null> {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n const record = await sessions.get({ sessionId });\n if (record?.status !== 'needs_reconciliation') return null;\n const flagged = parseReconcileContext(record);\n return flagged ? { record, flagged } : null;\n}\n\n/**\n * Operator action, inside one transaction (`ctx.db`): link a flagged paid\n * session to `tenantId` on purpose. `snapshot` is the subscription read back\n * from the provider before the transaction; it must still be the one recorded\n * when the session was flagged. The row is re-read under the lock, so a\n * session is reconciled at most once.\n */\nexport async function reconcileFlaggedCheckout(\n ctx: ApplyContext,\n input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n operatorId: string;\n snapshot: SubscriptionSnapshot;\n },\n): Promise<AppliedOutcome | null> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const loaded = await loadFlaggedCheckout(ctx.db, input.sessionId);\n const planId = input.planId ?? loaded?.flagged.planId;\n if (!loaded || !planId) return null;\n const { record, flagged } = loaded;\n if (\n input.snapshot.subscriptionId !== flagged.subscriptionId ||\n input.snapshot.customerId !== flagged.customerId\n ) {\n return { action: 'ignored', reason: 'checkout_subscription_mismatch' };\n }\n const outcome = await applyCheckoutCompleted(\n ctx,\n {\n eventId: `reconcile:${input.sessionId}`,\n eventType: CHECKOUT_COMPLETED,\n eventCreated: new Date(flagged.eventCreated),\n observedAt: new Date(),\n },\n {\n tenantId: input.tenantId,\n planId,\n checkoutSessionId: input.sessionId,\n },\n input.snapshot,\n );\n if (outcome.action === 'applied') {\n record.status = 'completed';\n record.targetTenantId = input.tenantId;\n record.reason = 'reconciled';\n record.completedAt = new Date();\n await record.save();\n ctx.logger?.warn?.('billing.checkout.reconciled', {\n sessionId: input.sessionId,\n tenantId: input.tenantId,\n operatorId: input.operatorId,\n subscriptionId: flagged.subscriptionId,\n });\n }\n return outcome;\n}\n\n/**\n * Operator action, inside one transaction (`ctx.db`): close a flagged session\n * without linking it. The row is re-read under the lock, so a session is\n * dismissed or reconciled at most once, whichever comes first.\n */\nexport async function dismissFlaggedCheckout(\n ctx: ApplyContext,\n input: { sessionId: string; operatorId: string; reason: string },\n): Promise<boolean> {\n await lockBillingKeys(ctx, [`checkout:${input.sessionId}`]);\n const loaded = await loadFlaggedCheckout(ctx.db, input.sessionId);\n if (!loaded) return false;\n loaded.record.status = 'dismissed';\n loaded.record.reason = 'dismissed';\n loaded.record.completedAt = new Date();\n await loaded.record.save();\n ctx.logger?.warn?.('billing.checkout.dismissed', {\n sessionId: input.sessionId,\n operatorId: input.operatorId,\n reason: input.reason,\n subscriptionId: loaded.flagged.subscriptionId,\n });\n return true;\n}\n","/**\n * Signed Checkout metadata and secret hygiene (#4786).\n *\n * Another integration on the same Stripe account can create Checkout Sessions\n * with any metadata it likes. A completed session is only trusted to link a\n * tenant and plan when its `smrt_*` metadata carries an HMAC made with a\n * server-side secret at session creation. Uses WebCrypto so the module loads\n * in every runtime the package does.\n */\n\nexport const METADATA_SIGNATURE_KEY = 'smrt_sig';\nexport const METADATA_PURPOSE = 'tenant_subscription';\n\nconst encoder = new TextEncoder();\n\nfunction toHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join(\n '',\n );\n}\n\nasync function hmacHex(secret: string, message: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n return toHex(\n new Uint8Array(\n await crypto.subtle.sign('HMAC', key, encoder.encode(message)),\n ),\n );\n}\n\n/** Compare without an early exit on the first differing character. */\nexport function constantTimeEqual(left: string, right: string): boolean {\n if (left.length !== right.length) return false;\n let diff = 0;\n for (let index = 0; index < left.length; index += 1) {\n diff |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return diff === 0;\n}\n\nfunction canonical(metadata: Record<string, string>): string {\n return JSON.stringify(\n Object.entries(metadata)\n .filter(\n ([key, value]) =>\n key.startsWith('smrt_') &&\n key !== METADATA_SIGNATURE_KEY &&\n value !== '',\n )\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)),\n );\n}\n\n/** Add the signature to `metadata`. Only `smrt_*` keys are covered. */\nexport async function signCheckoutMetadata(\n metadata: Record<string, string>,\n secret: string,\n): Promise<Record<string, string>> {\n return {\n ...metadata,\n [METADATA_SIGNATURE_KEY]: await hmacHex(\n `smrt-subscription-checkout:${secret}`,\n canonical(metadata),\n ),\n };\n}\n\nexport async function checkoutMetadataValid(\n metadata: Record<string, string>,\n secret: string,\n): Promise<boolean> {\n const given = metadata[METADATA_SIGNATURE_KEY];\n if (!given) return false;\n return constantTimeEqual(\n given,\n await hmacHex(`smrt-subscription-checkout:${secret}`, canonical(metadata)),\n );\n}\n\nconst SECRET_PATTERN = /\\b(?:sk|rk|pk|whsec)_[A-Za-z0-9_]{4,}/g;\n\n/**\n * Strip anything shaped like a Stripe key or signing secret. Applied to every\n * error message before it reaches a log, as provider errors can echo the\n * credential they were called with.\n */\nexport function redactSecrets(text: string): string {\n return text.replace(SECRET_PATTERN, '[redacted]');\n}\n\nexport function safeErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return redactSecrets(message).slice(0, 300);\n}\n","/**\n * Types for the billing host glue (#4786).\n *\n * The provider port is structural: `StripeAccountingProvider` from\n * `@happyvertical/accounting` satisfies it (a compile-time test pins that), so\n * this package carries no runtime or type dependency on the SDK. Every\n * provider call goes through that SDK; nothing here talks to Stripe directly.\n */\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\n\n/** A line item priced by a provider price id (never by a client-sent amount). */\nexport interface BillingCheckoutLineItem {\n price: string;\n quantity: number;\n}\n\nexport interface BillingCheckoutSessionInput {\n mode?: 'subscription';\n successUrl: string;\n cancelUrl: string;\n customerExternalId?: string;\n customerEmail?: string;\n clientReferenceId?: string;\n lineItems: BillingCheckoutLineItem[];\n metadata: Record<string, string>;\n idempotencyKey?: string;\n}\n\n/** The slice of a provider subscription this module reads. */\nexport interface BillingSubscriptionState {\n externalId: string;\n status: string;\n customerExternalId: string;\n currentPeriodStart?: Date;\n currentPeriodEnd?: Date;\n cancelAtPeriodEnd: boolean;\n canceledAt?: Date;\n trialEnd?: Date;\n raw?: unknown;\n}\n\n/** A parsed (not yet trusted until `verify` passed) webhook event. */\nexport interface BillingProviderWebhookEvent {\n id?: string;\n type: string;\n timestamp: Date;\n payload: unknown;\n}\n\n/**\n * The provider operations the glue needs. `StripeAccountingProvider` from\n * `@happyvertical/accounting` is assignable to this.\n */\nexport interface BillingProviderPort {\n readonly webhooks: {\n verify(payload: string, signature: string, secret: string): boolean;\n parse(payload: string): BillingProviderWebhookEvent;\n };\n readonly billing: {\n createCheckoutSession(\n input: BillingCheckoutSessionInput,\n ): Promise<{ externalId: string; url: string | null }>;\n createCustomerPortalSession(input: {\n customerExternalId: string;\n returnUrl: string;\n }): Promise<{ url: string }>;\n retrieveSubscriptionStatus(\n subscriptionExternalId: string,\n ): Promise<BillingSubscriptionState>;\n };\n}\n\n/** Fixed, host-configured destinations. Never taken from a request. */\nexport interface BillingUrls {\n /** Where Checkout sends the buyer after paying. */\n successUrl: string;\n /** Where Checkout sends the buyer when they back out. */\n cancelUrl: string;\n /** Where the customer portal returns to. */\n portalReturnUrl: string;\n}\n\n/**\n * Structured, secret-free log sink. Every field passed is safe to persist:\n * event ids, types, tenant ids and reason codes only.\n */\nexport interface BillingLogger {\n info?(message: string, fields?: Record<string, unknown>): void;\n warn?(message: string, fields?: Record<string, unknown>): void;\n error?(message: string, fields?: Record<string, unknown>): void;\n}\n\nexport interface BillingPlanPurchaseContext {\n tenantId: string;\n plan: SubscriptionPlan;\n}\n\nexport interface BillingHostOptions {\n /** The accounting provider (Stripe) from `@happyvertical/accounting`. */\n provider: BillingProviderPort;\n /**\n * Resolved database handle with `transaction()` support (SQLite or\n * PostgreSQL). Event idempotency and the subscription write share one\n * transaction on it. Take it from any collection, for example\n * `(await TenantSubscriptionCollection.create(config)).db`.\n */\n db: DatabaseInterface;\n /** Webhook endpoint signing secret (`whsec_…`). Required, never defaulted. */\n webhookSecret: string;\n /**\n * Secret used to sign new Checkout metadata. Defaults to `webhookSecret`, so\n * rotating the webhook secret also changes it: list the retired secret in\n * `metadataVerificationSecrets` for as long as sessions created under it can\n * still complete, or give the host its own stable secret here.\n */\n metadataSigningSecret?: string;\n /**\n * Retired secrets still accepted when a completed Checkout is verified (never\n * used to sign). Needed across a rotation of the signing secret, otherwise a\n * session paid after the rotation is not trusted and the purchase is dropped.\n */\n metadataVerificationSecrets?: readonly string[];\n /** Maximum webhook signature age in seconds (default 300, at most 900). */\n webhookToleranceSeconds?: number;\n /** Largest accepted webhook body in bytes (default 1 MiB). */\n maxWebhookBodyBytes?: number;\n urls: BillingUrls;\n /**\n * Whether tenant-owned plans (`SubscriptionPlan.tenantId` set) may be sold.\n * Default `deny`: only operator-owned global plans are sold, so a tenant\n * that can write plan rows cannot buy entitlements it defined itself. Use\n * `allow` only when tenants cannot write plans.\n */\n tenantPlans?: 'deny' | 'allow';\n /** Plan key to provider price id. Wins over the plan's own price binding. */\n prices?: Record<string, string>;\n /**\n * Extra purchase policy, evaluated after the built-in checks (plan visible\n * to the tenant, active, fixed price, price configured, tenant not already\n * subscribed). Return false to refuse.\n */\n canPurchasePlan?: (\n context: BillingPlanPurchaseContext,\n ) => boolean | Promise<boolean>;\n /** Namespaces the idempotency claim when several accounts share a database. */\n accountKey?: string;\n logger?: BillingLogger;\n}\n\n/** The tenant a host has already authenticated and authorised for billing. */\nexport interface BillingAuth {\n tenantId: string;\n /** Prefilled on Checkout for a tenant with no billing customer yet. */\n email?: string;\n}\n\nexport type BillingHostErrorCode =\n | 'invalid_request'\n | 'tenant_mismatch'\n | 'plan_unavailable'\n | 'plan_forbidden'\n | 'plan_not_purchasable'\n | 'price_unconfigured'\n | 'already_subscribed'\n | 'no_billing_account'\n | 'checkout_not_reconcilable'\n | 'provider_error';\n\nconst STATUS_BY_CODE: Record<BillingHostErrorCode, number> = {\n invalid_request: 400,\n tenant_mismatch: 403,\n plan_forbidden: 403,\n plan_unavailable: 404,\n plan_not_purchasable: 409,\n already_subscribed: 409,\n no_billing_account: 409,\n checkout_not_reconcilable: 409,\n price_unconfigured: 503,\n provider_error: 502,\n};\n\nconst MESSAGE_BY_CODE: Record<BillingHostErrorCode, string> = {\n invalid_request: 'The request is not valid.',\n tenant_mismatch: 'The request does not match the signed-in workspace.',\n plan_unavailable: 'That plan is not available.',\n plan_forbidden: 'This workspace cannot buy that plan.',\n plan_not_purchasable: 'That plan cannot be bought online.',\n price_unconfigured: 'Billing is not configured for that plan.',\n already_subscribed:\n 'This workspace already has a subscription. Use the billing portal to change it.',\n no_billing_account: 'This workspace has no billing account yet.',\n checkout_not_reconcilable: 'That checkout cannot be reconciled.',\n provider_error: 'The billing provider could not complete the request.',\n};\n\n/**\n * A refusal with a stable code and a fixed message. The message never carries\n * provider text, ids or configuration, so it is safe to return to a browser.\n */\nexport class BillingHostError extends Error {\n readonly code: BillingHostErrorCode;\n readonly status: number;\n\n constructor(code: BillingHostErrorCode) {\n super(MESSAGE_BY_CODE[code]);\n this.name = 'BillingHostError';\n this.code = code;\n this.status = STATUS_BY_CODE[code];\n }\n}\n\nexport interface BillingCheckoutResult {\n /** Hosted checkout page to send the buyer to. */\n url: string;\n sessionId: string;\n}\n\nexport interface BillingPortalResult {\n url: string;\n}\n\nexport type BillingWebhookOutcome =\n | 'applied'\n | 'ignored'\n | 'duplicate'\n /**\n * A paid first-purchase Checkout could not be tied to a session this host\n * created. It was not linked and not discarded: it is stored for an\n * operator (`listCheckoutsNeedingReconciliation`, `reconcileCheckout`).\n */\n | 'needs_reconciliation';\n\n/** A paid Checkout session waiting for an operator. Ids and codes only. */\nexport interface BillingUnreconciledCheckout {\n sessionId: string;\n /** `session_record_missing`, `session_record_mismatch` or `session_expired`. */\n reason: string;\n /** The tenant the signed metadata named (not trusted). */\n claimedTenantId: string;\n subscriptionId: string;\n /**\n * The provider customer that paid. Confirm it is the claimed tenant's own\n * customer before reconciling: it is the one value that decides who gets\n * control of the tenant's billing portal.\n */\n customerId: string;\n /** The tenant the host recorded the session for (empty when no record). */\n targetTenantId: string;\n /**\n * True when the claimed tenant has its own pending or completed session\n * recorded by this host, which suggests the flagged payment is a copy of\n * that tenant's signed metadata rather than the tenant's purchase.\n */\n claimedTenantHasOwnSession: boolean;\n eventId: string;\n flaggedAt: Date;\n}\n\nexport interface BillingWebhookResponse {\n status: number;\n body: {\n received: boolean;\n outcome?: BillingWebhookOutcome;\n error?: string;\n };\n}\n\nexport interface BillingHost {\n createCheckout(\n auth: BillingAuth,\n input: { planKey?: string; planId?: string },\n ): Promise<BillingCheckoutResult>;\n createPortalLink(auth: BillingAuth): Promise<BillingPortalResult>;\n /** Paid Checkout sessions flagged `needs_reconciliation`, oldest first. */\n listCheckoutsNeedingReconciliation(options?: {\n /** Page size, 1..1000 (default 200). */\n limit?: number;\n offset?: number;\n }): Promise<BillingUnreconciledCheckout[]>;\n /** How many paid sessions are flagged, so a page is never mistaken for all. */\n countCheckoutsNeedingReconciliation(): Promise<number>;\n /**\n * Operator-only (same rules as `reconcileCheckout`): close a flagged session\n * on purpose WITHOUT linking it (for example a payment from another\n * integration on the same account). Terminal state `dismissed`, logged with\n * the operator id and reason; throws `checkout_not_reconcilable` when the\n * session is not flagged.\n */\n dismissCheckout(input: {\n sessionId: string;\n operatorId: string;\n reason: string;\n }): Promise<void>;\n /**\n * Operator-only, called by host code that has already authenticated and\n * authorised an operator (never wired to a request handler). Links a flagged\n * paid session to `tenantId` on purpose, once: the subscription is re-read\n * from the provider and must be the one recorded when the session was\n * flagged. `planId` defaults to the plan the signed metadata named. Throws\n * `checkout_not_reconcilable` when the session is not flagged (or was\n * already reconciled); otherwise reports whether the link was `applied` or\n * `ignored` with a reason (for example `already_subscribed`).\n */\n reconcileCheckout(input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n /** Who is acting; recorded in the audit log. */\n operatorId: string;\n }): Promise<{ outcome: 'applied' | 'ignored'; reason?: string }>;\n handleWebhook(input: {\n payload: string;\n signature: string | null;\n }): Promise<BillingWebhookResponse>;\n /**\n * Fetch-API handlers for any framework (`+server.ts`, Hono, Workers). The\n * host authenticates and authorises the caller first and passes the tenant;\n * checkout and portal never read a tenant, price or URL from the request.\n */\n handlers: {\n checkout(request: Request, auth: BillingAuth): Promise<Response>;\n portal(request: Request, auth: BillingAuth): Promise<Response>;\n webhook(request: Request): Promise<Response>;\n };\n}\n","/**\n * Reusable billing host glue (#4786): hosted checkout, a verified idempotent\n * webhook, and a customer-portal link, for hosts that sell `SubscriptionPlan`s\n * through Stripe.\n *\n * Every provider call goes through `@happyvertical/accounting` (the\n * {@link BillingProviderPort}); this module owns the trust decisions around\n * it:\n *\n * - **Webhook**: signature and timestamp are checked on the raw body before\n * anything is parsed; the event id is claimed durably with the subscription\n * write in one transaction (`runOnce`), so a replay is a 2xx no-op and a\n * failed apply rolls the claim back for the provider's retry.\n * - **Checkout/portal**: the host authenticates and authorises the caller and\n * passes the tenant; price, URLs and customer come from server state only.\n * - **Responses and logs** carry fixed messages, ids and reason codes, never\n * provider text or configuration.\n */\nimport {\n deriveRunOnceClaimKey,\n digestRunOnceContent,\n isPostgresDatabase,\n RUN_ONCE_CLAIMS_TABLE,\n RunOnceClaimError,\n runOnce,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n withSystemContext,\n withTenant,\n} from '@happyvertical/smrt-tenancy';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport { BillingCheckoutSessionCollection } from '../models/BillingCheckoutSession.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport {\n type AppliedOutcome,\n applySubscriptionEvent,\n isHeldSubscription,\n} from './apply.js';\nimport {\n CHECKOUT_SESSION_TTL_MS,\n completeBoundCheckout,\n dismissFlaggedCheckout,\n loadFlaggedCheckout,\n METADATA_EXPIRY_KEY,\n parseReconcileContext,\n reconcileFlaggedCheckout,\n recordCheckoutSession,\n} from './checkout-sessions.js';\nimport {\n assertBillingUrl,\n assertWebhookTolerance,\n DEFAULT_WEBHOOK_TOLERANCE_SECONDS,\n} from './config.js';\nimport {\n CHECKOUT_COMPLETED,\n checkoutFactsFromObject,\n SUBSCRIPTION_EVENT_TYPES,\n stripeObject,\n subscriptionSnapshotFromObject,\n subscriptionSnapshotFromState,\n} from './events.js';\nimport { PlanDirectory, priceIdForPlan } from './plans.js';\nimport {\n checkoutMetadataValid,\n METADATA_PURPOSE,\n safeErrorMessage,\n signCheckoutMetadata,\n} from './signing.js';\nimport {\n type BillingAuth,\n type BillingCheckoutResult,\n type BillingHost,\n BillingHostError,\n type BillingHostOptions,\n type BillingPortalResult,\n type BillingUnreconciledCheckout,\n type BillingWebhookResponse,\n} from './types.js';\n\nconst DEFAULT_MAX_WEBHOOK_BODY_BYTES = 1024 * 1024;\nconst MAX_REQUEST_BODY_BYTES = 8 * 1024;\nconst CLAIM_SCOPE = 'smrt-subscriptions:billing-webhook';\nconst CHECKOUT_KEY_WINDOW_MS = 10 * 60 * 1000;\nconst REF_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;\nconst EMAIL_PATTERN = /^[^\\s@]{1,64}@[^\\s@]{1,190}\\.[^\\s@]{1,63}$/;\n/** Subscriptions that are still the tenant's live Stripe billing. */\nconst LIVE_STATUSES = new Set(['active', 'trialing', 'past_due', 'unpaid']);\n\nconst encoder = new TextEncoder();\n\nasync function sha256Hex(value: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', encoder.encode(value));\n return Array.from(new Uint8Array(digest), (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n}\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = {},\n): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'no-store',\n ...headers,\n },\n });\n}\n\n/**\n * The `t=` timestamp of a Stripe-Signature header, in seconds. A header with\n * more than one `t=` part is refused: the SDK verifier and this check could\n * otherwise read different ones.\n */\nfunction signatureTimestamp(header: string): number | null {\n let found: number | null = null;\n for (const part of header.split(',')) {\n const [key, value] = part.trim().split('=', 2);\n if (key !== 't') continue;\n if (found !== null || !value || !/^\\d{1,12}$/.test(value)) return null;\n found = Number.parseInt(value, 10);\n }\n return found;\n}\n\n/**\n * Read a request body as text, stopping as soon as it exceeds `limit` bytes\n * (a chunked body has no trustworthy Content-Length). Returns null when over.\n */\nasync function readBoundedText(\n request: Request,\n limit: number,\n): Promise<string | null> {\n const declared = Number(request.headers.get('content-length') ?? 0);\n if (declared > limit) return null;\n if (!request.body) return '';\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > limit) {\n await reader.cancel();\n return null;\n }\n chunks.push(value);\n }\n const bytes = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(bytes);\n}\n\nexport function createBillingHost(options: BillingHostOptions): BillingHost {\n const {\n provider,\n db,\n urls: rawUrls,\n prices,\n canPurchasePlan,\n logger,\n } = options;\n // Held in closures only: the returned host exposes no secret.\n if (\n typeof options.webhookSecret !== 'string' ||\n options.webhookSecret.trim() === ''\n ) {\n throw new Error('A webhook signing secret is required.');\n }\n const webhookSecret = options.webhookSecret.trim();\n const signingSecret = options.metadataSigningSecret?.trim() || webhookSecret;\n // New sessions are signed with one secret; a completed one may verify under\n // it or a retired one, so a rotation does not drop in-flight purchases.\n const verificationSecrets = [\n ...new Set([\n signingSecret,\n ...(options.metadataVerificationSecrets ?? [])\n .map((secret) => secret.trim())\n .filter(Boolean),\n ]),\n ];\n if (typeof db?.transaction !== 'function') {\n throw new Error(\n 'The billing host needs a database handle with transaction() support.',\n );\n }\n const toleranceSeconds = assertWebhookTolerance(\n options.webhookToleranceSeconds ?? DEFAULT_WEBHOOK_TOLERANCE_SECONDS,\n );\n const maxBodyBytes =\n options.maxWebhookBodyBytes ?? DEFAULT_MAX_WEBHOOK_BODY_BYTES;\n if (!Number.isSafeInteger(maxBodyBytes) || maxBodyBytes < 1) {\n throw new Error('maxWebhookBodyBytes must be a positive integer.');\n }\n const urls = {\n successUrl: assertBillingUrl('successUrl', rawUrls.successUrl),\n cancelUrl: assertBillingUrl('cancelUrl', rawUrls.cancelUrl),\n portalReturnUrl: assertBillingUrl(\n 'portalReturnUrl',\n rawUrls.portalReturnUrl,\n ),\n };\n const postgres = isPostgresDatabase(db);\n const tenantPlans = options.tenantPlans ?? 'deny';\n if (tenantPlans !== 'deny' && tenantPlans !== 'allow') {\n throw new Error(\"tenantPlans must be 'deny' or 'allow'.\");\n }\n const claimActor = `billing-webhook:${options.accountKey ?? 'default'}`;\n\n // -------------------------------------------------------------------------\n // Tenant, plan and subscription reads for checkout and portal\n // -------------------------------------------------------------------------\n\n function assertTenant(auth: BillingAuth): string {\n const tenantId = auth?.tenantId;\n if (typeof tenantId !== 'string' || tenantId.trim() === '') {\n throw new BillingHostError('invalid_request');\n }\n const ambient = getTenantId();\n if (ambient && ambient !== tenantId) {\n throw new BillingHostError('tenant_mismatch');\n }\n return tenantId;\n }\n\n async function currentSubscription(\n tenantId: string,\n ): Promise<TenantSubscription | null> {\n return withTenant({ tenantId }, async () => {\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n const rows = await subscriptions.list({\n where: { tenantId, subscriberKind: 'tenant' },\n limit: 1,\n });\n const row = rows[0] ?? null;\n return row && row.tenantId === tenantId ? row : null;\n });\n }\n\n // -------------------------------------------------------------------------\n // Checkout\n // -------------------------------------------------------------------------\n\n async function createCheckout(\n auth: BillingAuth,\n input: { planKey?: string; planId?: string },\n ): Promise<BillingCheckoutResult> {\n const tenantId = assertTenant(auth);\n const planKey = input?.planKey;\n const planId = input?.planId;\n if (\n (planKey === undefined) === (planId === undefined) ||\n (planKey !== undefined && !REF_PATTERN.test(planKey)) ||\n (planId !== undefined && !REF_PATTERN.test(planId))\n ) {\n throw new BillingHostError('invalid_request');\n }\n const email = auth.email?.trim();\n if (email && !EMAIL_PATTERN.test(email)) {\n throw new BillingHostError('invalid_request');\n }\n\n // Another tenant's plan, an unknown plan and an archived plan all look the\n // same to the caller.\n const plan = await new PlanDirectory(db, prices, tenantPlans).find(\n tenantId,\n {\n planKey,\n planId,\n },\n );\n if (!plan?.isActive()) {\n throw new BillingHostError('plan_unavailable');\n }\n if (\n plan.pricingMode !== 'fixed' ||\n plan.priceAmount <= 0 ||\n (plan.externalProvider && plan.externalProvider !== 'stripe')\n ) {\n throw new BillingHostError('plan_not_purchasable');\n }\n const priceId = priceIdForPlan(plan, prices);\n if (!priceId) throw new BillingHostError('price_unconfigured');\n\n const current = await currentSubscription(tenantId);\n if (\n current?.stripeSubscriptionId &&\n (LIVE_STATUSES.has(current.status) || isHeldSubscription(current))\n ) {\n throw new BillingHostError('already_subscribed');\n }\n if (canPurchasePlan && !(await canPurchasePlan({ tenantId, plan }))) {\n throw new BillingHostError('plan_forbidden');\n }\n\n const customerExternalId = current?.stripeCustomerId || undefined;\n const bucket = Math.floor(Date.now() / CHECKOUT_KEY_WINDOW_MS);\n // Same for every request in one idempotency window, so a repeated click\n // sends the provider identical parameters. Signed with the metadata.\n const expiresAt = new Date(\n (bucket + 1) * CHECKOUT_KEY_WINDOW_MS + CHECKOUT_SESSION_TTL_MS,\n );\n const idempotencyKey = `smrt-sub-checkout:${(\n await sha256Hex(\n [\n tenantId,\n String(plan.id),\n priceId,\n customerExternalId ?? email ?? '',\n bucket,\n ].join('|'),\n )\n ).slice(0, 48)}`;\n\n let session: { externalId: string; url: string | null };\n try {\n session = await provider.billing.createCheckoutSession({\n mode: 'subscription',\n successUrl: urls.successUrl,\n cancelUrl: urls.cancelUrl,\n ...(customerExternalId\n ? { customerExternalId }\n : email\n ? { customerEmail: email }\n : {}),\n clientReferenceId: tenantId,\n lineItems: [{ price: priceId, quantity: 1 }],\n metadata: await signCheckoutMetadata(\n {\n smrt_purpose: METADATA_PURPOSE,\n smrt_tenant_id: tenantId,\n smrt_plan_id: String(plan.id),\n // Bind the server-chosen price and, once known, the billing\n // customer: copied metadata cannot be reused for another price\n // or another customer's subscription.\n smrt_price_id: priceId,\n [METADATA_EXPIRY_KEY]: String(\n Math.floor(expiresAt.getTime() / 1000),\n ),\n ...(customerExternalId\n ? { smrt_customer_id: customerExternalId }\n : {}),\n },\n signingSecret,\n ),\n idempotencyKey,\n });\n if (!session.url) throw new Error('Checkout returned no URL.');\n } catch (error) {\n logger?.error?.('billing.checkout.provider_error', {\n tenantId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n // Record the session before the buyer gets its URL: a failure here\n // propagates, so no session is ever sold that completion cannot match.\n await withSystemContext(() =>\n recordCheckoutSession(db, {\n sessionId: session.externalId,\n tenantId,\n expiresAt,\n }),\n );\n return { url: session.url, sessionId: session.externalId };\n }\n\n // -------------------------------------------------------------------------\n // Customer portal\n // -------------------------------------------------------------------------\n\n async function createPortalLink(\n auth: BillingAuth,\n ): Promise<BillingPortalResult> {\n const tenantId = assertTenant(auth);\n // The customer is read from this tenant's own subscription row, never from\n // the request, so a link can only open the caller's own billing account.\n const current = await currentSubscription(tenantId);\n if (!current?.stripeCustomerId) {\n throw new BillingHostError('no_billing_account');\n }\n try {\n const session = await provider.billing.createCustomerPortalSession({\n customerExternalId: current.stripeCustomerId,\n returnUrl: urls.portalReturnUrl,\n });\n if (!session.url) throw new Error('Portal returned no URL.');\n return { url: session.url };\n } catch (error) {\n logger?.error?.('billing.portal.provider_error', {\n tenantId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n }\n\n // -------------------------------------------------------------------------\n // Webhook\n // -------------------------------------------------------------------------\n\n function reject(\n status: number,\n error: string,\n reason: string,\n fields: Record<string, unknown> = {},\n ): BillingWebhookResponse {\n logger?.warn?.('billing.webhook.rejected', { reason, ...fields });\n return { status, body: { received: false, error } };\n }\n\n async function claimExists(eventId: string): Promise<boolean> {\n const claimKey = deriveRunOnceClaimKey({\n tenantId: CLAIM_SCOPE,\n actor: claimActor,\n token: eventId,\n contentDigest: digestRunOnceContent({ provider: 'stripe' }),\n });\n const row = (await db.get(RUN_ONCE_CLAIMS_TABLE, {\n claim_key: claimKey,\n tenant_id: CLAIM_SCOPE,\n })) as { status?: string } | null;\n return row?.status === 'completed';\n }\n\n async function handleWebhook(input: {\n payload: string;\n signature: string | null;\n }): Promise<BillingWebhookResponse> {\n const { payload, signature } = input;\n if (typeof payload !== 'string') {\n return reject(400, 'invalid_payload', 'payload_not_text');\n }\n if (encoder.encode(payload).byteLength > maxBodyBytes) {\n return reject(413, 'payload_too_large', 'payload_too_large');\n }\n if (!signature)\n return reject(400, 'invalid_signature', 'missing_signature');\n\n const timestamp = signatureTimestamp(signature);\n if (timestamp === null) {\n return reject(400, 'invalid_signature', 'malformed_signature');\n }\n const ageSeconds = Math.abs(Date.now() / 1000 - timestamp);\n if (ageSeconds > toleranceSeconds) {\n return reject(400, 'invalid_signature', 'timestamp_outside_tolerance');\n }\n let verified = false;\n try {\n verified = provider.webhooks.verify(payload, signature, webhookSecret);\n } catch {\n verified = false;\n }\n if (!verified) return reject(400, 'invalid_signature', 'bad_signature');\n\n // From here the body is authentic and fresh.\n let event: ReturnType<BillingHostOptions['provider']['webhooks']['parse']>;\n try {\n event = provider.webhooks.parse(payload);\n } catch {\n return reject(400, 'invalid_payload', 'unparseable_payload');\n }\n const eventId = event.id;\n if (!eventId) return reject(400, 'invalid_payload', 'missing_event_id');\n\n const object = stripeObject(event.payload);\n const eventLog = { eventId, eventType: event.type };\n const ignoredResponse = (reason: string): BillingWebhookResponse => {\n logger?.info?.('billing.webhook.ignored', { ...eventLog, reason });\n return { status: 200, body: { received: true, outcome: 'ignored' } };\n };\n\n const isSubscriptionEvent = SUBSCRIPTION_EVENT_TYPES.has(event.type);\n if (!isSubscriptionEvent && event.type !== CHECKOUT_COMPLETED) {\n return ignoredResponse('event_type_not_handled');\n }\n if (!object) return ignoredResponse('malformed_object');\n\n const facts = {\n eventId,\n eventType: event.type,\n eventCreated: event.timestamp,\n };\n try {\n if (await claimExists(eventId)) {\n logger?.info?.('billing.webhook.duplicate', eventLog);\n return { status: 200, body: { received: true, outcome: 'duplicate' } };\n }\n let work: (tx: BillingHostOptions['db']) => Promise<AppliedOutcome>;\n if (isSubscriptionEvent) {\n const snapshot = subscriptionSnapshotFromObject(object, event.type);\n if (!snapshot) return ignoredResponse('malformed_object');\n work = (tx) =>\n applySubscriptionEvent(\n { db: tx, postgres, tenantPlans, prices, logger },\n facts,\n snapshot,\n );\n } else {\n const checkout = checkoutFactsFromObject(object);\n if (checkout?.mode !== 'subscription') {\n return ignoredResponse('not_a_subscription_checkout');\n }\n const { metadata } = checkout;\n if (metadata.smrt_purpose !== METADATA_PURPOSE) {\n // Not one of ours: another integration's session.\n logger?.warn?.('billing.webhook.unsigned_checkout', eventLog);\n return ignoredResponse('checkout_metadata_not_signed');\n }\n let signedByUs = false;\n for (const secret of verificationSecrets) {\n if (await checkoutMetadataValid(metadata, secret)) {\n signedByUs = true;\n break;\n }\n }\n if (!signedByUs) {\n // Claims to be ours but does not verify: a forgery, or a genuine\n // purchase whose signing secret rotated out of the accepted set (it\n // is then paid for and dropped). Loud so an operator sees the second.\n logger?.error?.('billing.webhook.checkout_signature_invalid', {\n ...eventLog,\n sessionId: checkout.sessionId,\n });\n return ignoredResponse('checkout_metadata_not_signed');\n }\n const tenantId = metadata.smrt_tenant_id;\n const planId = metadata.smrt_plan_id;\n if (\n !tenantId ||\n !planId ||\n !checkout.subscriptionId ||\n !checkout.customerId\n ) {\n return ignoredResponse('checkout_incomplete');\n }\n // Read the subscription back (outside the transaction): the row then\n // reflects current provider state however the events were ordered.\n const observedAt = new Date();\n const state = await provider.billing.retrieveSubscriptionStatus(\n checkout.subscriptionId,\n );\n if (\n state.externalId !== checkout.subscriptionId ||\n state.customerExternalId !== checkout.customerId\n ) {\n return ignoredResponse('checkout_subscription_mismatch');\n }\n const snapshot = subscriptionSnapshotFromState(state);\n if (\n !metadata.smrt_price_id ||\n snapshot.priceId !== metadata.smrt_price_id ||\n (metadata.smrt_customer_id &&\n metadata.smrt_customer_id !== checkout.customerId)\n ) {\n // The subscription is not the one this checkout was created for:\n // reused signed metadata, or a price remapped mid-checkout.\n logger?.error?.('billing.checkout.binding_mismatch', {\n ...eventLog,\n subscriptionId: state.externalId,\n });\n return ignoredResponse('checkout_binding_mismatch');\n }\n // Create the table on the base handle, outside the transaction.\n await BillingCheckoutSessionCollection.create({ db });\n work = (tx) =>\n completeBoundCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n {\n sessionId: checkout.sessionId,\n tenantId,\n planId,\n exp: metadata[METADATA_EXPIRY_KEY],\n eventId,\n eventTime: event.timestamp,\n },\n { ...facts, observedAt },\n snapshot,\n );\n }\n\n const outcome = await withSystemContext(() =>\n runOnce(\n {\n db,\n tenantId: CLAIM_SCOPE,\n actor: claimActor,\n token: eventId,\n content: { provider: 'stripe' },\n },\n work,\n ),\n );\n logger?.info?.('billing.webhook.processed', {\n ...eventLog,\n outcome: outcome.action,\n ...(outcome.reason ? { reason: outcome.reason } : {}),\n });\n return {\n status: 200,\n body: { received: true, outcome: outcome.action },\n };\n } catch (error) {\n if (error instanceof RunOnceClaimError) {\n // The same event is being applied right now; ask for a later retry\n // rather than acknowledge work that may yet fail.\n logger?.warn?.('billing.webhook.in_flight', eventLog);\n return { status: 409, body: { received: false, error: 'in_flight' } };\n }\n logger?.error?.('billing.webhook.failed', {\n ...eventLog,\n message: safeErrorMessage(error),\n });\n // Non-2xx: the provider retries, and the rolled-back claim lets it run.\n return {\n status: 500,\n body: { received: false, error: 'processing_failed' },\n };\n }\n }\n\n // -------------------------------------------------------------------------\n // Operator reconciliation of paid sessions that could not be bound (#4814)\n // -------------------------------------------------------------------------\n\n async function listCheckoutsNeedingReconciliation(options?: {\n limit?: number;\n offset?: number;\n }): Promise<BillingUnreconciledCheckout[]> {\n const limit = Math.min(\n Math.max(Math.trunc(Number(options?.limit ?? 200)) || 200, 1),\n 1000,\n );\n const offset = Math.max(Math.trunc(Number(options?.offset ?? 0)) || 0, 0);\n return withSystemContext(async () => {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n const rows = await sessions.list({\n where: { status: 'needs_reconciliation' },\n orderBy: 'created_at ASC',\n limit,\n offset,\n });\n const result: BillingUnreconciledCheckout[] = [];\n for (const row of rows) {\n const flagged = parseReconcileContext(row);\n const claimed = flagged?.claimedTenantId ?? '';\n let hasOwn = false;\n if (claimed) {\n for (const status of ['pending', 'completed'] as const) {\n const own = await sessions.list({\n where: { targetTenantId: claimed, status },\n limit: 1,\n });\n if (own.length > 0) hasOwn = true;\n }\n }\n result.push({\n sessionId: row.sessionId,\n reason: row.reason,\n claimedTenantId: claimed,\n subscriptionId: flagged?.subscriptionId ?? '',\n customerId: flagged?.customerId ?? '',\n targetTenantId: row.targetTenantId,\n claimedTenantHasOwnSession: hasOwn,\n eventId: flagged?.eventId ?? '',\n flaggedAt: new Date(row.updated_at ?? row.created_at ?? Date.now()),\n });\n }\n return result;\n });\n }\n\n async function countCheckoutsNeedingReconciliation(): Promise<number> {\n return withSystemContext(async () => {\n const sessions = await BillingCheckoutSessionCollection.create({ db });\n return sessions.count({ where: { status: 'needs_reconciliation' } });\n });\n }\n\n async function dismissCheckout(input: {\n sessionId: string;\n operatorId: string;\n reason: string;\n }): Promise<void> {\n const { sessionId, operatorId, reason } = input ?? {};\n if (\n typeof sessionId !== 'string' ||\n !REF_PATTERN.test(sessionId) ||\n typeof operatorId !== 'string' ||\n !/^\\S{1,128}$/.test(operatorId) ||\n typeof reason !== 'string' ||\n reason.trim().length === 0 ||\n reason.length > 200\n ) {\n throw new BillingHostError('invalid_request');\n }\n await withSystemContext(async () => {\n const done = await db.transaction?.((tx) =>\n dismissFlaggedCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n { sessionId, operatorId, reason: reason.trim() },\n ),\n );\n if (!done) throw new BillingHostError('checkout_not_reconcilable');\n });\n }\n\n async function reconcileCheckout(input: {\n sessionId: string;\n tenantId: string;\n planId?: string;\n operatorId: string;\n }): Promise<{ outcome: 'applied' | 'ignored'; reason?: string }> {\n const { sessionId, tenantId, planId, operatorId } = input ?? {};\n if (\n typeof sessionId !== 'string' ||\n !REF_PATTERN.test(sessionId) ||\n typeof tenantId !== 'string' ||\n !REF_PATTERN.test(tenantId) ||\n (planId !== undefined &&\n (typeof planId !== 'string' || !REF_PATTERN.test(planId))) ||\n typeof operatorId !== 'string' ||\n !/^\\S{1,128}$/.test(operatorId)\n ) {\n throw new BillingHostError('invalid_request');\n }\n return withSystemContext(async () => {\n const loaded = await loadFlaggedCheckout(db, sessionId);\n if (!loaded) throw new BillingHostError('checkout_not_reconcilable');\n let snapshot: ReturnType<typeof subscriptionSnapshotFromState>;\n try {\n snapshot = subscriptionSnapshotFromState(\n await provider.billing.retrieveSubscriptionStatus(\n loaded.flagged.subscriptionId,\n ),\n );\n } catch (error) {\n logger?.error?.('billing.reconcile.provider_error', {\n sessionId,\n message: safeErrorMessage(error),\n });\n throw new BillingHostError('provider_error');\n }\n const outcome = await db.transaction?.((tx) =>\n reconcileFlaggedCheckout(\n { db: tx, postgres, tenantPlans, prices, logger },\n { sessionId, tenantId, planId, operatorId, snapshot },\n ),\n );\n if (!outcome) throw new BillingHostError('checkout_not_reconcilable');\n return {\n outcome: outcome.action === 'applied' ? 'applied' : 'ignored',\n ...(outcome.reason ? { reason: outcome.reason } : {}),\n };\n });\n }\n\n // -------------------------------------------------------------------------\n // Fetch-API handlers\n // -------------------------------------------------------------------------\n\n function errorResponse(error: unknown): Response {\n if (error instanceof BillingHostError) {\n return jsonResponse(error.status, {\n error: error.code,\n message: error.message,\n });\n }\n logger?.error?.('billing.request.failed', {\n message: safeErrorMessage(error),\n });\n return jsonResponse(500, { error: 'internal_error' });\n }\n\n async function readSmallBody(request: Request): Promise<string> {\n const text = await readBoundedText(request, MAX_REQUEST_BODY_BYTES);\n if (text === null) throw new BillingHostError('invalid_request');\n return text;\n }\n\n async function readPlanRef(\n request: Request,\n ): Promise<{ planKey?: string; planId?: string }> {\n const type = request.headers.get('content-type') ?? '';\n let values: Record<string, unknown>;\n try {\n if (type.includes('application/json')) {\n const parsed: unknown = JSON.parse(await readSmallBody(request));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('not an object');\n }\n values = parsed as Record<string, unknown>;\n } else {\n const form = new URLSearchParams(await readSmallBody(request));\n values = Object.fromEntries(form.entries());\n }\n } catch (error) {\n if (error instanceof BillingHostError) throw error;\n throw new BillingHostError('invalid_request');\n }\n // Only these two fields are read: a price, amount, tenant or URL sent by\n // the client is ignored.\n const ref: { planKey?: string; planId?: string } = {};\n if (values.planKey !== undefined) {\n if (typeof values.planKey !== 'string') {\n throw new BillingHostError('invalid_request');\n }\n ref.planKey = values.planKey;\n }\n if (values.planId !== undefined) {\n if (typeof values.planId !== 'string') {\n throw new BillingHostError('invalid_request');\n }\n ref.planId = values.planId;\n }\n return ref;\n }\n\n const handlers: BillingHost['handlers'] = {\n async checkout(request, auth) {\n if (request.method !== 'POST') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'POST' },\n );\n }\n try {\n return jsonResponse(\n 200,\n await createCheckout(auth, await readPlanRef(request)),\n );\n } catch (error) {\n return errorResponse(error);\n }\n },\n\n async portal(request, auth) {\n if (request.method !== 'POST' && request.method !== 'GET') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'GET, POST' },\n );\n }\n try {\n return jsonResponse(200, await createPortalLink(auth));\n } catch (error) {\n return errorResponse(error);\n }\n },\n\n async webhook(request) {\n if (request.method !== 'POST') {\n return jsonResponse(\n 405,\n { error: 'method_not_allowed' },\n { allow: 'POST' },\n );\n }\n let payload: string | null;\n try {\n payload = await readBoundedText(request, maxBodyBytes);\n } catch {\n const rejected = reject(400, 'invalid_payload', 'unreadable_body');\n return jsonResponse(rejected.status, rejected.body);\n }\n if (payload === null) {\n const rejected = reject(413, 'payload_too_large', 'payload_too_large');\n return jsonResponse(rejected.status, rejected.body);\n }\n const result = await handleWebhook({\n payload,\n signature: request.headers.get('stripe-signature'),\n });\n return jsonResponse(result.status, result.body);\n },\n };\n\n return {\n createCheckout,\n createPortalLink,\n listCheckoutsNeedingReconciliation,\n countCheckoutsNeedingReconciliation,\n dismissCheckout,\n reconcileCheckout,\n handleWebhook,\n handlers,\n };\n}\n","import { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n JsonObject,\n Subscriber,\n SubscriberKind,\n TenantUsageMetricOptions,\n} from '../types.js';\nimport {\n assertSubscriberInvariant,\n parseJsonObject,\n stringifyJson,\n} from '../utils.js';\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_tenant_usage_metrics',\n api: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class TenantUsageMetric extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId()\n tenantId?: string;\n\n /**\n * Discriminator for which subscriber identity recorded this usage.\n * `'tenant'` (default) preserves the legacy shape; `'external'` indicates\n * the subscriber is `subscriberExternalId` under the issuing `tenantId`.\n */\n subscriberKind: SubscriberKind = 'tenant';\n\n /**\n * Opaque caller-namespaced subscriber id when `subscriberKind === 'external'`.\n * Empty string when kind is `'tenant'`.\n */\n subscriberExternalId: string = '';\n\n metricKey: string = '';\n quantity: number = 0.0;\n windowStart: Date = new Date();\n windowEnd: Date = new Date();\n source: string = '';\n sourceId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n provider: string = '';\n dimensions: string = '{}';\n\n constructor(options: TenantUsageMetricOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.subscriberKind !== undefined)\n this.subscriberKind = options.subscriberKind;\n if (options.subscriberExternalId !== undefined)\n this.subscriberExternalId = options.subscriberExternalId;\n // Construction-time guard; the same invariant is re-checked in\n // `validateBeforeSave` so the generated update path can't bypass it.\n assertSubscriberInvariant('TenantUsageMetric', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (options.metricKey !== undefined) this.metricKey = options.metricKey;\n if (options.quantity !== undefined) this.quantity = options.quantity;\n if (options.windowStart !== undefined)\n this.windowStart = options.windowStart;\n if (options.windowEnd !== undefined) this.windowEnd = options.windowEnd;\n if (options.source !== undefined) this.source = options.source;\n if (options.sourceId !== undefined) this.sourceId = options.sourceId;\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.workRefType !== undefined)\n this.workRefType = options.workRefType;\n if (options.workRefId !== undefined) this.workRefId = options.workRefId;\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.dimensions !== undefined) this.dimensions = options.dimensions;\n }\n\n /** See `TenantSubscription.validateBeforeSave` for the rationale. */\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n assertSubscriberInvariant('TenantUsageMetric', {\n subscriberKind: this.subscriberKind,\n subscriberExternalId: this.subscriberExternalId,\n });\n if (this.id) {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n const persisted = [\n row.tenant_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.metric_key,\n row.quantity,\n row.window_start,\n row.window_end,\n row.source,\n row.source_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.dimensions,\n ];\n const current = [\n this.tenantId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.metricKey,\n this.quantity,\n this.windowStart,\n this.windowEnd,\n this.source,\n this.sourceId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.dimensions,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeEvidence(value) !== normalizeEvidence(current[index]),\n )\n ) {\n throw new Error(\n 'Usage events are immutable; record a new event instead.',\n );\n }\n }\n }\n }\n\n /**\n * Project this row's polymorphic subscriber columns onto the\n * {@link Subscriber} discriminated union.\n */\n getSubscriber(): Subscriber | null {\n if (!this.tenantId) {\n return null;\n }\n if (this.subscriberKind === 'external') {\n if (!this.subscriberExternalId) {\n return null;\n }\n return {\n kind: 'external',\n tenantId: this.tenantId,\n externalId: this.subscriberExternalId,\n };\n }\n return { kind: 'tenant', tenantId: this.tenantId };\n }\n\n getDimensions(): JsonObject {\n return parseJsonObject(this.dimensions, {});\n }\n\n setDimensions(dimensions: JsonObject): void {\n this.dimensions = stringifyJson(dimensions);\n }\n}\n\nexport default TenantUsageMetric;\n\nfunction normalizeEvidence(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string') {\n const timestamp = Date.parse(value);\n if (/^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value) && Number.isFinite(timestamp)) {\n return new Date(timestamp).toISOString();\n }\n }\n return String(value ?? '');\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { TenantUsageMetric } from '../models/TenantUsageMetric.js';\nimport type {\n AiUsageSummary,\n RecordUsageOptions,\n SummarizeAiUsageOptions,\n SummarizeUsageBatchOptions,\n SummarizeUsageOptions,\n UsageSummary,\n} from '../types.js';\nimport {\n deterministicUuid,\n normalizeSubscriber,\n stringifyJson,\n subscriberToColumns,\n} from '../utils.js';\n\nexport class TenantUsageMetricCollection extends SmrtCollection<TenantUsageMetric> {\n static readonly _itemClass = TenantUsageMetric;\n\n async recordUsage(options: RecordUsageOptions): Promise<TenantUsageMetric> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n const sourcedId =\n options.source && options.sourceId\n ? await deterministicUuid([\n 'tenant-usage',\n columns.tenantId,\n columns.subscriberKind,\n columns.subscriberExternalId,\n options.metricKey,\n options.source,\n options.sourceId,\n ])\n : null;\n if (options.source && options.sourceId) {\n const existing = await this.get(sourcedId as string);\n if (existing) return existing;\n }\n try {\n return await this.create({\n ...(sourcedId ? { id: sourcedId } : {}),\n tenantId: columns.tenantId,\n subscriberKind: columns.subscriberKind,\n subscriberExternalId: columns.subscriberExternalId,\n metricKey: options.metricKey,\n quantity: options.quantity,\n windowStart: options.windowStart,\n windowEnd: options.windowEnd,\n source: options.source ?? '',\n sourceId: options.sourceId ?? '',\n projectId: options.projectId ?? '',\n workRefType: options.workRefType ?? '',\n workRefId: options.workRefId ?? '',\n provider: options.provider ?? '',\n dimensions: stringifyJson(options.dimensions ?? {}),\n _insertOnly: Boolean(sourcedId),\n });\n } catch (error) {\n if (sourcedId) {\n const existing = await this.get(sourcedId);\n if (existing) return existing;\n }\n throw error;\n }\n }\n\n /**\n * Legacy accessor — finds metrics for `subscriberKind = 'tenant'` under the\n * given tenant. External-kind rows scoped to the same tenant are excluded.\n */\n async findByTenantAndMetric(\n tenantId: string,\n metricKey: string,\n ): Promise<TenantUsageMetric[]> {\n return this.list({\n where: { tenantId, metricKey, subscriberKind: 'tenant' },\n orderBy: 'windowStart DESC',\n });\n }\n\n async summarizeUsage(options: SummarizeUsageOptions): Promise<UsageSummary> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n\n const where: Record<string, unknown> = {\n tenantId: columns.tenantId,\n subscriberKind: columns.subscriberKind,\n metricKey: options.metricKey,\n 'windowStart <': options.window.end.toISOString(),\n 'windowEnd >': options.window.start.toISOString(),\n };\n if (subscriber.kind === 'external') {\n where.subscriberExternalId = columns.subscriberExternalId;\n }\n\n const metrics = await this.list({ where });\n\n const baseSummary: UsageSummary = {\n tenantId: columns.tenantId,\n metricKey: options.metricKey,\n quantity: metrics.reduce((sum, metric) => sum + metric.quantity, 0),\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...baseSummary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return baseSummary;\n }\n\n async summarizeUsageBatch(\n options: SummarizeUsageBatchOptions,\n ): Promise<UsageSummary[]> {\n const metricKeys = Array.from(new Set(options.metricKeys));\n if (metricKeys.length === 0) {\n return [];\n }\n\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const columns = subscriberToColumns(subscriber);\n\n const metricPlaceholders = metricKeys.map(() => '?').join(', ');\n const params: unknown[] = [\n columns.tenantId,\n columns.subscriberKind,\n ...metricKeys,\n options.window.end.toISOString(),\n options.window.start.toISOString(),\n ];\n let subscriberSql = '';\n if (subscriber.kind === 'external') {\n subscriberSql = 'AND subscriber_external_id = ?';\n params.splice(2, 0, columns.subscriberExternalId);\n }\n\n const result = await this.db.query(\n `SELECT\n metric_key,\n COALESCE(SUM(quantity), 0) AS quantity\n FROM _smrt_tenant_usage_metrics\n WHERE tenant_id = ?\n AND subscriber_kind = ?\n ${subscriberSql}\n AND metric_key IN (${metricPlaceholders})\n AND window_start < ?\n AND window_end > ?\n GROUP BY metric_key`,\n ...params,\n );\n\n const quantityByMetric = new Map<string, number>();\n for (const row of resultRows(result)) {\n const metricKey = String(row.metric_key ?? row.metricKey ?? '');\n if (metricKey) {\n quantityByMetric.set(metricKey, numberFromRow(row, 'quantity'));\n }\n }\n\n return metricKeys.map((metricKey) => {\n const baseSummary: UsageSummary = {\n tenantId: columns.tenantId,\n metricKey,\n quantity: quantityByMetric.get(metricKey) ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...baseSummary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return baseSummary;\n });\n }\n\n /**\n * Summarize persisted AI usage for a tenant within a window.\n *\n * Reads the framework `_smrt_ai_usage` system table via a raw aggregate\n * query. This deliberately uses `this.db.query` rather than the inherited\n * `query()`: those rows are framework usage records, not `TenantUsageMetric`\n * instances, so model hydration would discard the aggregate columns. Tenant\n * scoping is applied explicitly through the `tenant_id` filter.\n *\n * Named distinctly from the inherited `SmrtClass.summarizeAiUsage` (which\n * returns grouped stats across all tenants) to avoid overriding it.\n */\n async summarizeTenantAiUsage(\n options: SummarizeAiUsageOptions,\n ): Promise<AiUsageSummary> {\n const result = await this.db.query(\n `SELECT\n COALESCE(SUM(prompt_tokens), 0) AS prompt_tokens,\n COALESCE(SUM(completion_tokens), 0) AS completion_tokens,\n COALESCE(SUM(total_tokens), 0) AS total_tokens,\n COALESCE(SUM(estimated_cost), 0) AS estimated_cost,\n COUNT(*) AS request_count\n FROM _smrt_ai_usage\n WHERE tenant_id = ?\n AND operation <> 'blocked'\n AND NOT (operation = 'external-agent' AND id LIKE 'external-agent:%')\n AND created_at >= ?\n AND created_at < ?`,\n options.tenantId,\n options.window.start.toISOString(),\n options.window.end.toISOString(),\n );\n const row = firstRow(result);\n\n return {\n tenantId: options.tenantId,\n promptTokens: numberFromRow(row, 'prompt_tokens'),\n completionTokens: numberFromRow(row, 'completion_tokens'),\n totalTokens: numberFromRow(row, 'total_tokens'),\n estimatedCost: numberFromRow(row, 'estimated_cost'),\n requestCount: numberFromRow(row, 'request_count'),\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n }\n}\n\nfunction firstRow(result: unknown): Record<string, unknown> {\n const rows = resultRows(result);\n return (rows[0] ?? {}) as Record<string, unknown>;\n}\n\nfunction resultRows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : ((result as { rows?: Record<string, unknown>[] })?.rows ?? []);\n}\n\nfunction numberFromRow(row: Record<string, unknown>, key: string): number {\n const value = row[key];\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'bigint') {\n return Number(value);\n }\n if (typeof value === 'string') {\n return Number.parseFloat(value) || 0;\n }\n return 0;\n}\n","/**\n * Subscriptions money columns: floating-point major units → integer minor units.\n *\n * Ships as an explicit, opt-in migration rather than a schema-differ upgrade\n * because REAL→INTEGER is not information-preserving: an automatic\n * `ALTER … TYPE integer` would truncate `19.99` to `19`. The values have to be\n * rescaled by the currency's minor-unit factor during the type change (#2401).\n *\n * ```ts\n * console.log((await preflightSubscriptionsMoneyMinorUnits(db)).summary);\n * await migrateSubscriptionsMoneyToMinorUnits(db);\n * ```\n *\n * On SQLite the values are rescaled but the declared type cannot change in\n * place; those columns come back in `declaredTypeChangePending` and need the\n * table-rebuild path (#2370).\n *\n * **Pricing rules are not migrated.** `PricingRule.terms` is a JSON blob whose\n * `unitPrice` / `overageUnitPrice` / `amount` / tier prices are now read as\n * *minor units per unit of usage*. They are deliberately left fractional (a\n * per-token rate is routinely a fraction of a cent), so there is no type to\n * change — but every existing rule's terms are in major units and must be\n * rescaled by the operator, who alone knows which keys in a given rule are\n * prices and which are quantities or ratios.\n */\n\nimport {\n type DatabaseInterface,\n type MinorUnitsPreflightResult,\n type MinorUnitsRescaleResult,\n type MoneyColumnTarget,\n preflightMinorUnitsRescale,\n rescaleMoneyColumnsToMinorUnits,\n} from '@happyvertical/smrt-core/migrations';\n\n/** Marker recorded in `_smrt_backfills` once the rescale has run. */\nexport const SUBSCRIPTIONS_MONEY_MINOR_UNITS_BACKFILL =\n '@happyvertical/smrt-subscriptions:money-minor-units:v1';\n\n/**\n * Every subscriptions money column that held major units before #2401.\n *\n * `quantity` columns are absent on purpose: metered quantities are genuinely\n * fractional and stay DECIMAL.\n */\nexport const SUBSCRIPTIONS_MONEY_COLUMNS: MoneyColumnTarget[] = [\n { table: '_smrt_subscription_plans', columns: ['price_amount'] },\n { table: '_smrt_client_charges', columns: ['amount'] },\n { table: '_smrt_billing_adjustments', columns: ['amount'] },\n { table: '_smrt_spending_policies', columns: ['limit_amount'] },\n];\n\n/**\n * Report what {@link migrateSubscriptionsMoneyToMinorUnits} would do, without\n * writing anything.\n */\nexport function preflightSubscriptionsMoneyMinorUnits(\n db: DatabaseInterface,\n options: { scale?: number; engineHint?: string } = {},\n): Promise<MinorUnitsPreflightResult> {\n return preflightMinorUnitsRescale(db, SUBSCRIPTIONS_MONEY_COLUMNS, options);\n}\n\n/**\n * Convert every subscriptions money column from floating-point major units to\n * integer minor units. Idempotent via a `_smrt_backfills` marker.\n *\n * @throws `MinorUnitsPreflightError` when a row would be rounded or would\n * overflow `int4` and `force` was not set.\n */\nexport function migrateSubscriptionsMoneyToMinorUnits(\n db: DatabaseInterface,\n options: { scale?: number; engineHint?: string; force?: boolean } = {},\n): Promise<MinorUnitsRescaleResult> {\n return rescaleMoneyColumnsToMinorUnits(db, SUBSCRIPTIONS_MONEY_COLUMNS, {\n ...options,\n backfillName: SUBSCRIPTIONS_MONEY_MINOR_UNITS_BACKFILL,\n packageName: '@happyvertical/smrt-subscriptions',\n });\n}\n","/**\n * Backfill effective-dated plan versions for data written before #4032.\n *\n * Run once after the manifest migration (`smrt db:migrate`) has created\n * `_smrt_subscription_plan_versions` and the `plan_version_*` columns on\n * `_smrt_tenant_subscriptions`:\n *\n * ```ts\n * const report = await migrateSubscriptionPlanVersions(db);\n * if (report.failed.length) console.error(report.failed);\n * ```\n *\n * - Every plan without versions gets version 1: its current terms, effective\n * from the plan's `created_at`. Nothing on the plan row changes.\n * - Every subscription without a pin is pinned to the version in force at its\n * period start (`currentPeriodStart ?? startedAt`) with\n * `planVersionPinReason: 'migration'`. With only version 1 present that is\n * always version 1, so no subscriber's entitlements change.\n *\n * Idempotent: plans with versions and pinned subscriptions are skipped. Runs\n * in system context across all tenants. A subscription whose existing row no\n * longer passes validation is reported in `failed` and left unpinned (it keeps\n * resolving through the live plan's version 1); the run continues.\n */\nimport { withSystemContext } from '@happyvertical/smrt-tenancy';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport { snapshotLegacyPlanVersion } from '../plan-versioning.js';\n\nexport interface SubscriptionPlanVersionsMigrationReport {\n /** Plans that received their version 1. */\n plansVersioned: number;\n /** Subscriptions that received a pin. */\n subscriptionsPinned: number;\n /** Subscriptions that could not be pinned, with the validation error. */\n failed: Array<{ subscriptionId: string; error: string }>;\n}\n\nexport async function migrateSubscriptionPlanVersions(\n db: DatabaseInterface,\n options: { pageSize?: number } = {},\n): Promise<SubscriptionPlanVersionsMigrationReport> {\n const pageSize = options.pageSize ?? 200;\n return withSystemContext(async () => {\n const report: SubscriptionPlanVersionsMigrationReport = {\n plansVersioned: 0,\n subscriptionsPinned: 0,\n failed: [],\n };\n const plans = await SubscriptionPlanCollection.create({ db });\n for (let offset = 0; ; offset += pageSize) {\n const page = await plans.list({\n orderBy: 'id ASC',\n limit: pageSize,\n offset,\n });\n for (const plan of page) {\n if (await snapshotLegacyPlanVersion(plan)) report.plansVersioned += 1;\n }\n if (page.length < pageSize) break;\n }\n const subscriptions = await TenantSubscriptionCollection.create({ db });\n for (let offset = 0; ; offset += pageSize) {\n const page = await subscriptions.list({\n orderBy: 'id ASC',\n limit: pageSize,\n offset,\n });\n for (const subscription of page) {\n if (subscription.planVersionId || !subscription.planId) continue;\n try {\n await subscription.save();\n if (subscription.planVersionId) report.subscriptionsPinned += 1;\n } catch (error) {\n report.failed.push({\n subscriptionId: String(subscription.id),\n error: rootMessage(error),\n });\n }\n }\n if (page.length < pageSize) break;\n }\n return report;\n });\n}\n\nfunction rootMessage(error: unknown): string {\n let current: unknown = error;\n while (current instanceof Error && current.cause instanceof Error) {\n current = current.cause;\n }\n return current instanceof Error ? current.message : String(current);\n}\n","import {\n crossPackageRef,\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\n\nexport type PricingStrategy =\n | 'fixed_unit'\n | 'cost_plus'\n | 'multiplier'\n | 'tiered'\n | 'included_overage'\n | 'flat'\n | 'custom';\nexport type SpendingPolicyBehavior =\n | 'observe'\n | 'warn'\n | 'block'\n | 'approval_required';\n/**\n * `balance` is a prepaid credit balance: the policy's limit is the sum of its\n * {@link CreditGrant}s and spend accumulates from `balanceFrom` onward.\n */\nexport type SpendingPeriod =\n | 'day'\n | 'week'\n | 'month'\n | 'year'\n | 'rolling'\n | 'balance';\n/**\n * Which charges a spending policy counts (#3059).\n *\n * - `billed`: provider charges payable by the policy tenant (`ClientCharge`\n * rows whose `tenantId` is the tenant) — the pre-#3059 behavior.\n * - `retail`: what the tenant owes its reseller (`RetailCharge` rows).\n * - `wholesale`: what the policy's parent (`setByTenantId`) pays the provider\n * for this tenant's usage (`ClientCharge` rows billed to the parent with\n * `usageTenantId` = the tenant). Requires a delegated policy.\n */\nexport type SpendingBasis = 'billed' | 'retail' | 'wholesale';\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_pricing_rules',\n api: true,\n cli: true,\n mcp: true,\n})\nexport class PricingRule extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n ruleKey: string = '';\n metricKey: string = '';\n serviceKey: string = '';\n strategy: PricingStrategy = 'fixed_unit';\n currency: string = 'USD';\n effectiveFrom: Date = new Date();\n effectiveTo: Date | null = null;\n priority: number = 0;\n terms: string = '{}';\n active: boolean = true;\n /**\n * The price book this rule belongs to (#3059), or empty for a tenant's\n * direct pricing. Book rules are priced only through\n * `CommercialUsageService.rateUsage()`; `price()` ignores them.\n */\n @foreignKey('PriceBook')\n priceBookId: string = '';\n\n getTerms(): Record<string, unknown> {\n try {\n return JSON.parse(this.terms) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n setTerms(value: Record<string, unknown>): void {\n this.terms = JSON.stringify(value);\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_client_charges',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n conflictColumns: ['usage_event_id'],\n})\nexport class ClientCharge extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The payer: the usage tenant, or its billing owner when parent-billed. */\n @tenantId() tenantId?: string;\n @foreignKey('TenantUsageMetric')\n usageEventId: string = '';\n /** The tenant whose usage was charged; differs from `tenantId` for wholesale. */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n usageTenantId: string = '';\n subscriberKind: string = 'tenant';\n subscriberExternalId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n @field({ description: 'Who supplied the service that was used.' })\n provider: string = '';\n @field({ description: 'The service that was used.' })\n serviceKey: string = '';\n @field({\n description: 'What was used, such as messages sent or minutes of audio.',\n })\n metricKey: string = '';\n /**\n * Metered quantity — genuinely fractional (`duration.seconds`, token counts\n * scaled by a rate), so it stays DECIMAL.\n */\n @field({ description: 'How much of it was used.' })\n quantity: number = 0.0;\n /**\n * Charge in **integer minor units** of {@link currency} (#2401).\n *\n * Summed against {@link BillingAdjustment.amount} and compared against\n * {@link SpendingPolicy.limitAmount}, so all three carry the same unit —\n * `CommercialService.calculateAmount()` rounds to a whole minor unit at the\n * one boundary where the fractional pricing terms meet money.\n */\n @field({ description: 'What it cost, in cents.' })\n amount: number = 0;\n @field({ description: 'The currency the amount is in, such as USD.' })\n currency: string = 'USD';\n @foreignKey('PricingRule')\n pricingRuleId: string = '';\n /** Wholesale book that priced this charge, or empty for direct pricing. */\n @foreignKey('PriceBook')\n priceBookId: string = '';\n pricingSnapshot: string = '{}';\n @field({\n description: 'Where the charge stands: draft, approved or adjusted.',\n })\n status: 'draft' | 'approved' | 'adjusted' = 'draft';\n @field({ description: 'When the charge was approved.' })\n approvedAt: Date | null = null;\n\n getPricingSnapshot(): Record<string, unknown> {\n try {\n return JSON.parse(this.pricingSnapshot) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.getCanonicalPersistedRow({ id: this.id });\n if (!row || (row.status !== 'approved' && row.status !== 'adjusted'))\n return;\n if (\n (row.status === 'approved' &&\n this.status !== 'approved' &&\n this.status !== 'adjusted') ||\n (row.status === 'adjusted' && this.status !== 'adjusted')\n ) {\n throw new Error(\n 'Approved client charges cannot be reverted to an editable status.',\n );\n }\n const persisted = [\n row.tenant_id,\n row.usage_event_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.service_key,\n row.metric_key,\n row.quantity,\n row.amount,\n row.currency,\n row.pricing_rule_id,\n row.pricing_snapshot,\n row.approved_at,\n row.usage_tenant_id,\n row.price_book_id,\n ];\n const current = [\n this.tenantId,\n this.usageEventId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.serviceKey,\n this.metricKey,\n this.quantity,\n this.amount,\n this.currency,\n this.pricingRuleId,\n this.pricingSnapshot,\n this.approvedAt,\n this.usageTenantId,\n this.priceBookId,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeSnapshot(value) !== normalizeSnapshot(current[index]),\n )\n ) {\n throw new Error(\n 'Approved client charges are immutable; append a BillingAdjustment instead.',\n );\n }\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_billing_adjustments',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class BillingAdjustment extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n @foreignKey('ClientCharge')\n clientChargeId: string = '';\n /**\n * Signed correction in **integer minor units**, same unit as\n * {@link ClientCharge.amount} it adjusts. Negative values are legitimate\n * (a credit) — that is why the non-negative guard in\n * `CommercialService.calculateAmount()` does not apply here (#2401).\n */\n amount: number = 0;\n currency: string = 'USD';\n reason: string = '';\n source: string = '';\n sourceId: string = '';\n createdBy: string = '';\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n throw new Error(\n 'Billing adjustments are append-only; create a new adjustment instead.',\n );\n }\n }\n}\n\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_spending_policies',\n conflictColumns: [\n 'tenant_id',\n 'subscriber_kind',\n 'subscriber_external_id',\n 'project_id',\n 'service_key',\n 'metric_key',\n 'period',\n 'name',\n ],\n api: true,\n cli: true,\n mcp: true,\n hooks: { beforeDelete: 'assertDelegationAuthority' },\n})\nexport class SpendingPolicy extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n name: string = '';\n subscriberKind: string = '';\n subscriberExternalId: string = '';\n projectId: string = '';\n serviceKey: string = '';\n metricKey: string = '';\n period: SpendingPeriod = 'month';\n rollingSeconds: number = 0;\n /**\n * Spending cap in **integer minor units** of {@link currency}. Compared\n * directly against the sum of `ClientCharge.amount` + `BillingAdjustment`s\n * plus the caller's estimate, so it must carry the same unit (#2401).\n * Must be zero for a `balance` policy, whose limit is its credit grants.\n */\n limitAmount: number = 0;\n currency: string = 'USD';\n behavior: SpendingPolicyBehavior = 'observe';\n priority: number = 0;\n active: boolean = true;\n /** Which charges count toward the policy; see {@link SpendingBasis}. */\n basis: SpendingBasis = 'billed';\n /**\n * The parent tenant that set this policy on its child (#3059), or empty for\n * a tenant's own policy. A delegated policy can be changed or deleted only\n * by that parent, a system context, or a super-admin bypass.\n */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n setByTenantId: string = '';\n /** Start of the spend window for a `balance` policy; defaults to creation. */\n balanceFrom: Date | null = null;\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (this.subscriberExternalId && !this.subscriberKind) {\n throw new Error(\n 'Spending policies with subscriberExternalId require subscriberKind.',\n );\n }\n if (\n this.period === 'rolling' &&\n (!Number.isFinite(this.rollingSeconds) || this.rollingSeconds <= 0)\n ) {\n throw new Error(\n 'Rolling spending policies require rollingSeconds greater than zero.',\n );\n }\n if (\n this.basis !== 'billed' &&\n this.basis !== 'retail' &&\n this.basis !== 'wholesale'\n ) {\n throw new Error(\n 'Spending policy basis must be billed, retail, or wholesale.',\n );\n }\n if (this.basis === 'wholesale' && !this.setByTenantId) {\n throw new Error(\n 'Wholesale spending policies must be delegated by a parent (setByTenantId).',\n );\n }\n if (this.period === 'balance') {\n if (this.limitAmount !== 0) {\n throw new Error(\n 'Balance spending policies take their limit from credit grants; limitAmount must be 0.',\n );\n }\n if (!this.balanceFrom) this.balanceFrom = new Date();\n }\n const targets = await this.persistedTargets();\n await this.assertBalanceLedgerStable(targets);\n await this.assertDelegationAuthority(targets);\n }\n\n /**\n * A balance policy's credit grants are scoped to its currency and period;\n * changing either would silently detach the ledger, so create a new\n * balance instead.\n */\n protected async assertBalanceLedgerStable(\n rows: Array<Record<string, unknown> | null>,\n ): Promise<void> {\n for (const row of rows) {\n if (row?.period !== 'balance') continue;\n if (this.period !== 'balance' || row.currency !== this.currency) {\n throw new Error(\n 'A balance policy cannot change currency or period; create a new balance policy.',\n );\n }\n }\n }\n\n /**\n * The rows this save can overwrite: by id and, because a new object may\n * already carry a generated id, by conflict key (an upsert target).\n */\n protected async persistedTargets(): Promise<\n Array<Record<string, unknown> | null>\n > {\n const byId = this.id\n ? await this.getCanonicalPersistedRow({ id: this.id })\n : null;\n const byKey = this.tenantId\n ? await this.getCanonicalPersistedRow({\n tenant_id: this.tenantId,\n subscriber_kind: this.subscriberKind,\n subscriber_external_id: this.subscriberExternalId,\n project_id: this.projectId,\n service_key: this.serviceKey,\n metric_key: this.metricKey,\n period: this.period,\n name: this.name,\n })\n : null;\n return [byId, byKey];\n }\n\n /**\n * A delegated policy belongs to the parent that set it: the constrained\n * child cannot create one in a parent's name, loosen it, or delete it.\n * The parent's-own-context allowance applies only where no tenancy\n * interceptor is registered; with one, the interceptor refuses a parent\n * writing the child's row, so parents change delegated policies through\n * `ResellerBillingService.setDelegatedSpendingPolicy()` (set\n * `active: false` to retire one).\n * Checks both the persisted row (by id, or by conflict key for an upsert)\n * and the incoming value.\n */\n protected async assertDelegationAuthority(\n targets?: Array<Record<string, unknown> | null>,\n ): Promise<void> {\n const [byId, byKey] = targets ?? (await this.persistedTargets());\n const owners = new Set(\n [byId?.set_by_tenant_id, byKey?.set_by_tenant_id, this.setByTenantId]\n .filter((value): value is string => Boolean(value))\n .map((value) => String(value).toLowerCase()),\n );\n if (owners.size === 0) return;\n if (isSystemContext() || isSuperAdminBypass()) return;\n const current = getTenantId()?.toLowerCase();\n if (owners.size === 1 && current && owners.has(current)) return;\n throw new TenantIsolationError(\n 'Delegated spending policies can be changed only by the parent that set them.',\n );\n }\n}\n\nexport class PricingRuleCollection extends SmrtCollection<PricingRule> {\n static readonly _itemClass = PricingRule;\n}\nexport class ClientChargeCollection extends SmrtCollection<ClientCharge> {\n static readonly _itemClass = ClientCharge;\n}\nexport class BillingAdjustmentCollection extends SmrtCollection<BillingAdjustment> {\n static readonly _itemClass = BillingAdjustment;\n}\nexport class SpendingPolicyCollection extends SmrtCollection<SpendingPolicy> {\n static readonly _itemClass = SpendingPolicy;\n}\n\nfunction normalizeSnapshot(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value)) {\n const timestamp = Date.parse(value);\n if (Number.isFinite(timestamp)) return new Date(timestamp).toISOString();\n }\n return String(value ?? '');\n}\n","/**\n * Reseller billing records (#3059): price books, their per-relationship\n * assignment, the reseller's retail ledger, and prepaid credit grants.\n *\n * Money is integer minor units throughout, exactly as in `commercial.ts`.\n */\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport { tenantKey } from '../utils.js';\n\n/**\n * `wholesale` books price what a service provider charges a reseller for its\n * children's usage; `retail` books price what a reseller charges its children.\n */\nexport type PriceBookKind = 'wholesale' | 'retail';\n\nconst PRICE_BOOK_KINDS: readonly PriceBookKind[] = ['wholesale', 'retail'];\nconst CURRENCY_PATTERN = /^[A-Z]{3}$/;\n\nexport function isPriceBookKind(value: unknown): value is PriceBookKind {\n return PRICE_BOOK_KINDS.includes(value as PriceBookKind);\n}\n\n/** ISO 4217-shaped (three upper-case letters) currency code check. */\nexport function isCurrencyCode(value: unknown): value is string {\n return typeof value === 'string' && CURRENCY_PATTERN.test(value);\n}\n\n/**\n * A named set of prices published by one seller tenant. Its prices are\n * ordinary {@link PricingRule} rows that carry this book's id and the same\n * tenant; one rule per currency gives a price in several currencies.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_price_books',\n conflictColumns: ['tenant_id', 'book_key'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class PriceBook extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The seller that publishes and owns the book. */\n @tenantId() tenantId?: string;\n bookKey: string = '';\n name: string = '';\n kind: PriceBookKind = 'retail';\n active: boolean = true;\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.bookKey.trim()) {\n throw new Error('Price books require a bookKey.');\n }\n if (!isPriceBookKind(this.kind)) {\n throw new Error('Price book kind must be wholesale or retail.');\n }\n }\n}\n\n/**\n * Which price books rate one child tenant's usage, keyed like the tenancy\n * billing relationship it belongs to (one row per child). The reseller is\n * recorded so an assignment made under one relationship never prices usage\n * after the child moves to a different reseller.\n *\n * A system table managed through `ResellerBillingService`, like\n * `_smrt_billing_relationships`; it has no generated API surface.\n */\n@smrt({\n tableName: '_smrt_price_book_assignments',\n conflictColumns: ['child_tenant_id'],\n api: false,\n cli: false,\n mcp: false,\n})\nexport class PriceBookAssignment extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n @field({ required: true })\n childTenantId: string = '';\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n @field({ required: true })\n resellerTenantId: string = '';\n @foreignKey('PriceBook')\n wholesalePriceBookId: string = '';\n wholesaleCurrency: string = '';\n @foreignKey('PriceBook')\n retailPriceBookId: string = '';\n retailCurrency: string = '';\n}\n\n/**\n * What a reseller charges one child for one usage event, priced from the\n * reseller's retail book. The provider's charge for the same event is the\n * {@link ClientCharge} in `clientChargeId`, payable by the billing owner.\n *\n * `tenantId` is always the payer (the child), so tenant-scoped reads and the\n * child's `retail`-basis spending policies see exactly what it owes.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_retail_charges',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n conflictColumns: ['usage_event_id'],\n})\nexport class RetailCharge extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n @tenantId() tenantId?: string;\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n resellerTenantId: string = '';\n @foreignKey('TenantUsageMetric')\n usageEventId: string = '';\n @foreignKey('ClientCharge')\n clientChargeId: string = '';\n subscriberKind: string = 'tenant';\n subscriberExternalId: string = '';\n projectId: string = '';\n workRefType: string = '';\n workRefId: string = '';\n provider: string = '';\n serviceKey: string = '';\n metricKey: string = '';\n /** Metered quantity; fractional, like `ClientCharge.quantity`. */\n quantity: number = 0.0;\n /** Charge in integer minor units of {@link currency}. */\n amount: number = 0;\n currency: string = 'USD';\n @foreignKey('PriceBook')\n priceBookId: string = '';\n @foreignKey('PricingRule')\n pricingRuleId: string = '';\n pricingSnapshot: string = '{}';\n status: 'draft' | 'approved' = 'draft';\n approvedAt: Date | null = null;\n\n getPricingSnapshot(): Record<string, unknown> {\n try {\n return JSON.parse(this.pricingSnapshot) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!this.id) return;\n const row = await this.getCanonicalPersistedRow({ id: this.id });\n if (row?.status !== 'approved') return;\n const persisted = [\n row.tenant_id,\n row.reseller_tenant_id,\n row.usage_event_id,\n row.client_charge_id,\n row.subscriber_kind,\n row.subscriber_external_id,\n row.project_id,\n row.work_ref_type,\n row.work_ref_id,\n row.provider,\n row.service_key,\n row.metric_key,\n row.quantity,\n row.amount,\n row.currency,\n row.price_book_id,\n row.pricing_rule_id,\n row.pricing_snapshot,\n row.status,\n row.approved_at,\n ];\n const current = [\n this.tenantId,\n this.resellerTenantId,\n this.usageEventId,\n this.clientChargeId,\n this.subscriberKind,\n this.subscriberExternalId,\n this.projectId,\n this.workRefType,\n this.workRefId,\n this.provider,\n this.serviceKey,\n this.metricKey,\n this.quantity,\n this.amount,\n this.currency,\n this.priceBookId,\n this.pricingRuleId,\n this.pricingSnapshot,\n this.status,\n this.approvedAt,\n ];\n if (\n persisted.some(\n (value, index) =>\n normalizeLedgerValue(value) !== normalizeLedgerValue(current[index]),\n )\n ) {\n throw new Error('Approved retail charges are immutable.');\n }\n }\n}\n\n/**\n * An append-only credit on a prepaid (`period: 'balance'`) spending policy.\n * Positive amounts add credit; a negative amount reverses an earlier grant.\n */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: '_smrt_credit_grants',\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n hooks: { beforeDelete: 'refuseDelete' },\n})\nexport class CreditGrant extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-subscriptions\";\n /** The tenant whose balance is credited (the policy's tenant). */\n @tenantId() tenantId?: string;\n @foreignKey('SpendingPolicy')\n spendingPolicyId: string = '';\n /** Signed credit in integer minor units of {@link currency}. */\n amount: number = 0;\n currency: string = 'USD';\n reason: string = '';\n source: string = '';\n sourceId: string = '';\n /** A parent tenant that granted the credit, or empty when self-granted. */\n @crossPackageRef('@happyvertical/smrt-users:Tenant')\n grantedByTenantId: string = '';\n\n /** Append-only: history is corrected by a reversing grant, never removed. */\n protected refuseDelete(): void {\n throw new Error(\n 'Credit grants are append-only; record a reversing grant instead of deleting.',\n );\n }\n\n protected async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n if (!Number.isSafeInteger(this.amount) || this.amount === 0) {\n throw new Error(\n 'Credit grant amounts must be nonzero integer minor units (cents).',\n );\n }\n if (this.id) {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row) {\n throw new Error(\n 'Credit grants are append-only; record a reversing grant instead.',\n );\n }\n }\n const policy = this.spendingPolicyId\n ? ((await this.db.get('_smrt_spending_policies', {\n id: this.spendingPolicyId,\n })) as Record<string, unknown> | null)\n : null;\n if (\n policy?.period !== 'balance' ||\n tenantKey(policy.tenant_id as string) !== tenantKey(this.tenantId) ||\n policy.currency !== this.currency\n ) {\n throw new Error(\n 'Credit grants must credit a balance policy of the same tenant and currency.',\n );\n }\n // A parent's delegated balance is funded only by that parent.\n const setBy = tenantKey(policy.set_by_tenant_id as string);\n if (!setBy) return;\n if (tenantKey(this.grantedByTenantId) !== setBy) {\n throw new TenantIsolationError(\n 'Delegated balance credit must be granted by the parent that set it.',\n );\n }\n if (\n !isSystemContext() &&\n !isSuperAdminBypass() &&\n tenantKey(getTenantId()) !== setBy\n ) {\n throw new TenantIsolationError(\n 'Only the parent that set a delegated policy can grant it credit.',\n );\n }\n }\n}\n\nexport class PriceBookCollection extends SmrtCollection<PriceBook> {\n static readonly _itemClass = PriceBook;\n}\nexport class PriceBookAssignmentCollection extends SmrtCollection<PriceBookAssignment> {\n static readonly _itemClass = PriceBookAssignment;\n}\nexport class RetailChargeCollection extends SmrtCollection<RetailCharge> {\n static readonly _itemClass = RetailCharge;\n}\nexport class CreditGrantCollection extends SmrtCollection<CreditGrant> {\n static readonly _itemClass = CreditGrant;\n}\n\nfunction normalizeLedgerValue(value: unknown): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}[T ]/.test(value)) {\n const timestamp = Date.parse(value);\n if (Number.isFinite(timestamp)) return new Date(timestamp).toISOString();\n }\n if (typeof value === 'boolean') return value ? '1' : '0';\n return String(value ?? '');\n}\n","/**\n * Declared recipes for smrt-subscriptions (#4409): user-facing units of\n * functionality an app or agent can pick instead of the whole package.\n * The scanner reads these statics into the `recipes` array of `manifest.json`\n * and `smrt-knowledge.json`; nothing here runs at that point.\n *\n * @packageDocumentation\n */\n\nimport { SmrtRecipe } from '@happyvertical/smrt-core';\nimport { ClientCharge } from './models/commercial.js';\nimport { SubscriptionPlan } from './models/SubscriptionPlan.js';\nimport { SubscriptionPlanVersion } from './models/SubscriptionPlanVersion.js';\nimport { TenantSubscription } from './models/TenantSubscription.js';\n\n/**\n * Subscriptions: the plans you sell, who is subscribed to which, the terms\n * each paid period is held to, and what usage was charged. Reseller pricing\n * (price books, pricing rules, credits) stays out: it is a wholesale concern,\n * not something a person opens day to day.\n */\nexport class SubscriptionPlansRecipe extends SmrtRecipe {\n static id = 'subscriptions.plans';\n static help = './plans.recipe.md';\n static label = 'Subscriptions';\n static summary =\n 'Sell plans that renew, see who is subscribed to which, and what their usage cost.';\n static synonyms = [\n 'subscriptions',\n 'subscription plans',\n 'plans',\n 'memberships',\n 'recurring billing',\n 'pricing tiers',\n ];\n static section = {\n id: 'sales',\n label: 'Sales',\n icon: 'shoppingBag',\n description: 'Customers, orders and quotes: everything you sell.',\n };\n static models = [\n SubscriptionPlan,\n SubscriptionPlanVersion,\n TenantSubscription,\n ClientCharge,\n ];\n static nav = [\n {\n label: 'Plans',\n model: SubscriptionPlan,\n icon: 'tag',\n description:\n 'The plans you sell, with their price and how often they bill.',\n noun: 'plan',\n },\n {\n label: 'Subscriptions',\n model: TenantSubscription,\n icon: 'repeat',\n description:\n 'Who is subscribed to which plan, and where each one stands.',\n noun: 'subscription',\n },\n {\n label: 'Plan versions',\n model: SubscriptionPlanVersion,\n icon: 'fileText',\n description:\n 'Every set of terms a plan has had, and from when each applied.',\n noun: 'plan version',\n },\n {\n label: 'Charges',\n model: ClientCharge,\n icon: 'receipt',\n description: 'What each subscriber used and what it cost them.',\n noun: 'charge',\n },\n ];\n static options = {\n SubscriptionPlan: {\n fields: {\n name: { order: 1 },\n planKey: { label: 'Plan code', order: 2 },\n description: { order: 3 },\n status: { order: 4 },\n priceAmount: { label: 'Price (in cents)', order: 5 },\n currency: { order: 6 },\n billingInterval: { label: 'Billed every', order: 7 },\n pricingMode: { label: 'How it is priced', order: 8 },\n minimumAmount: {\n label: 'Minimum (in cents)',\n visibility: 'advanced',\n },\n suggestedAmount: {\n label: 'Suggested (in cents)',\n visibility: 'advanced',\n },\n sortOrder: { label: 'Position in list', visibility: 'advanced' },\n tenantId: { visibility: 'hidden' },\n features: { visibility: 'hidden' },\n thresholds: { visibility: 'hidden' },\n externalProvider: { visibility: 'hidden' },\n providerProductId: { visibility: 'hidden' },\n providerPriceId: { visibility: 'hidden' },\n stripeProductId: { visibility: 'hidden' },\n stripePriceId: { visibility: 'hidden' },\n metadata: { visibility: 'hidden' },\n },\n },\n SubscriptionPlanVersion: {\n fields: {\n planId: { label: 'Plan', order: 1 },\n version: { label: 'Version number', order: 2 },\n effectiveFrom: { label: 'In force from', order: 3 },\n name: { order: 4 },\n status: { order: 5 },\n priceAmount: { label: 'Price (in cents)', order: 6 },\n currency: { order: 7 },\n billingInterval: { label: 'Billed every', order: 8 },\n planKey: { label: 'Plan code', visibility: 'advanced' },\n pricingMode: { label: 'How it is priced', visibility: 'advanced' },\n minimumAmount: {\n label: 'Minimum (in cents)',\n visibility: 'advanced',\n },\n suggestedAmount: {\n label: 'Suggested (in cents)',\n visibility: 'advanced',\n },\n tenantId: { visibility: 'hidden' },\n features: { visibility: 'hidden' },\n thresholds: { visibility: 'hidden' },\n },\n },\n TenantSubscription: {\n fields: {\n planId: { label: 'Plan', order: 1 },\n status: { order: 2 },\n startedAt: { label: 'Started on', order: 3 },\n currentPeriodStart: { label: 'Current period starts', order: 4 },\n currentPeriodEnd: { label: 'Current period ends', order: 5 },\n trialEndsAt: { label: 'Trial ends', order: 6 },\n cancelAtPeriodEnd: { label: 'Cancel at end of period', order: 7 },\n canceledAt: { label: 'Cancelled on', visibility: 'advanced' },\n agreedAmount: {\n label: 'Agreed amount (in cents)',\n visibility: 'advanced',\n },\n subscriberKind: { label: 'Subscriber type', visibility: 'advanced' },\n subscriberExternalId: {\n label: 'Outside subscriber',\n visibility: 'advanced',\n },\n planVersionId: {\n label: 'Plan version',\n visibility: 'advanced',\n locked: true,\n },\n tenantId: { visibility: 'hidden' },\n planVersionPinnedAt: { visibility: 'hidden' },\n planVersionPinReason: { visibility: 'hidden' },\n planVersionPinNote: { visibility: 'hidden' },\n retainsPaidPeriod: { visibility: 'hidden' },\n externalProvider: { visibility: 'hidden' },\n stripeCustomerId: { visibility: 'hidden' },\n stripeSubscriptionId: { visibility: 'hidden' },\n stripeCheckoutSessionId: { visibility: 'hidden' },\n metadata: { visibility: 'hidden' },\n },\n },\n ClientCharge: {\n fields: {\n metricKey: { label: 'What was used', order: 1 },\n quantity: { label: 'How much', order: 2 },\n amount: { label: 'Amount (in cents)', order: 3 },\n currency: { order: 4 },\n status: { order: 5 },\n approvedAt: { label: 'Approved on', order: 6 },\n serviceKey: { label: 'Service', visibility: 'advanced' },\n provider: { visibility: 'advanced' },\n tenantId: { visibility: 'hidden' },\n usageEventId: { visibility: 'hidden' },\n usageTenantId: { visibility: 'hidden' },\n subscriberKind: { visibility: 'hidden' },\n subscriberExternalId: { visibility: 'hidden' },\n projectId: { visibility: 'hidden' },\n workRefType: { visibility: 'hidden' },\n workRefId: { visibility: 'hidden' },\n pricingRuleId: { visibility: 'hidden' },\n priceBookId: { visibility: 'hidden' },\n pricingSnapshot: { visibility: 'hidden' },\n },\n },\n } as const;\n}\n","export type ResellerBillingErrorCode =\n | 'INVALID_TENANT'\n | 'INVALID_CURRENCY'\n | 'INVALID_AMOUNT'\n | 'PRICE_BOOK_NOT_FOUND'\n | 'PRICE_BOOK_INACTIVE'\n | 'PRICE_BOOK_KIND_MISMATCH'\n | 'PRICE_BOOK_OWNER_MISMATCH'\n | 'PRICE_BOOK_NOT_ASSIGNED'\n | 'NO_EFFECTIVE_PRICE'\n | 'RELATIONSHIP_REQUIRED'\n | 'POLICY_NOT_FOUND'\n | 'POLICY_NOT_BALANCE'\n | 'POLICY_CONFLICT'\n | 'ASSIGNMENT_CONFLICT';\n\n/** A reseller price book, rating, or delegated-spending rule was violated. */\nexport class ResellerBillingError extends Error {\n constructor(\n message: string,\n public readonly code: ResellerBillingErrorCode,\n ) {\n super(message);\n this.name = 'ResellerBillingError';\n }\n}\n","import {\n type DatabaseConfig,\n isDatabaseInterface,\n isEmbeddedDatabase,\n type SmrtClassOptions,\n withEmbeddedWriteTransaction,\n} from '@happyvertical/smrt-core';\nimport {\n type BillingRelationshipService,\n type BillingRelationshipView,\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport type { SqlAdapterType } from '@happyvertical/sql';\nimport { TenantUsageMetricCollection } from '../collections/TenantUsageMetricCollection.js';\nimport {\n BillingAdjustmentCollection,\n type ClientCharge,\n ClientChargeCollection,\n type PricingRule,\n PricingRuleCollection,\n type PricingStrategy,\n type SpendingBasis,\n type SpendingPolicy,\n SpendingPolicyCollection,\n} from '../models/commercial.js';\nimport {\n type CreditGrant,\n CreditGrantCollection,\n type PriceBook,\n PriceBookAssignmentCollection,\n PriceBookCollection,\n type PriceBookKind,\n type RetailCharge,\n RetailChargeCollection,\n} from '../models/reseller.js';\nimport type { TenantUsageMetric } from '../models/TenantUsageMetric.js';\nimport type { RecordUsageOptions, SubscriberKind } from '../types.js';\nimport {\n deterministicUuid,\n normalizeSubscriber,\n subscriberToColumns,\n tenantKey,\n} from '../utils.js';\nimport { ResellerBillingError } from './reseller-errors.js';\n\nexport interface PriceUsageOptions {\n usageEventId: string;\n approved?: boolean;\n at?: Date;\n}\n\n/** The released smrt-tenancy billing-owner read this package depends on. */\nexport type BillingRelationshipReader = Pick<\n BillingRelationshipService,\n 'getRelationship'\n>;\n\nexport interface RateUsageOptions extends PriceUsageOptions {\n /** Resolves the usage tenant's reseller relationship and billing owner. */\n billingRelationships: BillingRelationshipReader;\n}\n\n/**\n * The outcome of rating one usage event (#3059). A usage event is rated\n * exactly once: the first rating fixes the payer and price books, and later\n * calls return the same records even if the billing owner has since changed.\n */\nexport interface UsageRating {\n /** The tenant that produced the usage. */\n usageTenantId: string;\n /** Who pays the provider: the usage tenant, or its reseller. */\n billingOwnerTenantId: string;\n /** `direct` for self-billed usage, `wholesale` for reseller-billed usage. */\n mode: 'direct' | 'wholesale';\n /** The provider's charge, payable by {@link billingOwnerTenantId}. */\n charge: ClientCharge;\n /** The reseller's retail charge to the child, when a retail book applies. */\n retailCharge: RetailCharge | null;\n}\nexport interface CustomPricingContext {\n usage: { quantity: number; dimensions: Record<string, unknown> };\n rule: PricingRule;\n terms: Record<string, unknown>;\n}\nexport type CustomPricingStrategy = (\n context: CustomPricingContext,\n) => number | Promise<number>;\n\nexport interface CommercialBillingStorage {\n adapterType: SqlAdapterType;\n writeStrategy?: 'immediate' | 'manual' | 'none';\n}\n\nexport interface CommercialUsageServiceOptions extends SmrtClassOptions {\n /**\n * Required when `db` is an already-resolved database handle, whose public\n * interface does not expose its adapter/write-back configuration.\n */\n billingStorage?: CommercialBillingStorage;\n}\n\nconst embeddedAdjustmentLocks = new Map<string | object, Promise<void>>();\n\nasync function withEmbeddedSourcedAdjustmentLock<T>(\n db: { url?: string },\n storage: CommercialBillingStorage,\n sourced: boolean,\n operation: () => Promise<T>,\n): Promise<T> {\n if (!sourced || storage.adapterType === 'postgres') return operation();\n\n const key = db.url ? `${storage.adapterType}:${db.url}` : (db as object);\n const previous = embeddedAdjustmentLocks.get(key) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const queued = previous.then(() => current);\n embeddedAdjustmentLocks.set(key, queued);\n await previous;\n try {\n return await operation();\n } finally {\n release();\n if (embeddedAdjustmentLocks.get(key) === queued) {\n embeddedAdjustmentLocks.delete(key);\n }\n }\n}\n\nexport class UnsupportedCommercialBillingStorageError extends Error {\n readonly code = 'UNSUPPORTED_COMMERCIAL_BILLING_STORAGE';\n\n constructor(storage: CommercialBillingStorage) {\n super(\n `Commercial billing does not support ${storage.adapterType} ` +\n `with immediate JSON write-back because exported files are not ` +\n `transactionally rolled back. Use PostgreSQL, SQLite, ordinary ` +\n `DuckDB, or a non-immediate write strategy.`,\n );\n this.name = 'UnsupportedCommercialBillingStorageError';\n }\n}\n\nexport class CommercialBillingStorageConfigurationError extends Error {\n readonly code = 'COMMERCIAL_BILLING_STORAGE_CONFIGURATION_REQUIRED';\n\n constructor(message?: string) {\n super(\n message ??\n 'Commercial billing requires billingStorage when db is an already-resolved handle because adapter write-back capabilities are not public on that interface.',\n );\n this.name = 'CommercialBillingStorageConfigurationError';\n }\n}\n\nfunction assertValidCommercialBillingWriteStrategy(\n writeStrategy: unknown,\n): asserts writeStrategy is CommercialBillingStorage['writeStrategy'] {\n if (\n writeStrategy !== undefined &&\n writeStrategy !== 'immediate' &&\n writeStrategy !== 'manual' &&\n writeStrategy !== 'none'\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing database writeStrategy must be immediate, manual, or none.',\n );\n }\n}\n\nfunction snapshotCommercialBillingStorage(\n storage: CommercialBillingStorage,\n): CommercialBillingStorage {\n const adapterType: unknown = storage.adapterType;\n if (\n adapterType !== 'sqlite' &&\n adapterType !== 'postgres' &&\n adapterType !== 'duckdb' &&\n adapterType !== 'json'\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing storage adapterType must be sqlite, postgres, duckdb, or json.',\n );\n }\n const writeStrategy: unknown = storage.writeStrategy;\n assertValidCommercialBillingWriteStrategy(writeStrategy);\n return { adapterType, writeStrategy };\n}\n\nfunction snapshotCommercialUsageServiceOptions(\n options: CommercialUsageServiceOptions,\n): CommercialUsageServiceOptions {\n const snapshot = { ...options };\n if (snapshot.billingStorage) {\n snapshot.billingStorage = snapshotCommercialBillingStorage(\n snapshot.billingStorage,\n );\n }\n for (const key of ['db', 'persistence'] as const) {\n const database = snapshot[key];\n if (\n database &&\n typeof database !== 'string' &&\n !isDatabaseInterface(database)\n ) {\n snapshot[key] = { ...database };\n }\n }\n return snapshot;\n}\n\nexport function assertCommercialBillingStorageSupported(\n storage: CommercialBillingStorage,\n): void {\n const snapshot = snapshotCommercialBillingStorage(storage);\n const writeStrategy =\n snapshot.adapterType === 'json'\n ? (snapshot.writeStrategy ?? 'immediate')\n : snapshot.writeStrategy;\n if (\n (snapshot.adapterType === 'json' || snapshot.adapterType === 'duckdb') &&\n writeStrategy === 'immediate'\n ) {\n throw new UnsupportedCommercialBillingStorageError({\n ...snapshot,\n writeStrategy,\n });\n }\n}\n\nfunction inferAdapterType(url: string): SqlAdapterType | undefined {\n if (/^postgres(?:ql)?:/iu.test(url)) return 'postgres';\n if (/^(?:https?|libsql):\\/\\//iu.test(url)) return 'sqlite';\n if (/\\.duckdb(?:$|\\?)/iu.test(url)) return 'duckdb';\n if (url === ':memory:' || url.startsWith('file:')) return 'sqlite';\n return undefined;\n}\n\nfunction environmentAdapterType(): SqlAdapterType | undefined {\n const type = process.env.HAVE_SQL_TYPE;\n if (type === undefined || type === '') return undefined;\n if (\n type === 'sqlite' ||\n type === 'postgres' ||\n type === 'duckdb' ||\n type === 'json'\n ) {\n return type;\n }\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing HAVE_SQL_TYPE must be sqlite, postgres, duckdb, or json.',\n );\n}\n\nfunction environmentWriteStrategy(): CommercialBillingStorage['writeStrategy'] {\n const strategy = process.env.HAVE_SQL_WRITE_STRATEGY;\n if (strategy === undefined || strategy === '') return undefined;\n if (\n strategy === 'immediate' ||\n strategy === 'manual' ||\n strategy === 'none'\n ) {\n return strategy;\n }\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billing HAVE_SQL_WRITE_STRATEGY must be immediate, manual, or none.',\n );\n}\n\nfunction billingStorageFromConfig(\n config: DatabaseConfig | undefined,\n declared?: CommercialBillingStorage,\n): CommercialBillingStorage {\n // Validate a configured environment value even when an explicit config type\n // wins adapter precedence. Otherwise normalization below could hide an SDK\n // configuration error by replacing the invalid environment value.\n const environmentType = environmentAdapterType();\n if (config === undefined) {\n if (environmentType)\n return {\n adapterType: environmentType,\n writeStrategy: environmentWriteStrategy(),\n };\n return { adapterType: 'sqlite' };\n }\n if (isDatabaseInterface(config)) {\n throw new CommercialBillingStorageConfigurationError();\n }\n if (typeof config === 'string') {\n const adapterType =\n environmentType ?? inferAdapterType(config) ?? declared?.adapterType;\n if (adapterType)\n return {\n adapterType,\n writeStrategy: environmentWriteStrategy() ?? declared?.writeStrategy,\n };\n throw new Error(\n 'Commercial billing requires an explicit billingStorage adapter contract for ambiguous database URLs.',\n );\n }\n const adapterType =\n config.type ??\n environmentType ??\n inferAdapterType(String(config.url ?? '')) ??\n declared?.adapterType;\n if (!adapterType) {\n throw new Error(\n 'Commercial billing requires an explicit database type or billingStorage adapter contract.',\n );\n }\n const configuredWriteStrategy = config.writeStrategy;\n assertValidCommercialBillingWriteStrategy(configuredWriteStrategy);\n const writeStrategy =\n configuredWriteStrategy === 'immediate' ||\n configuredWriteStrategy === 'manual' ||\n configuredWriteStrategy === 'none'\n ? configuredWriteStrategy\n : (environmentWriteStrategy() ?? declared?.writeStrategy);\n return { adapterType, writeStrategy };\n}\n\nfunction effectiveWriteStrategy(\n storage: CommercialBillingStorage,\n): CommercialBillingStorage['writeStrategy'] {\n if (storage.writeStrategy) return storage.writeStrategy;\n if (storage.adapterType === 'json') return 'immediate';\n if (storage.adapterType === 'duckdb') return 'none';\n return undefined;\n}\n\nfunction resolveCommercialBillingStorage(\n options: CommercialUsageServiceOptions,\n): CommercialBillingStorage {\n // Environment declarations are configuration contracts, even when explicit\n // options win precedence. Reject invalid nonempty values before setup.\n environmentAdapterType();\n environmentWriteStrategy();\n const configuredDatabase = options.db ?? options.persistence;\n if (isDatabaseInterface(configuredDatabase)) {\n if (!options.billingStorage) {\n throw new CommercialBillingStorageConfigurationError();\n }\n return options.billingStorage;\n }\n const configured = billingStorageFromConfig(\n configuredDatabase,\n options.billingStorage,\n );\n if (\n options.billingStorage &&\n (options.billingStorage.adapterType !== configured.adapterType ||\n effectiveWriteStrategy(options.billingStorage) !==\n effectiveWriteStrategy(configured))\n ) {\n throw new CommercialBillingStorageConfigurationError(\n 'Commercial billingStorage must match the configured database adapter and write strategy.',\n );\n }\n return configured;\n}\n\nfunction normalizedCommercialClassOptions(\n options: CommercialUsageServiceOptions,\n billingStorage: CommercialBillingStorage,\n): SmrtClassOptions {\n const { billingStorage: _billingStorage, ...classOptions } = options;\n const configuredDatabase = options.db ?? options.persistence;\n if (configuredDatabase && !isDatabaseInterface(configuredDatabase)) {\n const normalizedDatabase =\n typeof configuredDatabase === 'string'\n ? {\n type: billingStorage.adapterType,\n url: configuredDatabase,\n writeStrategy: billingStorage.writeStrategy,\n }\n : {\n ...configuredDatabase,\n type: billingStorage.adapterType,\n writeStrategy: billingStorage.writeStrategy,\n };\n if (options.db !== undefined) classOptions.db = normalizedDatabase;\n else classOptions.persistence = normalizedDatabase;\n }\n return classOptions;\n}\n\ninterface ResellerCollections {\n books: PriceBookCollection;\n assignments: PriceBookAssignmentCollection;\n retailCharges: RetailChargeCollection;\n}\n\nexport class CommercialUsageService {\n private readonly customStrategies = new Map<string, CustomPricingStrategy>();\n private resellerCollections?: Promise<ResellerCollections>;\n constructor(\n private readonly usage: TenantUsageMetricCollection,\n private readonly rules: PricingRuleCollection,\n private readonly charges: ClientChargeCollection,\n private readonly adjustments: BillingAdjustmentCollection,\n private readonly billingStorage: CommercialBillingStorage,\n ) {\n if (!billingStorage) {\n throw new CommercialBillingStorageConfigurationError();\n }\n assertCommercialBillingStorageSupported(billingStorage);\n }\n\n static async create(\n options: CommercialUsageServiceOptions = {},\n ): Promise<CommercialUsageService> {\n const optionSnapshot = snapshotCommercialUsageServiceOptions(options);\n const billingStorage = resolveCommercialBillingStorage(optionSnapshot);\n assertCommercialBillingStorageSupported(billingStorage);\n const classOptions = normalizedCommercialClassOptions(\n optionSnapshot,\n billingStorage,\n );\n const usage = await TenantUsageMetricCollection.create(classOptions);\n const sharedOptions = { ...classOptions, db: usage.db };\n return new CommercialUsageService(\n usage,\n await PricingRuleCollection.create(sharedOptions),\n await ClientChargeCollection.create(sharedOptions),\n await BillingAdjustmentCollection.create(sharedOptions),\n billingStorage,\n );\n }\n\n registerCustomStrategy(key: string, strategy: CustomPricingStrategy): void {\n this.customStrategies.set(key, strategy);\n }\n\n async record(options: RecordUsageOptions) {\n return this.usage.recordUsage(options);\n }\n\n async price(options: PriceUsageOptions): Promise<ClientCharge> {\n const existing = await this.charges.list({\n where: { usageEventId: options.usageEventId },\n limit: 1,\n });\n if (existing[0]) {\n return this.approveCharge(existing[0], options.approved);\n }\n const usage = await this.usage.get(options.usageEventId);\n if (!usage)\n throw new Error(`Usage event ${options.usageEventId} was not found.`);\n const at = options.at ?? usage.windowStart;\n const dimensions = usage.getDimensions();\n const rules = await this.rules.list({\n where: {\n tenantId: usage.tenantId,\n metricKey: usage.metricKey,\n active: true,\n },\n });\n // Price-book rules are published by a seller for rateUsage(); they are\n // never a tenant's own direct pricing.\n const rule = selectRule(\n rules.filter((candidate) => !candidate.priceBookId),\n at,\n String(dimensions.serviceKey ?? ''),\n );\n if (!rule)\n throw new Error(\n `No effective pricing rule for metric '${usage.metricKey}'.`,\n );\n if (!usage.id)\n throw new Error(\n `Usage event ${options.usageEventId} has no persisted id.`,\n );\n if (!rule.id)\n throw new Error(`Pricing rule '${rule.ruleKey}' has no persisted id.`);\n const amount = await this.calculateAmount(rule, usage.quantity, dimensions);\n const chargeId = await deterministicUuid([\n 'client-charge',\n String(usage.tenantId),\n String(usage.id),\n ]);\n try {\n return await this.charges.create({\n id: chargeId,\n tenantId: usage.tenantId,\n usageEventId: String(usage.id),\n usageTenantId: usage.tenantId,\n subscriberKind: usage.subscriberKind,\n subscriberExternalId: usage.subscriberExternalId,\n projectId: usage.projectId,\n workRefType: usage.workRefType,\n workRefId: usage.workRefId,\n provider: usage.provider,\n serviceKey: String(dimensions.serviceKey ?? ''),\n metricKey: usage.metricKey,\n quantity: usage.quantity,\n amount,\n currency: rule.currency,\n pricingRuleId: String(rule.id),\n pricingSnapshot: JSON.stringify({\n ruleKey: rule.ruleKey,\n strategy: rule.strategy,\n terms: rule.getTerms(),\n effectiveFrom: rule.effectiveFrom,\n }),\n status: options.approved ? 'approved' : 'draft',\n approvedAt: options.approved ? new Date() : null,\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent = await this.charges.get(chargeId);\n if (!concurrent) throw error;\n return this.approveCharge(concurrent, options.approved);\n }\n }\n\n /**\n * Rate one usage event under its billing owner's price books (#3059).\n *\n * - No reseller relationship, or a `self`-billed one: the usage tenant pays\n * the provider directly, priced exactly as {@link price} prices it.\n * - `reseller`-billed: the reseller pays the provider from the child's\n * assigned wholesale book (a {@link ClientCharge} with `tenantId` = the\n * reseller and `usageTenantId` = the child) and, when the child has a\n * retail book assigned, the child owes the reseller a\n * {@link RetailCharge}. Both records commit in one transaction.\n *\n * Rating is idempotent per usage event and frozen at first rating: a later\n * billing-owner change never re-prices or double-charges an event that\n * already has a provider charge, because `ClientCharge` holds exactly one\n * row per usage event.\n *\n * Rating reads the seller's books across tenants; run it where the host's\n * tenancy rules allow that (typically a system context).\n */\n async rateUsage(options: RateUsageOptions): Promise<UsageRating> {\n const { retailCharges } = await this.getResellerCollections();\n const existing = await this.charges.list({\n where: { usageEventId: options.usageEventId },\n limit: 1,\n });\n if (existing[0]) {\n return this.frozenRating(existing[0], retailCharges, options.approved);\n }\n const usage = await this.usage.get(options.usageEventId);\n if (!usage)\n throw new Error(`Usage event ${options.usageEventId} was not found.`);\n if (!usage.id || !usage.tenantId)\n throw new Error(\n `Usage event ${options.usageEventId} has no persisted tenant id.`,\n );\n const relationship = await options.billingRelationships.getRelationship(\n usage.tenantId,\n );\n if (relationship?.billingOwnerMode !== 'reseller') {\n const charge = await this.price(options);\n return this.frozenRating(charge, retailCharges, options.approved);\n }\n let failure: unknown;\n try {\n await this.rateResellerBilled(usage, relationship, options);\n } catch (error) {\n failure = error;\n }\n // Return root-bound records (never the committed transaction's handles).\n // After a failure, a concurrent rating of the same event may have won the\n // one-row-per-event insert; its transaction wrote the complete rating.\n const rated = await this.charges.list({\n where: { usageEventId: String(usage.id) },\n limit: 1,\n });\n if (!rated[0]) throw failure ?? new Error('Rating was not persisted.');\n return this.frozenRating(rated[0], retailCharges, options.approved);\n }\n\n private async rateResellerBilled(\n usage: TenantUsageMetric,\n relationship: BillingRelationshipView,\n options: RateUsageOptions,\n ): Promise<UsageRating> {\n const { books, assignments } = await this.getResellerCollections();\n const childTenantId = relationship.childTenantId;\n const resellerTenantId = relationship.resellerTenantId;\n const assignment = await assignments.get({ childTenantId });\n if (\n !assignment?.wholesalePriceBookId ||\n tenantKey(assignment.resellerTenantId) !== resellerTenantId\n ) {\n throw new ResellerBillingError(\n `No wholesale price book is assigned to tenant ${childTenantId} under reseller ${resellerTenantId}.`,\n 'PRICE_BOOK_NOT_ASSIGNED',\n );\n }\n const at = options.at ?? usage.windowStart;\n const dimensions = usage.getDimensions();\n const serviceKey = String(dimensions.serviceKey ?? '');\n const wholesaleBook = await loadBook(\n books,\n assignment.wholesalePriceBookId,\n 'wholesale',\n );\n assertWholesalePublisher(wholesaleBook, resellerTenantId, childTenantId);\n const wholesaleRule = await this.selectBookRule(\n wholesaleBook,\n usage.metricKey,\n serviceKey,\n assignment.wholesaleCurrency,\n at,\n );\n let retail: { book: PriceBook; rule: PricingRule } | null = null;\n if (assignment.retailPriceBookId) {\n const retailBook = await loadBook(\n books,\n assignment.retailPriceBookId,\n 'retail',\n );\n if (tenantKey(retailBook.tenantId) !== resellerTenantId) {\n throw new ResellerBillingError(\n `Retail price book '${retailBook.bookKey}' is not published by reseller ${resellerTenantId}.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n retail = {\n book: retailBook,\n rule: await this.selectBookRule(\n retailBook,\n usage.metricKey,\n serviceKey,\n assignment.retailCurrency,\n at,\n ),\n };\n }\n const wholesaleAmount = await this.calculateAmount(\n wholesaleRule,\n usage.quantity,\n dimensions,\n );\n const retailAmount = retail\n ? await this.calculateAmount(retail.rule, usage.quantity, dimensions)\n : 0;\n const usageEventId = String(usage.id);\n const chargeId = await deterministicUuid([\n 'client-charge',\n String(usage.tenantId),\n usageEventId,\n ]);\n const retailChargeId = await deterministicUuid([\n 'retail-charge',\n String(usage.tenantId),\n usageEventId,\n ]);\n const approvedAt = options.approved ? new Date() : null;\n const status = options.approved ? 'approved' : 'draft';\n const usageColumns = {\n usageEventId,\n subscriberKind: usage.subscriberKind,\n subscriberExternalId: usage.subscriberExternalId,\n projectId: usage.projectId,\n workRefType: usage.workRefType,\n workRefId: usage.workRefId,\n provider: usage.provider,\n serviceKey,\n metricKey: usage.metricKey,\n quantity: usage.quantity,\n };\n const snapshot = (book: PriceBook, rule: PricingRule) =>\n JSON.stringify({\n ruleKey: rule.ruleKey,\n strategy: rule.strategy,\n terms: rule.getTerms(),\n effectiveFrom: rule.effectiveFrom,\n priceBookKey: book.bookKey,\n priceBookKind: book.kind,\n usageTenantId: childTenantId,\n billingOwnerTenantId: resellerTenantId,\n });\n const db = this.charges.db;\n return withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const charges = await ClientChargeCollection.create({\n db: transaction,\n });\n const retailCharges = await RetailChargeCollection.create({\n db: transaction,\n });\n const charge = await charges.create({\n id: chargeId,\n tenantId: resellerTenantId,\n usageTenantId: childTenantId,\n ...usageColumns,\n amount: wholesaleAmount,\n currency: wholesaleRule.currency,\n pricingRuleId: String(wholesaleRule.id),\n priceBookId: String(wholesaleBook.id),\n pricingSnapshot: snapshot(wholesaleBook, wholesaleRule),\n status,\n approvedAt,\n _insertOnly: true,\n });\n const retailCharge = retail\n ? await retailCharges.create({\n id: retailChargeId,\n tenantId: childTenantId,\n resellerTenantId,\n clientChargeId: chargeId,\n ...usageColumns,\n amount: retailAmount,\n currency: retail.rule.currency,\n priceBookId: String(retail.book.id),\n pricingRuleId: String(retail.rule.id),\n pricingSnapshot: snapshot(retail.book, retail.rule),\n status,\n approvedAt,\n _insertOnly: true,\n })\n : null;\n return {\n usageTenantId: childTenantId,\n billingOwnerTenantId: resellerTenantId,\n mode: 'wholesale' as const,\n charge,\n retailCharge,\n };\n },\n );\n }\n\n private async selectBookRule(\n book: PriceBook,\n metricKey: string,\n serviceKey: string,\n currency: string,\n at: Date,\n ): Promise<PricingRule> {\n const rules = await this.rules.list({\n where: {\n tenantId: book.tenantId,\n priceBookId: book.id,\n metricKey,\n currency,\n active: true,\n },\n });\n const rule = selectRule(\n // The owner check keeps a rule filed under someone else's book (the\n // rules API is tenant-writable) from pricing that book.\n rules.filter(\n (candidate) =>\n candidate.priceBookId === book.id &&\n candidate.tenantId === book.tenantId &&\n candidate.currency === currency,\n ),\n at,\n serviceKey,\n );\n if (!rule?.id) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' has no effective ${currency} price for metric '${metricKey}'.`,\n 'NO_EFFECTIVE_PRICE',\n );\n }\n return rule;\n }\n\n private async frozenRating(\n charge: ClientCharge,\n retailCharges: RetailChargeCollection,\n approved = false,\n ): Promise<UsageRating> {\n const retail = await retailCharges.list({\n where: { usageEventId: charge.usageEventId },\n limit: 1,\n });\n let providerCharge = charge;\n let retailCharge: RetailCharge | null = retail[0] ?? null;\n if (\n approved &&\n (providerCharge.status === 'draft' || retailCharge?.status === 'draft')\n ) {\n // Approve both legs in one transaction so they never disagree.\n const db = this.charges.db;\n [providerCharge, retailCharge] = await withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const charges = await ClientChargeCollection.create({\n db: transaction,\n });\n const retails = await RetailChargeCollection.create({\n db: transaction,\n });\n const provider = await charges.get(String(charge.id));\n if (!provider) {\n throw new Error(`Client charge ${charge.id} was not found.`);\n }\n const leg = retailCharge\n ? await retails.get(String(retailCharge.id))\n : null;\n const approvedAt = new Date();\n if (provider.status === 'draft') {\n provider.status = 'approved';\n provider.approvedAt = approvedAt;\n await provider.save();\n }\n if (leg?.status === 'draft') {\n leg.status = 'approved';\n leg.approvedAt = approvedAt;\n await leg.save();\n }\n return [provider, leg ?? null] as const;\n },\n );\n // Hand back root-bound records, not the committed transaction's.\n providerCharge = (await this.charges.get(String(charge.id))) ?? charge;\n retailCharge = retailCharge?.id\n ? ((await retailCharges.get(String(retailCharge.id))) ?? null)\n : null;\n }\n return {\n usageTenantId:\n tenantKey(providerCharge.usageTenantId) ||\n tenantKey(providerCharge.tenantId),\n billingOwnerTenantId: tenantKey(providerCharge.tenantId),\n mode: providerCharge.priceBookId ? 'wholesale' : 'direct',\n charge: providerCharge,\n retailCharge,\n };\n }\n\n private getResellerCollections(): Promise<ResellerCollections> {\n this.resellerCollections ??= (async () => {\n const options = { db: this.charges.db };\n return {\n books: await PriceBookCollection.create(options),\n assignments: await PriceBookAssignmentCollection.create(options),\n retailCharges: await RetailChargeCollection.create(options),\n };\n })();\n this.resellerCollections.catch(() => {\n this.resellerCollections = undefined;\n });\n return this.resellerCollections;\n }\n\n private async approveCharge(\n charge: ClientCharge,\n approved = false,\n ): Promise<ClientCharge> {\n if (approved && charge.status === 'draft') {\n charge.status = 'approved';\n charge.approvedAt = new Date();\n await charge.save();\n }\n return charge;\n }\n\n /**\n * Append a signed correction to an approved charge.\n *\n * @param amount - Signed correction in **integer minor units**, same unit as\n * the charge (#2401). Negative is legitimate — that is a credit. A\n * fractional value is rejected rather than silently rounded, because it\n * almost always means the caller passed major units.\n */\n async adjust(\n chargeId: string,\n amount: number,\n reason: string,\n source = '',\n sourceId = '',\n ) {\n if (!Number.isInteger(amount)) {\n throw new Error(\n `Billing adjustment amount must be an integer number of minor units ` +\n `(cents) — got ${amount}. Money is exact: -$0.25 is -25, not -0.25.`,\n );\n }\n const sourced = Boolean(source && sourceId);\n return withEmbeddedSourcedAdjustmentLock(\n this.charges.db,\n this.billingStorage,\n sourced,\n () => this.adjustWithinLock(chargeId, amount, reason, source, sourceId),\n );\n }\n\n private async adjustWithinLock(\n chargeId: string,\n amount: number,\n reason: string,\n source: string,\n sourceId: string,\n ) {\n const initialCharge = await this.charges.get(chargeId);\n if (!initialCharge)\n throw new Error(`Client charge ${chargeId} was not found.`);\n if (\n initialCharge.status !== 'approved' &&\n initialCharge.status !== 'adjusted'\n ) {\n throw new Error(\n `Client charge ${chargeId} must be approved before it can be adjusted.`,\n );\n }\n const sourcedId =\n source && sourceId\n ? await deterministicUuid([\n 'billing-adjustment',\n String(initialCharge.tenantId),\n chargeId,\n source,\n sourceId,\n ])\n : null;\n const db = this.charges.db;\n if (!db.transaction) {\n throw new Error('Atomic billing adjustment requires transaction support');\n }\n try {\n return await withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n const options = { db: transaction };\n const charges = await ClientChargeCollection.create(options);\n const adjustments = await BillingAdjustmentCollection.create(options);\n const charge = await charges.get(chargeId);\n if (!charge)\n throw new Error(`Client charge ${chargeId} was not found.`);\n if (charge.status !== 'approved' && charge.status !== 'adjusted') {\n throw new Error(\n `Client charge ${chargeId} must be approved before it can be adjusted.`,\n );\n }\n let adjustment = sourcedId\n ? await adjustments.get(sourcedId)\n : undefined;\n if (!adjustment) {\n adjustment = await adjustments.create({\n ...(sourcedId ? { id: sourcedId } : {}),\n tenantId: charge.tenantId,\n clientChargeId: chargeId,\n amount,\n currency: charge.currency,\n reason,\n source,\n sourceId,\n _insertOnly: Boolean(sourcedId),\n });\n }\n if (charge.status === 'approved') {\n charge.status = 'adjusted';\n await charge.save();\n }\n return adjustment;\n },\n );\n } catch (error) {\n // A concurrent sourced adjustment may win the deterministic insert. Its\n // transaction also owns the charge-state transition, so it is safe to\n // return only after both durable records are visible.\n if (sourcedId) {\n // Embedded adapters multiplex one native handle. Keep recovery reads\n // sequential just like the transaction flow protected above.\n const adjustment = await this.adjustments.get(sourcedId);\n const charge = await this.charges.get(chargeId);\n if (adjustment && charge?.status === 'adjusted') return adjustment;\n }\n throw error;\n }\n }\n\n /**\n * Price one usage event, in **integer minor units** (#2401).\n *\n * The pricing terms stay fractional on purpose — a per-token rate is\n * routinely a fraction of a cent, and an integer `unitPrice` would truncate\n * it to zero — so terms are read as *minor units per unit of usage* and only\n * the result is rounded. This is the single boundary in the package where a\n * rate meets money, which is what lets `evaluateSpending()` compare sums\n * against `SpendingPolicy.limitAmount` exactly.\n *\n * Replaces the old micro-unit rounding (`Math.round(amount * 1e6) / 1e6`),\n * which kept six sub-cent digits in a column that is now integral.\n */\n async calculateAmount(\n rule: PricingRule,\n quantity: number,\n dimensions: Record<string, unknown> = {},\n ): Promise<number> {\n const terms = rule.getTerms();\n const number = (key: string, fallback = 0) =>\n Number(terms[key] ?? fallback);\n let amount: number;\n switch (rule.strategy as PricingStrategy) {\n case 'fixed_unit':\n amount = quantity * number('unitPrice');\n break;\n case 'cost_plus':\n amount =\n Number(dimensions.providerCost ?? 0) +\n number('fixedMarkup') +\n Number(dimensions.providerCost ?? 0) * number('markupRatio');\n break;\n case 'multiplier':\n amount =\n Number(dimensions.providerCost ?? quantity) * number('multiplier', 1);\n break;\n case 'flat':\n amount = number('amount');\n break;\n case 'included_overage':\n amount =\n Math.max(0, quantity - number('includedQuantity')) *\n number('overageUnitPrice');\n break;\n case 'tiered':\n amount = priceTiers(\n quantity,\n Array.isArray(terms.tiers) ? terms.tiers : [],\n );\n break;\n case 'custom': {\n const custom = this.customStrategies.get(\n String(terms.strategyKey ?? ''),\n );\n if (!custom)\n throw new Error(\n `Custom pricing strategy '${String(terms.strategyKey ?? '')}' is not registered.`,\n );\n amount = await custom({ usage: { quantity, dimensions }, rule, terms });\n break;\n }\n }\n if (!Number.isFinite(amount) || amount < 0)\n throw new Error('Pricing produced an invalid amount.');\n return Math.round(amount);\n }\n}\n\nexport interface SpendingDecision {\n allowed: boolean;\n approvalRequired: boolean;\n state: 'ok' | 'observed' | 'warned' | 'blocked' | 'approval_required';\n /**\n * Already-spent plus estimated, in **integer minor units** — the same unit as\n * `SpendingPolicy.limitAmount` it is compared against (#2401).\n */\n projectedAmount: number;\n matchedPolicyId: string | null;\n /**\n * For a prepaid `balance` policy: credit remaining before this estimate\n * (grants minus spend), in integer minor units. Absent for other periods.\n */\n balanceAmount?: number;\n}\n\nexport interface SpendingEvaluationInput {\n tenantId: string;\n subscriberKind?: SubscriberKind;\n subscriberExternalId?: string;\n projectId?: string;\n serviceKey?: string;\n metricKey: string;\n /** Estimated cost of the pending call, in integer minor units (#2401). */\n estimatedAmount: number;\n /**\n * Per-basis estimates, in integer minor units, for policies whose basis\n * prices the call differently (a retail estimate for `retail` policies, a\n * wholesale estimate for `wholesale` ones). Falls back to\n * {@link estimatedAmount}.\n */\n estimatedAmounts?: Partial<Record<SpendingBasis, number>>;\n currency: string;\n at?: Date;\n}\n\n/** Context handed to an {@link AutoTopUpHook} when a balance would run out. */\nexport interface AutoTopUpRequest {\n policyId: string;\n tenantId: string;\n /** The parent that set the policy, or empty for the tenant's own policy. */\n setByTenantId: string;\n currency: string;\n /** Credit remaining before the estimate, in integer minor units. */\n balanceAmount: number;\n estimatedAmount: number;\n /** How far the estimate overshoots the balance, in integer minor units. */\n shortfall: number;\n /**\n * Recompute the shortfall against the credit and spend recorded now. A\n * hook that secures funds asynchronously calls it before charging: a\n * concurrent evaluation may have topped the balance up since this one read\n * it, and the evaluator re-reads the credit after the hook returns.\n */\n currentShortfall?: () => Promise<number>;\n}\n\n/**\n * A top-up the hook has secured. `sourceId` makes it idempotent: the same\n * `source`/`sourceId` pair is credited once however often it is returned.\n */\nexport interface AutoTopUpGrant {\n amount: number;\n sourceId: string;\n source?: string;\n reason?: string;\n}\n\n/**\n * Host hook for prepaid balances. Called when a pending charge would exhaust a\n * `balance` policy; return a grant to credit it (after the host has secured\n * the funds) or nothing to let the policy's behavior apply. The evaluator\n * never calls a payment provider itself, and re-reads the balance after the\n * hook returns either way, so credit granted meanwhile by another path counts.\n */\nexport type AutoTopUpHook = (\n request: AutoTopUpRequest,\n) =>\n | AutoTopUpGrant\n | null\n | undefined\n | Promise<AutoTopUpGrant | null | undefined>;\n\nexport interface SpendingPolicyEvaluatorOptions extends SmrtClassOptions {\n autoTopUp?: AutoTopUpHook;\n /**\n * The smrt-tenancy relationship reader. When supplied, a delegated policy\n * applies only while its `setByTenantId` is the tenant's current reseller;\n * without it every delegated policy applies (fail closed).\n */\n billingRelationships?: BillingRelationshipReader;\n}\n\nexport interface GrantCreditInput {\n spendingPolicyId: string;\n /** Signed, nonzero credit in integer minor units of the policy currency. */\n amount: number;\n reason?: string;\n /** With `sourceId`, makes the grant idempotent (a payment or order id). */\n source?: string;\n sourceId?: string;\n /** The parent granting credit on its child's delegated policy. */\n grantedByTenantId?: string;\n}\n\nexport interface SpendingPolicyEvaluatorExtensions {\n retailCharges?: RetailChargeCollection;\n credits?: CreditGrantCollection;\n autoTopUp?: AutoTopUpHook;\n billingRelationships?: BillingRelationshipReader;\n}\n\ninterface LedgerRow {\n id?: string | null;\n amount: number;\n status: string;\n projectId: string;\n serviceKey: string;\n metricKey: string;\n subscriberKind: string;\n subscriberExternalId: string;\n}\n\nexport class SpendingPolicyEvaluator {\n private ledgers?: Promise<{\n retailCharges: RetailChargeCollection;\n credits: CreditGrantCollection;\n }>;\n constructor(\n private readonly policies: SpendingPolicyCollection,\n private readonly charges: ClientChargeCollection,\n private readonly adjustments: BillingAdjustmentCollection,\n private readonly extensions: SpendingPolicyEvaluatorExtensions = {},\n ) {}\n static async create(options: SpendingPolicyEvaluatorOptions = {}) {\n const { autoTopUp, billingRelationships, ...classOptions } = options;\n const policies = await SpendingPolicyCollection.create(classOptions);\n const sharedOptions = { ...classOptions, db: policies.db };\n return new SpendingPolicyEvaluator(\n policies,\n await ClientChargeCollection.create(sharedOptions),\n await BillingAdjustmentCollection.create(sharedOptions),\n {\n retailCharges: await RetailChargeCollection.create(sharedOptions),\n credits: await CreditGrantCollection.create(sharedOptions),\n autoTopUp,\n billingRelationships,\n },\n );\n }\n\n async evaluate(input: SpendingEvaluationInput): Promise<SpendingDecision> {\n const at = input.at ?? new Date();\n const normalizedInput = {\n ...input,\n ...subscriberToColumns(\n normalizeSubscriber({\n tenantId: input.tenantId,\n subscriberKind: input.subscriberKind,\n subscriberExternalId: input.subscriberExternalId,\n }),\n ),\n };\n const candidates = await this.policies.list({\n where: {\n tenantId: input.tenantId,\n currency: input.currency,\n active: true,\n },\n });\n const matchingPolicies = await this.withoutStaleDelegations(\n input.tenantId,\n selectPolicies(candidates, normalizedInput),\n );\n if (matchingPolicies.length === 0)\n return {\n allowed: true,\n approvalRequired: false,\n state: 'ok',\n projectedAmount: input.estimatedAmount,\n matchedPolicyId: null,\n };\n const decisions = await Promise.all(\n matchingPolicies.map((policy) =>\n this.evaluatePolicy(policy, normalizedInput, at),\n ),\n );\n return decisions.reduce((mostRestrictive, decision) =>\n decisionRank(decision) > decisionRank(mostRestrictive)\n ? decision\n : mostRestrictive,\n );\n }\n\n /**\n * Drop delegated policies whose parent is no longer the tenant's reseller,\n * when a relationship reader is configured.\n */\n private async withoutStaleDelegations(\n tenantId: string,\n policies: SpendingPolicy[],\n ): Promise<SpendingPolicy[]> {\n const reader = this.extensions.billingRelationships;\n if (!reader || !policies.some((policy) => tenantKey(policy.setByTenantId)))\n return policies;\n const relationship = await reader.getRelationship(tenantId);\n const currentParent = tenantKey(relationship?.resellerTenantId);\n return policies.filter((policy) => {\n const setBy = tenantKey(policy.setByTenantId);\n return !setBy || setBy === currentParent;\n });\n }\n\n /**\n * Credit a prepaid `balance` policy. A delegated policy accepts grants only\n * from the parent that set it (or a system context / super-admin bypass).\n */\n async grantCredit(input: GrantCreditInput): Promise<CreditGrant> {\n const policy = await this.policies.get(input.spendingPolicyId);\n if (!policy?.id) {\n throw new ResellerBillingError(\n `Spending policy ${input.spendingPolicyId} was not found.`,\n 'POLICY_NOT_FOUND',\n );\n }\n const setBy = tenantKey(policy.setByTenantId);\n if (\n setBy &&\n !isSystemContext() &&\n !isSuperAdminBypass() &&\n getTenantId()?.toLowerCase() !== setBy\n ) {\n throw new TenantIsolationError(\n 'Only the parent that set a delegated policy can grant it credit.',\n );\n }\n if (\n input.grantedByTenantId &&\n setBy &&\n tenantKey(input.grantedByTenantId) !== setBy\n ) {\n throw new TenantIsolationError(\n 'Delegated policy credit must be granted by the parent that set it.',\n );\n }\n return this.recordGrant(policy, {\n ...input,\n grantedByTenantId: input.grantedByTenantId || setBy,\n });\n }\n\n private async recordGrant(\n policy: SpendingPolicy,\n input: GrantCreditInput,\n ): Promise<CreditGrant> {\n if (policy.period !== 'balance') {\n throw new ResellerBillingError(\n `Spending policy '${policy.name}' is not a balance policy.`,\n 'POLICY_NOT_BALANCE',\n );\n }\n if (!Number.isSafeInteger(input.amount) || input.amount === 0) {\n throw new ResellerBillingError(\n `Credit amount must be a nonzero integer number of minor units — got ${input.amount}.`,\n 'INVALID_AMOUNT',\n );\n }\n const { credits } = await this.getLedgers();\n const source = input.source ?? '';\n const sourceId = input.sourceId ?? '';\n const id =\n source && sourceId\n ? await deterministicUuid([\n 'credit-grant',\n String(policy.tenantId),\n String(policy.id),\n source,\n sourceId,\n ])\n : undefined;\n if (id) {\n const existing = await credits.get(id);\n if (existing) return existing;\n }\n try {\n return await credits.create({\n ...(id ? { id } : {}),\n tenantId: policy.tenantId,\n spendingPolicyId: String(policy.id),\n amount: input.amount,\n currency: policy.currency,\n reason: input.reason ?? '',\n source,\n sourceId,\n grantedByTenantId: input.grantedByTenantId ?? '',\n _insertOnly: Boolean(id),\n });\n } catch (error) {\n const concurrent = id ? await credits.get(id) : undefined;\n if (concurrent) return concurrent;\n throw error;\n }\n }\n\n private async evaluatePolicy(\n policy: SpendingPolicy,\n input: SpendingEvaluationInput,\n at: Date,\n ): Promise<SpendingDecision> {\n const estimatedAmount =\n input.estimatedAmounts?.[policy.basis] ?? input.estimatedAmount;\n const [start, end] = policyWindow(policy, at);\n const spent = await this.spentFor(policy, input.tenantId, start, end);\n if (policy.period !== 'balance') {\n return decide(policy, spent + estimatedAmount, policy.limitAmount);\n }\n let credit = await this.creditFor(policy);\n const projectedAmount = spent + estimatedAmount;\n const policyId = policy.id;\n if (projectedAmount > credit && this.extensions.autoTopUp && policyId) {\n const grant = await this.extensions.autoTopUp({\n policyId,\n tenantId: String(policy.tenantId),\n setByTenantId: tenantKey(policy.setByTenantId),\n currency: policy.currency,\n balanceAmount: credit - spent,\n estimatedAmount,\n shortfall: projectedAmount - credit,\n currentShortfall: async () =>\n (await this.spentFor(policy, input.tenantId, start, end)) +\n estimatedAmount -\n (await this.creditFor(policy)),\n });\n if (grant) {\n // The hook is host code configured on this evaluator; its grant is\n // recorded with the policy's own grantor even when evaluation runs in\n // the constrained child's tenant context.\n await withSystemContext(() =>\n this.recordGrant(policy, {\n spendingPolicyId: policyId,\n amount: grant.amount,\n reason: grant.reason ?? 'auto top-up',\n source: grant.source ?? 'auto_top_up',\n sourceId: grant.sourceId,\n grantedByTenantId: tenantKey(policy.setByTenantId),\n }),\n );\n }\n // Re-read either way: a concurrent top-up may have landed.\n credit = await this.creditFor(policy);\n }\n return {\n ...decide(policy, projectedAmount, credit),\n balanceAmount: credit - spent,\n };\n }\n\n /** Approved spend in the policy's window, currency, scope, and basis. */\n private async spentFor(\n policy: SpendingPolicy,\n tenantId: string,\n start: Date,\n end: Date,\n ): Promise<number> {\n const scope: Record<string, unknown> = {\n currency: policy.currency,\n 'approvedAt >=': start.toISOString(),\n 'approvedAt <': end.toISOString(),\n };\n if (policy.metricKey) scope.metricKey = policy.metricKey;\n if (policy.projectId) scope.projectId = policy.projectId;\n if (policy.serviceKey) scope.serviceKey = policy.serviceKey;\n if (policy.subscriberKind) scope.subscriberKind = policy.subscriberKind;\n if (policy.subscriberExternalId)\n scope.subscriberExternalId = policy.subscriberExternalId;\n\n const setBy = tenantKey(policy.setByTenantId);\n if (policy.basis === 'retail') {\n const { retailCharges } = await this.getLedgers();\n const where: Record<string, unknown> = {\n ...scope,\n tenantId,\n status: 'approved',\n };\n // A parent's cap counts only what the child owes that parent.\n if (setBy) where.resellerTenantId = setBy;\n const rows = await retailCharges.list({ where });\n return sumScoped(\n policy,\n rows.filter(\n (row) => !setBy || tenantKey(row.resellerTenantId) === setBy,\n ),\n ['approved'],\n );\n }\n\n if (policy.basis === 'wholesale') {\n if (!setBy) return 0;\n // Reviewed cross-tenant read: the parent's provider charges for this\n // child's usage, bounded to (payer = setBy, usageTenantId = tenant) and\n // reduced to a sum, so a child-context evaluation can enforce its\n // parent's wholesale cap without reading the parent's other rows.\n return withSystemContext(() =>\n this.sumProviderCharges(policy, scope, setBy, tenantId),\n );\n }\n return this.sumProviderCharges(policy, scope, tenantId);\n }\n\n private async sumProviderCharges(\n policy: SpendingPolicy,\n scope: Record<string, unknown>,\n payer: string,\n usageTenantId?: string,\n ): Promise<number> {\n const where: Record<string, unknown> = {\n ...scope,\n tenantId: payer,\n status: ['approved', 'adjusted'],\n };\n if (usageTenantId) where.usageTenantId = usageTenantId;\n const rows = await this.charges.list({ where });\n const scopedCharges = rows.filter(\n (charge) =>\n (!usageTenantId ||\n tenantKey(charge.usageTenantId) === tenantKey(usageTenantId)) &&\n (charge.status === 'approved' || charge.status === 'adjusted') &&\n matchesChargeScope(policy, charge),\n );\n const chargeIds = scopedCharges\n .map((charge) => charge.id)\n .filter((id): id is string => Boolean(id));\n const chargeIdSet = new Set(chargeIds);\n const adjustmentRows =\n chargeIds.length > 0\n ? await this.adjustments.list({\n where: {\n tenantId: payer,\n currency: policy.currency,\n clientChargeId: chargeIds,\n },\n })\n : [];\n const spent = scopedCharges.reduce((sum, charge) => sum + charge.amount, 0);\n return (\n spent +\n adjustmentRows\n .filter((adjustment) => chargeIdSet.has(adjustment.clientChargeId))\n .reduce((sum, adjustment) => sum + adjustment.amount, 0)\n );\n }\n\n private async creditFor(policy: SpendingPolicy): Promise<number> {\n const { credits } = await this.getLedgers();\n const grants = await credits.list({\n where: {\n tenantId: policy.tenantId,\n spendingPolicyId: policy.id,\n currency: policy.currency,\n },\n });\n // A delegated balance holds only credit its current parent granted: when\n // a new parent takes over the policy, a former parent's grants stay with\n // that former relationship instead of funding the new one.\n const setBy = tenantKey(policy.setByTenantId);\n return grants\n .filter(\n (grant) =>\n grant.spendingPolicyId === policy.id &&\n (!setBy || tenantKey(grant.grantedByTenantId) === setBy),\n )\n .reduce((sum, grant) => sum + grant.amount, 0);\n }\n\n private getLedgers(): Promise<{\n retailCharges: RetailChargeCollection;\n credits: CreditGrantCollection;\n }> {\n this.ledgers ??= (async () => {\n const options = { db: this.policies.db };\n return {\n retailCharges:\n this.extensions.retailCharges ??\n (await RetailChargeCollection.create(options)),\n credits:\n this.extensions.credits ??\n (await CreditGrantCollection.create(options)),\n };\n })();\n this.ledgers.catch(() => {\n this.ledgers = undefined;\n });\n return this.ledgers;\n }\n}\n\nfunction decide(\n policy: SpendingPolicy,\n projectedAmount: number,\n limitAmount: number,\n): SpendingDecision {\n const exceeded = projectedAmount > limitAmount;\n const matchedPolicyId = policy.id ?? null;\n if (!exceeded || policy.behavior === 'observe')\n return {\n allowed: true,\n approvalRequired: false,\n state: exceeded ? 'observed' : 'ok',\n projectedAmount,\n matchedPolicyId,\n };\n if (policy.behavior === 'warn')\n return {\n allowed: true,\n approvalRequired: false,\n state: 'warned',\n projectedAmount,\n matchedPolicyId,\n };\n if (policy.behavior === 'approval_required')\n return {\n allowed: false,\n approvalRequired: true,\n state: 'approval_required',\n projectedAmount,\n matchedPolicyId,\n };\n return {\n allowed: false,\n approvalRequired: false,\n state: 'blocked',\n projectedAmount,\n matchedPolicyId,\n };\n}\n\nfunction sumScoped(\n policy: SpendingPolicy,\n rows: LedgerRow[],\n statuses: string[],\n): number {\n return rows\n .filter(\n (row) => statuses.includes(row.status) && matchesChargeScope(policy, row),\n )\n .reduce((sum, row) => sum + row.amount, 0);\n}\n\n/**\n * The provider leg must be priced by someone other than the payer: a reseller\n * (or its child) never publishes the wholesale book it is charged from.\n */\nexport function assertWholesalePublisher(\n book: PriceBook,\n resellerTenantId: string,\n childTenantId: string,\n): void {\n const publisher = tenantKey(book.tenantId);\n if (publisher === resellerTenantId || publisher === childTenantId) {\n throw new ResellerBillingError(\n `Wholesale price book '${book.bookKey}' is published by the tenant it would charge.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n}\n\nasync function loadBook(\n books: PriceBookCollection,\n id: string,\n kind: PriceBookKind,\n): Promise<PriceBook> {\n const book = await books.get(id);\n if (!book?.id) {\n throw new ResellerBillingError(\n `Price book ${id} was not found.`,\n 'PRICE_BOOK_NOT_FOUND',\n );\n }\n if (book.kind !== kind) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is a ${book.kind} book, not ${kind}.`,\n 'PRICE_BOOK_KIND_MISMATCH',\n );\n }\n if (!book.active) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is inactive.`,\n 'PRICE_BOOK_INACTIVE',\n );\n }\n return book;\n}\n\nfunction selectRule(\n rules: PricingRule[],\n at: Date,\n serviceKey: string,\n): PricingRule | undefined {\n return rules\n .filter(\n (rule) =>\n rule.effectiveFrom <= at &&\n (!rule.effectiveTo || rule.effectiveTo > at) &&\n (!rule.serviceKey || rule.serviceKey === serviceKey),\n )\n .sort(\n (a, b) =>\n Number(Boolean(b.serviceKey)) - Number(Boolean(a.serviceKey)) ||\n b.priority - a.priority ||\n b.effectiveFrom.getTime() - a.effectiveFrom.getTime(),\n )[0];\n}\nfunction priceTiers(quantity: number, tiers: unknown[]): number {\n let remaining = quantity,\n prior = 0,\n amount = 0;\n for (const raw of tiers as Array<Record<string, unknown>>) {\n const upTo = raw.upTo == null ? Infinity : Number(raw.upTo);\n const units = Math.max(0, Math.min(remaining, upTo - prior));\n amount += units * Number(raw.unitPrice ?? 0);\n remaining -= units;\n prior = upTo;\n if (remaining <= 0) break;\n }\n return amount;\n}\nfunction selectPolicies(\n policies: SpendingPolicy[],\n input: Record<string, unknown>,\n): SpendingPolicy[] {\n return policies\n .filter(\n (p) =>\n hasValidSubscriberScope(p) &&\n (!p.metricKey || p.metricKey === input.metricKey) &&\n p.currency === input.currency &&\n (!p.projectId || p.projectId === input.projectId) &&\n (!p.serviceKey || p.serviceKey === input.serviceKey) &&\n (!p.subscriberKind ||\n (p.subscriberKind === (input.subscriberKind ?? 'tenant') &&\n (!p.subscriberExternalId ||\n p.subscriberExternalId === input.subscriberExternalId))),\n )\n .sort((a, b) => scopeScore(b) - scopeScore(a) || b.priority - a.priority);\n}\n\nfunction decisionRank(decision: SpendingDecision): number {\n return {\n ok: 0,\n observed: 1,\n warned: 2,\n approval_required: 3,\n blocked: 4,\n }[decision.state];\n}\nfunction scopeScore(p: SpendingPolicy): number {\n return (\n Number(Boolean(p.subscriberKind)) +\n Number(Boolean(p.subscriberExternalId)) +\n Number(Boolean(p.projectId)) +\n Number(Boolean(p.serviceKey)) +\n Number(Boolean(p.metricKey))\n );\n}\nfunction matchesChargeScope(p: SpendingPolicy, c: LedgerRow): boolean {\n return (\n hasValidSubscriberScope(p) &&\n (!p.projectId || p.projectId === c.projectId) &&\n (!p.serviceKey || p.serviceKey === c.serviceKey) &&\n (!p.metricKey || p.metricKey === c.metricKey) &&\n (!p.subscriberKind ||\n (p.subscriberKind === c.subscriberKind &&\n (!p.subscriberExternalId ||\n p.subscriberExternalId === c.subscriberExternalId)))\n );\n}\nfunction hasValidSubscriberScope(p: SpendingPolicy): boolean {\n return !p.subscriberExternalId || Boolean(p.subscriberKind);\n}\nfunction policyWindow(policy: SpendingPolicy, at: Date): [Date, Date] {\n const end = new Date(at);\n const start = new Date(at);\n if (policy.period === 'balance')\n start.setTime(\n new Date(policy.balanceFrom ?? policy.created_at ?? 0).getTime(),\n );\n else if (policy.period === 'rolling')\n start.setTime(at.getTime() - policy.rollingSeconds * 1000);\n else if (policy.period === 'day') start.setUTCHours(0, 0, 0, 0);\n else if (policy.period === 'week') {\n start.setUTCHours(0, 0, 0, 0);\n start.setUTCDate(start.getUTCDate() - ((start.getUTCDay() + 6) % 7));\n } else if (policy.period === 'month') {\n start.setUTCDate(1);\n start.setUTCHours(0, 0, 0, 0);\n } else {\n start.setUTCMonth(0, 1);\n start.setUTCHours(0, 0, 0, 0);\n }\n return [start, end];\n}\n","import type {\n PlanThreshold,\n ThresholdEvaluation,\n UsageSummary,\n} from '../types.js';\n\nexport function evaluateThreshold(\n threshold: PlanThreshold,\n usage: UsageSummary,\n): ThresholdEvaluation {\n const ratio =\n threshold.limit === 0\n ? usage.quantity > 0\n ? Infinity\n : 0\n : usage.quantity / threshold.limit;\n const warningRatio = threshold.warningRatio ?? 0.8;\n const blocked =\n threshold.enforcement === 'block' &&\n (threshold.limit === 0\n ? usage.quantity > 0\n : usage.quantity >= threshold.limit);\n const warned = !blocked && ratio >= warningRatio;\n\n return {\n threshold,\n usage,\n ratio,\n state: blocked ? 'blocked' : warned ? 'warn' : 'ok',\n allowed: !blocked,\n remaining: Math.max(0, threshold.limit - usage.quantity),\n };\n}\n\nexport function evaluateThresholds(\n thresholds: PlanThreshold[],\n usage: UsageSummary[],\n): ThresholdEvaluation[] {\n const usageByMetric = new Map(\n usage.map((summary) => [summary.metricKey, summary]),\n );\n\n return thresholds.map((threshold) => {\n const summary =\n usageByMetric.get(threshold.metricKey) ??\n emptyUsageSummary(threshold.metricKey);\n return evaluateThreshold(threshold, summary);\n });\n}\n\nfunction emptyUsageSummary(metricKey: string): UsageSummary {\n const now = new Date();\n return {\n tenantId: '',\n metricKey,\n quantity: 0,\n windowStart: now,\n windowEnd: now,\n };\n}\n","import type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport { TenantUsageMetricCollection } from '../collections/TenantUsageMetricCollection.js';\nimport type {\n AiUsageSummary,\n RecordUsageOptions,\n SummarizeAiUsageOptions,\n SummarizeUsageBatchOptions,\n SummarizeUsageOptions,\n UsageSummary,\n} from '../types.js';\nimport { normalizeSubscriber } from '../utils.js';\n\nexport class TenantUsageMeter {\n constructor(\n private readonly metrics: TenantUsageMetricCollection,\n private readonly classOptions: SmrtClassOptions = {},\n ) {}\n\n static async create(\n classOptions: SmrtClassOptions = {},\n ): Promise<TenantUsageMeter> {\n const metrics = await TenantUsageMetricCollection.create(classOptions);\n return new TenantUsageMeter(metrics, classOptions);\n }\n\n /**\n * Record one usage row.\n *\n * Accepts the polymorphic subscriber fields directly on the options object\n * (`subscriberKind`/`subscriberExternalId`); when omitted defaults to a\n * `'tenant'`-kind row keyed off `tenantId`. The collection layer enforces\n * the XOR invariant — passing `subscriberKind: 'external'` without a\n * non-empty `subscriberExternalId` throws.\n */\n async record(options: RecordUsageOptions): Promise<void> {\n await this.metrics.recordUsage(options);\n }\n\n /**\n * Summarize usage over a window for a given subscriber.\n *\n * The `ai.*` short-circuit only fires for `'tenant'`-kind subscribers since\n * the `_smrt_ai_usage` system table is tenant-scoped; external subscribers\n * fall through to the normal `_smrt_tenant_usage_metrics` aggregation.\n */\n async summarize(options: SummarizeUsageOptions): Promise<UsageSummary> {\n // Normalize at the boundary so the `ai.*` short-circuit and the standard\n // `summarizeUsage` path both refuse the same XOR violations (e.g. caller\n // passes subscriberExternalId without subscriberKind: 'external'). Without\n // this, the AI short-circuit would silently re-scope to tenant-wide\n // _smrt_ai_usage totals.\n normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n\n const aiSummary = await this.trySummarizeAiMetric(options);\n if (aiSummary) {\n return aiSummary;\n }\n\n return this.metrics.summarizeUsage(options);\n }\n\n async summarizeBatch(\n options: SummarizeUsageBatchOptions,\n ): Promise<UsageSummary[]> {\n const subscriber = normalizeSubscriber({\n tenantId: options.tenantId,\n subscriberKind: options.subscriberKind,\n subscriberExternalId: options.subscriberExternalId,\n });\n const metricKeys = Array.from(new Set(options.metricKeys));\n if (metricKeys.length === 0) {\n return [];\n }\n\n const useTenantAiSummary = subscriber.kind === 'tenant';\n const aiMetricKeys = useTenantAiSummary\n ? metricKeys.filter((metricKey) => metricKey.startsWith('ai.'))\n : [];\n const persistedMetricKeys = useTenantAiSummary\n ? metricKeys.filter((metricKey) => !metricKey.startsWith('ai.'))\n : metricKeys;\n\n const summaries = new Map<string, UsageSummary>();\n let fallbackAiMetricKeys: string[] = [];\n if (aiMetricKeys.length > 0) {\n if (!(await this.hasAiUsageTable())) {\n fallbackAiMetricKeys = aiMetricKeys;\n } else {\n try {\n const aiSummary = await this.summarizeAiUsage({\n tenantId: options.tenantId,\n window: options.window,\n });\n const quantityByMetric = aiQuantityByMetric(aiSummary);\n for (const metricKey of aiMetricKeys) {\n summaries.set(metricKey, {\n tenantId: options.tenantId,\n metricKey,\n quantity: quantityByMetric[metricKey] ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n });\n }\n } catch (error) {\n if (!isMissingAiUsageTableError(error)) {\n throw error;\n }\n fallbackAiMetricKeys = aiMetricKeys;\n }\n }\n }\n\n const persistedSummaries = await this.metrics.summarizeUsageBatch({\n ...options,\n metricKeys: [...persistedMetricKeys, ...fallbackAiMetricKeys],\n });\n for (const summary of persistedSummaries) {\n summaries.set(summary.metricKey, summary);\n }\n\n return metricKeys.map(\n (metricKey) =>\n summaries.get(metricKey) ??\n emptyUsageSummary(subscriber, metricKey, options.window),\n );\n }\n\n async summarizeAiUsage(\n options: SummarizeAiUsageOptions,\n ): Promise<AiUsageSummary> {\n return this.metrics.summarizeTenantAiUsage(options);\n }\n\n getOptions(): SmrtClassOptions {\n return this.classOptions;\n }\n\n private async trySummarizeAiMetric(\n options: SummarizeUsageOptions,\n ): Promise<UsageSummary | null> {\n if (!options.metricKey.startsWith('ai.')) {\n return null;\n }\n // _smrt_ai_usage is tenant-scoped only; external subscribers must use the\n // standard usage path. Skip the short-circuit so the caller's recorded\n // usage rows are summed instead.\n const kind = options.subscriberKind ?? 'tenant';\n if (kind !== 'tenant') {\n return null;\n }\n if (!(await this.hasAiUsageTable())) {\n return null;\n }\n\n let summary: AiUsageSummary;\n try {\n summary = await this.summarizeAiUsage({\n tenantId: options.tenantId,\n window: options.window,\n });\n } catch (error) {\n if (isMissingAiUsageTableError(error)) {\n return null;\n }\n throw error;\n }\n\n const quantityByMetric: Record<string, number> = {\n ...aiQuantityByMetric(summary),\n };\n\n return {\n tenantId: options.tenantId,\n metricKey: options.metricKey,\n quantity: quantityByMetric[options.metricKey] ?? 0,\n windowStart: options.window.start,\n windowEnd: options.window.end,\n };\n }\n\n private async hasAiUsageTable(): Promise<boolean> {\n return this.metrics.db.tableExists('_smrt_ai_usage');\n }\n}\n\nfunction aiQuantityByMetric(summary: AiUsageSummary): Record<string, number> {\n return {\n 'ai.tokens.prompt': summary.promptTokens,\n 'ai.tokens.completion': summary.completionTokens,\n 'ai.tokens.total': summary.totalTokens,\n 'ai.cost.estimated': summary.estimatedCost,\n 'ai.requests': summary.requestCount,\n };\n}\n\nfunction isMissingAiUsageTableError(\n error: unknown,\n seen = new Set<unknown>(),\n): boolean {\n if (!error) {\n return false;\n }\n if (typeof error !== 'object') {\n return isMissingAiUsageTableMessage(String(error));\n }\n if (seen.has(error)) {\n return false;\n }\n seen.add(error);\n\n const err = error as {\n code?: unknown;\n message?: unknown;\n cause?: unknown;\n context?: Record<string, unknown>;\n };\n const codes = [err?.code, err?.context?.code, err?.context?.errorCode];\n if (codes.some((code) => code === '42P01')) {\n return true;\n }\n\n const messages = [\n err?.message,\n err?.context?.originalError,\n err?.context?.error,\n err?.context?.details,\n ];\n for (const candidate of messages) {\n if (\n candidate &&\n typeof candidate === 'object' &&\n isMissingAiUsageTableError(candidate, seen)\n ) {\n return true;\n }\n if (isMissingAiUsageTableMessage(String(candidate ?? ''))) {\n return true;\n }\n }\n\n return err?.cause ? isMissingAiUsageTableError(err.cause, seen) : false;\n}\n\nfunction isMissingAiUsageTableMessage(message: string): boolean {\n const normalized = message.toLowerCase();\n return (\n normalized.includes('_smrt_ai_usage') &&\n (normalized.includes('no such table') ||\n normalized.includes('does not exist') ||\n normalized.includes('undefined table'))\n );\n}\n\nfunction emptyUsageSummary(\n subscriber: ReturnType<typeof normalizeSubscriber>,\n metricKey: string,\n window: SummarizeUsageBatchOptions['window'],\n): UsageSummary {\n const summary: UsageSummary = {\n tenantId: subscriber.tenantId,\n metricKey,\n quantity: 0,\n windowStart: window.start,\n windowEnd: window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...summary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return summary;\n}\n","import { isSystemContext } from '@happyvertical/smrt-tenancy';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport { SubscriptionPlanVersionCollection } from '../collections/SubscriptionPlanVersionCollection.js';\nimport { TenantSubscriptionCollection } from '../collections/TenantSubscriptionCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport type { SubscriptionPlanVersion } from '../models/SubscriptionPlanVersion.js';\nimport type { TenantSubscription } from '../models/TenantSubscription.js';\nimport type {\n EntitlementResolution,\n EntitlementResolutionContext,\n PlanFeatureGrant,\n PlanThreshold,\n SmrtClassOptions,\n Subscriber,\n SubscriptionResolverOptions,\n ThresholdEvaluation,\n UsageSummary,\n UsageWindow,\n} from '../types.js';\nimport {\n getWindowForThreshold,\n getWindowKey,\n isValidThreshold,\n} from '../utils.js';\nimport { evaluateThreshold } from './threshold-evaluator.js';\nimport { TenantUsageMeter } from './usage-meter.js';\n\nexport interface SubscriptionPlanReader {\n get(criteria: { id: string }): Promise<SubscriptionPlan | null>;\n}\n\n/**\n * Reader for effective-dated plan versions (#4032). `findInForce` resolves\n * subscriptions that have no pinned version yet (rows written before\n * versioning and not yet migrated).\n */\nexport interface SubscriptionPlanVersionReader {\n get(criteria: { id: string }): Promise<SubscriptionPlanVersion | null>;\n findInForce?(\n planId: string,\n at: Date,\n ): Promise<SubscriptionPlanVersion | null>;\n}\n\n/**\n * Reader contract for finding the current subscription for a subscriber.\n *\n * The legacy `findCurrentForTenant(tenantId)` signature stays for backward\n * compatibility with the original tenant-only resolver. New implementations\n * should provide `findCurrentForSubscriber(subscriber)` — it's preferred when\n * present and lets the resolver work with both `'tenant'` and `'external'`\n * subscribers without callers having to pre-narrow the discriminator.\n */\nexport interface TenantSubscriptionReader {\n findCurrentForTenant(\n tenantId: string,\n now?: Date,\n ): Promise<TenantSubscription | null>;\n findCurrentForSubscriber?(\n subscriber: Subscriber,\n now?: Date,\n ): Promise<TenantSubscription | null>;\n}\n\n/**\n * Reader contract for summarizing usage.\n *\n * `summarize(options)` already accepts the polymorphic\n * `subscriberKind`/`subscriberExternalId` fields. When omitted the reader\n * defaults to `'tenant'`, which is what existing callers got before this\n * change — no behavior shift for them. The discriminator type is derived\n * from `Subscriber['kind']` rather than inlined so any future additions to\n * the union stay consistent across the package.\n */\nexport interface UsageSummaryReader {\n summarize(options: {\n tenantId: string;\n subscriberKind?: Subscriber['kind'];\n subscriberExternalId?: string;\n metricKey: string;\n window: UsageWindow;\n }): Promise<UsageSummary>;\n summarizeBatch?(options: {\n tenantId: string;\n subscriberKind?: Subscriber['kind'];\n subscriberExternalId?: string;\n metricKeys: string[];\n window: UsageWindow;\n }): Promise<UsageSummary[]>;\n}\n\nexport interface SubscriptionResolverReaders {\n plans: SubscriptionPlanReader;\n subscriptions: TenantSubscriptionReader;\n usage: UsageSummaryReader;\n /**\n * Plan versions. When present, entitlements come from the version frozen\n * for the subscription's current period instead of the live plan row.\n * Omitting it keeps the pre-#4032 live-plan behavior.\n */\n planVersions?: SubscriptionPlanVersionReader;\n}\n\nexport class SubscriptionResolver {\n constructor(private readonly readers: SubscriptionResolverReaders) {}\n\n /**\n * Build the default resolver readers once for a request or app lifecycle and\n * reuse the returned resolver across entitlement checks.\n */\n static async create(\n classOptions: SmrtClassOptions = {},\n ): Promise<SubscriptionResolver> {\n const [plans, subscriptions, usage, planVersions] = await Promise.all([\n SubscriptionPlanCollection.create(classOptions),\n TenantSubscriptionCollection.create(classOptions),\n TenantUsageMeter.create(classOptions),\n SubscriptionPlanVersionCollection.create(classOptions),\n ]);\n return new SubscriptionResolver({\n plans,\n subscriptions,\n usage,\n // Pinned versions of legacy global plans stay readable under a tenant\n // context through the collection's bounded global fallback.\n planVersions: {\n get: ({ id }) => planVersions.findVisibleById(id),\n findInForce: (planId, at) => planVersions.findInForce(planId, at),\n },\n });\n }\n\n /**\n * Load the subscription/plan pair used by entitlement resolution. Callers\n * that need both the entitlement snapshot and the backing records can load\n * this once, then pass it back via `options.context`.\n */\n async loadEntitlementContext(\n subscriberOrTenantId: Subscriber | string,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolutionContext> {\n const subscriber = toSubscriber(subscriberOrTenantId);\n const now = options.now ?? new Date();\n const subscription = await this.resolveSubscription(\n subscriber,\n now,\n options.context,\n );\n const plan = await this.resolvePlan(subscription, options.context);\n const planVersion = await this.resolvePlanVersion(\n subscription,\n options.context,\n );\n return { subscription, plan, planVersion };\n }\n\n /**\n * Feature keys the subscriber's entitled terms grant, without evaluating\n * usage thresholds (#4761). Same subscription, plan-version and entitlement\n * rules as {@link resolveEntitlements}; used by `SubscriptionFeatureSource`\n * so a flag check never reads usage meters.\n */\n async resolveFeatureGrants(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<{\n featureKeys: string[];\n /** The entitled terms' grants with their `metadata` (#4759). */\n grants: PlanFeatureGrant[];\n planId: string | null;\n planKey: string | null;\n }> {\n const now = options.now ?? new Date();\n const { identity, terms } = await this.resolveEntitledTerms(\n subscriber,\n now,\n options,\n );\n return {\n featureKeys: terms ? terms.getFeatureKeys() : [],\n grants: terms ? terms.getFeatureGrants() : [],\n planId: identity?.planId ?? null,\n planKey: identity?.planKey ?? null,\n };\n }\n\n /**\n * The entitled plan terms' thresholds, without reading any usage meter\n * (#4760). Same subscription, plan-version and entitlement rules as\n * {@link resolveEntitlements}; `entitled` is false when there is no\n * current subscription or it does not entitle now (thresholds are then\n * empty). The hosted inference gate reads its spend caps from here and\n * meters `_smrt_ai_usage` itself. Thresholds are returned as stored, valid\n * or not (the models' `getThresholds()` drops invalid entries), so a caller\n * can refuse a malformed cap instead of skipping it; thresholds JSON that\n * is not an array throws.\n */\n async resolvePlanThresholds(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<{\n entitled: boolean;\n thresholds: PlanThreshold[];\n planId: string | null;\n planKey: string | null;\n planVersionId: string | null;\n subscriptionId: string | null;\n }> {\n const now = options.now ?? new Date();\n const { identity, terms } = await this.resolveEntitledTerms(\n subscriber,\n now,\n options,\n );\n return {\n entitled: terms !== null,\n thresholds: terms ? rawThresholds(terms.thresholds) : [],\n planId: identity?.planId ?? null,\n planKey: identity?.planKey ?? null,\n planVersionId: identity?.planVersionId ?? null,\n subscriptionId: identity?.subscriptionId ?? null,\n };\n }\n\n private async resolveEntitledTerms(\n subscriber: Subscriber,\n now: Date,\n options: SubscriptionResolverOptions,\n ): Promise<{\n identity: EntitlementIdentity | null;\n terms: SubscriptionPlan | SubscriptionPlanVersion | null;\n }> {\n const { subscription, plan, planVersion } =\n await this.loadEntitlementContext(subscriber, { ...options, now });\n\n if (!subscription) {\n return { identity: null, terms: null };\n }\n\n // With versioning the frozen version is authoritative: a later edit,\n // archive or entitlement removal on the live plan never reaches a paid\n // period. A pinned version that cannot be found fails closed; only an\n // unpinned subscription to a plan with no versions (unmigrated legacy\n // data) falls back to the live plan.\n // Without a version reader or context (custom pre-#4032 readers) the\n // live plan stays authoritative.\n const terms =\n planVersion === undefined\n ? plan\n : (planVersion ?? (subscription.planVersionId ? null : plan));\n const identity = {\n planId: plan?.id ?? planVersion?.planId ?? subscription.planId ?? null,\n planKey: plan?.planKey ?? planVersion?.planKey ?? null,\n planVersionId: terms === planVersion ? (planVersion?.id ?? null) : null,\n planVersion:\n terms === planVersion ? (planVersion?.version ?? null) : null,\n subscriptionId: subscription.id ?? null,\n status: subscription.status,\n };\n\n if (!terms?.isActive() || !subscription.isEntitled(now)) {\n return { identity, terms: null };\n }\n return { identity, terms };\n }\n\n /**\n * Polymorphic entitlement resolution. Works for both `'tenant'`-kind and\n * `'external'`-kind subscribers and is the preferred surface — the\n * `resolveTenantEntitlements(tenantId)` method below is a thin wrapper.\n */\n async resolveEntitlements(\n subscriber: Subscriber,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolution> {\n const now = options.now ?? new Date();\n const entitled = await this.resolveEntitledTerms(subscriber, now, options);\n\n if (!entitled.identity) {\n return emptyResolution(subscriber);\n }\n const { identity, terms } = entitled;\n if (!terms) {\n return { ...emptyResolution(subscriber), ...identity };\n }\n\n const thresholds = terms.getThresholds().filter(isValidThreshold);\n const thresholdEvaluations = await this.resolveThresholdEvaluations(\n subscriber,\n thresholds,\n now,\n options,\n );\n\n return {\n tenantId: subscriber.tenantId,\n subscriber,\n ...identity,\n featureKeys: terms.getFeatureKeys(),\n thresholds,\n thresholdEvaluations,\n allowed: thresholdEvaluations.every((evaluation) => evaluation.allowed),\n };\n }\n\n /**\n * Legacy single-tenant wrapper around {@link resolveEntitlements}. Kept so\n * existing tenant-only callers don't need to update their call sites.\n */\n async resolveTenantEntitlements(\n tenantId: string,\n options: SubscriptionResolverOptions = {},\n ): Promise<EntitlementResolution> {\n return this.resolveEntitlements({ kind: 'tenant', tenantId }, options);\n }\n\n async isFeatureEnabled(\n subscriberOrTenantId: Subscriber | string,\n featureKey: string,\n options: SubscriptionResolverOptions = {},\n ): Promise<boolean> {\n const resolution = await this.resolveEntitlements(\n toSubscriber(subscriberOrTenantId),\n options,\n );\n return resolution.featureKeys.includes(featureKey);\n }\n\n async assertWithinThresholds(\n subscriberOrTenantId: Subscriber | string,\n options: SubscriptionResolverOptions = {},\n ): Promise<void> {\n const subscriber = toSubscriber(subscriberOrTenantId);\n const resolution = await this.resolveEntitlements(subscriber, options);\n const blocked = resolution.thresholdEvaluations.find(\n (evaluation) => !evaluation.allowed,\n );\n\n if (blocked) {\n const subject =\n subscriber.kind === 'external'\n ? `external:${subscriber.externalId}`\n : `Tenant ${subscriber.tenantId}`;\n throw new Error(\n `${subject} exceeded subscription threshold ${blocked.threshold.metricKey}`,\n );\n }\n }\n\n private async resolveSubscription(\n subscriber: Subscriber,\n now: Date,\n context?: EntitlementResolutionContext,\n ): Promise<TenantSubscription | null> {\n if (hasContextValue(context, 'subscription')) {\n const subscription = context?.subscription ?? null;\n assertSubscriptionMatchesSubscriber(subscription, subscriber);\n return subscription;\n }\n return this.findCurrentSubscription(subscriber, now);\n }\n\n private async resolvePlan(\n subscription: TenantSubscription | null,\n context?: EntitlementResolutionContext,\n ): Promise<SubscriptionPlan | null> {\n if (!subscription?.planId) {\n return null;\n }\n if (hasContextValue(context, 'plan')) {\n const plan = context?.plan ?? null;\n assertPlanMatchesSubscription(plan, subscription);\n return plan;\n }\n const plan = await this.readers.plans.get({ id: subscription.planId });\n assertPlanMatchesSubscription(plan, subscription);\n return plan;\n }\n\n /**\n * The version frozen for the subscription's current period: its pinned\n * `planVersionId`, or — for rows not yet pinned — the version in force at\n * its period start. Null when the subscription has no plan or a pinned\n * version is missing (the resolver then fails closed); undefined when no\n * version reader or context is available.\n */\n private async resolvePlanVersion(\n subscription: TenantSubscription | null,\n context?: EntitlementResolutionContext,\n ): Promise<SubscriptionPlanVersion | null | undefined> {\n if (!subscription?.planId) {\n return null;\n }\n if (hasContextValue(context, 'planVersion')) {\n const planVersion = context?.planVersion ?? null;\n assertPlanVersionMatchesSubscription(planVersion, subscription);\n return planVersion;\n }\n const reader = this.readers.planVersions;\n if (!reader) {\n return undefined;\n }\n const planVersion = subscription.planVersionId\n ? await reader.get({ id: subscription.planVersionId })\n : ((await reader.findInForce?.(\n subscription.planId,\n new Date(subscription.currentPeriodStart ?? subscription.startedAt),\n )) ?? null);\n assertPlanVersionMatchesSubscription(planVersion, subscription);\n return planVersion;\n }\n\n /**\n * Bridge the legacy and polymorphic reader contracts.\n *\n * Prefers `findCurrentForSubscriber` when the reader provides it (the\n * preferred shape). For `'tenant'` subscribers we fall back to the legacy\n * `findCurrentForTenant`. For `'external'` subscribers the reader MUST\n * implement `findCurrentForSubscriber` — otherwise we have no way to scope\n * the lookup and we throw rather than silently returning the tenant's\n * primary subscription.\n */\n private async findCurrentSubscription(\n subscriber: Subscriber,\n now: Date,\n ): Promise<TenantSubscription | null> {\n if (this.readers.subscriptions.findCurrentForSubscriber) {\n return this.readers.subscriptions.findCurrentForSubscriber(\n subscriber,\n now,\n );\n }\n if (subscriber.kind === 'tenant') {\n return this.readers.subscriptions.findCurrentForTenant(\n subscriber.tenantId,\n now,\n );\n }\n throw new Error(\n 'External-subscriber resolution requires a TenantSubscriptionReader ' +\n 'that implements findCurrentForSubscriber()',\n );\n }\n\n private async resolveThresholdEvaluations(\n subscriber: Subscriber,\n thresholds: PlanThreshold[],\n now: Date,\n options: SubscriptionResolverOptions,\n ): Promise<ThresholdEvaluation[]> {\n if (thresholds.length === 0) {\n return [];\n }\n\n if (!this.readers.usage.summarizeBatch) {\n const evaluations: ThresholdEvaluation[] = [];\n for (const threshold of thresholds) {\n const window =\n options.usageWindows?.[threshold.window] ??\n getWindowForThreshold(threshold.window, now);\n const usage = await this.readers.usage.summarize({\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n subscriberExternalId:\n subscriber.kind === 'external' ? subscriber.externalId : undefined,\n metricKey: threshold.metricKey,\n window,\n });\n evaluations.push(evaluateThreshold(threshold, usage));\n }\n return evaluations;\n }\n\n const groups = new Map<\n string,\n {\n window: UsageWindow;\n entries: Array<{ index: number; threshold: PlanThreshold }>;\n }\n >();\n\n thresholds.forEach((threshold, index) => {\n const window =\n options.usageWindows?.[threshold.window] ??\n getWindowForThreshold(threshold.window, now);\n const key = getWindowKey(window);\n const group = groups.get(key) ?? { window, entries: [] };\n group.entries.push({ index, threshold });\n groups.set(key, group);\n });\n\n const evaluations: ThresholdEvaluation[] = new Array(thresholds.length);\n await Promise.all(\n Array.from(groups.values()).map(async ({ window, entries }) => {\n const metricKeys = uniqueMetricKeys(\n entries.map((entry) => entry.threshold.metricKey),\n );\n const summaries = await this.readers.usage.summarizeBatch?.({\n tenantId: subscriber.tenantId,\n subscriberKind: subscriber.kind,\n subscriberExternalId:\n subscriber.kind === 'external' ? subscriber.externalId : undefined,\n metricKeys,\n window,\n });\n const summaryByMetric = new Map(\n (summaries ?? []).map((summary) => [summary.metricKey, summary]),\n );\n\n for (const { index, threshold } of entries) {\n const usage =\n summaryByMetric.get(threshold.metricKey) ??\n emptyUsageSummary(subscriber, threshold.metricKey, window);\n evaluations[index] = evaluateThreshold(threshold, usage);\n }\n }),\n );\n\n return evaluations;\n }\n}\n\ntype EntitlementIdentity = Pick<\n EntitlementResolution,\n | 'planId'\n | 'planKey'\n | 'planVersionId'\n | 'planVersion'\n | 'subscriptionId'\n | 'status'\n>;\n\nfunction toSubscriber(input: Subscriber | string): Subscriber {\n if (typeof input === 'string') {\n return { kind: 'tenant', tenantId: input };\n }\n return input;\n}\n\nfunction emptyResolution(subscriber: Subscriber): EntitlementResolution {\n return {\n tenantId: subscriber.tenantId,\n subscriber,\n planId: null,\n planKey: null,\n planVersionId: null,\n planVersion: null,\n subscriptionId: null,\n status: 'none',\n featureKeys: [],\n thresholds: [],\n thresholdEvaluations: [],\n allowed: false,\n };\n}\n\nfunction hasContextValue<K extends keyof EntitlementResolutionContext>(\n context: EntitlementResolutionContext | undefined,\n key: K,\n): boolean {\n return context?.[key] !== undefined;\n}\n\nfunction assertSubscriptionMatchesSubscriber(\n subscription: TenantSubscription | null,\n subscriber: Subscriber,\n): void {\n if (!subscription) {\n return;\n }\n const subscriptionSubscriber = subscription.getSubscriber();\n if (\n !subscriptionSubscriber ||\n !sameSubscriber(subscriptionSubscriber, subscriber)\n ) {\n throw new Error(\n 'Provided entitlement context subscription does not match requested subscriber',\n );\n }\n}\n\nfunction assertPlanMatchesSubscription(\n plan: SubscriptionPlan | null,\n subscription: TenantSubscription,\n): void {\n if (!plan) {\n return;\n }\n if (\n !isSystemContext() &&\n plan.tenantId !== null &&\n plan.tenantId !== subscription.tenantId\n ) {\n throw new Error('Entitlement plan does not belong to subscription tenant');\n }\n if (!plan.id || plan.id !== subscription.planId) {\n throw new Error(\n 'Provided entitlement context plan does not match subscription.planId',\n );\n }\n}\n\nfunction assertPlanVersionMatchesSubscription(\n planVersion: SubscriptionPlanVersion | null,\n subscription: TenantSubscription,\n): void {\n if (!planVersion) {\n return;\n }\n if (\n !isSystemContext() &&\n planVersion.tenantId !== null &&\n planVersion.tenantId !== subscription.tenantId\n ) {\n throw new Error(\n 'Entitlement plan version does not belong to subscription tenant',\n );\n }\n if (\n !planVersion.id ||\n planVersion.planId !== subscription.planId ||\n (subscription.planVersionId !== null &&\n planVersion.id !== subscription.planVersionId)\n ) {\n throw new Error(\n 'Provided entitlement plan version does not match the subscription',\n );\n }\n}\n\nfunction sameSubscriber(left: Subscriber, right: Subscriber): boolean {\n if (left.kind !== right.kind || left.tenantId !== right.tenantId) {\n return false;\n }\n if (left.kind === 'tenant') {\n return true;\n }\n return right.kind === 'external' && left.externalId === right.externalId;\n}\n\nfunction uniqueMetricKeys(metricKeys: string[]): string[] {\n return Array.from(new Set(metricKeys));\n}\n\nfunction emptyUsageSummary(\n subscriber: Subscriber,\n metricKey: string,\n window: UsageWindow,\n): UsageSummary {\n const summary: UsageSummary = {\n tenantId: subscriber.tenantId,\n metricKey,\n quantity: 0,\n windowStart: window.start,\n windowEnd: window.end,\n };\n if (subscriber.kind === 'external') {\n return {\n ...summary,\n subscriberKind: 'external',\n subscriberExternalId: subscriber.externalId,\n };\n }\n return summary;\n}\n\nexport type { PlanThreshold };\n\n/**\n * Every stored threshold object, without the validity filter the plan\n * models apply (#4760). Unparseable or non-array JSON throws: a broken\n * plan must never read as \"no caps\".\n */\nfunction rawThresholds(value: string | null | undefined): PlanThreshold[] {\n if (value === null || value === undefined || value.trim() === '') return [];\n const parsed: unknown = JSON.parse(value);\n if (!Array.isArray(parsed)) {\n throw new Error('Plan thresholds are not a JSON array.');\n }\n return parsed.filter(\n (entry): entry is PlanThreshold =>\n entry !== null && typeof entry === 'object' && !Array.isArray(entry),\n );\n}\n","/**\n * Plan feature grants as `smrt-features` flags (#4761).\n *\n * `SubscriptionFeatureSource` implements `smrt-features`' `FeatureGrantSource`\n * structurally, so this package does not depend on `smrt-features` and\n * `smrt-features` never depends on this one. Hosts either pass a per-request\n * source as `grantSource` in the feature resolution context, or register an\n * app-wide one with {@link registerSubscriptionFeatureSource}, which writes the\n * `Symbol.for('@happyvertical/smrt-features:grant-source')` slot that\n * `FeatureResolver` reads.\n *\n * Local installs: when the subscription tables do not exist, or the tenant has\n * no entitled subscription, the source reports no grants and logs nothing, so\n * paid keys stay at their (off) defaults. Every other failure propagates: a\n * database outage must not silently look like \"no plan\".\n */\nimport {\n classifyDatabaseError,\n type SmrtClassOptions,\n} from '@happyvertical/smrt-core';\nimport { SubscriptionPlanCollection } from '../collections/SubscriptionPlanCollection.js';\nimport type { SubscriptionPlan } from '../models/SubscriptionPlan.js';\nimport { SubscriptionResolver } from './subscription-resolver.js';\n\n/** Structural mirror of `smrt-features`' `FeatureGrantSnapshot`. */\nexport interface SubscriptionFeatureGrants {\n featureKeys: readonly string[];\n planId: string | null;\n planKey: string | null;\n}\n\n/** Structural mirror of `smrt-features`' `FeatureGrantingPlan`. */\nexport interface SubscriptionGrantingPlan {\n planKey: string;\n planId: string | null;\n name: string | null;\n}\n\n/** Reader for the plan catalog an upgrade response searches. */\nexport interface GrantingPlanReader {\n findActive(): Promise<SubscriptionPlan[]>;\n}\n\nexport interface SubscriptionFeatureSourceOptions {\n /** One resolver for the request (or app lifetime); never built per flag. */\n resolver: SubscriptionResolver;\n /** Plan catalog for `findGrantingPlan()`; omitted means no plan is named. */\n plans?: GrantingPlanReader;\n /**\n * Memoize grants per tenant for this instance's lifetime (default `true`).\n * Keep it on for a request-scoped source; a process-wide source registered\n * with {@link registerSubscriptionFeatureSource} turns it off so a plan\n * change is visible on the next check.\n */\n memoize?: boolean;\n /** Clock for entitlement checks; defaults to the current time. */\n now?: () => Date;\n}\n\n/** `Symbol.for()` key `smrt-features` reads its global grant source from. */\nexport const FEATURE_GRANT_SOURCE_SLOT_KEY =\n '@happyvertical/smrt-features:grant-source';\n\nconst SUBSCRIPTION_TABLES = new Set([\n '_smrt_tenant_subscriptions',\n '_smrt_subscription_plans',\n '_smrt_subscription_plan_versions',\n]);\n\nexport class SubscriptionFeatureSource {\n private readonly resolver: SubscriptionResolver;\n private readonly plans: GrantingPlanReader | undefined;\n private readonly memoize: boolean;\n private readonly now: () => Date;\n private readonly grants = new Map<\n string,\n Promise<SubscriptionFeatureGrants | null>\n >();\n private catalog: Promise<SubscriptionPlan[] | null> | null = null;\n\n constructor(options: SubscriptionFeatureSourceOptions) {\n this.resolver = options.resolver;\n this.plans = options.plans;\n this.memoize = options.memoize ?? true;\n this.now = options.now ?? (() => new Date());\n }\n\n /**\n * Build one source with its own resolver and plan catalog. Call once per\n * request (or once at setup with `memoize: false` for a global source).\n */\n static async create(\n classOptions: SmrtClassOptions = {},\n options: Omit<SubscriptionFeatureSourceOptions, 'resolver' | 'plans'> = {},\n ): Promise<SubscriptionFeatureSource> {\n const [resolver, plans] = await Promise.all([\n SubscriptionResolver.create(classOptions),\n SubscriptionPlanCollection.create(classOptions),\n ]);\n return new SubscriptionFeatureSource({ ...options, resolver, plans });\n }\n\n /** Feature keys the tenant's entitled plan grants, or `null` for none. */\n getGrants(tenantId: string): Promise<SubscriptionFeatureGrants | null> {\n if (!this.memoize) {\n return this.loadGrants(tenantId);\n }\n let pending = this.grants.get(tenantId);\n if (!pending) {\n pending = this.loadGrants(tenantId);\n this.grants.set(tenantId, pending);\n // A failed lookup is not cached; the next check retries.\n pending.catch(() => this.grants.delete(tenantId));\n }\n return pending;\n }\n\n /**\n * The first active plan (by `sortOrder`) visible in the current context\n * that grants `featureKey`, for an upgrade response.\n */\n async findGrantingPlan(\n featureKey: string,\n _tenantId: string | null,\n ): Promise<SubscriptionGrantingPlan | null> {\n const catalog = await this.loadCatalog();\n const plan = catalog?.find((candidate) =>\n candidate.getFeatureKeys().includes(featureKey),\n );\n if (!plan) {\n return null;\n }\n return {\n planKey: plan.planKey,\n planId: plan.id ? String(plan.id) : null,\n name: plan.name || null,\n };\n }\n\n private async loadGrants(\n tenantId: string,\n ): Promise<SubscriptionFeatureGrants | null> {\n try {\n const grants = await this.resolver.resolveFeatureGrants(\n { kind: 'tenant', tenantId },\n { now: this.now() },\n );\n return grants.featureKeys.length > 0\n ? {\n featureKeys: grants.featureKeys,\n planId: grants.planId,\n planKey: grants.planKey,\n }\n : null;\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return null;\n }\n throw error;\n }\n }\n\n private loadCatalog(): Promise<SubscriptionPlan[] | null> {\n if (!this.plans) {\n return Promise.resolve(null);\n }\n const load = async () => {\n try {\n return (await this.plans?.findActive()) ?? null;\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return null;\n }\n throw error;\n }\n };\n if (!this.memoize) {\n return load();\n }\n if (!this.catalog) {\n this.catalog = load();\n this.catalog.catch(() => {\n this.catalog = null;\n });\n }\n return this.catalog;\n }\n}\n\n/**\n * Register `source` as `smrt-features`' process-wide grant source, or clear it\n * with `undefined`. Equivalent to `setFeatureGrantSource()` from\n * `smrt-features`, without importing that package. Register a source built\n * with `memoize: false`; pass request-scoped sources per call instead.\n */\nexport function registerSubscriptionFeatureSource(\n source: SubscriptionFeatureSource | undefined,\n): void {\n (globalThis as unknown as Record<symbol, unknown>)[\n Symbol.for(FEATURE_GRANT_SOURCE_SLOT_KEY)\n ] = source;\n}\n\n/**\n * True when `error` reports that one of this package's tables does not exist\n * — core's `DB_SCHEMA_MISSING` or a raw \"no such table\" / \"relation does not\n * exist\" driver error naming a subscription table.\n */\nexport function isMissingSubscriptionTableError(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; current && depth < 8; depth++) {\n const candidate = current as {\n code?: unknown;\n details?: { tableName?: unknown };\n cause?: unknown;\n };\n if (\n candidate.code === 'DB_SCHEMA_MISSING' &&\n typeof candidate.details?.tableName === 'string' &&\n SUBSCRIPTION_TABLES.has(candidate.details.tableName)\n ) {\n return true;\n }\n current = candidate.cause;\n }\n\n const classification = classifyDatabaseError(error);\n if (classification.kind !== 'undefined_object') {\n return false;\n }\n if (classification.driverCodes.includes('42703')) {\n // Undefined column: schema drift, not a missing table.\n return false;\n }\n return classification.driverMessages.some((message) => {\n const lower = message.toLowerCase();\n return (\n (lower.includes('no such table') || lower.includes('does not exist')) &&\n Array.from(SUBSCRIPTION_TABLES).some((table) => lower.includes(table))\n );\n });\n}\n","/**\n * Entitlement change hook (#4759).\n *\n * A plan change arrives through the host's billing webhook (Stripe in\n * smrt-saas-starter, #4667): the host writes the new `TenantSubscription`\n * state. Code that must react to a feature key being gained or lost (hosted\n * inference provisioning, #4759) registers a listener here; the host wraps\n * its webhook write in {@link trackEntitlementChange}, which snapshots the\n * tenant's feature grants before and after and notifies listeners with the\n * difference.\n *\n * Listeners run after the write has been applied (and committed, when the\n * host's write commits inside `apply`). A listener failure never undoes the\n * write: it is collected in the outcome's `failures` so the host can log it,\n * alert, or retry the reaction (listeners are expected to be idempotent;\n * hosted provisioning is, through `runOnce()`). This package stays free of\n * any listener's dependencies: listeners satisfy the structural\n * {@link EntitlementChangeListener} type.\n */\nimport type { PlanFeatureGrant } from '../types.js';\nimport { isMissingSubscriptionTableError } from './subscription-feature-source.js';\nimport type { SubscriptionResolver } from './subscription-resolver.js';\n\n/** A tenant's entitled grants at one moment. */\nexport interface EntitlementSnapshot {\n planId: string | null;\n planKey: string | null;\n /** Enabled feature keys, sorted. */\n featureKeys: string[];\n /** Enabled grants (with their `metadata`), sorted by key. */\n grants: PlanFeatureGrant[];\n}\n\n/** The difference between two snapshots of one tenant. */\nexport interface EntitlementChange {\n tenantId: string;\n /** Keys granted after but not before. */\n gained: string[];\n /** Keys granted before but not after. */\n lost: string[];\n /**\n * Keys granted both before and after whose grant `metadata` changed (a\n * plan's budget for `inference.hosted`, for instance).\n */\n changed: string[];\n before: EntitlementSnapshot;\n after: EntitlementSnapshot;\n}\n\n/** Reacts to an {@link EntitlementChange}; may be async. */\nexport type EntitlementChangeListener = (\n change: EntitlementChange,\n) => void | Promise<void>;\n\n/** One listener that threw. */\nexport interface EntitlementChangeFailure {\n error: unknown;\n}\n\n/** What {@link notifyEntitlementChange} reports. */\nexport interface EntitlementChangeOutcome {\n change: EntitlementChange;\n /** Listeners that threw, in registration order. Empty when all succeeded. */\n failures: EntitlementChangeFailure[];\n}\n\n/** `Symbol.for()` key of the process-wide listener set. */\nexport const ENTITLEMENT_CHANGE_LISTENERS_SLOT_KEY =\n '@happyvertical/smrt-subscriptions:entitlement-change-listeners';\n\nfunction listenerSet(): Set<EntitlementChangeListener> {\n const slot = globalThis as unknown as Record<symbol, unknown>;\n const key = Symbol.for(ENTITLEMENT_CHANGE_LISTENERS_SLOT_KEY);\n let set = slot[key] as Set<EntitlementChangeListener> | undefined;\n if (!set) {\n set = new Set();\n slot[key] = set;\n }\n return set;\n}\n\n/**\n * Register a process-wide listener. Returns a function that unregisters it.\n * Registering the same function twice keeps one registration.\n */\nexport function registerEntitlementChangeListener(\n listener: EntitlementChangeListener,\n): () => void {\n const set = listenerSet();\n set.add(listener);\n return () => {\n set.delete(listener);\n };\n}\n\n/** The registered listeners, in registration order. */\nexport function getEntitlementChangeListeners(): EntitlementChangeListener[] {\n return [...listenerSet()];\n}\n\n/** An empty snapshot: no entitled subscription. */\nexport function emptyEntitlementSnapshot(): EntitlementSnapshot {\n return { planId: null, planKey: null, featureKeys: [], grants: [] };\n}\n\nfunction canonicalJson(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;\n if (value && typeof value === 'object') {\n return `{${Object.keys(value as Record<string, unknown>)\n .sort()\n .map(\n (key) =>\n `${JSON.stringify(key)}:${canonicalJson((value as Record<string, unknown>)[key])}`,\n )\n .join(',')}}`;\n }\n return JSON.stringify(value ?? null);\n}\n\n/**\n * Snapshot the tenant's entitled grants through `resolver` (no usage\n * meters are read). Missing subscription tables read as no plan, like\n * `SubscriptionFeatureSource`; every other error propagates.\n */\nexport async function snapshotEntitlements(\n resolver: Pick<SubscriptionResolver, 'resolveFeatureGrants'>,\n tenantId: string,\n options: { now?: Date } = {},\n): Promise<EntitlementSnapshot> {\n try {\n const resolved = await resolver.resolveFeatureGrants(\n { kind: 'tenant', tenantId },\n options.now ? { now: options.now } : {},\n );\n const grants = (resolved.grants ?? [])\n .filter((grant) => grant.enabled !== false)\n .sort((a, b) => a.featureKey.localeCompare(b.featureKey));\n return {\n planId: resolved.planId,\n planKey: resolved.planKey,\n featureKeys: [...new Set(resolved.featureKeys)].sort(),\n grants,\n };\n } catch (error) {\n if (isMissingSubscriptionTableError(error)) {\n return emptyEntitlementSnapshot();\n }\n throw error;\n }\n}\n\n/** Compute the {@link EntitlementChange} between two snapshots. */\nexport function diffEntitlements(\n tenantId: string,\n before: EntitlementSnapshot,\n after: EntitlementSnapshot,\n): EntitlementChange {\n const was = new Set(before.featureKeys);\n const now = new Set(after.featureKeys);\n const metadataOf = (snapshot: EntitlementSnapshot, key: string) =>\n canonicalJson(\n snapshot.grants.find((grant) => grant.featureKey === key)?.metadata ??\n null,\n );\n return {\n tenantId,\n gained: after.featureKeys.filter((key) => !was.has(key)),\n lost: before.featureKeys.filter((key) => !now.has(key)),\n changed: after.featureKeys.filter(\n (key) =>\n was.has(key) && metadataOf(before, key) !== metadataOf(after, key),\n ),\n before,\n after,\n };\n}\n\n/** True when the change gains, loses or changes at least one key. */\nexport function hasEntitlementChange(change: EntitlementChange): boolean {\n return (\n change.gained.length > 0 ||\n change.lost.length > 0 ||\n change.changed.length > 0\n );\n}\n\n/**\n * Notify `listeners` (default: the registered ones) of `change`, one after\n * another. A change with nothing gained, lost or changed notifies nobody.\n * Never throws for a listener: failures are returned.\n */\nexport async function notifyEntitlementChange(\n change: EntitlementChange,\n options: { listeners?: readonly EntitlementChangeListener[] } = {},\n): Promise<EntitlementChangeOutcome> {\n const failures: EntitlementChangeFailure[] = [];\n if (!hasEntitlementChange(change)) return { change, failures };\n for (const listener of options.listeners ?? getEntitlementChangeListeners()) {\n try {\n await listener(change);\n } catch (error) {\n failures.push({ error });\n }\n }\n return { change, failures };\n}\n\n/** Options for {@link trackEntitlementChange}. */\nexport interface TrackEntitlementChangeOptions {\n tenantId: string;\n /** Resolver used for both snapshots (build one per webhook delivery). */\n resolver: Pick<SubscriptionResolver, 'resolveFeatureGrants'>;\n /** Listeners to notify instead of the registered ones. */\n listeners?: readonly EntitlementChangeListener[];\n /** Clock for both snapshots; defaults to the current time at each. */\n now?: () => Date;\n}\n\n/**\n * Snapshot the tenant's grants, run `apply` (the webhook's subscription\n * write), snapshot again, and notify listeners of the difference. `apply`'s\n * error propagates and notifies nobody. Listener failures are returned in\n * `failures`, never thrown.\n *\n * ```ts\n * const { failures } = await trackEntitlementChange(\n * { tenantId, resolver: await SubscriptionResolver.create({ db }) },\n * () => applyStripeSubscriptionUpdate(event),\n * );\n * ```\n */\nexport async function trackEntitlementChange<T>(\n options: TrackEntitlementChangeOptions,\n apply: () => Promise<T>,\n): Promise<EntitlementChangeOutcome & { result: T }> {\n const at = () => (options.now ? { now: options.now() } : {});\n const before = await snapshotEntitlements(\n options.resolver,\n options.tenantId,\n at(),\n );\n const result = await apply();\n const after = await snapshotEntitlements(\n options.resolver,\n options.tenantId,\n at(),\n );\n const outcome = await notifyEntitlementChange(\n diffEntitlements(options.tenantId, before, after),\n options.listeners ? { listeners: options.listeners } : {},\n );\n return { ...outcome, result };\n}\n","/**\n * Hosted AI spend policy (#4760, epic #4667).\n *\n * A plan caps platform-paid (`source: hosted`) inference with ordinary\n * `PlanThreshold`s on two reserved metric keys, so the window, amount and\n * enforcement come from the plan (and its pinned version) like every other\n * threshold:\n *\n * - {@link AI_HOSTED_SPEND_METRIC}: the tenant's hosted spend per window.\n * - {@link AI_HOSTED_USER_SPEND_METRIC}: each user's hosted spend per window\n * (the per-user cap within the tenant's plan).\n *\n * `limit` is **integer micro-dollars** (1 USD = 1,000,000): the repo's\n * integer-minor-unit money rule at the precision per-call AI costs need.\n * `enforcement: 'block'` blocks at or over the cap; `'warn'` only warns;\n * `'observe'` never affects a call. `warningRatio` (default 0.8) warns\n * before the cap. A cap of 0 blocks every hosted call.\n *\n * Spend is read from `_smrt_ai_usage.estimated_cost` (USD, summed and\n * rounded to micro-dollars) for rows of the tenant in the threshold's\n * window whose `tags` record `source: hosted` (and, for the per-user cap,\n * the `userId` tag), matched as case-sensitive exact JSON fragments. Blocked rows (`operation: 'blocked'`) and\n * external-agent measurements never count. Rows without a cost rate add\n * nothing; give hosted models a cost rate.\n *\n * These keys are evaluated by {@link HostedAiSpendEvaluator} only:\n * `resolveEntitlements()` reports them with quantity 0 (the tenant usage\n * meter has no hosted or per-user meter).\n */\n\nimport { usesPostgresDialect } from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type {\n PlanThreshold,\n SmrtClassOptions,\n SubscriptionResolverOptions,\n UsageWindow,\n} from '../types.js';\nimport { getWindowForThreshold, isValidThreshold } from '../utils.js';\nimport { SubscriptionResolver } from './subscription-resolver.js';\n\n/** Plan threshold key: the tenant's hosted AI spend, micro-dollars. */\nexport const AI_HOSTED_SPEND_METRIC = 'ai.hosted.spend_micros';\n/** Plan threshold key: each user's hosted AI spend, micro-dollars. */\nexport const AI_HOSTED_USER_SPEND_METRIC = 'ai.hosted.user_spend_micros';\n\n/** Micro-dollars per US dollar. */\nexport const MICROS_PER_USD = 1_000_000;\n\n/** Length of a `rolling` threshold window (as `getWindowForThreshold`). */\nconst ROLLING_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;\n\n/** The cap a decision names: tenant or per-user. */\nexport type HostedAiSpendPolicy = 'tenant-cap' | 'user-cap';\n\n/** One evaluated hosted spend threshold. */\nexport interface HostedAiSpendEvaluation {\n policy: HostedAiSpendPolicy;\n threshold: PlanThreshold;\n /** The cap, integer micro-dollars. */\n cap: number;\n /** Metered hosted spend in the window, integer micro-dollars. */\n spend: number;\n window: UsageWindow;\n /**\n * When the cap lifts: the calendar window's end; for a blocked `rolling`\n * cap, the moment enough counted spend has left the 30-day window to bring\n * the total below the cap (null when no expiry can, e.g. a 0 cap, or the\n * cap is not blocked).\n */\n resetsAt: Date | null;\n state: 'ok' | 'warn' | 'blocked';\n}\n\n/** The most restrictive outcome over every hosted spend threshold. */\nexport interface HostedAiSpendDecision {\n state: 'ok' | 'warn' | 'blocked';\n /** False when the tenant has no current entitled subscription. */\n entitled: boolean;\n planId: string | null;\n planKey: string | null;\n /**\n * The deciding evaluation: for `blocked`, the blocking cap that lifts\n * last (the call runs again only when every blocking cap has lifted);\n * for `warn`, the warning cap closest to its limit.\n */\n decidedBy: HostedAiSpendEvaluation | null;\n evaluations: HostedAiSpendEvaluation[];\n}\n\n/** Hosted spend totals for one window. */\nexport interface HostedAiSpendSummary {\n /** Integer micro-dollars. */\n spend: number;\n}\n\n/** The scope of one spend read. */\nexport interface HostedAiSpendScope {\n tenantId: string;\n /** Only this user's rows (the `userId` tag); omitted: the whole tenant. */\n userId?: string;\n window: UsageWindow;\n}\n\n/** Reads hosted spend; the default reads `_smrt_ai_usage`. */\nexport interface HostedAiSpendReader {\n summarize(options: HostedAiSpendScope): Promise<HostedAiSpendSummary>;\n /**\n * For a rolling window: the earliest moment the counted rows, expiring\n * oldest first after `windowMs`, bring the scope's spend below `cap`;\n * null when no expiry can. Optional: without it a blocked rolling cap\n * reports no reset time.\n */\n liftsAt?(\n options: HostedAiSpendScope & { cap: number; windowMs: number },\n ): Promise<Date | null>;\n}\n\n/** A plan cap the gate cannot evaluate: the caller must fail closed. */\nexport class HostedAiSpendPolicyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HostedAiSpendPolicyError';\n }\n}\n\nfunction rows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : ((result as { rows?: Record<string, unknown>[] })?.rows ?? []);\n}\n\nfunction numberOf(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0;\n if (typeof value === 'bigint') return Number(value);\n if (typeof value === 'string') return Number.parseFloat(value) || 0;\n return 0;\n}\n\nfunction dateOf(value: unknown): Date | null {\n if (value === null || value === undefined) return null;\n const date = value instanceof Date ? value : new Date(String(value));\n return Number.isNaN(date.getTime()) ? null : date;\n}\n\n/**\n * The exact fragment one tag leaves in `_smrt_ai_usage.tags` as\n * `JSON.stringify` writes it (core's persistence handler): `\"key\":\"value\"`.\n * The value is JSON-encoded, so a quote inside it cannot end the match\n * early, and the closing quote anchors it, so `u1` never matches `u10`.\n */\nexport function hostedAiTagFragment(key: string, value: string): string {\n return `${JSON.stringify(key)}:${JSON.stringify(value)}`;\n}\n\n/**\n * A case-sensitive substring test: `LIKE` folds ASCII case on SQLite, which\n * would merge users `Alice` and `alice`.\n */\nfunction containsSql(db: DatabaseInterface): string {\n return usesPostgresDialect(db) ? 'strpos(tags, ?) > 0' : 'instr(tags, ?) > 0';\n}\n\nfunction scopeSql(\n db: DatabaseInterface,\n { tenantId, userId, window }: HostedAiSpendScope,\n): { where: string; params: unknown[] } {\n const contains = containsSql(db);\n const params: unknown[] = [\n tenantId,\n window.start.toISOString(),\n window.end.toISOString(),\n hostedAiTagFragment('source', 'hosted'),\n ];\n let where = `tenant_id = ?\n AND created_at >= ?\n AND created_at < ?\n AND operation <> 'blocked'\n AND NOT (operation = 'external-agent' AND id LIKE 'external-agent:%')\n AND ${contains}`;\n if (userId !== undefined) {\n params.push(hostedAiTagFragment('userId', userId));\n where += `\\n AND ${contains}`;\n }\n return { where, params };\n}\n\n/**\n * The default {@link HostedAiSpendReader}: one aggregate query over\n * `_smrt_ai_usage` by `tenant_id` and `created_at` (served by\n * `idx_smrt_ai_usage_tenant_created`), filtered on the `source` and\n * `userId` tag fragments (`strpos` on PostgreSQL, `instr` on SQLite and\n * DuckDB). A fragment can only over-count (a row whose tags contain it\n * elsewhere), never miss a row core wrote, so the error is always toward\n * the cap.\n */\nexport function createHostedAiSpendReader(\n db: DatabaseInterface,\n): HostedAiSpendReader {\n return {\n async summarize(scope) {\n const { where, params } = scopeSql(db, scope);\n const result = await db.query(\n `SELECT COALESCE(SUM(estimated_cost), 0) AS cost\n FROM _smrt_ai_usage\n WHERE ${where}`,\n ...params,\n );\n const row = rows(result)[0] ?? {};\n return { spend: Math.round(numberOf(row.cost) * MICROS_PER_USD) };\n },\n async liftsAt({ cap, windowMs, ...scope }) {\n // Nothing lifts a 0 cap: spend can never drop below it.\n if (cap <= 0) return null;\n const { where, params } = scopeSql(db, scope);\n // Rows expire oldest first, so the cap lifts when the newest row whose\n // newest-first running total reaches the cap leaves the window. The\n // running total is the raw USD sum, compared with the same rounding\n // `summarize()` applies (Math.round(x) >= cap <=> x >= cap - 0.5); the\n // database computes it, so only that one row is returned.\n const result = await db.query(\n `SELECT created_at\n FROM (\n SELECT created_at, id,\n SUM(estimated_cost) OVER (\n ORDER BY created_at DESC, id DESC\n ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n ) AS running\n FROM _smrt_ai_usage\n WHERE ${where}\n AND estimated_cost IS NOT NULL\n ) counted\n WHERE running * ${MICROS_PER_USD} >= ?\n ORDER BY created_at DESC, id DESC\n LIMIT 1`,\n ...params,\n cap - 0.5,\n );\n const at = dateOf(rows(result)[0]?.created_at);\n return at ? new Date(at.getTime() + windowMs) : null;\n },\n };\n}\n\nfunction policyFor(threshold: PlanThreshold): HostedAiSpendPolicy | null {\n if (threshold.metricKey === AI_HOSTED_SPEND_METRIC) return 'tenant-cap';\n if (threshold.metricKey === AI_HOSTED_USER_SPEND_METRIC) return 'user-cap';\n return null;\n}\n\n/**\n * The hosted spend thresholds of a plan. A hosted key whose threshold is\n * malformed (unknown window or enforcement, or a limit that is not a\n * non-negative safe integer of micro-dollars) throws\n * {@link HostedAiSpendPolicyError}: a broken cap must never read as \"no cap\".\n */\nexport function hostedAiSpendThresholds(\n thresholds: readonly PlanThreshold[],\n): Array<{ policy: HostedAiSpendPolicy; threshold: PlanThreshold }> {\n const result: Array<{\n policy: HostedAiSpendPolicy;\n threshold: PlanThreshold;\n }> = [];\n for (const threshold of thresholds) {\n const policy = policyFor(threshold);\n if (!policy) continue;\n if (\n !isValidThreshold(threshold) ||\n !Number.isSafeInteger(threshold.limit)\n ) {\n throw new HostedAiSpendPolicyError(\n `Plan threshold ${threshold.metricKey} is not a valid hosted AI cap (limit must be a non-negative integer of micro-dollars).`,\n );\n }\n result.push({ policy, threshold });\n }\n return result;\n}\n\n/** Evaluate one cap against its metered spend. */\nexport function evaluateHostedAiSpendThreshold(\n policy: HostedAiSpendPolicy,\n threshold: PlanThreshold,\n summary: HostedAiSpendSummary,\n window: UsageWindow,\n): HostedAiSpendEvaluation {\n const cap = threshold.limit;\n const spend = summary.spend;\n const over = spend >= cap;\n const warningRatio = threshold.warningRatio ?? 0.8;\n const nearing = cap === 0 ? over : spend >= cap * warningRatio;\n let state: HostedAiSpendEvaluation['state'] = 'ok';\n if (threshold.enforcement === 'block' && over) state = 'blocked';\n else if (threshold.enforcement !== 'observe' && nearing) state = 'warn';\n // A rolling cap's reset is computed from the rows by the evaluator, and\n // only when it blocks (`HostedAiSpendReader.liftsAt`).\n const resetsAt = threshold.window === 'rolling' ? null : window.end;\n return { policy, threshold, cap, spend, window, resetsAt, state };\n}\n\nfunction laterReset(\n a: HostedAiSpendEvaluation,\n b: HostedAiSpendEvaluation,\n): HostedAiSpendEvaluation {\n // An unknown reset (null) sorts last: it lifts no earlier than any other.\n if (!a.resetsAt) return a;\n if (!b.resetsAt) return b;\n return b.resetsAt.getTime() > a.resetsAt.getTime() ? b : a;\n}\n\nfunction closerToCap(\n a: HostedAiSpendEvaluation,\n b: HostedAiSpendEvaluation,\n): HostedAiSpendEvaluation {\n const ratio = (e: HostedAiSpendEvaluation) =>\n e.cap === 0 ? Number.POSITIVE_INFINITY : e.spend / e.cap;\n return ratio(b) > ratio(a) ? b : a;\n}\n\n/** Fold evaluations into the most restrictive decision. */\nexport function decideHostedAiSpend(\n evaluations: HostedAiSpendEvaluation[],\n plan: { entitled: boolean; planId: string | null; planKey: string | null },\n): HostedAiSpendDecision {\n const blocked = evaluations.filter((e) => e.state === 'blocked');\n const warned = evaluations.filter((e) => e.state === 'warn');\n const decidedBy =\n blocked.length > 0\n ? blocked.reduce(laterReset)\n : warned.length > 0\n ? warned.reduce(closerToCap)\n : null;\n return {\n state: blocked.length > 0 ? 'blocked' : warned.length > 0 ? 'warn' : 'ok',\n entitled: plan.entitled,\n planId: plan.planId,\n planKey: plan.planKey,\n decidedBy,\n evaluations,\n };\n}\n\n/** Options for {@link HostedAiSpendEvaluator}. */\nexport interface HostedAiSpendEvaluatorOptions {\n resolver: Pick<SubscriptionResolver, 'resolvePlanThresholds'>;\n spend: HostedAiSpendReader;\n /**\n * How long a tenant's plan thresholds are reused, in ms (default 30 000):\n * entitlements resolve once per request burst, while spend is always read\n * fresh. 0 disables the memo.\n */\n termsTtlMs?: number;\n now?: () => Date;\n}\n\ntype PlanThresholds = Awaited<\n ReturnType<SubscriptionResolver['resolvePlanThresholds']>\n>;\n\n/**\n * Evaluates a tenant's (and one user's) hosted AI spend against the plan's\n * caps. Plan thresholds come from `SubscriptionResolver` (memoized per\n * tenant for `termsTtlMs`); spend is read on every call. Errors (a resolver\n * or database outage, missing tables, a malformed cap) propagate: the gate\n * turns them into a fail-closed block.\n */\nexport class HostedAiSpendEvaluator {\n private readonly terms = new Map<\n string,\n { at: number; value: Promise<PlanThresholds> }\n >();\n private readonly termsTtlMs: number;\n private readonly now: () => Date;\n\n constructor(private readonly options: HostedAiSpendEvaluatorOptions) {\n this.termsTtlMs = options.termsTtlMs ?? 30_000;\n this.now = options.now ?? (() => new Date());\n }\n\n /** Build the default resolver and `_smrt_ai_usage` reader over one db. */\n static async create(\n classOptions: SmrtClassOptions & { db: DatabaseInterface },\n options: Omit<HostedAiSpendEvaluatorOptions, 'resolver' | 'spend'> = {},\n ): Promise<HostedAiSpendEvaluator> {\n return new HostedAiSpendEvaluator({\n ...options,\n resolver: await SubscriptionResolver.create(classOptions),\n spend: createHostedAiSpendReader(classOptions.db),\n });\n }\n\n /** Drop memoized plan thresholds (all tenants, or one). */\n invalidate(tenantId?: string): void {\n if (tenantId === undefined) this.terms.clear();\n else this.terms.delete(tenantId);\n }\n\n private planThresholds(\n tenantId: string,\n resolverOptions: SubscriptionResolverOptions,\n ): Promise<PlanThresholds> {\n const at = Date.now();\n const cached = this.terms.get(tenantId);\n if (cached && this.termsTtlMs > 0 && at - cached.at < this.termsTtlMs) {\n return cached.value;\n }\n const value = this.options.resolver.resolvePlanThresholds(\n { kind: 'tenant', tenantId },\n resolverOptions,\n );\n if (this.termsTtlMs > 0) {\n this.terms.set(tenantId, { at, value });\n value.catch(() => {\n if (this.terms.get(tenantId)?.value === value) {\n this.terms.delete(tenantId);\n }\n });\n }\n return value;\n }\n\n /**\n * Evaluate the plan's hosted caps for `tenantId` and, when given, the\n * per-user caps for `userId`. Without a `userId` the per-user caps are\n * skipped (no user to meter: jobs, shared agent clients).\n */\n async evaluate(input: {\n tenantId: string;\n userId?: string;\n resolverOptions?: SubscriptionResolverOptions;\n }): Promise<HostedAiSpendDecision> {\n const now = this.now();\n const plan = await this.planThresholds(input.tenantId, {\n ...(input.resolverOptions ?? {}),\n now,\n });\n const caps = hostedAiSpendThresholds(plan.thresholds).filter(\n ({ policy }) => policy === 'tenant-cap' || input.userId !== undefined,\n );\n const evaluations = await Promise.all(\n caps.map(async ({ policy, threshold }) => {\n const window = getWindowForThreshold(threshold.window, now);\n const scope = {\n tenantId: input.tenantId,\n ...(policy === 'user-cap' ? { userId: input.userId } : {}),\n window,\n };\n const summary = await this.options.spend.summarize(scope);\n const evaluation = evaluateHostedAiSpendThreshold(\n policy,\n threshold,\n summary,\n window,\n );\n if (\n evaluation.state === 'blocked' &&\n threshold.window === 'rolling' &&\n this.options.spend.liftsAt\n ) {\n evaluation.resetsAt = await this.options.spend.liftsAt({\n ...scope,\n cap: evaluation.cap,\n windowMs: ROLLING_WINDOW_MS,\n });\n }\n return evaluation;\n }),\n );\n return decideHostedAiSpend(evaluations, plan);\n }\n}\n","/**\n * Reseller price books and parent-delegated spending (#3059).\n *\n * Billing ownership comes from the released smrt-tenancy\n * `BillingRelationshipService`; this service never re-derives it. Rating lives\n * on `CommercialUsageService.rateUsage()`, enforcement on\n * `SpendingPolicyEvaluator` — this service manages the records they read.\n */\nimport {\n isEmbeddedDatabase,\n isPostgresDatabase,\n type SmrtClassOptions,\n withEmbeddedWriteTransaction,\n} from '@happyvertical/smrt-core';\nimport {\n type BillingRelationshipView,\n getTenantId,\n isSuperAdminBypass,\n isSystemContext,\n TenantIsolationError,\n withSystemContext,\n} from '@happyvertical/smrt-tenancy';\nimport {\n BillingAdjustmentCollection,\n ClientChargeCollection,\n type PricingRule,\n PricingRuleCollection,\n type PricingStrategy,\n type SpendingBasis,\n type SpendingPeriod,\n type SpendingPolicy,\n type SpendingPolicyBehavior,\n SpendingPolicyCollection,\n} from '../models/commercial.js';\nimport {\n type CreditGrant,\n CreditGrantCollection,\n isCurrencyCode,\n type PriceBook,\n type PriceBookAssignment,\n PriceBookAssignmentCollection,\n PriceBookCollection,\n type PriceBookKind,\n RetailChargeCollection,\n} from '../models/reseller.js';\nimport type { SubscriberKind } from '../types.js';\nimport { deterministicUuid, tenantKey } from '../utils.js';\nimport {\n assertWholesalePublisher,\n type BillingRelationshipReader,\n SpendingPolicyEvaluator,\n} from './commercial.js';\nimport { ResellerBillingError } from './reseller-errors.js';\n\nexport type ResellerBillingAction =\n | 'define_prices'\n | 'assign_wholesale_price_book'\n | 'assign_retail_price_book'\n | 'manage_child_spending';\n\nexport interface ResellerBillingServiceOptions extends SmrtClassOptions {\n /** The released smrt-tenancy billing relationship reader. */\n billingRelationships: BillingRelationshipReader;\n /**\n * Optional host permission check. Without it, only a system context or a\n * super-admin bypass may mutate reseller billing records, mirroring\n * `BillingRelationshipService`. Once it (or the context) authorizes a call,\n * the service performs that call's writes in a system context, because\n * they span tenants (a parent writes rows owned by its child).\n */\n authorize?: (request: {\n action: ResellerBillingAction;\n /**\n * The tenant whose authority the action exercises: the book's seller for\n * `define_prices` and `assign_wholesale_price_book`, the parent for\n * `assign_retail_price_book` and `manage_child_spending`.\n */\n tenantId: string;\n childTenantId?: string;\n /**\n * For price-book assignments and child spending: the child's current\n * reseller, which pays the wholesale leg. A host must confirm the caller\n * holds `tenantId`'s authority and, for `assign_wholesale_price_book`,\n * that the publisher is a legitimate provider for this reseller — the\n * package can refuse only a payer-published book.\n */\n resellerTenantId?: string;\n }) => Promise<boolean>;\n}\n\nexport interface DefinePriceBookPriceInput {\n priceBookId: string;\n ruleKey: string;\n metricKey: string;\n serviceKey?: string;\n strategy: PricingStrategy;\n effectiveFrom?: Date;\n effectiveTo?: Date | null;\n priority?: number;\n /**\n * One entry per currency. Terms use the same *minor units per unit of usage*\n * convention as any `PricingRule` (#2401).\n */\n prices: Array<{ currency: string; terms: Record<string, unknown> }>;\n}\n\nexport interface PriceBookLeg {\n priceBookId: string;\n /** Currency the leg is charged in; the book needs a price in it. */\n currency: string;\n}\n\nexport interface AssignPriceBooksInput {\n childTenantId: string;\n /** `undefined` keeps the current leg; `null` clears it. */\n wholesale?: PriceBookLeg | null;\n retail?: PriceBookLeg | null;\n}\n\nexport interface PriceBookAssignmentView {\n childTenantId: string;\n resellerTenantId: string;\n wholesale: PriceBookLeg | null;\n retail: PriceBookLeg | null;\n}\n\nexport interface DelegatedSpendingPolicyInput {\n parentTenantId: string;\n childTenantId: string;\n name: string;\n basis: SpendingBasis;\n currency: string;\n behavior: SpendingPolicyBehavior;\n period?: SpendingPeriod;\n rollingSeconds?: number;\n /** Integer minor units; must be 0 (the default) for a `balance` policy. */\n limitAmount?: number;\n metricKey?: string;\n serviceKey?: string;\n projectId?: string;\n subscriberKind?: SubscriberKind | '';\n subscriberExternalId?: string;\n priority?: number;\n active?: boolean;\n balanceFrom?: Date;\n}\n\nexport interface GrantChildCreditInput {\n parentTenantId: string;\n childTenantId: string;\n spendingPolicyId: string;\n /** Signed, nonzero integer minor units of the policy currency. */\n amount: number;\n reason?: string;\n source?: string;\n sourceId?: string;\n}\n\nconst UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nfunction canonicalTenantId(id: string): string {\n if (typeof id !== 'string' || !UUID_PATTERN.test(id)) {\n throw new ResellerBillingError(\n 'Tenant IDs must be UUIDs.',\n 'INVALID_TENANT',\n );\n }\n return id.toLowerCase();\n}\n\nfunction assertCurrency(currency: string): void {\n if (!isCurrencyCode(currency)) {\n throw new ResellerBillingError(\n `Currency '${currency}' must be a three-letter upper-case code.`,\n 'INVALID_CURRENCY',\n );\n }\n}\n\nfunction legView(\n priceBookId: string | null | undefined,\n currency: string,\n): PriceBookLeg | null {\n return priceBookId ? { priceBookId: String(priceBookId), currency } : null;\n}\n\nfunction assignmentView(row: PriceBookAssignment): PriceBookAssignmentView {\n return {\n childTenantId: tenantKey(row.childTenantId),\n resellerTenantId: tenantKey(row.resellerTenantId),\n wholesale: legView(row.wholesalePriceBookId, row.wholesaleCurrency),\n retail: legView(row.retailPriceBookId, row.retailCurrency),\n };\n}\n\n/**\n * Run an already-authorized operation in a system context. Only called after\n * `assertManage()` (or for a book metadata read that precedes it).\n */\nfunction authorized<T>(operation: () => Promise<T>): Promise<T> {\n return withSystemContext(operation);\n}\n\n/**\n * Manages price books, their per-relationship assignment, and the spending\n * policies and credits a parent tenant sets on its children.\n */\nexport class ResellerBillingService {\n private constructor(\n private readonly options: ResellerBillingServiceOptions,\n private readonly books: PriceBookCollection,\n private readonly assignments: PriceBookAssignmentCollection,\n private readonly rules: PricingRuleCollection,\n private readonly policies: SpendingPolicyCollection,\n private readonly evaluator: SpendingPolicyEvaluator,\n ) {}\n\n static async create(\n options: ResellerBillingServiceOptions,\n ): Promise<ResellerBillingService> {\n if (typeof options.billingRelationships?.getRelationship !== 'function') {\n throw new Error(\n 'Reseller billing requires a billingRelationships reader from smrt-tenancy.',\n );\n }\n const {\n billingRelationships: _reader,\n authorize: _authorize,\n ...rest\n } = options;\n const books = await PriceBookCollection.create(rest);\n const shared = { ...rest, db: books.db };\n const policies = await SpendingPolicyCollection.create(shared);\n const evaluator = new SpendingPolicyEvaluator(\n policies,\n await ClientChargeCollection.create(shared),\n await BillingAdjustmentCollection.create(shared),\n {\n retailCharges: await RetailChargeCollection.create(shared),\n credits: await CreditGrantCollection.create(shared),\n },\n );\n return new ResellerBillingService(\n options,\n books,\n await PriceBookAssignmentCollection.create(shared),\n await PricingRuleCollection.create(shared),\n policies,\n evaluator,\n );\n }\n\n /**\n * Publish one price in a book, in one or more currencies. Each currency is\n * a `PricingRule` owned by the book's seller; re-defining the same rule key,\n * currency, and effective date replaces that rule's terms.\n */\n async definePrice(input: DefinePriceBookPriceInput): Promise<PricingRule[]> {\n const book = await this.readBook(input.priceBookId);\n const sellerTenantId = canonicalTenantId(String(book.tenantId));\n await this.assertManage('define_prices', sellerTenantId, undefined, true);\n if (!input.ruleKey.trim() || !input.metricKey.trim()) {\n throw new Error('Price book prices require a ruleKey and metricKey.');\n }\n if (input.prices.length === 0) {\n throw new ResellerBillingError(\n 'A price needs at least one currency.',\n 'INVALID_CURRENCY',\n );\n }\n const currencies = new Set<string>();\n for (const { currency } of input.prices) {\n assertCurrency(currency);\n if (currencies.has(currency)) {\n throw new ResellerBillingError(\n `Currency ${currency} is listed twice for one price.`,\n 'INVALID_CURRENCY',\n );\n }\n currencies.add(currency);\n }\n const effectiveFrom = input.effectiveFrom ?? new Date();\n return authorized(async () => {\n const saved: PricingRule[] = [];\n for (const { currency, terms } of input.prices) {\n const id = await deterministicUuid([\n 'price-book-rule',\n String(book.id),\n input.ruleKey,\n input.metricKey,\n input.serviceKey ?? '',\n currency,\n effectiveFrom.toISOString(),\n ]);\n const values = {\n tenantId: book.tenantId,\n priceBookId: String(book.id),\n ruleKey: input.ruleKey,\n metricKey: input.metricKey,\n serviceKey: input.serviceKey ?? '',\n strategy: input.strategy,\n currency,\n effectiveFrom,\n effectiveTo: input.effectiveTo ?? null,\n priority: input.priority ?? 0,\n terms: JSON.stringify(terms),\n active: true,\n };\n const existing = await this.rules.get(id);\n if (existing) {\n Object.assign(existing, values);\n await existing.save();\n saved.push(existing);\n } else {\n saved.push(await this.rules.create({ id, ...values }));\n }\n }\n return saved;\n });\n }\n\n /**\n * Select the wholesale and/or retail book that rates a child's usage under\n * its current reseller relationship. The retail book must be published by\n * that reseller; the wholesale book must be published by someone other\n * than the reseller or child it charges. Each leg is authorized separately:\n * the wholesale leg by its publisher (`assign_wholesale_price_book`), the\n * retail leg by the reseller (`assign_retail_price_book`).\n */\n async assignPriceBooks(\n input: AssignPriceBooksInput,\n ): Promise<PriceBookAssignmentView> {\n const relationship = await this.requireRelationship(input.childTenantId);\n const { childTenantId, resellerTenantId } = relationship;\n const existing = await authorized(() =>\n this.assignments.get({ childTenantId }),\n );\n // An assignment made under a previous reseller does not carry over.\n const current =\n existing && tenantKey(existing.resellerTenantId) === resellerTenantId\n ? assignmentView(existing)\n : null;\n\n if (input.wholesale !== undefined) {\n let publisher = resellerTenantId;\n if (input.wholesale) {\n const book = await this.requireLeg(input.wholesale, 'wholesale');\n assertWholesalePublisher(book, resellerTenantId, childTenantId);\n publisher = tenantKey(book.tenantId);\n } else if (current?.wholesale) {\n publisher = tenantKey(\n (await this.readBook(current.wholesale.priceBookId)).tenantId,\n );\n }\n await this.assertManage(\n 'assign_wholesale_price_book',\n publisher,\n childTenantId,\n false,\n resellerTenantId,\n );\n }\n if (input.retail) {\n const book = await this.requireLeg(input.retail, 'retail');\n if (tenantKey(book.tenantId) !== resellerTenantId) {\n throw new ResellerBillingError(\n `Retail price book '${book.bookKey}' is not published by the child's reseller.`,\n 'PRICE_BOOK_OWNER_MISMATCH',\n );\n }\n }\n if (input.retail !== undefined || input.wholesale === undefined) {\n await this.assertManage(\n 'assign_retail_price_book',\n resellerTenantId,\n childTenantId,\n false,\n resellerTenantId,\n );\n }\n\n // Read-merge-write under one lock so concurrent single-leg updates\n // cannot overwrite each other's leg.\n const db = this.assignments.db;\n return authorized(() =>\n withEmbeddedWriteTransaction(\n db,\n isEmbeddedDatabase(db),\n async (transaction) => {\n if (isPostgresDatabase(transaction)) {\n await transaction.query(\n \"SELECT pg_advisory_xact_lock(hashtext('smrt-price-book-assignments'))\",\n );\n }\n const assignments = await PriceBookAssignmentCollection.create({\n db: transaction,\n });\n const row = await assignments.get({ childTenantId });\n const fresh =\n row && tenantKey(row.resellerTenantId) === resellerTenantId\n ? assignmentView(row)\n : null;\n if (\n input.wholesale === null &&\n fresh?.wholesale?.priceBookId !== current?.wholesale?.priceBookId\n ) {\n // The clear was authorized against a different wholesale book.\n throw new ResellerBillingError(\n 'The wholesale assignment changed concurrently; retry.',\n 'ASSIGNMENT_CONFLICT',\n );\n }\n const wholesale =\n input.wholesale === undefined\n ? (fresh?.wholesale ?? null)\n : input.wholesale;\n const retail =\n input.retail === undefined ? (fresh?.retail ?? null) : input.retail;\n const values = {\n childTenantId,\n resellerTenantId,\n wholesalePriceBookId: wholesale?.priceBookId ?? '',\n wholesaleCurrency: wholesale?.currency ?? '',\n retailPriceBookId: retail?.priceBookId ?? '',\n retailCurrency: retail?.currency ?? '',\n };\n if (row) {\n Object.assign(row, values);\n await row.save();\n return assignmentView(row);\n }\n return assignmentView(await assignments.create(values));\n },\n ),\n );\n }\n\n /** The child's assignment under its current reseller, if any. */\n async getPriceBookAssignment(\n childTenantId: string,\n ): Promise<PriceBookAssignmentView | null> {\n const relationship =\n await this.options.billingRelationships.getRelationship(\n canonicalTenantId(childTenantId),\n );\n if (!relationship) return null;\n const row = await this.assignments.get({\n childTenantId: relationship.childTenantId,\n });\n if (\n !row ||\n tenantKey(row.resellerTenantId) !== relationship.resellerTenantId\n ) {\n return null;\n }\n return assignmentView(row);\n }\n\n /**\n * Create or replace a spending policy that a parent sets on its child. The\n * row belongs to the child (so the ordinary evaluator enforces it for the\n * child) and records the parent in `setByTenantId`, which locks it against\n * changes by the child. A delegated limit left by a former parent may be\n * replaced (not a former parent's prepaid balance, which keeps its credit\n * ledger); one the child set for itself may not. Use `period: 'balance'`\n * for a prepaid credit balance and fund it with {@link grantChildCredit}.\n */\n async setDelegatedSpendingPolicy(\n input: DelegatedSpendingPolicyInput,\n ): Promise<SpendingPolicy> {\n const parentTenantId = canonicalTenantId(input.parentTenantId);\n const relationship = await this.requireChildOf(\n input.childTenantId,\n parentTenantId,\n );\n await this.assertManage(\n 'manage_child_spending',\n parentTenantId,\n relationship.childTenantId,\n false,\n relationship.resellerTenantId,\n );\n assertCurrency(input.currency);\n if (\n input.limitAmount !== undefined &&\n !Number.isSafeInteger(input.limitAmount)\n ) {\n throw new ResellerBillingError(\n `Spending limits must be integer minor units — got ${input.limitAmount}.`,\n 'INVALID_AMOUNT',\n );\n }\n const values = {\n tenantId: relationship.childTenantId,\n name: input.name,\n subscriberKind: input.subscriberKind ?? '',\n subscriberExternalId: input.subscriberExternalId ?? '',\n projectId: input.projectId ?? '',\n serviceKey: input.serviceKey ?? '',\n metricKey: input.metricKey ?? '',\n period: input.period ?? 'month',\n rollingSeconds: input.rollingSeconds ?? 0,\n limitAmount: input.limitAmount ?? 0,\n currency: input.currency,\n behavior: input.behavior,\n priority: input.priority ?? 0,\n active: input.active ?? true,\n basis: input.basis,\n setByTenantId: parentTenantId,\n ...(input.balanceFrom ? { balanceFrom: input.balanceFrom } : {}),\n };\n // Authorized above; the row belongs to the child, so write it outside\n // the parent's own tenant scope.\n return authorized(async () => {\n const existing = (\n await this.policies.list({\n where: {\n tenantId: values.tenantId,\n subscriberKind: values.subscriberKind,\n subscriberExternalId: values.subscriberExternalId,\n projectId: values.projectId,\n serviceKey: values.serviceKey,\n metricKey: values.metricKey,\n period: values.period,\n name: values.name,\n },\n limit: 1,\n })\n )[0];\n if (existing) {\n const owner = tenantKey(existing.setByTenantId);\n if (!owner) {\n throw new ResellerBillingError(\n `Spending policy '${input.name}' already exists for this child and was set by the child.`,\n 'POLICY_CONFLICT',\n );\n }\n // A former parent's prepaid balance keeps its credit ledger: taking\n // it over would strand that credit (or revive it if the child\n // returns), so the new parent must use a different name.\n if (owner !== parentTenantId && existing.period === 'balance') {\n throw new ResellerBillingError(\n `Balance policy '${input.name}' belongs to a former parent; choose another name.`,\n 'POLICY_CONFLICT',\n );\n }\n Object.assign(existing, values);\n await existing.save();\n return existing;\n }\n return this.policies.create(values);\n });\n }\n\n /** Credit a prepaid balance policy the parent set on its child. */\n async grantChildCredit(input: GrantChildCreditInput): Promise<CreditGrant> {\n const parentTenantId = canonicalTenantId(input.parentTenantId);\n const relationship = await this.requireChildOf(\n input.childTenantId,\n parentTenantId,\n );\n await this.assertManage(\n 'manage_child_spending',\n parentTenantId,\n relationship.childTenantId,\n false,\n relationship.resellerTenantId,\n );\n return authorized(async () => {\n const policy = await this.policies.get(input.spendingPolicyId);\n if (\n !policy ||\n tenantKey(policy.tenantId) !== relationship.childTenantId ||\n tenantKey(policy.setByTenantId) !== parentTenantId\n ) {\n throw new ResellerBillingError(\n `Spending policy ${input.spendingPolicyId} is not a policy this parent set on the child.`,\n 'POLICY_NOT_FOUND',\n );\n }\n return this.evaluator.grantCredit({\n spendingPolicyId: input.spendingPolicyId,\n amount: input.amount,\n reason: input.reason,\n source: input.source,\n sourceId: input.sourceId,\n grantedByTenantId: parentTenantId,\n });\n });\n }\n\n private async requireRelationship(\n childTenantId: string,\n ): Promise<BillingRelationshipView> {\n const relationship =\n await this.options.billingRelationships.getRelationship(\n canonicalTenantId(childTenantId),\n );\n if (!relationship) {\n throw new ResellerBillingError(\n `Tenant ${childTenantId} has no reseller relationship.`,\n 'RELATIONSHIP_REQUIRED',\n );\n }\n return relationship;\n }\n\n private async requireChildOf(\n childTenantId: string,\n parentTenantId: string,\n ): Promise<BillingRelationshipView> {\n const relationship = await this.requireRelationship(childTenantId);\n if (relationship.resellerTenantId !== parentTenantId) {\n throw new ResellerBillingError(\n `Tenant ${childTenantId} is not a child of ${parentTenantId}.`,\n 'RELATIONSHIP_REQUIRED',\n );\n }\n return relationship;\n }\n\n /**\n * Read a book's metadata to learn its publisher and kind before deciding\n * authorization. Books belong to their seller, so the read is not scoped to\n * the caller; nothing beyond a validation error is returned on denial.\n */\n private async readBook(id: string): Promise<PriceBook> {\n const book = await authorized(() => this.books.get(id));\n if (!book?.id) {\n throw new ResellerBillingError(\n `Price book ${id} was not found.`,\n 'PRICE_BOOK_NOT_FOUND',\n );\n }\n return book;\n }\n\n private async requireLeg(\n leg: PriceBookLeg,\n kind: PriceBookKind,\n ): Promise<PriceBook> {\n assertCurrency(leg.currency);\n const book = await this.readBook(leg.priceBookId);\n if (book.kind !== kind) {\n throw new ResellerBillingError(\n `Price book '${book.bookKey}' is a ${book.kind} book, not ${kind}.`,\n 'PRICE_BOOK_KIND_MISMATCH',\n );\n }\n return book;\n }\n\n private async assertManage(\n action: ResellerBillingAction,\n tenantId: string,\n childTenantId?: string,\n allowOwnTenant = false,\n resellerTenantId?: string,\n ): Promise<void> {\n if (\n isSystemContext() ||\n isSuperAdminBypass() ||\n (allowOwnTenant && getTenantId()?.toLowerCase() === tenantId) ||\n (await this.options.authorize?.({\n action,\n tenantId,\n childTenantId,\n ...(resellerTenantId ? { resellerTenantId } : {}),\n }))\n ) {\n return;\n }\n throw new TenantIsolationError('Reseller billing mutation denied.');\n }\n}\n","import { StepUpRequiredError } from '@happyvertical/smrt-users/step-up';\n\nexport { StepUpRequiredError };\n\n/** Stable machine code of {@link NotOwnerError}. */\nexport const NOT_OWNER_CODE = 'not_owner';\n\n/**\n * The caller is not the owner of the tenant that holds the account: a member,\n * a device-only or layered session, no session, or another tenant's account.\n * One message and code for all of them, so nothing about the account or the\n * tenant leaks.\n */\nexport class NotOwnerError extends Error {\n readonly code = NOT_OWNER_CODE;\n\n constructor(message = 'Only the account owner may do this.') {\n super(message);\n this.name = 'NotOwnerError';\n }\n}\n\n/** A refusal after both checks passed (the relay or directory said no). */\nexport class VaultAccountAdminError extends Error {\n readonly code: string;\n\n constructor(code: string, message = 'The vault account action failed.') {\n super(message);\n this.name = 'VaultAccountAdminError';\n this.code = code;\n }\n}\n","/**\n * Hosted vault-account admin actions (#4841): replace (supersede), un-replace\n * and provision the replacement of a family's vault account.\n *\n * The relay's admin token can silence or redirect any account, and the local\n * restart calls cannot tell the owner from someone holding an unlocked\n * device, so this layer is the only gate on a takeover of the backup line.\n * Each action therefore, in order:\n *\n * 1. requires the caller to be the tenant OWNER on a first-class session\n * (`not_owner` otherwise: a member, a device-only session, no session, or\n * an account of another tenant),\n * 2. requires a step-up: the owner proved a password or passkey on the\n * hosted account within `stepUpMaxAgeSeconds` (`step_up_required`),\n * 3. records `authorized` in the audit sink, and only then\n * 4. calls the relay, exactly once, and records the outcome.\n *\n * A refusal is audited (`denied`, with the reason code) and throws; the relay\n * is never called. Nothing here reads a request, a cookie or a secret.\n */\nimport {\n DEFAULT_STEP_UP_MAX_AGE_SECONDS,\n isTenantOwnerSession,\n requireRecentAuthentication,\n type StepUpSession,\n} from '@happyvertical/smrt-users/step-up';\nimport {\n NotOwnerError,\n StepUpRequiredError,\n VaultAccountAdminError,\n} from './errors.js';\nimport type {\n ProvisionRestartAccountInput,\n ProvisionRestartAccountResult,\n SupersedeVaultAccountInput,\n UnsupersedeVaultAccountInput,\n VaultAccountAction,\n VaultAccountAdminDeps,\n VaultAccountAuditEntry,\n} from './types.js';\n\n/** The relay's account and device id grammar. */\nconst IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;\n\ntype Subject = Pick<\n VaultAccountAuditEntry,\n 'oldAccountId' | 'newAccountId' | 'deviceId'\n>;\n\nfunction errorCode(error: unknown): string {\n if (error && typeof error === 'object') {\n const code = (error as { code?: unknown }).code;\n if (typeof code === 'string' && /^[\\w.:-]{1,64}$/.test(code)) return code;\n const name = (error as { name?: unknown }).name;\n if (typeof name === 'string') return name.slice(0, 64);\n }\n return 'unknown';\n}\n\nclass Gate {\n private readonly now: () => Date;\n\n constructor(\n private readonly deps: VaultAccountAdminDeps,\n private readonly action: VaultAccountAction,\n private readonly session: StepUpSession | null | undefined,\n private readonly subject: Subject,\n ) {\n this.now = deps.now ?? (() => new Date());\n }\n\n private entry(\n outcome: VaultAccountAuditEntry['outcome'],\n extra: Partial<VaultAccountAuditEntry> = {},\n ): VaultAccountAuditEntry {\n const entry: VaultAccountAuditEntry = {\n at: this.now().toISOString(),\n action: this.action,\n outcome,\n actorUserId: this.session?.user?.id ?? null,\n tenantId: this.session?.tenantId ?? null,\n ...extra,\n };\n for (const [key, value] of Object.entries(this.subject)) {\n if (typeof value === 'string') {\n (entry as unknown as Record<string, unknown>)[key] = value;\n }\n }\n return entry;\n }\n\n private async deny(\n error: NotOwnerError | StepUpRequiredError,\n ): Promise<never> {\n // A broken sink never turns a refusal into anything else.\n await this.recordQuietly(this.entry('denied', { denial: error.code }));\n throw error;\n }\n\n /**\n * Run both checks, then the audit-before-act record. Throws\n * {@link NotOwnerError} or {@link StepUpRequiredError}; resolves with the\n * verified tenant id.\n */\n async authorize(\n accounts: readonly string[],\n validate?: (tenantId: string) => void | Promise<void>,\n ): Promise<string> {\n const session = this.session;\n const isOwner = this.deps.isOwner ?? isTenantOwnerSession;\n let owner = false;\n try {\n owner = Boolean(session && isOwner(session));\n } catch {\n owner = false;\n }\n if (!session || !owner || !session.tenantId || !session.user?.id) {\n return this.deny(new NotOwnerError());\n }\n const tenantId = session.tenantId;\n const userId = session.user.id;\n\n // The accounts must be this tenant's: an owner of one tenant never moves\n // another's. Unknown and foreign accounts are refused alike.\n for (const accountId of accounts) {\n let owningTenant: string | null = null;\n if (IDENTIFIER.test(accountId)) {\n try {\n owningTenant = await this.deps.directory.tenantForAccount(accountId);\n } catch {\n owningTenant = null;\n }\n }\n if (owningTenant !== tenantId) return this.deny(new NotOwnerError());\n }\n\n try {\n requireRecentAuthentication(session, {\n maxAgeSeconds:\n this.deps.stepUpMaxAgeSeconds ?? DEFAULT_STEP_UP_MAX_AGE_SECONDS,\n now: this.now,\n expectedSessionId: session.sessionId,\n expectedUserId: userId,\n });\n } catch {\n return this.deny(new StepUpRequiredError());\n }\n\n // Malformed input from an authorized caller: refused, not audited as\n // authorized, and still before any relay call.\n try {\n await validate?.(tenantId);\n } catch (error) {\n // A foreign account named by the caller is a denied attempt: audited.\n if (error instanceof NotOwnerError) return this.deny(error);\n throw error;\n }\n\n // Audit before acting: if the record cannot be written, nothing happens.\n try {\n await this.deps.audit.record(this.entry('authorized'));\n } catch {\n throw new VaultAccountAdminError(\n 'audit_unavailable',\n 'The action could not be recorded, so it was not performed.',\n );\n }\n return tenantId;\n }\n\n /** Record the relay call's outcome; a sink failure never undoes the call. */\n async finish(\n outcome: 'succeeded' | 'failed',\n extra: Partial<VaultAccountAuditEntry> = {},\n ): Promise<void> {\n await this.recordQuietly(this.entry(outcome, extra));\n }\n\n private async recordQuietly(entry: VaultAccountAuditEntry): Promise<void> {\n try {\n await this.deps.audit.record(entry);\n } catch {\n // Observability only: never changes what the caller is told or does.\n }\n }\n\n /** Run the single relay call and audit its outcome. */\n async perform<T extends string | boolean>(\n call: () => Promise<T>,\n update: Partial<VaultAccountAuditEntry> = {},\n ): Promise<T> {\n let result: T;\n try {\n result = await call();\n } catch (error) {\n await this.finish('failed', { ...update, errorCode: errorCode(error) });\n throw error;\n }\n await this.finish('succeeded', { ...update, result: String(result) });\n return result;\n }\n}\n\nfunction invalid(field: string): VaultAccountAdminError {\n return new VaultAccountAdminError(\n 'invalid_request',\n `Invalid request: ${field}.`,\n );\n}\n\n/**\n * Replace `oldAccount` by `newAccount` (relay admin `PUT\n * .../superseded-by`). The new account must already hold an active device\n * (see {@link provisionRestartAccount}); the relay enforces that, and no\n * chains or loops. Idempotent for the same target.\n */\nexport async function supersedeVaultAccount(\n input: SupersedeVaultAccountInput,\n): Promise<'superseded' | 'unchanged'> {\n const { oldAccount, newAccount } = input;\n const gate = new Gate(input, 'supersede', input.session, {\n oldAccountId: oldAccount,\n newAccountId: newAccount,\n });\n await gate.authorize([oldAccount, newAccount], () => {\n if (oldAccount === newAccount) throw invalid('newAccount');\n });\n return gate.perform(() =>\n input.relay.supersedeAccount(oldAccount, newAccount),\n );\n}\n\n/**\n * Undo a supersession (relay admin `DELETE .../superseded-by`), for an\n * operator mistake or a restart that never reached the working device. Returns\n * false when `oldAccount` was not superseded.\n */\nexport async function unsupersedeVaultAccount(\n input: UnsupersedeVaultAccountInput,\n): Promise<boolean> {\n const { oldAccount } = input;\n const gate = new Gate(input, 'unsupersede', input.session, {\n oldAccountId: oldAccount,\n });\n await gate.authorize([oldAccount]);\n return gate.perform(() => input.relay.clearSupersession(oldAccount));\n}\n\n/**\n * Step 1 of the restart flow (app-runtime README, \"Restarting when the\n * recovery secret is lost\"), before the supersede: allocate a fresh vault\n * account id, link it to the caller's tenant (so `backup.vault` resolves for\n * it), and register the working device's relay signing key in it (relay admin\n * `PUT .../devices/:device`). The id is minted per call, so a retry after a\n * crash makes another empty account unless `newAccountId` is pinned.\n */\nexport async function provisionRestartAccount(\n input: ProvisionRestartAccountInput,\n): Promise<ProvisionRestartAccountResult> {\n const { oldAccount, deviceId, devicePublicKey } = input;\n const subject: Subject = { oldAccountId: oldAccount, deviceId };\n const gate = new Gate(\n input,\n 'provision_restart_account',\n input.session,\n subject,\n );\n let accountId = '';\n const tenantId = await gate.authorize([oldAccount], async (tenantId) => {\n if (!IDENTIFIER.test(deviceId)) throw invalid('deviceId');\n if (typeof devicePublicKey !== 'string' || !devicePublicKey) {\n throw invalid('devicePublicKey');\n }\n accountId = await (input.newAccountId ?? (() => crypto.randomUUID()))();\n if (!IDENTIFIER.test(accountId) || accountId === oldAccount) {\n throw invalid('newAccountId');\n }\n subject.newAccountId = accountId;\n // A pinned or retried id must not name another tenant's account: linking\n // it and registering a device key there would take over that backup line.\n let owningTenant: string | null;\n try {\n owningTenant = await input.directory.tenantForAccount(accountId);\n } catch {\n owningTenant = null;\n }\n if (owningTenant !== null && owningTenant !== tenantId) {\n throw new NotOwnerError();\n }\n });\n const device = await gate.perform(async () => {\n await input.directory.linkAccount(tenantId, accountId);\n const registered = await input.relay.registerDevice(\n accountId,\n deviceId,\n devicePublicKey,\n );\n if (registered === 'conflict') {\n throw new VaultAccountAdminError('device_conflict');\n }\n return registered;\n });\n return { accountId, deviceId, device };\n}\n","/**\n * {@link VaultRelayAdminPort} over the relay's admin HTTP API (private\n * listener, bearer token): `PUT /admin/v1/accounts/:account/devices/:device`,\n * `PUT` and `DELETE /admin/v1/accounts/:account/superseded-by`. The token is\n * sent as a header and never appears in an error, a message or a log.\n */\nimport { VaultAccountAdminError } from './errors.js';\nimport type { VaultRelayAdminPort } from './types.js';\n\nexport interface VaultRelayAdminClientOptions {\n /** Admin listener origin, e.g. `http://vault-relay-admin:8081`. */\n baseUrl: string;\n /** `VAULT_RELAY_ADMIN_TOKEN`. */\n adminToken: string;\n fetch?: typeof fetch;\n}\n\nconst SEGMENT = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;\n\nfunction segment(value: string): string {\n if (!SEGMENT.test(value)) {\n throw new VaultAccountAdminError('invalid_request');\n }\n return value;\n}\n\nexport function createVaultRelayAdminClient(\n options: VaultRelayAdminClientOptions,\n): VaultRelayAdminPort {\n if (!options.adminToken || options.adminToken.length < 32) {\n throw new Error('vault relay admin client: the admin token is required');\n }\n const base = new URL(options.baseUrl);\n const token = options.adminToken;\n const doFetch = options.fetch ?? fetch;\n\n async function call(\n method: 'PUT' | 'DELETE',\n path: string,\n body?: Record<string, string>,\n ): Promise<{ status: number; code: string | null }> {\n const response = await doFetch(new URL(path, base), {\n method,\n redirect: 'error',\n headers: {\n authorization: `Bearer ${token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n ...(body ? { body: JSON.stringify(body) } : {}),\n });\n let code: string | null = null;\n if (response.status >= 400) {\n try {\n const parsed = (await response.json()) as { error?: unknown };\n if (\n typeof parsed.error === 'string' &&\n /^\\w{1,64}$/.test(parsed.error)\n ) {\n code = parsed.error;\n }\n } catch {\n code = null;\n }\n }\n return { status: response.status, code };\n }\n\n const fail = (status: number, code: string | null): never => {\n throw new VaultAccountAdminError(\n code ?? `relay_${status}`,\n `The vault relay refused the request (${status}).`,\n );\n };\n\n return {\n async registerDevice(accountId, deviceId, publicKey) {\n const { status, code } = await call(\n 'PUT',\n `/admin/v1/accounts/${segment(accountId)}/devices/${segment(deviceId)}`,\n { publicKey },\n );\n if (status === 201) return 'registered';\n if (status === 200) return 'unchanged';\n if (status === 409) return 'conflict';\n return fail(status, code);\n },\n async supersedeAccount(accountId, supersededBy) {\n const { status, code } = await call(\n 'PUT',\n `/admin/v1/accounts/${segment(accountId)}/superseded-by`,\n { supersededBy: segment(supersededBy) },\n );\n if (status === 201) return 'superseded';\n if (status === 200) return 'unchanged';\n return fail(status, code);\n },\n async clearSupersession(accountId) {\n const { status, code } = await call(\n 'DELETE',\n `/admin/v1/accounts/${segment(accountId)}/superseded-by`,\n );\n if (status === 204) return true;\n if (status === 404 && code === 'no_supersession') return false;\n return fail(status, code);\n },\n };\n}\n"],"mappings":"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"}