Skip to content

[INFRA] Type-Safe Config Module with Zod Validation #11

Description

@oomokaro1

[INFRA] Type-Safe Config Module with Zod Validation

Priority: Medium

Difficulty: Medium
Estimated Effort: 1-2 days
Relevant Packages: OrbitStream_backend/
Labels: infrastructure, enhancement, priority:medium

Requirements

1. Zod Validation Schema

Create a comprehensive config schema using zod:

// src/config/config.schema.ts
import { z } from 'zod';

export const configSchema = z.object({
  NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
  PORT: z.coerce.number().int().positive().default(3001),

  DATABASE_URL: z.string().url({ message: 'DATABASE_URL must be a valid PostgreSQL URL' }),
  REDIS_URL: z.string().url({ message: 'REDIS_URL must be a valid Redis URL' }),

  JWT_SECRET: z.string().min(32, { message: 'JWT_SECRET must be at least 32 characters' }),
  JWT_EXPIRES_IN: z.string().default('7d'),

  STELLAR_NETWORK: z.enum(['testnet', 'mainnet']),
  STELLAR_HORIZON_URL: z.string().url(),
  STELLAR_NETWORK_PASSPHRASE: z.string().min(1),

  PLATFORM_RECEIVING_ACCOUNT: z.string().startsWith('G', { message: 'Must be a valid Stellar public key' }),

  FRONTEND_URL: z.string().url().default('http://localhost:3000'),
  CHECKOUT_SESSION_TTL_MINUTES: z.coerce.number().int().positive().default(30),
  CHALLENGE_TTL_SECONDS: z.coerce.number().int().positive().default(300),

  CORS_ALLOWED_ORIGINS: z.string().transform(s => s.split(',').map(o => o.trim())),
  REDIS_CURSOR_TTL_HOURS: z.coerce.number().int().positive().default(24),
});

export type Config = z.infer<typeof configSchema>;

2. Config Module

  • Create src/config/config.module.ts using @nestjs/config
  • Load and validate config on app bootstrap
  • If validation fails, crash with a clear error message showing which vars are invalid
  • Export a typed ConfigService that provides config.DATABASE_URL, config.JWT_SECRET, etc.

3. Environment-Specific Behavior

  • NODE_ENV=production: crash if any var uses a default value (all must be explicitly set)
  • NODE_ENV=development: allow defaults, log warnings for missing vars
  • Support .env.local overrides (loaded after .env)

4. Secrets Manager Support (Optional)

  • Support reading secrets from AWS SSM Parameter Store or HashiCorp Vault
  • If SECRETS_MANAGER env var is set, read JWT_SECRET and DATABASE_URL from the secrets manager instead of env vars
  • Keep env var as fallback for local development

5. Config Check Script

  • Add npm run config:check script that validates config without starting the app
  • Useful for CI/CD pipelines and Docker health checks

6. Update All Config Reads

  • Replace all process.env.X reads with config.X from the ConfigService
  • Update all services to inject ConfigService instead of reading env directly

7. Update .env.example

  • Add ALL required env vars with comments
  • Mark which are required vs optional
  • Add examples for each

8. Testing

  • Unit test: valid config passes validation
  • Unit test: missing required var fails with clear error
  • Unit test: invalid value (short JWT_SECRET) fails with clear error
  • Unit test: defaults applied correctly in development mode
  • Unit test: production mode rejects defaults

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions