fix(entitlements): trial seeding grants every paid capability, not the launch four (#1698)

seed_trial_capability_grants() still hardcoded ai/bank_sync/skatteverket/
email_send while PAID_CAPABILITIES grew to seven keys. Payers got all seven
via the Stripe webhook; every company created since 2026-07-12 was trialing
without stripe_payments (and later woocommerce_sync/shopify_sync). Redefine
the trigger with the full set, backfill existing trial grants by mirroring
bank_sync, and pin the pg test to PAID_CAPABILITIES so the lists cannot
drift again.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-19 11:09:10 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent 43cde6deb9
commit b07a4a4bca
3 changed files with 67 additions and 2 deletions
@@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest'
import { randomUUID } from 'node:crypto'
import { getPool, withUserContext } from '../../../tests/pg/setup'
import { seedCompany, insertAuthUser, insertCompany } from '../../../tests/pg/fixtures'
import { PAID_CAPABILITIES } from '../keys'
// pg-real coverage for migrations 20260628140000 (capability_grants /
// company_capability_config / metered_events + company_has_capability RPC +
@@ -186,7 +187,7 @@ describe('capability_grants scope constraint', () => {
})
})
describe('trial grant seeding trigger (20260629120000)', () => {
describe('trial grant seeding trigger (20260629120000, widened 20260818170000)', () => {
it('grants a new company a 30-day trial on the PAID keys at creation', async () => {
const userId = await insertAuthUser()
const companyId = await insertCompany({ createdBy: userId })
@@ -199,7 +200,10 @@ describe('trial grant seeding trigger (20260629120000)', () => {
WHERE company_id = $1 ORDER BY capability_key`,
[companyId],
)
expect(rows.map((r) => r.capability_key)).toEqual(['ai', 'bank_sync', 'email_send', 'skatteverket'])
// Every PAID key, compared against the constant itself so the trigger's
// hardcoded list (20260629120000, widened 20260818170000) can never drift
// from PAID_CAPABILITIES again without this test failing.
expect(rows.map((r) => r.capability_key)).toEqual([...PAID_CAPABILITIES].sort())
expect(rows.every((r) => r.source === 'trial')).toBe(true)
expect(rows.every((r) => r.expires_at !== null)).toBe(true)
expect(await rpc(companyId, 'ai')).toBe(true)