import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
import { ConfigManager } from '../../src/config/config';
// Mock logger to avoid console noise during tests
jest.mock('../../src/utils/logger');
describe('ConfigManager - Guardrails Config', () => {
let originalEnv: NodeJS.ProcessEnv;
beforeEach(() => {
originalEnv = { ...process.env };
// Clear guardrails env vars
Object.keys(process.env).forEach((key) => {
if (key.startsWith('GUARDRAILS_')) delete process.env[key];
});
// Ensure at least one provider exists
process.env.OPENAI_API_KEY = 'test-key';
});
afterEach(() => {
process.env = originalEnv;
});
describe('basic guardrails config', () => {
it('should not have guardrails by default', () => {
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails).toBeUndefined();
});
it('should enable guardrails when GUARDRAILS_ENABLED=true', () => {
process.env.GUARDRAILS_ENABLED = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.enabled).toBe(true);
});
it('should disable guardrails when GUARDRAILS_ENABLED=false', () => {
process.env.GUARDRAILS_ENABLED = 'false';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails).toBeUndefined();
});
it('should set log_violations from environment', () => {
process.env.GUARDRAILS_ENABLED = 'true';
process.env.GUARDRAILS_LOG_VIOLATIONS = 'false';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.log_violations).toBe(false);
});
it('should set log_modifications from environment', () => {
process.env.GUARDRAILS_ENABLED = 'true';
process.env.GUARDRAILS_LOG_MODIFICATIONS = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.log_modifications).toBe(true);
});
it('should set fail_open from environment', () => {
process.env.GUARDRAILS_ENABLED = 'true';
process.env.GUARDRAILS_FAIL_OPEN = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.fail_open).toBe(true);
});
});
describe('rate limiter config', () => {
it('should configure rate limiter from environment', () => {
process.env.GUARDRAILS_RATE_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_RATE_LIMITER_REQUESTS_PER_MINUTE = '30';
process.env.GUARDRAILS_RATE_LIMITER_REQUESTS_PER_HOUR = '500';
const configManager = new ConfigManager();
const config = configManager.getConfig();
expect(config.guardrails?.enabled).toBe(true);
expect(config.guardrails?.plugins?.rate_limiter?.enabled).toBe(true);
expect(config.guardrails?.plugins?.rate_limiter?.requests_per_minute).toBe(30);
expect(config.guardrails?.plugins?.rate_limiter?.requests_per_hour).toBe(500);
});
it('should configure per_provider setting', () => {
process.env.GUARDRAILS_RATE_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_RATE_LIMITER_PER_PROVIDER = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.rate_limiter?.per_provider).toBe(true);
});
it('should configure burst_allowance setting', () => {
process.env.GUARDRAILS_RATE_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_RATE_LIMITER_BURST_ALLOWANCE = '10';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.rate_limiter?.burst_allowance).toBe(10);
});
});
describe('token limiter config', () => {
it('should configure token limiter from environment', () => {
process.env.GUARDRAILS_TOKEN_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_TOKEN_LIMITER_MAX_INPUT_TOKENS = '4096';
const configManager = new ConfigManager();
const config = configManager.getConfig();
expect(config.guardrails?.enabled).toBe(true);
expect(config.guardrails?.plugins?.token_limiter?.enabled).toBe(true);
expect(config.guardrails?.plugins?.token_limiter?.max_input_tokens).toBe(4096);
});
it('should configure max_output_tokens setting', () => {
process.env.GUARDRAILS_TOKEN_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_TOKEN_LIMITER_MAX_OUTPUT_TOKENS = '2048';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.token_limiter?.max_output_tokens).toBe(2048);
});
it('should configure warn_at_percentage setting', () => {
process.env.GUARDRAILS_TOKEN_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_TOKEN_LIMITER_WARN_AT_PERCENTAGE = '90';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.token_limiter?.warn_at_percentage).toBe(90);
});
});
describe('pattern blocker config', () => {
it('should configure pattern blocker from environment', () => {
process.env.GUARDRAILS_PATTERN_BLOCKER_ENABLED = 'true';
process.env.GUARDRAILS_PATTERN_BLOCKER_PATTERNS = 'password,secret,api_key';
const configManager = new ConfigManager();
const config = configManager.getConfig();
expect(config.guardrails?.enabled).toBe(true);
expect(config.guardrails?.plugins?.pattern_blocker?.enabled).toBe(true);
expect(config.guardrails?.plugins?.pattern_blocker?.blocked_patterns).toEqual([
'password',
'secret',
'api_key',
]);
});
it('should configure regex patterns', () => {
process.env.GUARDRAILS_PATTERN_BLOCKER_ENABLED = 'true';
process.env.GUARDRAILS_PATTERN_BLOCKER_PATTERNS_REGEX = 'pass.*word,secret\\d+';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pattern_blocker?.blocked_patterns_regex).toEqual([
'pass.*word',
'secret\\d+',
]);
});
it('should configure case_sensitive setting', () => {
process.env.GUARDRAILS_PATTERN_BLOCKER_ENABLED = 'true';
process.env.GUARDRAILS_PATTERN_BLOCKER_CASE_SENSITIVE = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pattern_blocker?.case_sensitive).toBe(true);
});
it('should configure action_on_match setting', () => {
process.env.GUARDRAILS_PATTERN_BLOCKER_ENABLED = 'true';
process.env.GUARDRAILS_PATTERN_BLOCKER_ACTION = 'redact';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pattern_blocker?.action_on_match).toBe('redact');
});
});
describe('PII redactor config', () => {
it('should configure PII redactor from environment', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
const configManager = new ConfigManager();
const config = configManager.getConfig();
expect(config.guardrails?.enabled).toBe(true);
expect(config.guardrails?.plugins?.pii_redactor?.enabled).toBe(true);
});
it('should configure detection types', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_EMAILS = 'false';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_PHONES = 'true';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_SSN = 'false';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_API_KEYS = 'true';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_CREDIT_CARDS = 'false';
process.env.GUARDRAILS_PII_REDACTOR_DETECT_IP_ADDRESSES = 'true';
const configManager = new ConfigManager();
const piiConfig = configManager.getConfig().guardrails?.plugins?.pii_redactor;
expect(piiConfig?.detect_emails).toBe(false);
expect(piiConfig?.detect_phones).toBe(true);
expect(piiConfig?.detect_ssn).toBe(false);
expect(piiConfig?.detect_api_keys).toBe(true);
expect(piiConfig?.detect_credit_cards).toBe(false);
expect(piiConfig?.detect_ip_addresses).toBe(true);
});
it('should configure allowlist', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_ALLOWLIST = 'test@example.com,support@company.com';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pii_redactor?.allowlist).toEqual([
'test@example.com',
'support@company.com',
]);
});
it('should configure allowlist_domains', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_ALLOWLIST_DOMAINS = 'company.com,internal.org';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pii_redactor?.allowlist_domains).toEqual([
'company.com',
'internal.org',
]);
});
it('should configure restore_on_response', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_RESTORE_ON_RESPONSE = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pii_redactor?.restore_on_response).toBe(true);
});
it('should configure log_detections', () => {
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_LOG_DETECTIONS = 'false';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.plugins?.pii_redactor?.log_detections).toBe(false);
});
});
describe('auto-enable behavior', () => {
it('should auto-enable guardrails when a plugin is enabled', () => {
// Don't set GUARDRAILS_ENABLED, but enable a plugin
process.env.GUARDRAILS_RATE_LIMITER_ENABLED = 'true';
const configManager = new ConfigManager();
expect(configManager.getConfig().guardrails?.enabled).toBe(true);
});
it('should auto-enable with multiple plugins', () => {
process.env.GUARDRAILS_RATE_LIMITER_ENABLED = 'true';
process.env.GUARDRAILS_PII_REDACTOR_ENABLED = 'true';
const configManager = new ConfigManager();
const config = configManager.getConfig();
expect(config.guardrails?.enabled).toBe(true);
expect(config.guardrails?.plugins?.rate_limiter?.enabled).toBe(true);
expect(config.guardrails?.plugins?.pii_redactor?.enabled).toBe(true);
});
});
});