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';
|
||||
|
||||
/**
|
||||
* ADR 0004 — env vars Stripe. Tutte opzionali: se mancano, i flussi di
|
||||
* billing rispondono 503 (come abbiamo fatto per VAPID in ADR 0003).
|
||||
* Questo permette al PO di sviluppare features non-billing senza dover
|
||||
* configurare Stripe localmente.
|
||||
* ADR 0004 — env vars Stripe. Tutte opzionali: se mancano (o sono stringhe
|
||||
* vuote), i flussi di billing rispondono 503 (come per VAPID in ADR 0003).
|
||||
* Questo permette al PO di sviluppare/deployare features non-billing senza
|
||||
* 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({
|
||||
STRIPE_SECRET_KEY: z.string().min(1).optional(),
|
||||
STRIPE_WEBHOOK_SECRET: z.string().min(1).optional(),
|
||||
STRIPE_PRICE_ID_MONTHLY: z.string().min(1).optional(),
|
||||
STRIPE_PRICE_ID_YEARLY: z.string().min(1).optional(),
|
||||
STRIPE_SECRET_KEY: emptyAsUndefined,
|
||||
STRIPE_WEBHOOK_SECRET: emptyAsUndefined,
|
||||
STRIPE_PRICE_ID_MONTHLY: emptyAsUndefined,
|
||||
STRIPE_PRICE_ID_YEARLY: emptyAsUndefined,
|
||||
// URL di base usato per le redirect post-checkout. Deve coincidere col
|
||||
// dominio del frontend (apps/web).
|
||||
BILLING_RETURN_URL: z.string().url().optional(),
|
||||
// dominio del frontend (apps/web). Non valida l'URL se è stringa vuota.
|
||||
BILLING_RETURN_URL: emptyAsUndefined.pipe(z.string().url().optional()),
|
||||
});
|
||||
|
||||
export type BillingEnv = z.infer<typeof billingEnvSchema>;
|
||||
|
||||
Reference in new issue
Block a user