Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
confirmation.utils.ts3.53 kB
// ============================================================================ // Confirmation Flow Utilities // Provides secure token generation and validation for destructive operations // ============================================================================ import crypto from 'crypto'; /** * Secret key for HMAC token generation (in production, load from env or secure store) * For now, using a per-process secret */ const SECRET_KEY = process.env.CONFIRMATION_SECRET || crypto.randomBytes(32).toString('hex'); /** * Token expiry time in milliseconds (default: 5 minutes) */ const TOKEN_EXPIRY_MS = 5 * 60 * 1000; /** * Pending confirmations (in-memory store for simplicity) * In production, consider using Redis or database for distributed systems */ const pendingConfirmations = new Map<string, { action: string; params: any; createdAt: number; expiresAt: number; }>(); /** * Generate a secure confirmation token for a destructive action * * @param action - Action identifier (e.g., 'memory_clear', 'delete_node') * @param params - Parameters of the action (for verification) * @returns Confirmation ID that can be used to confirm the action */ export function generateConfirmationToken(action: string, params: any): string { const confirmationId = crypto.randomBytes(16).toString('hex'); const now = Date.now(); // Store pending confirmation pendingConfirmations.set(confirmationId, { action, params, createdAt: now, expiresAt: now + TOKEN_EXPIRY_MS }); // Cleanup expired tokens periodically (simple approach) cleanupExpiredTokens(); return confirmationId; } /** * Validate a confirmation token * * @param confirmationId - Token to validate * @param action - Expected action identifier * @param params - Expected parameters (for verification) * @returns true if token is valid, false otherwise */ export function validateConfirmationToken( confirmationId: string, action: string, params: any ): boolean { const pending = pendingConfirmations.get(confirmationId); if (!pending) { return false; // Token not found } // Check expiry if (Date.now() > pending.expiresAt) { pendingConfirmations.delete(confirmationId); return false; // Token expired } // Verify action matches if (pending.action !== action) { return false; // Action mismatch } // Verify params match (basic comparison) if (JSON.stringify(pending.params) !== JSON.stringify(params)) { return false; // Params changed } return true; } /** * Consume a confirmation token (one-time use) * * @param confirmationId - Token to consume */ export function consumeConfirmationToken(confirmationId: string): void { pendingConfirmations.delete(confirmationId); } /** * Clean up expired confirmation tokens */ function cleanupExpiredTokens(): void { const now = Date.now(); for (const [id, pending] of pendingConfirmations.entries()) { if (now > pending.expiresAt) { pendingConfirmations.delete(id); } } } /** * Get stats about pending confirmations (for monitoring) */ export function getConfirmationStats(): { pending: number; oldestAge: number | null; } { const now = Date.now(); let oldestAge: number | null = null; for (const pending of pendingConfirmations.values()) { const age = now - pending.createdAt; if (oldestAge === null || age > oldestAge) { oldestAge = age; } } return { pending: pendingConfirmations.size, oldestAge }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server