Essentials

Best Practices

Security, performance, and reliability best practices for device agents.

Security Best Practices

API Key Management

DO:

  • Store API keys securely (encrypted storage, environment variables)
  • Use separate API keys for each device
  • Rotate API keys periodically
  • Never log API keys in console or files

DON'T:

  • Hardcode API keys in source code
  • Commit API keys to version control
  • Share API keys between devices
  • Expose API keys in error messages

Example - Secure Storage:

// JavaScript - Use environment variables
const API_KEY = process.env.SULALA_API_KEY;

// Flutter - Use secure storage
final prefs = await SharedPreferences.getInstance();
final apiKey = prefs.getString('api_key');

Network Security

DO:

  • Always use HTTPS (never HTTP in production)
  • Validate SSL certificates
  • Implement certificate pinning for production
  • Use secure connection timeouts

DON'T:

  • Use HTTP for production
  • Ignore SSL certificate errors
  • Send sensitive data over unencrypted connections

Example - HTTPS Only:

// JavaScript
const BASE_URL = process.env.NODE_ENV === 'production' 
  ? 'https://sulala.ai' 
  : 'http://localhost:3000';

Data Privacy

DO:

  • Limit search scope to necessary directories
  • Exclude sensitive folders (e.g., ~/.ssh, ~/Documents/Private)
  • Implement user consent for file access
  • Encrypt sensitive data before transmission

DON'T:

  • Search system directories without permission
  • Access private user data without consent
  • Store sensitive file contents unnecessarily

Example - Safe Search Scope:

const SAFE_DIRECTORIES = [
  '~/Documents',
  '~/Downloads',
  '~/Desktop'
];

const EXCLUDED_DIRECTORIES = [
  '~/.ssh',
  '~/.config',
  '~/Library/Application Support'
];

Performance Best Practices

Polling Optimization

DO:

  • Use recommended polling intervals (30 seconds)
  • Combine heartbeat and search polling
  • Implement exponential backoff on errors
  • Stop polling when device is offline

DON'T:

  • Poll too frequently (wastes battery/bandwidth)
  • Poll when device is sleeping
  • Ignore rate limits

Example - Efficient Polling:

// Poll after heartbeat
async function pollCycle() {
  await sendHeartbeat();
  await pollForSearches();
  await pollForUploadRequests();
}

setInterval(pollCycle, 30000); // 30 seconds

Search Optimization

DO:

  • Limit search scope to what's needed
  • Use indexed search when possible
  • Cache recent search results
  • Implement search timeouts

DON'T:

  • Search entire filesystem unnecessarily
  • Search system directories
  • Return too many results (limit to top 100)

Example - Optimized Search:

async function searchFiles(query, maxResults = 100) {
  const results = [];
  const searchPaths = getSearchPaths();
  
  for (const path of searchPaths) {
    const files = await searchInDirectory(path, query);
    results.push(...files);
    
    if (results.length >= maxResults) break;
  }
  
  return results.slice(0, maxResults);
}

Resource Management

DO:

  • Limit memory usage for large searches
  • Use streaming for large file uploads
  • Clean up temporary files
  • Monitor resource usage

DON'T:

  • Load entire files into memory
  • Keep connections open unnecessarily
  • Accumulate memory leaks

Reliability Best Practices

Error Handling

DO:

  • Implement retry logic with exponential backoff
  • Log errors for debugging
  • Handle network timeouts gracefully
  • Provide user feedback on errors

DON'T:

  • Crash on errors
  • Retry indefinitely
  • Ignore error responses
  • Expose internal errors to users

Example - Robust Error Handling:

async function sendHeartbeatWithRetry(maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await sendHeartbeat();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await sleep(Math.pow(2, i) * 1000); // Exponential backoff
    }
  }
}

Connection Management

DO:

  • Implement connection pooling
  • Reuse HTTP connections
  • Handle connection drops gracefully
  • Verify connectivity before operations

DON'T:

  • Create new connections for each request
  • Ignore connection errors
  • Assume network is always available

Logging

DO:

  • Log important events (heartbeat, searches, errors)
  • Use appropriate log levels (debug, info, warn, error)
  • Rotate log files to prevent disk fill
  • Never log sensitive data (API keys, file contents)

DON'T:

  • Log everything (performance impact)
  • Log sensitive information
  • Keep logs indefinitely
  • Log in production at debug level

Example - Proper Logging:

logger.info('Heartbeat sent', { 
  deviceId: deviceId,
  status: 'online' 
});

logger.error('Search failed', { 
  queryId: queryId,
  error: error.message  // Don't log full stack trace in production
});

Development Best Practices

Code Organization

DO:

  • Separate concerns (heartbeat, search, upload)
  • Use configuration files for settings
  • Implement proper error types
  • Write unit tests

DON'T:

  • Mix concerns in single functions
  • Hardcode configuration values
  • Use generic error types
  • Skip tests

Configuration Management

DO:

  • Use environment variables for configuration
  • Provide sensible defaults
  • Validate configuration on startup
  • Document all configuration options

Example - Configuration:

const config = {
  apiKey: process.env.SULALA_API_KEY || '',
  baseUrl: process.env.SULALA_BASE_URL || 'http://localhost:3000',
  heartbeatInterval: parseInt(process.env.HEARTBEAT_INTERVAL || '30000'),
  pollingInterval: parseInt(process.env.POLLING_INTERVAL || '30000')
};

Testing

DO:

  • Test error scenarios
  • Test network failures
  • Test with invalid API keys
  • Test search functionality locally first

DON'T:

  • Only test happy path
  • Ignore edge cases
  • Skip integration tests

Deployment Best Practices

Startup Configuration

DO:

  • Start agent on system boot
  • Run as background service/daemon
  • Implement graceful shutdown
  • Handle system sleep/wake events

Example - System Service (macOS):

<!-- LaunchAgent plist -->
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>

Monitoring

DO:

  • Monitor device online status
  • Track search success rate
  • Monitor error rates
  • Alert on critical failures

DON'T:

  • Deploy without monitoring
  • Ignore error patterns
  • Skip health checks

Updates

DO:

  • Support configuration updates without restart
  • Implement update mechanism
  • Test updates in staging first
  • Provide rollback capability

Platform-Specific Best Practices

macOS

DO:

  • Request proper permissions (Full Disk Access)
  • Handle App Sandbox restrictions
  • Use system tray for background operation
  • Handle macOS sleep/wake events

Windows

DO:

  • Run as Windows Service for production
  • Handle Windows sleep/hibernate
  • Request proper UAC permissions
  • Use Windows notification area

Linux

DO:

  • Run as systemd service
  • Handle Linux power management
  • Request proper file permissions
  • Use desktop environment tray

Mobile (Flutter)

DO:

  • Request runtime permissions
  • Handle background execution limits
  • Optimize for battery usage
  • Handle app lifecycle events

Checklist

Before deploying to production:

  • API keys stored securely
  • HTTPS enabled for production
  • Error handling implemented
  • Logging configured properly
  • Resource limits set
  • Monitoring in place
  • Tests passing
  • Documentation updated
  • Backup/rollback plan ready

Next Steps