/** * Danger Zone Enforcer * * Provides programmatic enforcement for DANGER_ZONE safety tier. * Maintains a list of blocked agent execution contexts and prevents * further tool execution until verification is completed. * * This addresses Issue #110 - the semantic-only approach is insufficient * for the highest risk tier, as a compromised LLM could ignore warnings. * * Issue #402: Refactored from singleton to DI-managed class with * file-based persistence. Blocks survive server restarts via * ~/.dollhouse/security/blocked-agents.json. * * @since v2.0.0 - Agentic Loop Completion (Epic #380) * @since v2.1.0 - File-based persistence (Issue #402) */ import type { FileOperationsService } from '../services/FileOperationsService.js'; /** * Audit context captured when a danger zone block occurs (Issue #404). * Provides full execution context for post-hoc investigation of blocks. * * NOTE: The DangerZoneBlocker interface in types.ts has a structurally * identical inline type. Keep both in sync when modifying fields. */ export interface DangerZoneAuditContext { stepNumber?: number; currentStepDescription?: string; currentStepOutcome?: string; nextActionHint?: string; riskScore?: number; goalDescription?: string; goalId?: string; safetyFactors?: string[]; } /** * Result of a block check */ export interface BlockCheckResult { /** Whether the context is blocked */ blocked: boolean; /** Reason for blocking (if blocked) */ reason?: string; /** How to resolve the block */ resolution?: string; /** Verification ID if verification is required */ verificationId?: string; } /** * Metrics for danger zone enforcement */ export interface DangerZoneMetrics { /** Current number of blocked agents */ currentBlockedCount: number; /** Total blocks since startup */ totalBlocksSinceStartup: number; /** Total unblocks since startup */ totalUnblocksSinceStartup: number; /** Total clearAll calls since startup */ totalClearAllCalls: number; /** Average block duration in milliseconds (for unblocked agents) */ averageBlockDurationMs: number; /** Longest block duration in milliseconds */ longestBlockDurationMs: number; } /** * DI-managed class for danger zone enforcement with file-based persistence. * * Thread-safety note: This uses a Map which is not inherently thread-safe, * but in a Node.js single-threaded environment this is acceptable. * For multi-process deployments, consider Redis or similar. * * Persistence: Blocks are persisted to ~/.dollhouse/security/blocked-agents.json. * The in-memory Map is the hot path for check(); disk is the durable backing store. * Disk writes are fire-and-forget — disk failure does not block enforcement. */ export declare class DangerZoneEnforcer { private blockedContexts; private totalBlocksSinceStartup; private totalUnblocksSinceStartup; private totalClearAllCalls; private blockDurations; private adminToken; private readonly fileOps; private readonly securityDir; private readonly persistPath; constructor(fileOps: FileOperationsService, securityDir?: string); /** * Load persisted blocks from disk. * Call once after construction to restore state from a previous session. * If the file is missing or corrupt, starts with empty blocks. * * @example * ```ts * const enforcer = new DangerZoneEnforcer(fileOps); * await enforcer.initialize(); // restores blocks from ~/.dollhouse/security/blocked-agents.json * ``` */ initialize(): Promise; /** * Block an agent context due to danger zone trigger * * @param agentName - Name of the agent to block * @param reason - Why the agent is blocked * @param triggeredPatterns - Patterns that caused the block * @param verificationId - Optional verification ID for unblocking * @param auditContext - Optional execution context for audit trail (Issue #404) * @throws Error if agentName is invalid * * @example * ```ts * enforcer.block('code-reviewer', 'Danger zone pattern matched', ['rm -rf'], 'verify-abc'); * enforcer.check('code-reviewer').blocked; // true * ``` */ block(agentName: string, reason: string, triggeredPatterns: string[], verificationId?: string, auditContext?: DangerZoneAuditContext): void; /** * Unblock an agent context after verification * * @param agentName - Name of the agent to unblock * @param verificationId - Verification ID that was completed * @returns Whether the unblock was successful * @throws Error if agentName is invalid * * @example * ```ts * enforcer.block('code-reviewer', 'Blocked', ['rm -rf'], 'verify-abc'); * * enforcer.unblock('code-reviewer', 'wrong-id'); // false — mismatch * enforcer.unblock('code-reviewer', 'verify-abc'); // true — success * ``` */ unblock(agentName: string, verificationId?: string): boolean; /** * Check if an agent context is blocked * * @param agentName - Name of the agent to check * @returns Block check result * @throws Error if agentName is invalid * * @example * ```ts * const result = enforcer.check('code-reviewer'); * if (result.blocked) { * console.log(result.reason); // why it was blocked * console.log(result.resolution); // how to unblock * } * ``` */ check(agentName: string): BlockCheckResult; /** * Check if any agent is currently blocked * Useful for diagnostics * * @example * ```ts * if (enforcer.hasBlockedAgents()) { * console.log('Blocked agents:', enforcer.getBlockedAgents()); * } * ``` */ hasBlockedAgents(): boolean; /** * Get list of all blocked agents * Useful for admin/diagnostic purposes * * @example * ```ts * const agents = enforcer.getBlockedAgents(); // ['code-reviewer', 'data-agent'] * ``` */ getBlockedAgents(): string[]; /** * Clear all blocks (for testing or admin reset) * * When DOLLHOUSE_DANGER_ZONE_ADMIN_TOKEN is set, requires matching token. * Without environment variable, clearAll is unrestricted (for testing). * * @param adminToken - Admin token for authorization (required if env var is set) * @returns Whether the clear was successful * * @example * ```ts * // Without admin token configured * enforcer.clearAll(); // true * * // With admin token configured * enforcer.clearAll('wrong-token'); // false * enforcer.clearAll('correct-token'); // true * ``` */ clearAll(adminToken?: string): boolean; /** * Get metrics for danger zone enforcement * Useful for monitoring and diagnostics * * @example * ```ts * const metrics = enforcer.getMetrics(); * console.log(metrics.averageBlockDurationMs); // rolling window (see METRICS_WINDOW_SIZE) * ``` */ getMetrics(): DangerZoneMetrics; /** * Set admin token programmatically (for testing) * @internal */ setAdminToken(token: string | null): void; /** * Reset metrics (for testing) * @internal */ resetMetrics(): void; /** * Fire-and-forget persistence. Disk failure does not block enforcement. */ private persistAsync; /** * Write current block state to disk. */ private persist; } //# sourceMappingURL=DangerZoneEnforcer.d.ts.map