test(config): cover production validation
This commit is contained in:
parent
772b4bfc19
commit
8007fac947
137
backend/src/lib/config.test.ts
Normal file
137
backend/src/lib/config.test.ts
Normal file
@ -0,0 +1,137 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { DEFAULT_DEV_JWT_SECRET, envSchema, parseConfig } from './config.js';
|
||||
|
||||
const SAFE_PROD_ENV = {
|
||||
NODE_ENV: 'production',
|
||||
JWT_SECRET: 'prod-secret-at-least-32-characters',
|
||||
DB_PROVIDER: 'cosmos',
|
||||
COSMOS_ENDPOINT: 'https://cosmos.example.com',
|
||||
COSMOS_KEY: 'cosmos-key',
|
||||
COSMOS_DATABASE: 'bytelyst',
|
||||
FIELD_ENCRYPT_ENABLED: 'true',
|
||||
FIELD_ENCRYPT_KEY_PROVIDER: 'env',
|
||||
FIELD_ENCRYPT_KEY: 'field-key-material',
|
||||
} satisfies Record<string, string>;
|
||||
|
||||
function expectConfigIssue(env: Record<string, string | undefined>, path: string, message: string): void {
|
||||
const result = envSchema.safeParse(env);
|
||||
expect(result.success).toBe(false);
|
||||
if (result.success) return;
|
||||
|
||||
expect(result.error.issues).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
path: [path],
|
||||
message,
|
||||
}),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
describe('backend config', () => {
|
||||
it('keeps development ergonomics for local memory mode and empty JWT env values', () => {
|
||||
const config = parseConfig({
|
||||
NODE_ENV: 'development',
|
||||
JWT_SECRET: '',
|
||||
DB_PROVIDER: 'memory',
|
||||
FIELD_ENCRYPT_KEY_PROVIDER: 'memory',
|
||||
TELEMETRY_ENABLED: 'false',
|
||||
FEATURE_FLAGS_ENABLED: '0',
|
||||
});
|
||||
|
||||
expect(config.JWT_SECRET).toBe(DEFAULT_DEV_JWT_SECRET);
|
||||
expect(config.DB_PROVIDER).toBe('memory');
|
||||
expect(config.TELEMETRY_ENABLED).toBe(false);
|
||||
expect(config.FEATURE_FLAGS_ENABLED).toBe(false);
|
||||
});
|
||||
|
||||
it('accepts a safe production configuration', () => {
|
||||
const config = parseConfig(SAFE_PROD_ENV);
|
||||
|
||||
expect(config.NODE_ENV).toBe('production');
|
||||
expect(config.DB_PROVIDER).toBe('cosmos');
|
||||
expect(config.FIELD_ENCRYPT_ENABLED).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects missing production JWT secret because it would fall back to the dev default', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, JWT_SECRET: undefined },
|
||||
'JWT_SECRET',
|
||||
'Production JWT_SECRET must not use the development default'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects the development JWT secret in production', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, JWT_SECRET: DEFAULT_DEV_JWT_SECRET },
|
||||
'JWT_SECRET',
|
||||
'Production JWT_SECRET must not use the development default'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects short production JWT secrets', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, JWT_SECRET: 'short-prod-secret' },
|
||||
'JWT_SECRET',
|
||||
'Production JWT_SECRET must be at least 32 characters'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects memory DB in production', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, DB_PROVIDER: 'memory' },
|
||||
'DB_PROVIDER',
|
||||
'Production DB_PROVIDER must be cosmos'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects missing production Cosmos credentials', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, COSMOS_ENDPOINT: '', COSMOS_KEY: '', COSMOS_DATABASE: '' },
|
||||
'COSMOS_ENDPOINT',
|
||||
'COSMOS_ENDPOINT is required in production'
|
||||
);
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, COSMOS_ENDPOINT: '', COSMOS_KEY: '', COSMOS_DATABASE: '' },
|
||||
'COSMOS_KEY',
|
||||
'COSMOS_KEY is required in production'
|
||||
);
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, COSMOS_ENDPOINT: '', COSMOS_KEY: '', COSMOS_DATABASE: '' },
|
||||
'COSMOS_DATABASE',
|
||||
'COSMOS_DATABASE is required in production'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects disabled field encryption in production', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, FIELD_ENCRYPT_ENABLED: 'false' },
|
||||
'FIELD_ENCRYPT_ENABLED',
|
||||
'Field encryption must be enabled in production'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects production memory encryption provider', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, FIELD_ENCRYPT_KEY_PROVIDER: 'memory', FIELD_ENCRYPT_KEY: '' },
|
||||
'FIELD_ENCRYPT_KEY_PROVIDER',
|
||||
'Production FIELD_ENCRYPT_KEY_PROVIDER must be akv or env'
|
||||
);
|
||||
});
|
||||
|
||||
it('requires key material when FIELD_ENCRYPT_KEY_PROVIDER=env', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, FIELD_ENCRYPT_KEY_PROVIDER: 'env', FIELD_ENCRYPT_KEY: '' },
|
||||
'FIELD_ENCRYPT_KEY',
|
||||
'FIELD_ENCRYPT_KEY is required when FIELD_ENCRYPT_KEY_PROVIDER=env'
|
||||
);
|
||||
});
|
||||
|
||||
it('requires a Key Vault URL when FIELD_ENCRYPT_KEY_PROVIDER=akv', () => {
|
||||
expectConfigIssue(
|
||||
{ ...SAFE_PROD_ENV, FIELD_ENCRYPT_KEY_PROVIDER: 'akv', FIELD_ENCRYPT_KEY: '', AZURE_KEYVAULT_URL: '' },
|
||||
'AZURE_KEYVAULT_URL',
|
||||
'AZURE_KEYVAULT_URL is required when FIELD_ENCRYPT_KEY_PROVIDER=akv'
|
||||
);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user