feat: add flexible instance configuration support with security improvements

- Add InstanceContext interface for runtime configuration
- Implement dual-mode API client (singleton + instance-specific)
- Add secure SHA-256 hashing for cache keys
- Implement LRU cache with TTL (100 instances, 30min expiry)
- Add comprehensive input validation for URLs and API keys
- Sanitize all logging to prevent API key exposure
- Fix session context cleanup and memory management
- Add comprehensive security and integration tests
- Maintain full backward compatibility for single-player usage

Security improvements based on code review:
- Cache keys are now cryptographically hashed
- API credentials never appear in logs
- Memory-bounded cache prevents resource exhaustion
- Input validation rejects invalid/placeholder values
- Proper cleanup of orphaned session contexts

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-09-19 16:23:30 +02:00
parent 70653b16bd
commit 34fbdc30fe
11 changed files with 893 additions and 2571 deletions

View File

@@ -10,6 +10,7 @@ import { WorkflowDiffEngine } from '../services/workflow-diff-engine';
import { getN8nApiClient } from './handlers-n8n-manager';
import { N8nApiError, getUserFriendlyErrorMessage } from '../utils/n8n-errors';
import { logger } from '../utils/logger';
import { InstanceContext } from '../types/instance-context';
// Zod schema for the diff request
const workflowDiffSchema = z.object({
@@ -38,7 +39,7 @@ const workflowDiffSchema = z.object({
validateOnly: z.boolean().optional(),
});
export async function handleUpdatePartialWorkflow(args: unknown): Promise<McpToolResponse> {
export async function handleUpdatePartialWorkflow(args: unknown, context?: InstanceContext): Promise<McpToolResponse> {
try {
// Debug logging (only in debug mode)
if (process.env.DEBUG_MCP === 'true') {
@@ -54,7 +55,7 @@ export async function handleUpdatePartialWorkflow(args: unknown): Promise<McpToo
const input = workflowDiffSchema.parse(args);
// Get API client
const client = getN8nApiClient();
const client = getN8nApiClient(context);
if (!client) {
return {
success: false,