feat(api): retire prices safely and add a self-serve switch (#2637)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-10 17:28:16 +02:00
1 parent d79cd99050
commit 4a93b677af
77 files changed
+9242 -2542

No files matched your search

+1
View File
@@ -221,6 +221,7 @@ function defaultConfig(): MasterConfig {
secret_key: '',
webhook_secret: '',
prices: {},
legacy_prices: {},
},
ncmec: {
enabled: false,
+1
View File
@@ -268,6 +268,7 @@ export interface MasterConfig {
secret_key: string;
webhook_secret: string;
prices?: Record<string, string | undefined>;
legacy_prices?: Record<string, Array<string> | undefined>;
};
ncmec: {
enabled: boolean;
@@ -155,4 +155,85 @@ describe('buildNamedFluxerEnvOverrides', () => {
'FLUXER_LIVEKIT_DEFAULT_REGION must be valid JSON',
);
});
test('parses the legacy Stripe price map onto integrations.stripe.legacy_prices', () => {
const overrides = buildNamedFluxerEnvOverrides({
FLUXER_STRIPE_LEGACY_PRICES:
'{"monthly_brl":["price_old_monthly_brl","price_older_monthly_brl"],"yearly_brl":["price_old_yearly_brl"],"monthly_try":["price_archived_monthly_try"],"gift_1_month_brl":["price_old_gift_1_month_brl"],"gift_1_year_brl":["price_old_gift_1_year_brl"]}',
});
expect(overrides).toMatchObject({
integrations: {
stripe: {
legacy_prices: {
monthly_brl: ['price_old_monthly_brl', 'price_older_monthly_brl'],
yearly_brl: ['price_old_yearly_brl'],
monthly_try: ['price_archived_monthly_try'],
gift_1_month_brl: ['price_old_gift_1_month_brl'],
gift_1_year_brl: ['price_old_gift_1_year_brl'],
},
},
},
});
});
test('the legacy Stripe price map does not disturb the live price map', () => {
const overrides = buildNamedFluxerEnvOverrides({
FLUXER_STRIPE_PRICES: '{"monthly_brl":"price_new_monthly_brl"}',
FLUXER_STRIPE_LEGACY_PRICES: '{"monthly_brl":["price_old_monthly_brl"]}',
});
const stripe = (overrides.integrations as {stripe: Record<string, unknown>}).stripe;
expect(stripe.prices).toEqual({monthly_brl: 'price_new_monthly_brl'});
expect(stripe.legacy_prices).toEqual({monthly_brl: ['price_old_monthly_brl']});
});
test('rejects malformed JSON for the legacy Stripe price map', () => {
expect(() => buildNamedFluxerEnvOverrides({FLUXER_STRIPE_LEGACY_PRICES: '{"monthly_brl":['})).toThrow(
'FLUXER_STRIPE_LEGACY_PRICES must be valid JSON',
);
});
test('an individual Stripe price env var wins over the blob, and the blob keys it does not name survive', () => {
// The deploy runbook flips one slot at a time with FLUXER_STRIPE_PRICE_* while the blob stays
// pinned to the previous release. The individual variable is declared after the blob, so it is
// merged into the blob rather than replaced by it.
const overrides = buildNamedFluxerEnvOverrides({
FLUXER_STRIPE_PRICES:
'{"monthly_brl":"price_blob_monthly_brl","yearly_brl":"price_blob_yearly_brl","monthly_usd":"price_blob_monthly_usd"}',
FLUXER_STRIPE_PRICE_MONTHLY_BRL: 'price_individual_monthly_brl',
});
expect((overrides.integrations as {stripe: {prices: unknown}}).stripe.prices).toEqual({
monthly_brl: 'price_individual_monthly_brl',
yearly_brl: 'price_blob_yearly_brl',
monthly_usd: 'price_blob_monthly_usd',
});
});
test('several individual Stripe price env vars merge into the blob together', () => {
const overrides = buildNamedFluxerEnvOverrides({
FLUXER_STRIPE_PRICES: '{"monthly_brl":"price_blob_monthly_brl","yearly_brl":"price_blob_yearly_brl"}',
FLUXER_STRIPE_PRICE_MONTHLY_BRL: 'price_individual_monthly_brl',
FLUXER_STRIPE_PRICE_YEARLY_BRL: 'price_individual_yearly_brl',
FLUXER_STRIPE_PRICE_MONTHLY_EUR: 'price_individual_monthly_eur',
});
expect((overrides.integrations as {stripe: {prices: unknown}}).stripe.prices).toEqual({
monthly_brl: 'price_individual_monthly_brl',
yearly_brl: 'price_individual_yearly_brl',
monthly_eur: 'price_individual_monthly_eur',
});
});
test('the Stripe price blob applies on its own when no individual price var is set', () => {
const overrides = buildNamedFluxerEnvOverrides({
FLUXER_STRIPE_PRICES: '{"monthly_brl":"price_blob_monthly_brl","yearly_brl":"price_blob_yearly_brl"}',
});
expect((overrides.integrations as {stripe: {prices: unknown}}).stripe.prices).toEqual({
monthly_brl: 'price_blob_monthly_brl',
yearly_brl: 'price_blob_yearly_brl',
});
});
});
@@ -297,6 +297,7 @@ const NAMED_FLUXER_ENV_OVERRIDES: Record<string, NamedEnvOverride> = {
FLUXER_STRIPE_SECRET_KEY: {path: ['integrations', 'stripe', 'secret_key']},
FLUXER_STRIPE_WEBHOOK_SECRET: {path: ['integrations', 'stripe', 'webhook_secret']},
FLUXER_STRIPE_PRICES: {path: ['integrations', 'stripe', 'prices'], parse: parseEnvValue},
FLUXER_STRIPE_LEGACY_PRICES: {path: ['integrations', 'stripe', 'legacy_prices'], parse: parseEnvValue},
FLUXER_STRIPE_PRICE_MONTHLY_USD: {path: ['integrations', 'stripe', 'prices', 'monthly_usd']},
FLUXER_STRIPE_PRICE_MONTHLY_EUR: {path: ['integrations', 'stripe', 'prices', 'monthly_eur']},
FLUXER_STRIPE_PRICE_MONTHLY_BRL: {path: ['integrations', 'stripe', 'prices', 'monthly_brl']},