fix(billing): tratta env vars vuote come unset (soft-degradation)
Le `STRIPE_*` env vars in ADR 0004 sono opzionali — quando il provider non è ancora configurato l'app deve continuare a funzionare. Lo schema Zod però usava `.string().min(1).optional()` che fallisce con stringhe vuote: `STRIPE_SECRET_KEY=` in un .env diventa `process.env.STRIPE_SECRET_KEY = ''`, presente ma length=0, quindi rifiutato. Aggiunto `emptyAsUndefined` che traduce stringhe vuote → `undefined`. Il check di `isBillingConfigured()` rimane invariato (accetta solo valori non-empty). Sblocca il boot del backend con env Stripe vuote in produzione. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e76074869b
commit
6a5559fa0a
1 file changed
+18
-10
@@ -1,19 +1,27 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ADR 0004 — env vars Stripe. Tutte opzionali: se mancano, i flussi di
|
* ADR 0004 — env vars Stripe. Tutte opzionali: se mancano (o sono stringhe
|
||||||
* billing rispondono 503 (come abbiamo fatto per VAPID in ADR 0003).
|
* vuote), i flussi di billing rispondono 503 (come per VAPID in ADR 0003).
|
||||||
* Questo permette al PO di sviluppare features non-billing senza dover
|
* Questo permette al PO di sviluppare/deployare features non-billing senza
|
||||||
* configurare Stripe localmente.
|
* configurare Stripe.
|
||||||
|
*
|
||||||
|
* `emptyAsUndefined`: una env file scritta come `STRIPE_SECRET_KEY=` viene
|
||||||
|
* letta da Node come stringa vuota; la trattiamo equivalente a `undefined`.
|
||||||
*/
|
*/
|
||||||
|
const emptyAsUndefined = z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.transform((value) => (value && value.length > 0 ? value : undefined));
|
||||||
|
|
||||||
const billingEnvSchema = z.object({
|
const billingEnvSchema = z.object({
|
||||||
STRIPE_SECRET_KEY: z.string().min(1).optional(),
|
STRIPE_SECRET_KEY: emptyAsUndefined,
|
||||||
STRIPE_WEBHOOK_SECRET: z.string().min(1).optional(),
|
STRIPE_WEBHOOK_SECRET: emptyAsUndefined,
|
||||||
STRIPE_PRICE_ID_MONTHLY: z.string().min(1).optional(),
|
STRIPE_PRICE_ID_MONTHLY: emptyAsUndefined,
|
||||||
STRIPE_PRICE_ID_YEARLY: z.string().min(1).optional(),
|
STRIPE_PRICE_ID_YEARLY: emptyAsUndefined,
|
||||||
// URL di base usato per le redirect post-checkout. Deve coincidere col
|
// URL di base usato per le redirect post-checkout. Deve coincidere col
|
||||||
// dominio del frontend (apps/web).
|
// dominio del frontend (apps/web). Non valida l'URL se è stringa vuota.
|
||||||
BILLING_RETURN_URL: z.string().url().optional(),
|
BILLING_RETURN_URL: emptyAsUndefined.pipe(z.string().url().optional()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type BillingEnv = z.infer<typeof billingEnvSchema>;
|
export type BillingEnv = z.infer<typeof billingEnvSchema>;
|
||||||
|
|||||||
Reference in new issue
Block a user