# Phase 7: Integration Layer — Implementation Plan

## Architecture

### Data Model

**New table: `webhook_destinations`**
```sql
CREATE TABLE webhook_destinations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    site_id INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
    name TEXT NOT NULL DEFAULT 'Integration',
    type TEXT NOT NULL,  -- 'webhook', 'google_sheets', 'slack', 'discord', 'telegram', 'airtable', 'notion', 'csv_export', 'json_export'
    url TEXT,            -- webhook URL or API endpoint (NULL for export types)
    config TEXT,         -- JSON: additional config (channel, auth, headers, etc.)
    enabled INTEGER DEFAULT 1,
    last_status TEXT,    -- 'delivered', 'failed', null
    last_error TEXT,
    last_delivered_at TIMESTAMP,
    success_count INTEGER DEFAULT 0,
    failure_count INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_destinations_site ON webhook_destinations(site_id);
```

**Extend `webhook_logs`:**
- Add `destination_id INTEGER REFERENCES webhook_destinations(id)`
- Backfill existing entries with `destination_id = NULL` (legacy webhook_url)

### Integration Formatters

Each integration type has a formatter function: `format_payload(type, config, submission, field_config, site)` → `(url, payload, headers)`

| Type | URL Source | Payload Format | Extra Config |
|------|-----------|---------------|--------------|
| webhook | url field | Standard JSON (existing format) | Custom headers |
| google_sheets | Apps Script URL | CSV line or JSON | Sheet name |
| slack | Incoming Webhook URL | Blocks/markdown | Channel (optional) |
| discord | Webhook URL | Embed + fields | Username, avatar, color |
| telegram | Bot API URL | Formatted message | chat_id |
| airtable | API endpoint | JSON record | api_key, base_id, table |
| notion | API endpoint | JSON page | api_key, database_id |
| csv_export | N/A (download) | CSV response | N/A |
| json_export | N/A (download) | JSON response | N/A |

### Implementation Order

1. **7.1** Migration: `webhook_destinations` table + extend `webhook_logs`
2. **7.2** `app/services/integrations.py`: formatter functions
3. **7.2** Refactor `app/services/webhook.py`: iterate destinations, use formatters
4. **7.2** Refactor retry worker: per-destination retry
5. **7.11** Update models.py: destination delivery tracking functions
6. **7.3** UI: Integrations tab in edit_site.html
7. **7.4-7.10** Integration templates + setup docs (UI components)
8. **7.8** CSV/JSON export endpoints
9. **7.12** Delivery status UI (per-destination stats)

### Backward Compatibility

- Legacy `sites.webhook_url` + `sites.webhook_enabled` still works
- If `webhook_enabled=1` and no destinations exist, fire the legacy URL
- If destinations exist, fire destinations (ignoring legacy webhook_url)
- Old webhook_logs entries with NULL destination_id treated as legacy
