Files
chlova/orchestrator/test/config.test.ts
T
Kantin-Petit 93d93bef0e feat: gatekeeper service + gate de phase (v0.11.0)
Gatekeeper vérifie le statut d'asset avant chaque exécution : privilégié
inconnu → BLOQUÉ (aucun sursis) refusé jusqu'à review + hook d'alerte ;
approuvé → exécutable. Lecture seule autorisée sans asset. Gate de phase
CHLOVA_PHASE (défaut 1, fail-safe) ; assertReadOnlyPhase phase-aware. 7
nouveaux tests.

Palier de risque : reversible (logique de contrôle, n'exécute aucune mutation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 01:27:35 +02:00

75 lines
2.4 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { loadConfig, assertReadOnlyPhase, redactedConfig } from "../src/config.js";
const fullEnv = (): NodeJS.ProcessEnv => ({
OLLAMA_BASE_URL: "http://ollama:11434",
OLLAMA_API_KEY: "secret-ollama",
OLLAMA_MODEL: "qwen3:cloud",
MCP_N8N_URL: "http://mcp-n8n:3000",
MCP_N8N_AUTH_TOKEN: "secret-n8n",
MCP_PORTAINER_URL: "http://mcp-portainer:3000",
PORTAINER_MCP_AUTH_TOKEN: "secret-portainer",
PORTAINER_READ_ONLY: "true",
TELEGRAM_BOT_TOKEN: "secret-tg",
TELEGRAM_ALLOWED_USER_IDS: "111, 222",
});
describe("config fail-closed", () => {
it("charge une config complète", () => {
const cfg = loadConfig(fullEnv());
expect(cfg.ollamaModel).toBe("qwen3:cloud");
expect(cfg.telegramAllowedUserIds).toEqual(["111", "222"]);
});
it("refuse de démarrer si un secret manque", () => {
const env = fullEnv();
delete env.OLLAMA_API_KEY;
expect(() => loadConfig(env)).toThrow(/fail-closed/);
});
it("refuse une URL invalide", () => {
const env = fullEnv();
env.MCP_N8N_URL = "pas-une-url";
expect(() => loadConfig(env)).toThrow();
});
});
describe("verrou lecture seule Phase 1", () => {
it("accepte PORTAINER_READ_ONLY=true", () => {
expect(() => assertReadOnlyPhase(loadConfig(fullEnv()))).not.toThrow();
});
it("refuse PORTAINER_READ_ONLY=false en Phase 1", () => {
const env = fullEnv();
env.PORTAINER_READ_ONLY = "false";
expect(() => assertReadOnlyPhase(loadConfig(env))).toThrow(/lecture seule/);
});
it("Phase 2 autorise PORTAINER_READ_ONLY=false", () => {
const env = fullEnv();
env.CHLOVA_PHASE = "2";
env.PORTAINER_READ_ONLY = "false";
const cfg = loadConfig(env);
expect(cfg.phase).toBe(2);
expect(() => assertReadOnlyPhase(cfg)).not.toThrow();
});
it("phase invalide retombe sur 1 (fail-safe)", () => {
const env = fullEnv();
env.CHLOVA_PHASE = "9";
expect(loadConfig(env).phase).toBe(1);
});
});
describe("redactedConfig masque les secrets", () => {
it("ne révèle aucun secret", () => {
const red = redactedConfig(loadConfig(fullEnv()));
expect(red.ollamaApiKey).toBe("[REDACTED]");
expect(red.telegramBotToken).toBe("[REDACTED]");
expect(red.mcpN8nAuthToken).toBe("[REDACTED]");
expect(red.portainerMcpAuthToken).toBe("[REDACTED]");
// les non-secrets restent visibles
expect(red.ollamaModel).toBe("qwen3:cloud");
});
});