@dollhousemcp/mcp-server
Version:
DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.
186 lines • 7.32 kB
TypeScript
/**
* 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<string, ConfirmationRecord>;
/** Map of requestId -> CLI approval record (Issue #625 Phase 3) */
cliApprovals: Map<string, CliApprovalRecord>;
/** Map of toolName -> session-scoped CLI approval (Issue #625 Phase 3) */
cliSessionApprovals: Map<string, CliApprovalRecord>;
/** 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-<UUIDv4>).
*/
createCliApprovalRequest(toolName: string, toolInput: Record<string, unknown>, 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<string, unknown>): 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