MindPeeker Logo
Specifications

Integration Requirements

Technical requirements and guidelines for integrating with MindPeeker platform

System Requirements

Minimum Technical Specifications

Hardware Requirements

Client Applications:
  CPU: Dual-core 1.5GHz or equivalent
  RAM: 4GB minimum, 8GB recommended
  Storage: 500MB available space
  Network: Broadband internet connection (10 Mbps+)

Mobile Applications:
  OS: iOS 13+ or Android 8+
  RAM: 2GB minimum
  Storage: 200MB available space
  Network: 4G LTE or WiFi recommended

Server Integration:
  CPU: Quad-core 2.0GHz or equivalent
  RAM: 8GB minimum, 16GB recommended
  Storage: 50GB available space
  Network: Dedicated internet connection (100 Mbps+)

Software Requirements

Operating Systems:
  - Windows 10/11 (64-bit)
  - macOS 10.15+ (Catalina or later)
  - Ubuntu 20.04+ LTS
  - CentOS 8+ / RHEL 8+

Runtime Environments:
  - Node.js 18.0+ (for JavaScript SDK)
  - Python 3.8+ (for Python SDK)
  - Java 11+ (for Java SDK)
  - .NET 6.0+ (for C# SDK)
  - Go 1.18+ (for Go SDK)

Web Browsers:
  - Chrome 90+
  - Firefox 88+
  - Safari 14+
  - Edge 90+

Network Requirements

Connectivity Requirements

Bandwidth:
  Minimum: 10 Mbps sustained
  Recommended: 100 Mbps sustained
  Peak: 1 Gbps for enterprise deployments

Latency:
  Maximum: 500ms round-trip
  Recommended: <100ms round-trip
  Critical: <50ms for real-time features

Reliability:
  Uptime: 99.9% availability required
  Packet Loss: <0.1%
  Jitter: <20ms

Firewall Configuration

Required Ports:
  HTTPS (443/TCP): API access and web interface
  WSS (443/TCP): WebSocket connections
  HTTP (80/TCP): Redirect to HTTPS only

IP Ranges:
  Primary: 52.0.0.0/8 (AWS US-East)
  Backup: 54.0.0.0/8 (AWS US-West)
  CDN: 13.0.0.0/8 (CloudFront)

Domain Whitelist:
  - api.mindpeeker.com
  - cdn.mindpeeker.com
  - ws.mindpeeker.com
  - auth.mindpeeker.com

API Integration Requirements

Authentication Setup

API Key Generation

1. Navigate to Settings → API Keys
2. Click "Generate New Key"
3. Configure permissions and limits
4. Securely store the key

curl -X POST https://api.mindpeeker.com/v1/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production API Key",
    "permissions": [
      {"resource": "sessions", "actions": ["create", "read"]},
      {"resource": "analyses", "actions": ["read"]}
    ],
    "rate_limit_per_minute": 1000,
    "ip_whitelist": ["203.0.113.0/24"]
  }'

JWT Token Management

// Token refresh implementation
class TokenManager {
  private refreshToken: string;
  private accessToken: string;
  private tokenExpiry: Date;

  async getValidToken(): Promise<string> {
    if (!this.accessToken || this.isTokenExpired()) {
      await this.refreshAccessToken();
    }
    return this.accessToken;
  }

  private async refreshAccessToken(): Promise<void> {
    const response = await fetch('/api/auth/refresh', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ refresh_token: this.refreshToken })
    });

    const data = await response.json();
    this.accessToken = data.token;
    this.tokenExpiry = new Date(Date.now() + (data.expires_in * 1000));
  }

  private isTokenExpired(): boolean {
    return new Date() >= this.tokenExpiry;
  }
}

SDK Integration

JavaScript/TypeScript SDK

// Installation
npm install @mindpeeker/sdk

// Basic usage
import { MindPeekerClient } from '@mindpeeker/sdk';

const client = new MindPeekerClient({
  apiKey: process.env.MINDPEEKER_API_KEY,
  baseUrl: 'https://api.mindpeeker.com/v1',
  timeout: 30000
});

// Create session
const session = await client.sessions.create({
  cue: 'Describe the location of the missing artifact',
  session_type: 'remote_viewing',
  parameters: {
    confidence_threshold: 0.8,
    analysis_types: ['visual', 'spatial']
  }
});

// Monitor progress
client.sessions.onProgress(session.id, (update) => {
  console.log(`Progress: ${update.progress}%`);
  console.log(`Status: ${update.status}`);
});

// Get results
const results = await client.sessions.getResults(session.id);
console.log('Analysis complete:', results);

Python SDK

pip install mindpeeker-sdk

from mindpeeker import MindPeekerClient
import asyncio

async def main():
    client = MindPeekerClient(
        api_key=os.getenv('MINDPEEKER_API_KEY'),
        base_url='https://api.mindpeeker.com/v1'
    )
    
    # Create session
    session = await client.sessions.create(
        cue='Describe the location of the missing artifact',
        session_type='remote_viewing',
        parameters={
            'confidence_threshold': 0.8,
            'analysis_types': ['visual', 'spatial']
        }
    )
    
    # Wait for completion
    results = await client.sessions.wait_for_completion(
        session.id, 
        timeout=1800
    )
    
    print(f"Analysis complete: {results}")

asyncio.run(main())

Java SDK

// Installation (Maven)
<dependency>
    <groupId>com.mindpeeker</groupId>
    <artifactId>mindpeeker-sdk</artifactId>
    <version>1.5.0</version>
</dependency>

// Basic usage
import com.mindpeeker.client.MindPeekerClient;
import com.mindpeeker.model.*;

public class MindPeekerIntegration {
    public static void main(String[] args) {
        MindPeekerClient client = MindPeekerClient.builder()
            .apiKey(System.getenv("MINDPEEKER_API_KEY"))
            .baseUrl("https://api.mindpeeker.com/v1")
            .timeout(Duration.ofSeconds(30))
            .build();
        
        // Create session
        Session session = client.sessions().create(SessionCreateRequest.builder()
            .cue("Describe the location of the missing artifact")
            .sessionType(SessionType.REMOTE_VIEWING)
            .parameter("confidence_threshold", 0.8)
            .parameter("analysis_types", Arrays.asList("visual", "spatial"))
            .build());
        
        // Monitor progress
        client.sessions().subscribeToUpdates(session.id, update -> {
            System.out.println("Progress: " + update.getProgress() + "%");
            System.out.println("Status: " + update.getStatus());
        });
        
        // Get results
        SessionResults results = client.sessions().getResults(session.id);
        System.out.println("Analysis complete: " + results);
    }
}

Webhook Integration Requirements

Webhook Endpoint Setup

Secure Webhook Handler (Node.js)

import crypto from 'crypto';
import express from 'express';

const app = express();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

// Verify webhook signature
function verifyWebhookSignature(payload: string, signature: string): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

// Webhook endpoint
app.post('/webhooks/mindpeeker', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-mindpeeker-signature'] as string;
  const payload = req.body.toString();
  
  if (!verifyWebhookSignature(payload, signature)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  try {
    const event = JSON.parse(payload);
    
    switch (event.type) {
      case 'session.completed':
        handleSessionCompleted(event.data);
        break;
      case 'session.failed':
        handleSessionFailed(event.data);
        break;
      case 'analysis.ready':
        handleAnalysisReady(event.data);
        break;
      default:
        console.log(`Unhandled event type: ${event.type}`);
    }
    
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook processing error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

async function handleSessionCompleted(data: any) {
  console.log(`Session ${data.session_id} completed`);
  // Process completed session
  // Update database, notify users, etc.
}

async function handleSessionFailed(data: any) {
  console.log(`Session ${data.session_id} failed: ${data.error}`);
  // Handle failed session
  // Notify administrators, retry if appropriate, etc.
}

async function handleAnalysisReady(data: any) {
  console.log(`Analysis ${data.analysis_id} ready for session ${data.session_id}`);
  // Process analysis results
  // Store results, trigger notifications, etc.
}

app.listen(3000, () => {
  console.log('Webhook server listening on port 3000');
});

Webhook Handler (Python)

import hmac
import hashlib
import json
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = os.getenv('WEBHOOK_SECRET')

def verify_webhook_signature(payload: str, signature: str) -> bool:
    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)

@app.route('/webhooks/mindpeeker', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-MindPeeker-Signature')
    payload = request.get_data(as_text=True)
    
    if not verify_webhook_signature(payload, signature):
        return jsonify({'error': 'Invalid signature'}), 401
    
    try:
        event = json.loads(payload)
        
        if event['type'] == 'session.completed':
            handle_session_completed(event['data'])
        elif event['type'] == 'session.failed':
            handle_session_failed(event['data'])
        elif event['type'] == 'analysis.ready':
            handle_analysis_ready(event['data'])
        else:
            print(f"Unhandled event type: {event['type']}")
        
        return jsonify({'received': True}), 200
    except Exception as error:
        print(f"Webhook processing error: {error}")
        return jsonify({'error': 'Internal server error'}), 500

def handle_session_completed(data):
    print(f"Session {data['session_id']} completed")
    # Process completed session

def handle_session_failed(data):
    print(f"Session {data['session_id']} failed: {data['error']}")
    # Handle failed session

def handle_analysis_ready(data):
    print(f"Analysis {data['analysis_id']} ready for session {data['session_id']}")
    # Process analysis results

if __name__ == '__main__':
    app.run(port=3000)

Webhook Event Processing

Event Processing Architecture

interface WebhookEvent {
  id: string;
  type: WebhookEventType;
  data: any;
  timestamp: string;
  signature: string;
}

enum WebhookEventType {
  SESSION_COMPLETED = 'session.completed',
  SESSION_FAILED = 'session.failed',
  SESSION_CANCELLED = 'session.cancelled',
  ANALYSIS_READY = 'analysis.ready',
  ANALYSIS_FAILED = 'analysis.failed',
  USER_CREATED = 'user.created',
  USER_UPDATED = 'user.updated',
  BILLING_PAYMENT_SUCCEEDED = 'billing.payment_succeeded',
  BILLING_PAYMENT_FAILED = 'billing.payment_failed'
}

class WebhookProcessor {
  private eventHandlers: Map<WebhookEventType, EventHandler>;
  private retryQueue: RetryQueue;
  private deadLetterQueue: DeadLetterQueue;

  constructor() {
    this.eventHandlers = new Map();
    this.retryQueue = new RetryQueue();
    this.deadLetterQueue = new DeadLetterQueue();
    this.setupHandlers();
  }

  private setupHandlers(): void {
    this.eventHandlers.set(WebhookEventType.SESSION_COMPLETED, new SessionCompletedHandler());
    this.eventHandlers.set(WebhookEventType.SESSION_FAILED, new SessionFailedHandler());
    this.eventHandlers.set(WebhookEventType.ANALYSIS_READY, new AnalysisReadyHandler());
    // ... other handlers
  }

  async processEvent(event: WebhookEvent): Promise<void> {
    const handler = this.eventHandlers.get(event.type);
    
    if (!handler) {
      console.warn(`No handler for event type: ${event.type}`);
      return;
    }

    try {
      await handler.handle(event.data);
      console.log(`Successfully processed event: ${event.id}`);
    } catch (error) {
      console.error(`Failed to process event ${event.id}:`, error);
      await this.retryQueue.add(event, error);
    }
  }
}

interface EventHandler {
  handle(data: any): Promise<void>;
}

class SessionCompletedHandler implements EventHandler {
  async handle(data: any): Promise<void> {
    // Update local database
    await this.updateSessionStatus(data.session_id, 'completed');
    
    // Process results
    await this.processResults(data.session_id, data.results);
    
    // Send notifications
    await this.sendNotifications(data.user_id, data.session_id);
    
    // Update analytics
    await this.updateAnalytics(data);
  }

  private async updateSessionStatus(sessionId: string, status: string): Promise<void> {
    // Database update logic
  }

  private async processResults(sessionId: string, results: any): Promise<void> {
    // Results processing logic
  }

  private async sendNotifications(userId: string, sessionId: string): Promise<void> {
    // Notification logic
  }

  private async updateAnalytics(data: any): Promise<void> {
    // Analytics update logic
  }
}

Database Integration Requirements

Data Synchronization

Real-time Data Sync

interface DataSyncConfig {
  syncInterval: number;          // Sync interval in milliseconds
  batchSize: number;            // Records per batch
  maxRetries: number;           // Maximum retry attempts
  conflictResolution: ConflictResolutionStrategy;
}

enum ConflictResolutionStrategy {
  LAST_WRITE_WINS = 'last_write_wins',
  FIRST_WRITE_WINS = 'first_write_wins',
  MANUAL_REVIEW = 'manual_review',
  MERGE = 'merge'
}

class DataSynchronizer {
  private config: DataSyncConfig;
  private localDatabase: Database;
  private mindPeekerClient: MindPeekerClient;

  constructor(config: DataSyncConfig) {
    this.config = config;
    this.localDatabase = new Database();
    this.mindPeekerClient = new MindPeekerClient();
  }

  async startSync(): Promise<void> {
    setInterval(async () => {
      try {
        await this.syncSessions();
        await this.syncAnalyses();
        await this.syncUsers();
      } catch (error) {
        console.error('Sync error:', error);
      }
    }, this.config.syncInterval);
  }

  private async syncSessions(): Promise<void> {
    const lastSyncTime = await this.getLastSyncTime('sessions');
    const remoteSessions = await this.mindPeekerClient.sessions.list({
      updated_since: lastSyncTime,
      limit: this.config.batchSize
    });

    for (const session of remoteSessions.data) {
      const localSession = await this.localDatabase.sessions.findById(session.id);
      
      if (!localSession) {
        await this.localDatabase.sessions.create(session);
      } else if (this.hasConflict(localSession, session)) {
        await this.resolveConflict(localSession, session);
      } else if (this.needsUpdate(localSession, session)) {
        await this.localDatabase.sessions.update(session.id, session);
      }
    }

    await this.updateLastSyncTime('sessions');
  }

  private hasConflict(local: any, remote: any): boolean {
    return local.updated_at !== remote.updated_at && 
           local.version !== remote.version;
  }

  private async resolveConflict(local: any, remote: any): Promise<void> {
    switch (this.config.conflictResolution) {
      case ConflictResolutionStrategy.LAST_WRITE_WINS:
        await this.localDatabase.sessions.update(remote.id, remote);
        break;
      case ConflictResolutionStrategy.MANUAL_REVIEW:
        await this.queueForReview(local, remote);
        break;
      // ... other strategies
    }
  }
}

Backup and Recovery

Automated Backup Strategy

interface BackupConfig {
  schedule: string;              // Cron expression
  retentionDays: number;         // Days to retain backups
  compressionEnabled: boolean;   // Enable compression
  encryptionEnabled: boolean;    // Enable encryption
  storageLocation: StorageLocation;
}

enum StorageLocation {
  LOCAL = 'local',
  S3 = 's3',
  AZURE_BLOB = 'azure_blob',
  GOOGLE_CLOUD = 'google_cloud'
}

class BackupManager {
  private config: BackupConfig;
  private encryptionKey: string;

  constructor(config: BackupConfig, encryptionKey: string) {
    this.config = config;
    this.encryptionKey = encryptionKey;
  }

  async performBackup(): Promise<string> {
    const timestamp = new Date().toISOString();
    const backupId = `backup_${timestamp.replace(/[:.]/g, '-')}`;
    
    try {
      // Create backup
      const backupData = await this.createBackup();
      
      // Compress if enabled
      const compressedData = this.config.compressionEnabled 
        ? await this.compress(backupData)
        : backupData;
      
      // Encrypt if enabled
      const encryptedData = this.config.encryptionEnabled
        ? await this.encrypt(compressedData)
        : compressedData;
      
      // Store backup
      const backupUrl = await this.storeBackup(backupId, encryptedData);
      
      // Update backup registry
      await this.updateBackupRegistry(backupId, backupUrl, timestamp);
      
      // Clean old backups
      await this.cleanupOldBackups();
      
      return backupId;
    } catch (error) {
      console.error('Backup failed:', error);
      throw error;
    }
  }

  private async createBackup(): Promise<any> {
    // Export all relevant data
    const users = await this.exportUsers();
    const sessions = await this.exportSessions();
    const analyses = await this.exportAnalyses();
    const metadata = await this.exportMetadata();

    return {
      timestamp: new Date().toISOString(),
      version: '1.0',
      data: {
        users,
        sessions,
        analyses,
        metadata
      }
    };
  }

  private async storeBackup(backupId: string, data: Buffer): Promise<string> {
    switch (this.config.storageLocation) {
      case StorageLocation.S3:
        return await this.storeToS3(backupId, data);
      case StorageLocation.AZURE_BLOB:
        return await this.storeToAzureBlob(backupId, data);
      case StorageLocation.GOOGLE_CLOUD:
        return await this.storeToGoogleCloud(backupId, data);
      default:
        return await this.storeLocally(backupId, data);
    }
  }

  async restoreFromBackup(backupId: string): Promise<void> {
    try {
      // Retrieve backup
      const backupData = await this.retrieveBackup(backupId);
      
      // Decrypt if encrypted
      const decryptedData = this.config.encryptionEnabled
        ? await this.decrypt(backupData)
        : backupData;
      
      // Decompress if compressed
      const decompressedData = this.config.compressionEnabled
        ? await this.decompress(decryptedData)
        : decryptedData;
      
      // Parse backup data
      const backup = JSON.parse(decompressedData.toString());
      
      // Validate backup integrity
      await this.validateBackup(backup);
      
      // Restore data
      await this.restoreUsers(backup.data.users);
      await this.restoreSessions(backup.data.sessions);
      await this.restoreAnalyses(backup.data.analyses);
      await this.restoreMetadata(backup.data.metadata);
      
      console.log(`Successfully restored from backup: ${backupId}`);
    } catch (error) {
      console.error('Restore failed:', error);
      throw error;
    }
  }
}

Security Integration Requirements

Data Encryption

Client-Side Encryption

import crypto from 'crypto';

class ClientEncryption {
  private encryptionKey: Buffer;

  constructor(keyBase64: string) {
    this.encryptionKey = Buffer.from(keyBase64, 'base64');
  }

  encryptSensitiveData(data: string): string {
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipher('aes-256-gcm', this.encryptionKey);
    cipher.setAAD(Buffer.from('mindpeeker-data'));
    
    let encrypted = cipher.update(data, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    
    const authTag = cipher.getAuthTag();
    
    return JSON.stringify({
      iv: iv.toString('hex'),
      encrypted,
      authTag: authTag.toString('hex')
    });
  }

  decryptSensitiveData(encryptedData: string): string {
    const { iv, encrypted, authTag } = JSON.parse(encryptedData);
    
    const decipher = crypto.createDecipher('aes-256-gcm', this.encryptionKey);
    decipher.setAAD(Buffer.from('mindpeeker-data'));
    decipher.setAuthTag(Buffer.from(authTag, 'hex'));
    
    let decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    
    return decrypted;
  }
}

// Usage example
const encryption = new ClientEncryption(process.env.ENCRYPTION_KEY);

// Encrypt sensitive cue data before sending
const sensitiveCue = "Private investigation details about case #12345";
const encryptedCue = encryption.encryptSensitiveData(sensitiveCue);

// Send to API
await client.sessions.create({
  cue: encryptedCue,
  session_type: 'remote_viewing',
  metadata: { encrypted: true }
});

Access Control Integration

Role-Based Access Control (RBAC)

interface Role {
  id: string;
  name: string;
  permissions: Permission[];
  conditions?: AccessCondition[];
}

interface Permission {
  resource: string;
  actions: string[];
  conditions?: AccessCondition[];
}

interface AccessCondition {
  field: string;
  operator: 'eq' | 'ne' | 'in' | 'not_in' | 'gt' | 'lt';
  value: any;
}

class AccessControlManager {
  private roles: Map<string, Role>;
  private userRoles: Map<string, string[]>;

  constructor() {
    this.roles = new Map();
    this.userRoles = new Map();
    this.loadRoles();
  }

  async checkPermission(
    userId: string, 
    resource: string, 
    action: string, 
    context?: any
  ): Promise<boolean> {
    const userRoleIds = this.userRoles.get(userId) || [];
    
    for (const roleId of userRoleIds) {
      const role = this.roles.get(roleId);
      if (!role) continue;

      for (const permission of role.permissions) {
        if (this.matchesPermission(permission, resource, action, context)) {
          return true;
        }
      }
    }

    return false;
  }

  private matchesPermission(
    permission: Permission, 
    resource: string, 
    action: string, 
    context?: any
  ): boolean {
    // Check resource match
    if (!this.matchesResource(permission.resource, resource)) {
      return false;
    }

    // Check action match
    if (!permission.actions.includes(action) && !permission.actions.includes('*')) {
      return false;
    }

    // Check conditions
    if (permission.conditions && context) {
      return this.evaluateConditions(permission.conditions, context);
    }

    return true;
  }

  private matchesResource(permissionResource: string, actualResource: string): boolean {
    if (permissionResource === '*') return true;
    if (permissionResource === actualResource) return true;
    
    // Support wildcard patterns like 'sessions.*'
    const pattern = permissionResource.replace('*', '.*');
    const regex = new RegExp(`^${pattern}$`);
    return regex.test(actualResource);
  }

  private evaluateConditions(conditions: AccessCondition[], context: any): boolean {
    return conditions.every(condition => {
      const contextValue = this.getNestedValue(context, condition.field);
      
      switch (condition.operator) {
        case 'eq':
          return contextValue === condition.value;
        case 'ne':
          return contextValue !== condition.value;
        case 'in':
          return Array.isArray(condition.value) && condition.value.includes(contextValue);
        case 'not_in':
          return Array.isArray(condition.value) && !condition.value.includes(contextValue);
        case 'gt':
          return contextValue > condition.value;
        case 'lt':
          return contextValue < condition.value;
        default:
          return false;
      }
    });
  }

  private getNestedValue(obj: any, path: string): any {
    return path.split('.').reduce((current, key) => current?.[key], obj);
  }
}

// Middleware for API protection
function requirePermission(resource: string, action: string) {
  return async (req: any, res: any, next: any) => {
    const userId = req.user.id;
    const accessControl = new AccessControlManager();
    
    const hasPermission = await accessControl.checkPermission(
      userId, 
      resource, 
      action, 
      {
        sessionId: req.params.sessionId,
        userId: req.params.userId,
        organization: req.user.organization
      }
    );

    if (!hasPermission) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }

    next();
  };
}

// Usage in API routes
app.get('/sessions/:sessionId', 
  authenticateUser,
  requirePermission('sessions', 'read'),
  async (req, res) => {
    // Session retrieval logic
  }
);

Performance Integration Requirements

Caching Strategy

Multi-Level Caching

interface CacheConfig {
  levels: CacheLevel[];
  defaultTTL: number;
  maxSize: number;
  evictionPolicy: EvictionPolicy;
}

enum CacheLevel {
  MEMORY = 'memory',
  REDIS = 'redis',
  DATABASE = 'database'
}

enum EvictionPolicy {
  LRU = 'lru',
  LFU = 'lfu',
  FIFO = 'fifo'
}

class MultiLevelCache {
  private config: CacheConfig;
  private memoryCache: Map<string, CacheEntry>;
  private redisClient: Redis;

  constructor(config: CacheConfig) {
    this.config = config;
    this.memoryCache = new Map();
    this.redisClient = new Redis(process.env.REDIS_URL);
  }

  async get<T>(key: string): Promise<T | null> {
    // Try memory cache first
    const memoryEntry = this.memoryCache.get(key);
    if (memoryEntry && !this.isExpired(memoryEntry)) {
      return memoryEntry.value;
    }

    // Try Redis cache
    try {
      const redisValue = await this.redisClient.get(key);
      if (redisValue) {
        const parsed = JSON.parse(redisValue);
        
        // Promote to memory cache
        this.memoryCache.set(key, {
          value: parsed,
          timestamp: Date.now(),
          ttl: this.config.defaultTTL
        });
        
        return parsed;
      }
    } catch (error) {
      console.error('Redis cache error:', error);
    }

    return null;
  }

  async set<T>(key: string, value: T, ttl?: number): Promise<void> {
    const effectiveTTL = ttl || this.config.defaultTTL;
    const entry: CacheEntry = {
      value,
      timestamp: Date.now(),
      ttl: effectiveTTL
    };

    // Set in memory cache
    this.memoryCache.set(key, entry);
    this.enforceMemoryLimit();

    // Set in Redis cache
    try {
      await this.redisClient.setex(
        key, 
        Math.ceil(effectiveTTL / 1000), 
        JSON.stringify(value)
      );
    } catch (error) {
      console.error('Redis cache set error:', error);
    }
  }

  async invalidate(pattern: string): Promise<void> {
    // Invalidate memory cache
    for (const key of this.memoryCache.keys()) {
      if (this.matchesPattern(key, pattern)) {
        this.memoryCache.delete(key);
      }
    }

    // Invalidate Redis cache
    try {
      const keys = await this.redisClient.keys(pattern);
      if (keys.length > 0) {
        await this.redisClient.del(...keys);
      }
    } catch (error) {
      console.error('Redis cache invalidation error:', error);
    }
  }

  private enforceMemoryLimit(): void {
    if (this.memoryCache.size <= this.config.maxSize) {
      return;
    }

    const entries = Array.from(this.memoryCache.entries());
    
    switch (this.config.evictionPolicy) {
      case EvictionPolicy.LRU:
        entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
        break;
      case EvictionPolicy.LFU:
        // Implementation would need access frequency tracking
        entries.sort((a, b) => (a[1].accessCount || 0) - (b[1].accessCount || 0));
        break;
      case EvictionPolicy.FIFO:
        entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
        break;
    }

    const toRemove = entries.slice(0, entries.length - this.config.maxSize);
    toRemove.forEach(([key]) => this.memoryCache.delete(key));
  }

  private isExpired(entry: CacheEntry): boolean {
    return Date.now() - entry.timestamp > entry.ttl;
  }

  private matchesPattern(key: string, pattern: string): boolean {
    const regex = new RegExp(pattern.replace('*', '.*'));
    return regex.test(key);
  }
}

interface CacheEntry {
  value: any;
  timestamp: number;
  ttl: number;
  accessCount?: number;
}

Rate Limiting

Distributed Rate Limiting

interface RateLimitConfig {
  windowMs: number;
  maxRequests: number;
  keyGenerator: (req: any) => string;
  skipSuccessfulRequests: boolean;
  skipFailedRequests: boolean;
}

class DistributedRateLimiter {
  private config: RateLimitConfig;
  private redisClient: Redis;

  constructor(config: RateLimitConfig) {
    this.config = config;
    this.redisClient = new Redis(process.env.REDIS_URL);
  }

  async isAllowed(req: any): Promise<{ allowed: boolean; remaining: number; resetTime: number }> {
    const key = this.config.keyGenerator(req);
    const now = Date.now();
    const windowStart = now - this.config.windowMs;

    // Remove expired entries
    await this.redisClient.zremrangebyscore(key, 0, windowStart);

    // Count current requests
    const currentRequests = await this.redisClient.zcard(key);

    if (currentRequests >= this.config.maxRequests) {
      const oldestRequest = await this.redisClient.zrange(key, 0, 0, 'WITHSCORES');
      const resetTime = parseInt(oldestRequest[1]) + this.config.windowMs;
      
      return {
        allowed: false,
        remaining: 0,
        resetTime
      };
    }

    // Add current request
    await this.redisClient.zadd(key, now, `${now}-${Math.random()}`);
    await this.redisClient.expire(key, Math.ceil(this.config.windowMs / 1000));

    return {
      allowed: true,
      remaining: this.config.maxRequests - currentRequests - 1,
      resetTime: now + this.config.windowMs
    };
  }

  middleware() {
    return async (req: any, res: any, next: any) => {
      const result = await this.isAllowed(req);
      
      res.set({
        'X-RateLimit-Limit': this.config.maxRequests,
        'X-RateLimit-Remaining': result.remaining,
        'X-RateLimit-Reset': new Date(result.resetTime).toISOString()
      });

      if (!result.allowed) {
        return res.status(429).json({
          error: 'Too many requests',
          message: `Rate limit exceeded. Try again in ${Math.ceil((result.resetTime - Date.now()) / 1000)} seconds.`
        });
      }

      next();
    };
  }
}

// Usage example
const rateLimiter = new DistributedRateLimiter({
  windowMs: 60 * 1000, // 1 minute
  maxRequests: 100,
  keyGenerator: (req) => `rate_limit:${req.user?.id || req.ip}`,
  skipSuccessfulRequests: false,
  skipFailedRequests: false
});

app.use('/api/', rateLimiter.middleware());

These integration requirements provide comprehensive guidelines for successfully integrating with the MindPeeker platform, covering authentication, SDK usage, webhooks, data synchronization, security, and performance considerations.