/** * Gatekeeper Session Management * * Manages per-connection session state for the Gatekeeper Policy Engine. * Each MCP client connection gets a separate session with isolated state. * * CRITICAL: Session state is IN-MEMORY only. * - Confirmations are NOT persisted to disk * - Each Claude Code / Claude Desktop / etc. = separate session * - No cross-session policy leakage * - Crash = fresh session (security-first decision) */ import type { ConfirmationRecord, PermissionLevel, CliApprovalRecord, CliApprovalScope } from './GatekeeperTypes.js'; /** * Client information from MCP capabilities. * Identifies which MCP client is making requests. */ export interface ClientInfo { /** Client name (e.g., "claude-code", "claude-desktop") */ name: string; /** Client version */ version: string; } /** * Session state for a single MCP connection. * Tracks confirmations and activity for this session only. */ export interface GatekeeperSessionState { /** Unique session identifier */ sessionId: string; /** Client information from MCP capabilities */ clientInfo?: ClientInfo; /** When the session was created */ createdAt: string; /** Last activity timestamp */ lastActivity: string; /** Map of operation -> confirmation record */ confirmations: Map; /** Map of requestId -> CLI approval record (Issue #625 Phase 3) */ cliApprovals: Map; /** Map of toolName -> session-scoped CLI approval (Issue #625 Phase 3) */ cliSessionApprovals: Map; /** Whether permission_prompt has been called at least once this session (Issue #625 Phase 4) */ permissionPromptActive: boolean; } export declare class GatekeeperSession { private readonly state; private readonly maxConfirmations; private readonly maxCliApprovals; private lastExpirySweep; constructor(clientInfo?: ClientInfo, maxConfirmations?: number, maxCliApprovals?: number); /** * Get the unique session identifier. */ get sessionId(): string; /** * Get the client information. */ get clientInfo(): ClientInfo | undefined; /** * Get the session creation timestamp. */ get createdAt(): string; /** * Get the last activity timestamp. */ get lastActivity(): string; /** * Whether permission_prompt has been invoked at least once this session. * Used for fail-safe detection (Issue #625 Phase 4). */ get isPermissionPromptActive(): boolean; /** * Mark that permission_prompt has been invoked. * Called on first invocation to track that the CLI client supports it. */ markPermissionPromptActive(): void; /** * Update the last activity timestamp. */ touch(): void; /** * Record a confirmation for an operation. * Confirmations are scoped to this session only. * * @param operation - The operation being confirmed * @param permissionLevel - The permission level being confirmed * @param elementType - Optional element type scope */ recordConfirmation(operation: string, permissionLevel: PermissionLevel.CONFIRM_SESSION | PermissionLevel.CONFIRM_SINGLE_USE, elementType?: string): void; /** * Check if an operation has a valid session confirmation. * For CONFIRM_SINGLE_USE, this invalidates the confirmation after checking. * * RACE CONDITION NOTE: * The check-then-delete for CONFIRM_SINGLE_USE is safe because: * 1. Node.js is single-threaded - no concurrent access to Map * 2. MCP requests are processed sequentially per connection * 3. Each session instance is tied to a single client connection * If this code is ever used in a multi-threaded context or with shared * state across processes, atomic operations would be required. * * @param operation - The operation to check * @param elementType - Optional element type scope * @returns The confirmation record if valid, undefined otherwise */ checkConfirmation(operation: string, elementType?: string): ConfirmationRecord | undefined; /** * Check if an operation has a session confirmation WITHOUT consuming it. * Use this to check status without affecting the confirmation state. * * @param operation - The operation to check * @param elementType - Optional element type scope * @returns The confirmation record if exists, undefined otherwise */ peekConfirmation(operation: string, elementType?: string): ConfirmationRecord | undefined; /** * Revoke a confirmation for an operation. * * @param operation - The operation to revoke * @param elementType - Optional element type scope * @returns true if a confirmation was revoked */ revokeConfirmation(operation: string, elementType?: string): boolean; /** * Revoke all confirmations for this session. * Useful when security-sensitive changes occur. */ revokeAllConfirmations(): void; /** * Get all active confirmations for this session. * Useful for debugging and audit logging. */ getActiveConfirmations(): ConfirmationRecord[]; /** * Create a CLI approval request. * Returns a unique request ID (format: cli-). */ createCliApprovalRequest(toolName: string, toolInput: Record, riskLevel: string, riskScore: number, irreversible: boolean, denyReason: string, policySource?: string, ttlMs?: number): string; /** * Approve a pending CLI approval request. * Sets approvedAt, and promotes to session approvals if tool_session scope. * * @returns The approved record, or undefined if not found */ approveCliRequest(requestId: string, scope?: CliApprovalScope): CliApprovalRecord | undefined; /** * Check if a CLI tool call has a valid approval. * Checks session approvals first (fast path), then individual approvals. * Consumes single-scope approvals on use. * * @returns The matching approval record, or undefined */ checkCliApproval(toolName: string, _toolInput: Record): CliApprovalRecord | undefined; /** * Get all pending (unapproved) CLI approval requests. * Forces expiry sweep to ensure accurate user-facing results. */ getPendingCliApprovals(): CliApprovalRecord[]; /** * Expire stale approval requests. * Uses per-record ttlMs if set, otherwise DEFAULT_APPROVAL_TTL_MS (5 minutes). * * @param force - Skip throttle check (used by write paths that must ensure capacity) */ private expireStaleApprovals; /** * Get a summary of the session state. * Safe to expose for debugging without revealing sensitive data. */ getSummary(): { sessionId: string; clientInfo?: ClientInfo; createdAt: string; lastActivity: string; confirmationCount: number; cliApprovalCount: number; permissionPromptActive: boolean; }; /** * Generate a unique key for confirmation lookups. * Combines operation and optional element type. */ private getConfirmationKey; } //# sourceMappingURL=GatekeeperSession.d.ts.map