# External Integrations Schema

**MSP Mode Database Schema - External Systems Integration**

**Status:** Designed 2026-01-15 (Future Capability)
**Database:** msp_tracking (MariaDB on Jupiter)

---

## Overview

The External Integrations subsystem enables MSP Mode to connect with external MSP platforms, automate workflows, and link session data to ticketing and documentation systems. This bridges MSP Mode's intelligent tracking with real-world business systems.

**Core Integration Systems:**
- **SyncroMSP** - PSA/RMM platform (tickets, time tracking, assets)
- **MSP Backups** - Backup management and reporting
- **Zapier** - Automation platform (webhooks and triggers)

**Related Documentation:**
- [MSP-MODE-SPEC.md](../MSP-MODE-SPEC.md) - Full system specification
- [ARCHITECTURE_OVERVIEW.md](ARCHITECTURE_OVERVIEW.md) - System architecture
- [API_SPEC.md](API_SPEC.md) - API endpoints for integrations
- [SCHEMA_CREDENTIALS.md](SCHEMA_CREDENTIALS.md) - Integration credential storage

---

## Tables Summary

| Table | Purpose | Encryption |
|-------|---------|------------|
| `external_integrations` | Track all external system interactions | No (API responses) |
| `integration_credentials` | OAuth/API key storage for integrations | AES-256-GCM |
| `ticket_links` | Link sessions to external tickets | No |
| `backup_log` | Backup tracking with verification | No |

**Total:** 4 tables

**Specialized Agent:**
- **Integration Workflow Agent** - Executes multi-step integration workflows (ticket updates, report pulling, file attachments)

---

## Table Schemas

### `external_integrations`

Comprehensive tracking of all interactions with external systems. Audit trail for integration workflows.

```sql
CREATE TABLE external_integrations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id UUID REFERENCES sessions(id) ON DELETE CASCADE,
    work_item_id UUID REFERENCES work_items(id) ON DELETE CASCADE,
    client_id UUID REFERENCES clients(id) ON DELETE SET NULL,

    -- Integration details
    integration_type VARCHAR(100) NOT NULL CHECK(integration_type IN (
        'syncro_ticket', 'syncro_time', 'syncro_asset',
        'msp_backups_report', 'msp_backups_status',
        'zapier_webhook', 'zapier_trigger',
        'email_notification', 'custom_integration'
    )),
    integration_name VARCHAR(255), -- "SyncroMSP", "MSP Backups", "Zapier"

    -- External resource identification
    external_id VARCHAR(255), -- ticket ID, asset ID, webhook ID, etc.
    external_url VARCHAR(500), -- direct link to resource
    external_reference VARCHAR(255), -- human-readable: "T12345", "WH-ABC123"

    -- Action tracking
    action VARCHAR(50) CHECK(action IN (
        'created', 'updated', 'linked', 'attached',
        'retrieved', 'searched', 'deleted', 'triggered'
    )),
    direction VARCHAR(20) CHECK(direction IN ('outbound', 'inbound')),
    -- outbound: MSP Mode → External system
    -- inbound: External system → MSP Mode (via webhook)

    -- Request/Response data
    request_data TEXT, -- JSON: what we sent
    response_data TEXT, -- JSON: what we received
    response_status VARCHAR(50), -- "success", "error", "timeout"
    error_message TEXT,

    -- Performance tracking
    request_duration_ms INTEGER,
    retry_count INTEGER DEFAULT 0,

    -- Metadata
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(255), -- user who authorized

    INDEX idx_ext_int_session (session_id),
    INDEX idx_ext_int_work_item (work_item_id),
    INDEX idx_ext_int_client (client_id),
    INDEX idx_ext_int_type (integration_type),
    INDEX idx_ext_int_external (external_id),
    INDEX idx_ext_int_status (response_status),
    INDEX idx_ext_int_created (created_at)
);
```

**Example Integration Records:**

**SyncroMSP Ticket Update:**
```json
{
  "session_id": "current-session-uuid",
  "client_id": "dataforth-uuid",
  "integration_type": "syncro_ticket",
  "integration_name": "SyncroMSP",
  "external_id": "12345",
  "external_url": "https://azcomputerguru.syncromsp.com/tickets/12345",
  "external_reference": "T12345",
  "action": "updated",
  "direction": "outbound",
  "request_data": {
    "comment": "Changes made today:\n- Configured Veeam backup job for D2TESTNAS\n- Set retention: 30 days local, 90 days cloud\n- Tested backup: successful (45GB)\n- Verified restore point creation",
    "internal": false
  },
  "response_data": {
    "comment_id": "67890",
    "created_at": "2026-01-15T14:32:10Z"
  },
  "response_status": "success",
  "request_duration_ms": 245,
  "created_by": "mike@azcomputerguru.com"
}
```

**MSP Backups Report Retrieval:**
```json
{
  "session_id": "current-session-uuid",
  "client_id": "dataforth-uuid",
  "integration_type": "msp_backups_report",
  "integration_name": "MSP Backups",
  "action": "retrieved",
  "direction": "outbound",
  "request_data": {
    "customer": "Dataforth",
    "date": "2026-01-15",
    "format": "pdf"
  },
  "response_data": {
    "report_url": "https://storage.mspbackups.com/reports/dataforth_2026-01-15.pdf",
    "file_size_bytes": 1048576,
    "summary": {
      "total_jobs": 5,
      "successful": 5,
      "failed": 0,
      "total_size_gb": 245
    }
  },
  "response_status": "success",
  "request_duration_ms": 3420
}
```

**SyncroMSP File Attachment:**
```json
{
  "session_id": "current-session-uuid",
  "integration_type": "syncro_ticket",
  "external_id": "12345",
  "action": "attached",
  "direction": "outbound",
  "request_data": {
    "file_name": "dataforth_backup_report_2026-01-15.pdf",
    "file_size_bytes": 1048576
  },
  "response_data": {
    "attachment_id": "att_789",
    "url": "https://azcomputerguru.syncromsp.com/attachments/att_789"
  },
  "response_status": "success"
}
```

**Zapier Webhook Trigger (Inbound):**
```json
{
  "integration_type": "zapier_webhook",
  "external_id": "webhook_abc123",
  "action": "triggered",
  "direction": "inbound",
  "request_data": {
    "event": "ticket_created",
    "ticket_id": "12346",
    "customer": "Grabb & Durando",
    "subject": "Network connectivity issues"
  },
  "response_data": {
    "msp_mode_action": "created_pending_task",
    "task_id": "task-uuid"
  },
  "response_status": "success"
}
```

**Failed Integration (Timeout):**
```json
{
  "integration_type": "syncro_ticket",
  "action": "updated",
  "direction": "outbound",
  "request_data": {
    "ticket_id": "12345",
    "comment": "Work completed..."
  },
  "response_status": "error",
  "error_message": "Request timeout after 30000ms",
  "request_duration_ms": 30000,
  "retry_count": 3
}
```

---

### `integration_credentials`

Secure storage for integration authentication credentials (OAuth tokens, API keys).

```sql
CREATE TABLE integration_credentials (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    integration_name VARCHAR(100) NOT NULL UNIQUE, -- 'syncro', 'msp_backups', 'zapier'

    -- Credential type
    credential_type VARCHAR(50) CHECK(credential_type IN ('oauth', 'api_key', 'basic_auth', 'bearer_token')),

    -- Encrypted credentials (AES-256-GCM)
    api_key_encrypted BYTEA,
    oauth_token_encrypted BYTEA,
    oauth_refresh_token_encrypted BYTEA,
    oauth_client_id VARCHAR(255), -- not encrypted (public)
    oauth_client_secret_encrypted BYTEA,
    oauth_expires_at TIMESTAMP,
    basic_auth_username VARCHAR(255),
    basic_auth_password_encrypted BYTEA,

    -- OAuth metadata
    oauth_scopes TEXT, -- JSON array: ["tickets:read", "tickets:write"]
    oauth_authorize_url VARCHAR(500),
    oauth_token_url VARCHAR(500),

    -- API endpoints
    api_base_url VARCHAR(500) NOT NULL,
    webhook_url VARCHAR(500), -- for receiving webhooks
    webhook_secret_encrypted BYTEA,

    -- Status and health
    is_active BOOLEAN DEFAULT true,
    last_tested_at TIMESTAMP,
    last_test_status VARCHAR(50), -- "success", "auth_failed", "connection_error"
    last_test_error TEXT,
    last_used_at TIMESTAMP,

    -- Rate limiting
    rate_limit_requests INTEGER, -- requests per period
    rate_limit_period_seconds INTEGER, -- period in seconds
    rate_limit_remaining INTEGER, -- current remaining requests

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_int_cred_name (integration_name),
    INDEX idx_int_cred_active (is_active)
);
```

**Example Integration Credentials:**

**SyncroMSP (OAuth):**
```json
{
  "integration_name": "syncro",
  "credential_type": "oauth",
  "oauth_token_encrypted": "<encrypted_access_token>",
  "oauth_refresh_token_encrypted": "<encrypted_refresh_token>",
  "oauth_client_id": "syncro_client_id",
  "oauth_client_secret_encrypted": "<encrypted_secret>",
  "oauth_expires_at": "2026-01-16T14:30:00Z",
  "oauth_scopes": ["tickets:read", "tickets:write", "customers:read", "time_entries:write"],
  "oauth_authorize_url": "https://azcomputerguru.syncromsp.com/oauth/authorize",
  "oauth_token_url": "https://azcomputerguru.syncromsp.com/oauth/token",
  "api_base_url": "https://azcomputerguru.syncromsp.com/api/v1",
  "is_active": true,
  "last_tested_at": "2026-01-15T14:00:00Z",
  "last_test_status": "success",
  "rate_limit_requests": 1000,
  "rate_limit_period_seconds": 3600
}
```

**MSP Backups (API Key):**
```json
{
  "integration_name": "msp_backups",
  "credential_type": "api_key",
  "api_key_encrypted": "<encrypted_api_key>",
  "api_base_url": "https://api.mspbackups.com/v2",
  "is_active": true,
  "last_tested_at": "2026-01-15T09:00:00Z",
  "last_test_status": "success"
}
```

**Zapier (Webhook):**
```json
{
  "integration_name": "zapier",
  "credential_type": "bearer_token",
  "api_key_encrypted": "<encrypted_bearer_token>",
  "api_base_url": "https://hooks.zapier.com/hooks/catch",
  "webhook_url": "https://msp-api.azcomputerguru.com/api/v1/webhooks/zapier",
  "webhook_secret_encrypted": "<encrypted_webhook_secret>",
  "is_active": true
}
```

**Security Features:**
- All sensitive fields encrypted with AES-256-GCM
- Same master key as credentials table
- Automatic OAuth token refresh
- Rate limit tracking to prevent API abuse
- Health check monitoring

---

### `ticket_links`

Links MSP Mode sessions to external ticketing system tickets. Bi-directional reference.

```sql
CREATE TABLE ticket_links (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id UUID REFERENCES sessions(id) ON DELETE CASCADE,
    client_id UUID REFERENCES clients(id) ON DELETE CASCADE,
    work_item_id UUID REFERENCES work_items(id) ON DELETE SET NULL,

    -- Ticket identification
    integration_type VARCHAR(100) NOT NULL CHECK(integration_type IN (
        'syncro', 'autotask', 'connectwise', 'zendesk', 'freshdesk'
    )),
    ticket_id VARCHAR(255) NOT NULL, -- external system ticket ID
    ticket_number VARCHAR(100), -- human-readable: "T12345", "#12345"
    ticket_subject VARCHAR(500),
    ticket_url VARCHAR(500),
    ticket_status VARCHAR(100), -- "open", "in_progress", "resolved", "closed"
    ticket_priority VARCHAR(50), -- "low", "medium", "high", "critical"

    -- Linking metadata
    link_type VARCHAR(50) CHECK(link_type IN ('related', 'resolves', 'documents', 'caused_by')),
    -- related: session work related to ticket
    -- resolves: session work resolves the ticket
    -- documents: session documents work done for ticket
    -- caused_by: session work was triggered by ticket

    link_direction VARCHAR(20) CHECK(link_direction IN ('manual', 'automatic')),
    linked_by VARCHAR(255), -- user who created link

    -- Sync status
    auto_sync_enabled BOOLEAN DEFAULT false, -- auto-post session updates to ticket
    last_synced_at TIMESTAMP,
    sync_errors TEXT, -- JSON array of sync error messages

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_ticket_session (session_id),
    INDEX idx_ticket_client (client_id),
    INDEX idx_ticket_work_item (work_item_id),
    INDEX idx_ticket_external (integration_type, ticket_id),
    INDEX idx_ticket_status (ticket_status)
);
```

**Example Ticket Links:**

**Session Resolves Ticket:**
```json
{
  "session_id": "session-uuid",
  "client_id": "dataforth-uuid",
  "integration_type": "syncro",
  "ticket_id": "12345",
  "ticket_number": "T12345",
  "ticket_subject": "Backup configuration for NAS",
  "ticket_url": "https://azcomputerguru.syncromsp.com/tickets/12345",
  "ticket_status": "resolved",
  "ticket_priority": "high",
  "link_type": "resolves",
  "link_direction": "manual",
  "linked_by": "mike@azcomputerguru.com",
  "auto_sync_enabled": true,
  "last_synced_at": "2026-01-15T15:00:00Z"
}
```

**Work Item Documents Ticket:**
```json
{
  "session_id": "session-uuid",
  "work_item_id": "work-item-uuid",
  "client_id": "grabb-uuid",
  "integration_type": "syncro",
  "ticket_id": "12346",
  "ticket_number": "T12346",
  "ticket_subject": "DNS migration to UDM",
  "link_type": "documents",
  "link_direction": "automatic"
}
```

**Ticket Triggered Session:**
```json
{
  "session_id": "session-uuid",
  "client_id": "client-uuid",
  "integration_type": "syncro",
  "ticket_id": "12347",
  "ticket_subject": "Email delivery issues",
  "ticket_status": "in_progress",
  "link_type": "caused_by",
  "link_direction": "automatic",
  "auto_sync_enabled": true
}
```

---

### `backup_log`

Backup tracking with verification status. Can be populated from MSP Backups integration or local backup operations.

```sql
CREATE TABLE backup_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID REFERENCES clients(id) ON DELETE SET NULL,
    infrastructure_id UUID REFERENCES infrastructure(id) ON DELETE SET NULL,
    session_id UUID REFERENCES sessions(id) ON DELETE SET NULL,

    -- Backup classification
    backup_type VARCHAR(50) NOT NULL CHECK(backup_type IN (
        'daily', 'weekly', 'monthly', 'manual', 'pre-migration',
        'pre-upgrade', 'disaster_recovery'
    )),
    backup_source VARCHAR(100), -- "local", "veeam", "msp_backups", "manual"

    -- File details
    file_path VARCHAR(500) NOT NULL,
    file_name VARCHAR(255),
    file_size_bytes BIGINT NOT NULL,
    storage_location VARCHAR(500), -- "NAS", "Cloud", "Local", "Off-site"

    -- Timing
    backup_started_at TIMESTAMP NOT NULL,
    backup_completed_at TIMESTAMP NOT NULL,
    duration_seconds INTEGER GENERATED ALWAYS AS (
        TIMESTAMPDIFF(SECOND, backup_started_at, backup_completed_at)
    ) STORED,

    -- Verification
    verification_status VARCHAR(50) CHECK(verification_status IN (
        'passed', 'failed', 'not_verified', 'in_progress'
    )),
    verification_method VARCHAR(100), -- "test_restore", "checksum", "file_count", "manual"
    verification_details TEXT, -- JSON: specific check results
    verification_completed_at TIMESTAMP,

    -- Backup metadata
    database_host VARCHAR(255),
    database_name VARCHAR(100),
    backup_method VARCHAR(50), -- "mysqldump", "mariabackup", "file_copy", "veeam"
    compression_type VARCHAR(50), -- "gzip", "zip", "none"
    encryption_enabled BOOLEAN DEFAULT false,

    -- Retention
    retention_days INTEGER,
    scheduled_deletion_date TIMESTAMP,
    deleted_at TIMESTAMP,

    -- Status
    backup_status VARCHAR(50) DEFAULT 'completed' CHECK(backup_status IN (
        'in_progress', 'completed', 'failed', 'deleted'
    )),
    error_message TEXT,

    -- Integration linkage
    external_integration_id UUID REFERENCES external_integrations(id),

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_backup_client (client_id),
    INDEX idx_backup_infrastructure (infrastructure_id),
    INDEX idx_backup_type (backup_type),
    INDEX idx_backup_date (backup_completed_at),
    INDEX idx_backup_verification (verification_status),
    INDEX idx_backup_status (backup_status)
);
```

**Example Backup Records:**

**Successful Daily Backup:**
```json
{
  "client_id": "dataforth-uuid",
  "infrastructure_id": "ad2-uuid",
  "backup_type": "daily",
  "backup_source": "veeam",
  "file_path": "/mnt/backups/AD2_2026-01-15_daily.vbk",
  "file_name": "AD2_2026-01-15_daily.vbk",
  "file_size_bytes": 48318382080,
  "storage_location": "D2TESTNAS",
  "backup_started_at": "2026-01-15T02:00:00Z",
  "backup_completed_at": "2026-01-15T02:45:30Z",
  "verification_status": "passed",
  "verification_method": "test_restore",
  "verification_details": {
    "restore_test_successful": true,
    "files_verified": 12543,
    "checksum_valid": true
  },
  "verification_completed_at": "2026-01-15T03:15:00Z",
  "backup_method": "veeam",
  "compression_type": "veeam_proprietary",
  "encryption_enabled": true,
  "retention_days": 30,
  "backup_status": "completed"
}
```

**Pre-Migration Backup:**
```json
{
  "client_id": "grabb-uuid",
  "infrastructure_id": "pfsense-uuid",
  "session_id": "migration-session-uuid",
  "backup_type": "pre-migration",
  "backup_source": "manual",
  "file_path": "/backups/pfsense_config_pre_migration_2026-01-15.xml",
  "file_size_bytes": 524288,
  "storage_location": "Local",
  "backup_started_at": "2026-01-15T14:00:00Z",
  "backup_completed_at": "2026-01-15T14:00:15Z",
  "verification_status": "passed",
  "verification_method": "manual",
  "backup_method": "file_copy",
  "backup_status": "completed"
}
```

**Failed Backup:**
```json
{
  "client_id": "client-uuid",
  "infrastructure_id": "nas-uuid",
  "backup_type": "daily",
  "backup_source": "veeam",
  "file_path": "/mnt/backups/NAS_2026-01-15_daily.vbk",
  "backup_started_at": "2026-01-15T02:00:00Z",
  "backup_completed_at": "2026-01-15T02:05:00Z",
  "backup_status": "failed",
  "error_message": "Insufficient disk space on target. Available: 2GB, Required: 50GB",
  "verification_status": "not_verified"
}
```

**Database Backup:**
```json
{
  "backup_type": "daily",
  "backup_source": "local",
  "file_path": "/var/backups/mysql/msp_tracking_2026-01-15.sql.gz",
  "file_size_bytes": 10485760,
  "storage_location": "Jupiter",
  "backup_started_at": "2026-01-15T01:00:00Z",
  "backup_completed_at": "2026-01-15T01:02:30Z",
  "verification_status": "passed",
  "verification_method": "checksum",
  "database_host": "172.16.3.20",
  "database_name": "msp_tracking",
  "backup_method": "mysqldump",
  "compression_type": "gzip",
  "retention_days": 90,
  "backup_status": "completed"
}
```

---

## Integration Workflows

### SyncroMSP Ticket Update Workflow (Agent-Based)

**User Request:**
> "Find the ticket for Dataforth about Backups - update it with the changes we've made today, and pull a report from MSP backups to attach to that ticket"

**Execution:**

1. **Main Claude launches Integration Workflow Agent**

2. **Agent performs multi-step workflow:**

   **Step 1: Search for ticket**
   ```http
   GET https://azcomputerguru.syncromsp.com/api/v1/tickets?customer_id=12345&subject=backup
   Authorization: Bearer <oauth_token>
   ```
   - Result: Ticket #12345 "Backup configuration for NAS"

   **Step 2: Generate work summary**
   - Process current session work_items
   - Create dense summary:
     ```
     Changes made today:
     - Configured Veeam backup job for D2TESTNAS
     - Set retention: 30 days local, 90 days cloud
     - Tested backup: successful (45GB)
     - Verified restore point creation
     ```

   **Step 3: Update ticket**
   ```http
   POST https://azcomputerguru.syncromsp.com/api/v1/tickets/12345/comments
   {
     "comment": "<work_summary>",
     "internal": false
   }
   ```
   - Store in external_integrations table

   **Step 4: Pull backup report**
   ```http
   GET https://api.mspbackups.com/v2/reports?customer=Dataforth&date=2026-01-15
   ```
   - Receives report PDF (agent handles large file)
   - Summarize: "5 backup jobs, all successful, total size 245GB"

   **Step 5: Attach report to ticket**
   ```http
   POST https://azcomputerguru.syncromsp.com/api/v1/tickets/12345/attachments
   Content-Type: multipart/form-data
   file: dataforth_backup_report.pdf
   ```

   **Step 6: Create ticket link**
   ```sql
   INSERT INTO ticket_links (
     session_id, client_id, integration_type,
     ticket_id, ticket_subject, link_type
   ) VALUES (
     'current-session-uuid', 'dataforth-uuid', 'syncro',
     '12345', 'Backup configuration for NAS', 'documents'
   );
   ```

3. **Agent returns concise summary:**
   ```
   Workflow complete:
   ✓ Found ticket #12345: Backup configuration for NAS
   ✓ Added work summary comment
   ✓ Pulled backup report (5 jobs, all successful, 245GB)
   ✓ Attached report to ticket
   ```

4. **Main Claude confirms to user**

**Context Saved:**
- Agent handled all API calls, file transfers, database updates
- Main Claude only received 50-word summary
- Large PDF file never entered main context

---

### Auto Time Tracking Workflow

**When session ends with billable hours:**

1. **Ask user:**
   - "Log 2.5 hours to SyncroMSP ticket T12345? (y/n)"

2. **If yes, call SyncroMSP API:**
   ```http
   POST https://azcomputerguru.syncromsp.com/api/v1/time_entries
   {
     "ticket_id": 12345,
     "user_id": 12,
     "duration_minutes": 150,
     "work_description": "Backup configuration and testing",
     "billable": true
   }
   ```

3. **Log in external_integrations:**
   ```json
   {
     "integration_type": "syncro_time",
     "action": "created",
     "external_id": "time_entry_789",
     "request_data": {...},
     "response_status": "success"
   }
   ```

---

### Backup Report Automation

**Trigger:** User mentions "backup" in MSP session

1. **Detect keyword** "backup"

2. **Auto-suggest:**
   - "Pull latest backup report for Dataforth? (y/n)"

3. **If yes, query MSP Backups API:**
   ```http
   GET https://api.mspbackups.com/v2/reports?customer=Dataforth&date=latest
   ```

4. **Display summary to user:**
   - "Latest backup report: 5 jobs, all successful, 245GB total"

5. **Options:**
   - Attach to ticket
   - Save to session
   - Email to client

---

## OAuth Flow

**User initiates:** `/msp integrate syncro`

1. **Generate OAuth URL:**
   ```
   https://azcomputerguru.syncromsp.com/oauth/authorize
     ?client_id=<client_id>
     &redirect_uri=https://msp-api.azcomputerguru.com/oauth/callback
     &response_type=code
     &scope=tickets:read tickets:write time_entries:write
   ```

2. **User authorizes in browser**

3. **Callback receives authorization code:**
   ```http
   GET https://msp-api.azcomputerguru.com/oauth/callback?code=abc123
   ```

4. **Exchange code for tokens:**
   ```http
   POST https://azcomputerguru.syncromsp.com/oauth/token
   {
     "grant_type": "authorization_code",
     "code": "abc123",
     "client_id": "<client_id>",
     "client_secret": "<client_secret>",
     "redirect_uri": "https://msp-api.azcomputerguru.com/oauth/callback"
   }
   ```

5. **Encrypt and store tokens:**
   ```sql
   INSERT INTO integration_credentials (
     integration_name, credential_type,
     oauth_token_encrypted, oauth_refresh_token_encrypted,
     oauth_expires_at, ...
   )
   ```

6. **Confirm to user:**
   - "SyncroMSP connected successfully. Scopes: tickets:read, tickets:write, time_entries:write"

---

## Security Considerations

### API Key Storage
- All integration credentials encrypted with AES-256-GCM
- Same master key as credentials table
- Separate from user credentials (different permission scopes)

### OAuth Token Refresh
```python
# Automatic token refresh before expiration
if oauth_expires_at <= NOW() + INTERVAL 5 MINUTE:
    # Refresh token
    response = requests.post(oauth_token_url, data={
        'grant_type': 'refresh_token',
        'refresh_token': decrypt(oauth_refresh_token_encrypted),
        'client_id': oauth_client_id,
        'client_secret': decrypt(oauth_client_secret_encrypted)
    })

    # Update stored tokens
    update_integration_credentials(
        new_access_token=response['access_token'],
        new_refresh_token=response.get('refresh_token'),
        expires_at=NOW() + response['expires_in']
    )
```

### Rate Limiting
- Track API rate limits per integration
- Implement exponential backoff on rate limit errors
- Queue requests if rate limit reached

### Webhook Security
- Verify webhook signatures
- Store webhook secrets encrypted
- IP whitelist for webhook endpoints (optional)

---

## Future Enhancements

**Phase 1 (MVP):**
- SyncroMSP ticket search and read
- Manual ticket linking
- Session summary → ticket comment (manual)

**Phase 2:**
- MSP Backups report pulling
- File attachments to tickets
- OAuth token refresh automation
- Auto-suggest ticket linking

**Phase 3:**
- Zapier webhook triggers
- Auto time tracking
- Multi-step workflows
- Natural language commands

**Phase 4:**
- Bi-directional sync
- Advanced automation
- Additional PSA integrations (Autotask, ConnectWise)
- IT Glue documentation sync

---

**Document Version:** 1.0
**Last Updated:** 2026-01-15
**Author:** MSP Mode Schema Design Team
