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.