10 KiB
10 KiB
Integration Settings Workflow & Data Flow
Part 1: How Global Settings Load on Frontend
Admin Configures Global Settings
URL: https://api.igny8.com/admin/system/globalintegrationsettings/1/change/
What's Stored:
- Platform-wide API keys (OpenAI, DALL-E, Runware)
- Default model selections (gpt-4o-mini, dall-e-3, runware:97@1)
- Default parameters (temperature: 0.7, max_tokens: 8192)
- Default image settings (size, quality, style)
Who Can Access: Only platform administrators
Normal User Opens Integration Page
URL: https://app.igny8.com/settings/integration
What Happens:
-
Frontend Request:
- User browser requests:
GET /api/v1/system/settings/integrations/openai/ - User browser requests:
GET /api/v1/system/settings/integrations/image_generation/
- User browser requests:
-
Backend Processing (
integration_views.py-get_settings()method):- Checks if user's account has custom overrides in
IntegrationSettingstable - Gets global defaults from
GlobalIntegrationSettingssingleton - Merges data with this priority:
- If account has overrides → use account settings
- If no overrides → use global defaults
- NEVER returns API keys (security)
- Checks if user's account has custom overrides in
-
Response to Frontend:
{ "id": "openai", "enabled": true, "model": "gpt-4o-mini", // From global OR account override "temperature": 0.7, // From global OR account override "max_tokens": 8192, // From global OR account override "using_global": true // Flag: true if using defaults } -
Frontend Display:
- Shows current model selection
- Shows "Using platform defaults" badge if
using_global: true - Shows "Custom settings" badge if
using_global: false - User can change model, temperature, etc.
- API key status is NOT shown (user cannot see/change platform keys)
Part 2: How User Changes Are Saved
User Changes Settings on Frontend
-
User Actions:
- Opens settings modal
- Changes model from
gpt-4o-minitogpt-4o - Changes temperature from
0.7to0.8 - Clicks "Save"
-
Frontend Request:
- Sends:
PUT /api/v1/system/settings/integrations/openai/ - Body:
{"model": "gpt-4o", "temperature": 0.8, "max_tokens": 8192}
- Sends:
-
Backend Processing (
integration_views.py-save_settings()method):- CRITICAL SECURITY: Strips ANY API keys from request (apiKey, api_key, openai_api_key, etc.)
- Validates account exists
- Builds clean config with ONLY allowed overrides:
- For OpenAI: model, temperature, max_tokens
- For Image: service, model, image_quality, image_style, sizes
- Saves to
IntegrationSettingstable:account_id: 123 integration_type: "openai" config: {"model": "gpt-4o", "temperature": 0.8, "max_tokens": 8192} is_active: true
-
Database Structure:
-
GlobalIntegrationSettings (1 row, pk=1):
- Contains: API keys + default settings
- Used by: ALL accounts for API keys
-
IntegrationSettings (multiple rows):
- Row per account per integration type
- Contains: ONLY overrides (no API keys)
- Example:
id | account_id | integration_type | config 100 | 123 | openai | {"model": "gpt-4o", "temperature": 0.8} 101 | 456 | openai | {"model": "gpt-4.1", "max_tokens": 4000} 102 | 123 | image_generation| {"service": "runware", "model": "runware:100@1"}
-
-
Next Request from User:
- Frontend requests:
GET /api/v1/system/settings/integrations/openai/ - Backend finds IntegrationSettings row for account 123
- Returns:
{"model": "gpt-4o", "temperature": 0.8, "using_global": false} - User sees their custom settings
- Frontend requests:
Data Flow Architecture
┌─────────────────────────────────────────────────────────────┐
│ ADMIN SIDE │
│ https://api.igny8.com/admin/ │
│ │
│ GlobalIntegrationSettings (pk=1) │
│ ├── openai_api_key: "sk-xxx" ← Platform-wide │
│ ├── openai_model: "gpt-4o-mini" ← Default │
│ ├── openai_temperature: 0.7 ← Default │
│ ├── dalle_api_key: "sk-xxx" ← Platform-wide │
│ ├── runware_api_key: "xxx" ← Platform-wide │
│ └── image_quality: "standard" ← Default │
└─────────────────────────────────────────────────────────────┘
│
│ Backend reads from
↓
┌─────────────────────────────────────────────────────────────┐
│ BACKEND API LAYER │
│ integration_views.py │
│ │
│ get_settings(): │
│ 1. Load GlobalIntegrationSettings (for defaults) │
│ 2. Check IntegrationSettings (for account overrides) │
│ 3. Merge: account overrides > global defaults │
│ 4. Return to frontend (NO API keys) │
│ │
│ save_settings(): │
│ 1. Receive request from frontend │
│ 2. Strip ALL API keys (security) │
│ 3. Save ONLY overrides to IntegrationSettings │
└─────────────────────────────────────────────────────────────┘
│
│ API sends data
↓
┌─────────────────────────────────────────────────────────────┐
│ FRONTEND - USER SIDE │
│ https://app.igny8.com/settings/integration │
│ │
│ User sees: │
│ ├── Model: gpt-4o-mini (dropdown) │
│ ├── Temperature: 0.7 (slider) │
│ ├── Status: ✓ Connected (test connection works) │
│ └── Badge: "Using platform defaults" │
│ │
│ User CANNOT see: │
│ ✗ API keys (security) │
│ ✗ Platform configuration │
└─────────────────────────────────────────────────────────────┘
│
│ User changes settings
↓
┌─────────────────────────────────────────────────────────────┐
│ IntegrationSettings Table │
│ (Per-account overrides - NO API KEYS) │
│ │
│ Account 123: │
│ ├── openai: {"model": "gpt-4o", "temperature": 0.8} │
│ └── image_generation: {"service": "runware"} │
│ │
│ Account 456: │
│ ├── openai: {"model": "gpt-4.1"} │
│ └── image_generation: (no row = uses global defaults) │
└─────────────────────────────────────────────────────────────┘
Important Security Rules
-
API Keys Flow:
- Admin sets → GlobalIntegrationSettings
- Backend uses → For ALL accounts
- Frontend NEVER sees → Security
- Users NEVER save → Stripped by backend
-
Settings Flow:
- Admin sets defaults → GlobalIntegrationSettings
- Users customize → IntegrationSettings (overrides only)
- Backend merges → Global defaults + account overrides
- Frontend displays → Merged result (no keys)
-
Free Plan Restriction:
- Cannot create IntegrationSettings rows
- Must use global defaults only
- Enforced at frontend (UI disabled)
- TODO: Add backend validation
Example Scenarios
Scenario 1: New User First Visit
- User has NO IntegrationSettings row
- Backend returns global defaults
using_global: true- User sees platform defaults
- API operations use platform API key
Scenario 2: User Customizes Model
- User changes model to "gpt-4o"
- Frontend sends:
{"model": "gpt-4o"} - Backend creates IntegrationSettings row
- Next visit:
using_global: false - API operations use platform API key + user's model choice
Scenario 3: User Resets to Default
- Frontend sends:
{"model": "gpt-4o-mini"}(same as global) - Backend still saves override row
- Alternative: Delete row to truly use global
- TODO: Add "Reset to defaults" button
Scenario 4: Admin Changes Global Default
- Admin changes global model to "gpt-4.1"
- Users WITH overrides: See their custom model
- Users WITHOUT overrides: See new "gpt-4.1" default
- All users: Use platform API key