Phase 8 Production Hardening with complete governance infrastructure: - Vault integration with tiered policies (T0-T4) - DragonflyDB state management - SQLite audit ledger - Pipeline DSL and templates - Promotion/revocation engine - Checkpoint system for session persistence - Health manager and circuit breaker for fault tolerance - GitHub/Slack integrations - Architectural test pipeline with bug watcher, suggestion engine, council review - Multi-agent chaos testing framework Test Results: - Governance tests: 68/68 passing - E2E workflow: 16/16 passing - Phase 2 Vault: 14/14 passing - Integration tests: 27/27 passing Coverage: 57.6% average across 12 phases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
326 lines
10 KiB
TypeScript
326 lines
10 KiB
TypeScript
#!/usr/bin/env bun
|
|
/**
|
|
* Comprehensive Governance System Tests - TypeScript/Bun
|
|
* =======================================================
|
|
* Tests all components of the agent governance framework from TypeScript
|
|
*/
|
|
|
|
import { $ } from "bun";
|
|
import { Database } from "bun:sqlite";
|
|
import { createClient, type RedisClientType } from "redis";
|
|
|
|
// Colors
|
|
const GREEN = "\x1b[92m";
|
|
const RED = "\x1b[91m";
|
|
const YELLOW = "\x1b[93m";
|
|
const BLUE = "\x1b[94m";
|
|
const RESET = "\x1b[0m";
|
|
|
|
interface TestResults {
|
|
passed: number;
|
|
failed: number;
|
|
skipped: number;
|
|
}
|
|
|
|
const results: TestResults = { passed: 0, failed: 0, skipped: 0 };
|
|
|
|
function logTest(name: string, passed: boolean, message?: string): void {
|
|
if (passed) {
|
|
results.passed++;
|
|
const status = `${GREEN}PASS${RESET}`;
|
|
console.log(` [${status}] ${name}${message ? ` - ${message}` : ""}`);
|
|
} else {
|
|
results.failed++;
|
|
const status = `${RED}FAIL${RESET}`;
|
|
console.log(` [${status}] ${name}${message ? ` - ${message}` : ""}`);
|
|
}
|
|
}
|
|
|
|
function logSkip(name: string, reason: string): void {
|
|
results.skipped++;
|
|
console.log(` [${YELLOW}SKIP${RESET}] ${name} - ${reason}`);
|
|
}
|
|
|
|
function logSection(title: string): void {
|
|
console.log(`\n${BLUE}${"=".repeat(60)}${RESET}`);
|
|
console.log(`${BLUE}${title}${RESET}`);
|
|
console.log(`${BLUE}${"=".repeat(60)}${RESET}`);
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: Vault Connectivity
|
|
// =============================================================================
|
|
|
|
async function testVault(): Promise<void> {
|
|
logSection("VAULT TESTS (Bun)");
|
|
|
|
// Test 1: Vault status via docker
|
|
try {
|
|
const result = await $`docker exec vault vault status -format=json`.quiet();
|
|
const status = JSON.parse(result.stdout.toString());
|
|
logTest("Vault is running", true);
|
|
logTest("Vault is initialized", status.initialized === true);
|
|
logTest("Vault is unsealed", status.sealed === false);
|
|
} catch (e) {
|
|
logTest("Vault is running", false, String(e));
|
|
return;
|
|
}
|
|
|
|
// Test 2: Read root token
|
|
try {
|
|
const keysFile = Bun.file("/opt/vault/init-keys.json");
|
|
const keys = await keysFile.json();
|
|
logTest("Root token readable", !!keys.root_token);
|
|
} catch (e) {
|
|
logTest("Root token readable", false, String(e));
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: DragonflyDB Connectivity
|
|
// =============================================================================
|
|
|
|
async function testDragonfly(): Promise<void> {
|
|
logSection("DRAGONFLYDB TESTS (Bun)");
|
|
|
|
let client: RedisClientType | null = null;
|
|
|
|
try {
|
|
// Get credentials
|
|
const keysFile = Bun.file("/opt/vault/init-keys.json");
|
|
const keys = await keysFile.json();
|
|
const rootToken = keys.root_token;
|
|
|
|
const response = await fetch(
|
|
"https://127.0.0.1:8200/v1/secret/data/services/dragonfly",
|
|
{
|
|
headers: { "X-Vault-Token": rootToken },
|
|
// @ts-ignore - Bun supports this
|
|
tls: { rejectUnauthorized: false },
|
|
}
|
|
);
|
|
|
|
if (!response.ok) {
|
|
logTest("DragonflyDB credentials from Vault", false);
|
|
return;
|
|
}
|
|
|
|
const data = await response.json();
|
|
const creds = data.data.data;
|
|
logTest("DragonflyDB credentials from Vault", true);
|
|
|
|
// Connect
|
|
client = createClient({
|
|
socket: {
|
|
host: creds.host,
|
|
port: parseInt(creds.port),
|
|
},
|
|
password: creds.password,
|
|
});
|
|
|
|
await client.connect();
|
|
logTest("DragonflyDB connection", true);
|
|
|
|
// Test operations
|
|
await client.set("test:bun:ping", "pong", { EX: 60 });
|
|
const value = await client.get("test:bun:ping");
|
|
logTest("DragonflyDB read/write", value === "pong");
|
|
|
|
// Test list
|
|
await client.del("test:bun:list");
|
|
await client.lPush("test:bun:list", ["item1", "item2"]);
|
|
const items = await client.lRange("test:bun:list", 0, -1);
|
|
logTest("DragonflyDB list operations", items.length === 2);
|
|
await client.del("test:bun:list");
|
|
} catch (e) {
|
|
logTest("DragonflyDB operations", false, String(e));
|
|
} finally {
|
|
if (client) {
|
|
await client.quit();
|
|
}
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: SQLite Ledger
|
|
// =============================================================================
|
|
|
|
async function testLedger(): Promise<void> {
|
|
logSection("LEDGER TESTS (Bun)");
|
|
|
|
const dbPath = "/opt/agent-governance/ledger/governance.db";
|
|
const dbFile = Bun.file(dbPath);
|
|
|
|
logTest("Ledger database exists", await dbFile.exists());
|
|
|
|
if (!(await dbFile.exists())) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const db = new Database(dbPath);
|
|
|
|
// Check tables
|
|
const tables = db
|
|
.query("SELECT name FROM sqlite_master WHERE type='table'")
|
|
.all() as { name: string }[];
|
|
const tableNames = tables.map((t) => t.name);
|
|
|
|
logTest("Table 'agent_metrics' exists", tableNames.includes("agent_metrics"));
|
|
logTest("Table 'violations' exists", tableNames.includes("violations"));
|
|
logTest("Table 'promotions' exists", tableNames.includes("promotions"));
|
|
logTest("Table 'orchestration_log' exists", tableNames.includes("orchestration_log"));
|
|
|
|
// Test insert/query
|
|
db.run(`
|
|
INSERT OR REPLACE INTO agent_metrics
|
|
(agent_id, current_tier, compliant_runs, consecutive_compliant, total_runs, updated_at)
|
|
VALUES ('test-agent-bun', 0, 0, 0, 0, datetime('now'))
|
|
`);
|
|
|
|
const row = db
|
|
.query("SELECT * FROM agent_metrics WHERE agent_id='test-agent-bun'")
|
|
.get();
|
|
logTest("Ledger insert/query", row !== null);
|
|
|
|
// Cleanup
|
|
db.run("DELETE FROM agent_metrics WHERE agent_id='test-agent-bun'");
|
|
db.close();
|
|
} catch (e) {
|
|
logTest("Ledger operations", false, String(e));
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: CLI Tools
|
|
// =============================================================================
|
|
|
|
async function testCLITools(): Promise<void> {
|
|
logSection("CLI TOOLS TESTS (Bun)");
|
|
|
|
// Test checkpoint CLI
|
|
try {
|
|
const result = await $`/opt/agent-governance/bin/checkpoint list`.quiet();
|
|
logTest("Checkpoint CLI works", result.exitCode === 0);
|
|
} catch (e) {
|
|
logTest("Checkpoint CLI works", false, String(e));
|
|
}
|
|
|
|
// Test model-controller CLI
|
|
try {
|
|
const result = await $`/opt/agent-governance/bin/model-controller status`.quiet();
|
|
logTest("Model controller CLI works", result.exitCode === 0);
|
|
} catch (e) {
|
|
logTest("Model controller CLI works", false, String(e));
|
|
}
|
|
|
|
// Test tier0 agent
|
|
try {
|
|
const result =
|
|
await $`cd /opt/agent-governance/agents/tier0-agent && python3 agent.py status`.quiet();
|
|
logTest("Tier 0 agent CLI works", result.exitCode === 0);
|
|
} catch (e) {
|
|
logTest("Tier 0 agent CLI works", false, String(e));
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: File System Structure
|
|
// =============================================================================
|
|
|
|
async function testFileStructure(): Promise<void> {
|
|
logSection("FILE STRUCTURE TESTS (Bun)");
|
|
|
|
const paths = [
|
|
"/opt/agent-governance/checkpoint/checkpoint.py",
|
|
"/opt/agent-governance/orchestrator/model_controller.py",
|
|
"/opt/agent-governance/orchestrator/config.json",
|
|
"/opt/agent-governance/preflight/preflight.py",
|
|
"/opt/agent-governance/runtime/promotion.py",
|
|
"/opt/agent-governance/runtime/revocation.py",
|
|
"/opt/agent-governance/agents/tier0-agent/agent.py",
|
|
"/opt/agent-governance/wrappers/tf-governed.sh",
|
|
"/opt/agent-governance/wrappers/ansible-governed.sh",
|
|
"/opt/agent-governance/evidence/evidence.py",
|
|
];
|
|
|
|
for (const path of paths) {
|
|
const file = Bun.file(path);
|
|
const name = path.split("/").pop() || path;
|
|
logTest(`${name} exists`, await file.exists());
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Test: Config Files
|
|
// =============================================================================
|
|
|
|
async function testConfigFiles(): Promise<void> {
|
|
logSection("CONFIG FILES TESTS (Bun)");
|
|
|
|
// Test orchestrator config
|
|
try {
|
|
const configFile = Bun.file("/opt/agent-governance/orchestrator/config.json");
|
|
const config = await configFile.json();
|
|
logTest("Orchestrator config valid JSON", true);
|
|
logTest("Config has models section", !!config.models);
|
|
logTest("Config has execution section", !!config.execution);
|
|
logTest("Config has safety section", !!config.safety);
|
|
} catch (e) {
|
|
logTest("Orchestrator config", false, String(e));
|
|
}
|
|
|
|
// Test agent config
|
|
try {
|
|
const agentConfig = Bun.file(
|
|
"/opt/agent-governance/agents/tier0-agent/config/agent.json"
|
|
);
|
|
const config = await agentConfig.json();
|
|
logTest("Agent config valid JSON", true);
|
|
logTest("Agent config has capabilities", !!config.capabilities);
|
|
logTest("Agent config has constraints", !!config.constraints);
|
|
} catch (e) {
|
|
logTest("Agent config", false, String(e));
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Main
|
|
// =============================================================================
|
|
|
|
async function main(): Promise<number> {
|
|
console.log(`\n${BLUE}${"#".repeat(60)}${RESET}`);
|
|
console.log(`${BLUE}# AGENT GOVERNANCE SYSTEM - BUN/TYPESCRIPT TESTS${RESET}`);
|
|
console.log(`${BLUE}# ${new Date().toISOString()}${RESET}`);
|
|
console.log(`${BLUE}${"#".repeat(60)}${RESET}`);
|
|
|
|
await testVault();
|
|
await testDragonfly();
|
|
await testLedger();
|
|
await testCLITools();
|
|
await testFileStructure();
|
|
await testConfigFiles();
|
|
|
|
// Summary
|
|
console.log(`\n${BLUE}${"=".repeat(60)}${RESET}`);
|
|
console.log(`${BLUE}TEST SUMMARY${RESET}`);
|
|
console.log(`${BLUE}${"=".repeat(60)}${RESET}`);
|
|
|
|
const total = results.passed + results.failed + results.skipped;
|
|
console.log(` ${GREEN}Passed:${RESET} ${results.passed}`);
|
|
console.log(` ${RED}Failed:${RESET} ${results.failed}`);
|
|
console.log(` ${YELLOW}Skipped:${RESET} ${results.skipped}`);
|
|
console.log(` Total: ${total}`);
|
|
|
|
if (results.failed > 0) {
|
|
console.log(`\n${RED}Some tests failed!${RESET}`);
|
|
return 1;
|
|
} else {
|
|
console.log(`\n${GREEN}All tests passed!${RESET}`);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const exitCode = await main();
|
|
process.exit(exitCode);
|