diff --git a/veza-backend-api/internal/config/config.go b/veza-backend-api/internal/config/config.go index b63f5444a..482d6e351 100644 --- a/veza-backend-api/internal/config/config.go +++ b/veza-backend-api/internal/config/config.go @@ -147,6 +147,11 @@ type Config struct { StripeConnectWebhookSecret string // STRIPE_CONNECT_WEBHOOK_SECRET PlatformFeeRate float64 // PLATFORM_FEE_RATE (default 0.10 = 10% commission) + // Transfer Retry Worker (v0.701) + TransferRetryEnabled bool // TRANSFER_RETRY_ENABLED (default true) + TransferRetryMaxAttempts int // TRANSFER_RETRY_MAX (default 3) + TransferRetryInterval time.Duration // TRANSFER_RETRY_INTERVAL (default 5m) + // Email & Jobs EmailSender *email.SMTPEmailSender JobWorker *workers.JobWorker @@ -364,6 +369,11 @@ func NewConfig() (*Config, error) { StripeConnectWebhookSecret: getEnv("STRIPE_CONNECT_WEBHOOK_SECRET", ""), PlatformFeeRate: getEnvFloat64("PLATFORM_FEE_RATE", 0.10), + // Transfer Retry Worker (v0.701) + TransferRetryEnabled: getEnvBool("TRANSFER_RETRY_ENABLED", true), + TransferRetryMaxAttempts: getEnvInt("TRANSFER_RETRY_MAX", 3), + TransferRetryInterval: getEnvDuration("TRANSFER_RETRY_INTERVAL", 5*time.Minute), + // Log Files Configuration // En développement, utiliser ./logs si /var/log n'est pas accessible LogDir: func() string { @@ -912,6 +922,23 @@ func (c *Config) Validate() error { return fmt.Errorf("RATE_LIMIT_WINDOW validation failed: %w", err) } + // v0.701: Validate PlatformFeeRate range + if c.PlatformFeeRate < 0 || c.PlatformFeeRate > 1 { + return fmt.Errorf("PLATFORM_FEE_RATE must be between 0 and 1, got %f", c.PlatformFeeRate) + } + + // v0.701: Validate Stripe Connect config coherence + if c.StripeConnectEnabled && c.StripeConnectSecretKey == "" { + if c.Env == EnvProduction { + return errors.New("STRIPE_CONNECT_ENABLED=true but STRIPE_SECRET_KEY is empty") + } + } + + // v0.701: Validate transfer retry config + if c.TransferRetryEnabled && c.TransferRetryMaxAttempts < 1 { + return errors.New("TRANSFER_RETRY_MAX must be >= 1 when retry is enabled") + } + // Audit 1.7: Fail startup if bypass flags are set in production if err := validateNoBypassFlagsInProduction(c.Env); err != nil { return err