# GLOBAL SETTINGS - CORRECT IMPLEMENTATION **Date**: December 20, 2025 **Status**: ✅ FIXED AND WORKING --- ## WHAT WAS WRONG The initial implementation had: - AccountIntegrationOverride model allowing users to use their own API keys - Enterprise plan that doesn't exist - Confusing override logic where accounts could bring their own API keys ## WHAT IS NOW CORRECT ### Architecture **1. Plans (Only 4 Valid)**: - Free Plan - Cannot override anything, uses global defaults - Starter Plan - Can override model/settings - Growth Plan - Can override model/settings - Scale Plan - Can override model/settings **2. API Keys** (Platform-Wide): - Stored in GlobalIntegrationSettings (singleton, pk=1) - ALL accounts use platform API keys - NO user can bring their own API keys - NO exceptions for any plan level **3. Model & Parameter Overrides** (Per-Account): - Stored in IntegrationSettings model (per-account) - Free plan: CANNOT create overrides - Starter/Growth/Scale: CAN override model, temperature, max_tokens, image settings - NULL values in config = use global default - API keys NEVER stored here **4. Prompts** (Global + Override): - GlobalAIPrompt: Platform-wide default prompts - AIPrompt: Per-account with default_prompt field - When user customizes: prompt_value changes, default_prompt stays same - Reset to default: Copies default_prompt back to prompt_value - is_customized flag tracks if using custom or default --- ## WHERE TO FIND SETTINGS IN DJANGO ADMIN ### 1. Global Integration Settings **URL**: /admin/system/globalintegrationsettings/ **What It Stores**: - Platform OpenAI API key (used by ALL accounts) - Platform DALL-E API key (used by ALL accounts) - Platform Anthropic API key (used by ALL accounts) - Platform Runware API key (used by ALL accounts) - Default model selections for each service - Default parameters (temperature, max_tokens, image quality, etc.) **Important**: - Singleton model (only 1 record, pk=1) - Changes affect ALL accounts using global defaults - Free plan accounts MUST use these (cannot override) - Other plans can override model/params but NOT API keys ### 2. Integration Settings (Per-Account Overrides) **URL**: /admin/system/integrationsettings/ **What It Stores**: - Per-account model selection overrides - Per-account parameter overrides (temperature, max_tokens, etc.) - Per-account image setting overrides (size, quality, style) **What It DOES NOT Store**: - API keys (those come from global) **Who Can Create**: - Starter/Growth/Scale plans only - Free plan users cannot create these **How It Works**: - If account has IntegrationSettings record with config values → uses those - If config field is NULL or missing → uses global default - API key ALWAYS from GlobalIntegrationSettings **Example Config**: ```json { "model": "gpt-4", "temperature": 0.8, "max_tokens": 4000 } ``` ### 3. Global AI Prompts **URL**: /admin/system/globalaiprompt/ **What It Stores**: - Platform-wide default prompt templates - Used for: clustering, ideas, content_generation, etc. **How Accounts Use Them**: - All accounts start with global prompts - When user wants to customize, system creates AIPrompt record - AIPrompt.default_prompt = GlobalAIPrompt.prompt_value (for reset) - AIPrompt.prompt_value = user's custom text - AIPrompt.is_customized = True ### 4. AI Prompts (Per-Account) **URL**: /admin/system/aiprompt/ **What It Stores**: - Account-specific prompt customizations - default_prompt field = global default (for reset) - prompt_value = current prompt (custom or default) - is_customized = True if user modified it **Actions Available**: - "Reset selected prompts to global default" - Copies default_prompt → prompt_value, sets is_customized=False --- ## HOW IT WORKS (Complete Flow) ### Text Generation Request 1. Code calls: `get_model_config(function_name='generate_content', account=some_account)` 2. System gets API key from GlobalIntegrationSettings: - `global_settings = GlobalIntegrationSettings.get_instance()` - `api_key = global_settings.openai_api_key` # ALWAYS from global 3. System checks for account overrides: - Try to find IntegrationSettings for this account + integration_type='openai' - If found: Use config['model'], config['temperature'], config['max_tokens'] - If not found OR config field is NULL: Use global defaults 4. Result returned: ```python { 'api_key': 'sk-xxx', # Always from global 'model': 'gpt-4', # From account override OR global 'temperature': 0.8, # From account override OR global 'max_tokens': 4000 # From account override OR global } ``` ### Prompt Retrieval 1. Code calls: `AIPrompt.get_effective_prompt(account=some_account, prompt_type='clustering')` 2. System checks for account-specific prompt: - Try to find AIPrompt for this account + prompt_type - If found and is_customized=True: Return prompt_value - If found and is_customized=False: Return default_prompt 3. If no account prompt found: - Get GlobalAIPrompt for prompt_type - Return global prompt_value ### User Customizes a Prompt 1. User edits prompt in frontend 2. Frontend saves to AIPrompt model: - If AIPrompt doesn't exist: Create new record - Set default_prompt = GlobalAIPrompt.prompt_value (for future reset) - Set prompt_value = user's custom text - Set is_customized = True ### User Resets Prompt 1. User clicks "Reset to Default" 2. System calls: `AIPrompt.reset_to_default()` 3. Method does: - prompt_value = default_prompt - is_customized = False - save() --- ## MIGRATION APPLIED **File**: 0004_fix_global_settings_remove_override.py **Changes**: - Added default_prompt field to AIPrompt model - Updated help text on IntegrationSettings.config field - Updated integration_type choices (removed GSC, image_generation) - Updated GlobalIntegrationSettings help text - Removed AccountIntegrationOverride model --- ## ADMIN INTERFACE CHANGES **GlobalIntegrationSettings Admin**: - Shows all platform API keys and default settings - One record only (singleton) - Help text clarifies these are used by ALL accounts **IntegrationSettings Admin**: - Help text emphasizes: "NEVER store API keys here" - Config field description explains it's for overrides only - Removed bulk_test_connection action - Free plan check should be added to prevent creation **AIPrompt Admin**: - Added default_prompt to readonly_fields - Added "Reset selected prompts to global default" bulk action - Fieldsets show both prompt_value and default_prompt **Removed**: - AccountIntegrationOverride model - AccountIntegrationOverrideAdmin class - All references to per-account API keys --- ## SIDEBAR NAVIGATION (TODO) Need to add links in app sidebar to access global settings: **For Superusers/Admin**: - Global Settings - Platform API Keys (/admin/system/globalintegrationsettings/) - Global Prompts (/admin/system/globalaiprompt/) - Global Author Profiles (/admin/system/globalauthorprofile/) - Global Strategies (/admin/system/globalstrategy/) **For All Users** (Starter+ plans): - Account Settings - AI Model Selection (/settings/ai) - Configure IntegrationSettings - Custom Prompts (/settings/prompts) - Manage AIPrompts - Author Profiles (/settings/profiles) - Manage AuthorProfiles - Content Strategies (/settings/strategies) - Manage Strategies --- ## VERIFICATION Run these commands to verify: ```bash # Check migration applied docker exec igny8_backend python manage.py showmigrations system # Verify global settings exist docker exec igny8_backend python manage.py shell -c " from igny8_core.modules.system.global_settings_models import GlobalIntegrationSettings obj = GlobalIntegrationSettings.get_instance() print(f'OpenAI Model: {obj.openai_model}') print(f'Max Tokens: {obj.openai_max_tokens}') " # Check AIPrompt has default_prompt field docker exec igny8_backend python manage.py shell -c " from igny8_core.modules.system.models import AIPrompt fields = [f.name for f in AIPrompt._meta.get_fields()] print('default_prompt' in fields) " # Verify AccountIntegrationOverride removed docker exec igny8_backend python manage.py shell -c " try: from igny8_core.modules.system.global_settings_models import AccountIntegrationOverride print('ERROR: Model still exists!') except ImportError: print('✓ Model correctly removed') " ``` --- ## QUICK START 1. **Configure Platform API Keys**: - Login to Django Admin - Go to: System → Global integration settings - Fill in OpenAI, DALL-E API keys - Set default models - Save 2. **Create Global Prompts**: - Go to: System → Global ai prompts - Add prompts for: clustering, ideas, content_generation - These become defaults for all accounts 3. **Test with Account**: - Create test account on Starter plan - Account automatically uses global API keys - Account can create IntegrationSettings to override model selection - Account CANNOT override API keys 4. **Verify Free Plan Restriction**: - Create test account on Free plan - Verify they CANNOT create IntegrationSettings records - Verify they use global defaults only --- ## SUMMARY ✅ **Correct**: Platform API keys used by all accounts ✅ **Correct**: No user can bring their own API keys ✅ **Correct**: Only 4 plans (Free, Starter, Growth, Scale) ✅ **Correct**: Free plan cannot override, must use global ✅ **Correct**: Other plans can override model/params only ✅ **Correct**: Prompts have default_prompt for reset ✅ **Correct**: Global settings NOT associated with any account ❌ **Removed**: AccountIntegrationOverride model ❌ **Removed**: Enterprise plan references ❌ **Removed**: "Bring your own API key" functionality 🔧 **TODO**: Add sidebar navigation links to global settings 🔧 **TODO**: Add plan check to IntegrationSettings creation --- *For complete implementation details, see COMPLETE-IMPLEMENTATION-GUIDE.md*