23 KiB
System Architecture Analysis: Super User Access & Global Settings Strategy
Date: December 20, 2025
Purpose: Strategic analysis of super user access, global settings architecture, and separation of admin functions
Status: Planning & Analysis Phase
Executive Summary
This document analyzes the current super user/aws-admin architecture and proposes a cleaner separation between:
- Backend administrative access (Django admin - keep as is)
- Frontend user interface (remove super user exceptions)
- Global system settings (true global config, not account-based fallbacks)
Current State Analysis
1. Backend Super User Access (Django Admin)
Current Implementation: ✅ WELL DESIGNED - KEEP AS IS
Purpose:
- Full database access and management
- Account, user, billing administration
- System configuration
- Data cleanup and maintenance
- Background task monitoring
Verdict: REQUIRED - Backend super user is essential for:
- Database migrations
- Emergency data fixes
- Account management
- Billing operations
- System maintenance
2. Frontend Super User Access (React App)
Current Implementation: ⚠️ QUESTIONABLE - NEEDS REVIEW
2.1 What Frontend Admin Pages Currently Do
| Page Category | Current Pages | Functionality | Django Admin Equivalent | Recommendation |
|---|---|---|---|---|
| System Dashboard | /admin/dashboard |
Account stats, usage metrics | ✅ Available via django-admin dashboard | 🔄 MOVE to Django admin |
| Account Management | /admin/accounts/admin/subscriptions/admin/account-limits |
View/edit all accounts | ✅ Available in django admin | 🔄 MOVE to Django admin |
| Billing Admin | /admin/billing/admin/invoices/admin/payments/admin/credit-costs/admin/credit-packages |
Billing operations | ✅ Available in django admin | 🔄 MOVE to Django admin |
| User Admin | /admin/users/admin/roles/admin/activity-logs |
User management | ✅ Available in django admin | 🔄 MOVE to Django admin |
| System Config | /admin/system-settings/admin/ai-settings/settings/modules/admin/integration-settings |
Global settings | ⚠️ Partially in django admin | ⚠️ REVIEW - See section 3 |
| Monitoring | /settings/status/settings/api-monitor/settings/debug-status |
API health, debug info | ❌ Not in django admin | 🔄 MOVE to Django admin |
| Developer Tools | /admin/function-testing/admin/system-testing |
Testing utilities | ❌ Not in django admin | 🗑️ REMOVE or move to Django admin |
| UI Elements | 22 demo pages | Component library showcase | ❌ Not needed in admin | 🗑️ REMOVE from production |
2.2 Problems with Current Frontend Admin Access
Issue 1: Duplicate Interfaces
- Same data manageable in both Django admin and React frontend
- Two UIs to maintain for the same operations
- Inconsistent behavior between the two
Issue 2: Security Surface Area
- Frontend admin pages increase attack surface
- Additional routes to protect
- Client-side code can be inspected/manipulated
Issue 3: Development Complexity
- Special cases throughout codebase for super user
- Fallback logic mixed with primary logic
- Harder to test and maintain
Issue 4: User Confusion
- Normal users wonder why menu items don't work
- Unclear which interface to use (Django admin vs frontend)
- UI elements demo pages in production
3. Global Settings Architecture
Current Implementation: ⚠️ POORLY DESIGNED - NEEDS REFACTORING
3.1 Current "Fallback" Pattern (WRONG APPROACH)
File: backend/igny8_core/ai/settings.py (Lines 53-65)
# Current: "Fallback" to aws-admin settings
if not settings_obj:
for slug in ['aws-admin', 'default-account', 'default']:
system_account = Account.objects.filter(slug=slug).first()
if system_account:
settings_obj = IntegrationSettings.objects.filter(account=system_account).first()
if settings_obj:
break
Problems:
- ❌ Called "fallback" but actually used as primary global settings
- ❌ Settings tied to an account (aws-admin) when they should be account-independent
- ❌ If aws-admin account deleted, global settings lost
- ❌ Confusing: "aws-admin account settings" vs "global platform settings"
- ❌ Users might think they need API keys, but system uses shared keys
3.2 Settings Currently Using Fallback Pattern
Integration Settings (OpenAI, DALL-E, Anthropic, etc.):
- ❌ Current: Per-account with fallback to aws-admin
- ✅ Should be: Global system settings (no account association)
- ⚠️ Exception: Allow power users to override with their own keys (optional)
AI Prompts:
- ❌ Current: Per-account with system defaults
- ✅ Should be: Global prompt library with account-level customization
Content Strategies:
- ❌ Current: Mixed account-level and global
- ✅ Should be: Global templates + account customization
Author Profiles:
- ❌ Current: Mixed account-level and global
- ✅ Should be: Global library + account customization
Publishing Channels:
- ✅ Current: Already global (correct approach)
- ✅ Keep as is
Proposed Architecture
Phase 1: Remove Frontend Admin Exceptions
1.1 Remove Frontend Admin Routes
Pages to Remove from Frontend:
/admin/dashboard → Use Django admin dashboard
/admin/accounts → Use Django admin
/admin/subscriptions → Use Django admin
/admin/account-limits → Use Django admin
/admin/billing → Use Django admin
/admin/invoices → Use Django admin
/admin/payments → Use Django admin
/admin/credit-costs → Use Django admin
/admin/credit-packages → Use Django admin
/admin/users → Use Django admin
/admin/roles → Use Django admin
/admin/activity-logs → Use Django admin
/admin/system-settings → Use Django admin
/admin/ai-settings → Use Django admin
/admin/integration-settings → Use Django admin
/admin/function-testing → Remove (dev tool)
/admin/system-testing → Remove (dev tool)
/ui-elements/* → Remove (22 demo pages)
Pages to Move to Django Admin:
/settings/status → Create Django admin page
/settings/api-monitor → Create Django admin page
/settings/debug-status → Create Django admin page
Pages to Keep in Frontend (Normal user features):
/settings/modules → Keep (account owners enable/disable modules)
/settings/account → Keep (account settings, team management)
/settings/billing → Keep (view own invoices, payment methods)
/settings/integrations → Keep (configure own WordPress sites)
1.2 Remove Frontend Super User Checks
Files to Clean Up:
- AppSidebar.tsx - Remove admin section entirely
- AdminGuard.tsx - Remove (no admin routes to guard)
- ProtectedRoute.tsx - Remove
isPrivilegedchecks - ApiStatusIndicator.tsx - Move to Django admin
- ResourceDebugOverlay.tsx - Remove or django admin only
- api.ts - Remove comments about admin/developer overrides
Result: Frontend becomes pure user interface with no special cases for super users.
Phase 2: Refactor Global Settings Architecture
2.1 Create True Global Settings Models
New Database Structure:
# NEW: Global system settings (no account foreign key)
class GlobalIntegrationSettings(models.Model):
"""
Global platform-wide integration settings
Used by all accounts unless they provide their own keys
"""
# OpenAI
openai_api_key = EncryptedCharField(max_length=500, blank=True)
openai_model = models.CharField(max_length=100, default='gpt-4')
openai_temperature = models.FloatField(default=0.7)
# DALL-E
dalle_api_key = EncryptedCharField(max_length=500, blank=True)
dalle_model = models.CharField(max_length=100, default='dall-e-3')
# Anthropic
anthropic_api_key = EncryptedCharField(max_length=500, blank=True)
anthropic_model = models.CharField(max_length=100, default='claude-3-sonnet')
# System metadata
is_active = models.BooleanField(default=True)
last_updated = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Global Integration Settings"
verbose_name_plural = "Global Integration Settings"
def __str__(self):
return "Global Integration Settings"
# MODIFIED: Account-specific overrides (optional)
class AccountIntegrationSettings(models.Model):
"""
Optional account-specific API key overrides
If not set, uses GlobalIntegrationSettings
"""
account = models.OneToOneField(Account, on_delete=models.CASCADE)
# Override OpenAI (blank = use global)
openai_api_key = EncryptedCharField(max_length=500, blank=True, null=True)
openai_model = models.CharField(max_length=100, blank=True, null=True)
# Override DALL-E (blank = use global)
dalle_api_key = EncryptedCharField(max_length=500, blank=True, null=True)
use_own_keys = models.BooleanField(default=False,
help_text="If True, account must provide their own API keys. If False, uses global keys.")
def get_effective_settings(self):
"""Get effective settings (own keys or global)"""
if self.use_own_keys and self.openai_api_key:
return {
'openai_api_key': self.openai_api_key,
'openai_model': self.openai_model or GlobalIntegrationSettings.objects.first().openai_model,
# ... etc
}
else:
# Use global settings
global_settings = GlobalIntegrationSettings.objects.first()
return {
'openai_api_key': global_settings.openai_api_key,
'openai_model': global_settings.openai_model,
# ... etc
}
2.2 Updated Settings Lookup Logic
Before (Confusing Fallback):
# Look for account settings → fallback to aws-admin account
settings_obj = IntegrationSettings.objects.filter(account=account).first()
if not settings_obj:
# "Fallback" to aws-admin (confusing - actually primary!)
system_account = Account.objects.filter(slug='aws-admin').first()
settings_obj = IntegrationSettings.objects.filter(account=system_account).first()
After (Clear Global Settings):
# Try account-specific override first
account_settings = AccountIntegrationSettings.objects.filter(account=account).first()
if account_settings and account_settings.use_own_keys:
# Account provides their own keys
return account_settings.get_effective_settings()
else:
# Use global platform settings
global_settings = GlobalIntegrationSettings.objects.first()
return global_settings
2.3 Settings That Should Be Global
Truly Global (No account association):
- ✅ OpenAI/DALL-E/Anthropic API keys (system default)
- ✅ Default AI models (gpt-4, dall-e-3, etc.)
- ✅ Default temperature/parameters
- ✅ Rate limiting rules
- ✅ Cost per operation (CreditCostConfig)
- ✅ System-wide feature flags
Global Library with Account Customization:
- ✅ AI Prompts (global library + account custom prompts)
- ✅ Content Strategies (global templates + account strategies)
- ✅ Author Profiles (global personas + account authors)
- ✅ Publishing Channels (global available channels)
Purely Account-Specific:
- ✅ WordPress site integrations
- ✅ Account billing settings
- ✅ Team member permissions
- ✅ Site/Sector structure
Phase 3: Django Admin Enhancement
3.1 New Django Admin Pages to Create
Monitoring Dashboard (Replace /settings/status):
# backend/igny8_core/admin/monitoring.py
def system_health_dashboard(request):
"""
Django admin page showing:
- Database connections
- Redis status
- Celery workers
- API response times
- Error rates
"""
context = {
'db_status': check_database(),
'redis_status': check_redis(),
'celery_workers': check_celery(),
'api_health': check_api_endpoints(),
}
return render(request, 'admin/monitoring/system_health.html', context)
API Monitor (Replace /settings/api-monitor):
def api_monitor_dashboard(request):
"""
Django admin page showing:
- All API endpoints status
- Response time graphs
- Error rate by endpoint
- Recent failed requests
"""
# Current ApiStatusIndicator logic moved here
pass
Debug Console (Replace /settings/debug-status):
def debug_console(request):
"""
Django admin page showing:
- Environment variables
- Active settings
- Feature flags
- Cache status
"""
pass
3.2 Add to Django Admin Site URLs
# backend/igny8_core/admin/site.py
def get_urls(self):
urls = super().get_urls()
custom_urls = [
# Existing
path('dashboard/', self.admin_view(admin_dashboard), name='dashboard'),
path('reports/revenue/', self.admin_view(revenue_report), name='report_revenue'),
# NEW: Monitoring pages
path('monitoring/system-health/', self.admin_view(system_health_dashboard), name='monitoring_system_health'),
path('monitoring/api-monitor/', self.admin_view(api_monitor_dashboard), name='monitoring_api_monitor'),
path('monitoring/debug-console/', self.admin_view(debug_console), name='monitoring_debug_console'),
]
return custom_urls + urls
Pros & Cons Analysis
Current Architecture (Frontend Admin Access)
Pros:
- ✅ Modern UI for admin operations
- ✅ Real-time monitoring in React
- ✅ Consistent look with rest of app
- ✅ Easier to build complex dashboards
Cons:
- ❌ Duplicate interfaces (Django + React)
- ❌ More code to maintain
- ❌ Larger security surface area
- ❌ Special cases throughout codebase
- ❌ Confusing fallback patterns
- ❌ Client-side admin code visible
Proposed Architecture (Django Admin Only)
Pros:
- ✅ Single source of truth for admin operations
- ✅ Smaller attack surface
- ✅ Less code to maintain
- ✅ No special cases in frontend
- ✅ Clear separation of concerns
- ✅ Django admin is battle-tested
- ✅ Better security (server-side only)
- ✅ Truly global settings (not account-based)
Cons:
- ⚠️ Need to build monitoring pages in Django admin
- ⚠️ Less modern UI (Django admin vs React)
- ⚠️ Some features need recreation
Migration Strategy
Step 1: Create Global Settings Models (Week 1)
Tasks:
- ✅ Create
GlobalIntegrationSettingsmodel - ✅ Create
GlobalSystemSettingsmodel - ✅ Migrate existing aws-admin settings to global settings
- ✅ Create migration script
- ✅ Update
get_settings()functions to use global first
Migration Script:
# management/commands/migrate_to_global_settings.py
def handle(self):
# 1. Get aws-admin account settings
aws_account = Account.objects.filter(slug='aws-admin').first()
if aws_account:
account_settings = IntegrationSettings.objects.filter(account=aws_account).first()
# 2. Create global settings from aws-admin settings
GlobalIntegrationSettings.objects.create(
openai_api_key=account_settings.openai_api_key,
openai_model=account_settings.openai_model,
dalle_api_key=account_settings.dalle_api_key,
# ... copy all settings
)
# 3. Delete aws-admin specific settings (now global)
account_settings.delete()
print("✅ Migrated to global settings")
Step 2: Update Backend Logic (Week 1-2)
Files to Update:
ai/settings.py- Use global settingsai/ai_core.py- Remove aws-admin fallbackapi/permissions.py- RemoveIsSystemAccountOrDeveloper(no longer needed)- API views - Remove super user bypasses
Example Change:
# BEFORE
def get_openai_settings(account):
settings = IntegrationSettings.objects.filter(account=account).first()
if not settings:
# Fallback to aws-admin
aws = Account.objects.filter(slug='aws-admin').first()
settings = IntegrationSettings.objects.filter(account=aws).first()
return settings
# AFTER
def get_openai_settings(account):
# Check if account has custom keys
account_settings = AccountIntegrationSettings.objects.filter(account=account).first()
if account_settings and account_settings.use_own_keys:
return account_settings.get_effective_settings()
# Use global settings
return GlobalIntegrationSettings.objects.first()
Step 3: Create Django Admin Monitoring Pages (Week 2)
Create:
- System Health Dashboard
- API Monitor
- Debug Console
- Add to Django admin menu
Test:
- Access from Django admin at
/admin/monitoring/ - Verify functionality matches React pages
Step 4: Remove Frontend Admin Routes (Week 3)
Remove Routes:
// Remove from src/routes.tsx
- /admin/dashboard
- /admin/accounts
- /admin/*
- /ui-elements/*
Remove Components:
src/pages/Admin/ → DELETE entire directory
src/pages/UIElements/ → DELETE entire directory
src/components/auth/AdminGuard.tsx → DELETE
Clean Sidebar:
// src/layout/AppSidebar.tsx
// Remove entire adminSection
// Remove isAwsAdminAccount checks
Step 5: Clean Up Frontend Code (Week 3-4)
Remove:
- Super user checks in ProtectedRoute
- Developer role checks everywhere
isAwsAdminvariables- Comments about admin/developer overrides
Keep:
- Normal user role checks (owner, admin, editor, viewer)
- Account-level permission checks
- Module enable/disable settings (account level)
Step 6: Test & Deploy (Week 4)
Test Cases:
- ✅ Regular users can't access Django admin
- ✅ Super user can access Django admin monitoring
- ✅ Global settings work for all accounts
- ✅ Account-level overrides work
- ✅ No frontend admin routes accessible
- ✅ All user features still work
Recommended Approach
✅ RECOMMENDED: Hybrid Approach
Backend: Keep super user in Django admin (essential for system management)
Frontend: Remove all super user access - make it pure user interface
Settings: True global settings, not account-based fallbacks
Monitoring: Django admin only
Implementation Priority
Phase 1 (Immediate - Week 1-2):
- ✅ Create global settings models
- ✅ Migrate aws-admin settings to global
- ✅ Update backend logic to use global settings
- ✅ Test thoroughly
Phase 2 (Short-term - Week 3-4):
- ✅ Create Django admin monitoring pages
- ✅ Remove frontend admin routes
- ✅ Clean up frontend code
- ✅ Test end-to-end
Phase 3 (Optional - Month 2):
- ⚠️ Allow account-level API key overrides (for power users)
- ⚠️ Add usage tracking per account
- ⚠️ Alert on API key quota issues
Settings Architecture Decision Matrix
| Setting Type | Current | Proposed | Reasoning |
|---|---|---|---|
| OpenAI API Key | aws-admin fallback | Global with optional override | Most users should use shared key for simplicity |
| AI Model Selection | aws-admin fallback | Global default, allow account override | Power users may want specific models |
| AI Prompts | Mixed | Global library + account custom | Templates global, customization per account |
| Content Strategies | Mixed | Global templates + account strategies | Same as prompts |
| Author Profiles | Mixed | Global library + account authors | Same as prompts |
| Credit Costs | Global | Global (keep as is) | System-wide pricing |
| Publishing Channels | Global | Global (keep as is) | Already correct |
| WordPress Integrations | Per-account | Per-account (keep as is) | User-specific connections |
Benefits of Proposed Architecture
For Development Team
- ✅ Less code to maintain - Remove entire frontend admin section
- ✅ Clearer architecture - No special cases for super users
- ✅ Easier testing - No need to test admin UI in React
- ✅ Better separation - Admin vs user concerns clearly separated
For Security
- ✅ Smaller attack surface - No client-side admin code
- ✅ Single admin interface - Only Django admin to secure
- ✅ No frontend bypasses - No special logic in React
- ✅ True global settings - Not dependent on aws-admin account
For Users
- ✅ Clearer interface - No confusing admin menu items
- ✅ Simpler setup - Global settings work out of box
- ✅ Optional customization - Can override with own keys if needed
- ✅ Better performance - Less code loaded in frontend
For Operations
- ✅ Single source of truth - Django admin for all admin tasks
- ✅ Better monitoring - Centralized in Django admin
- ✅ Audit trail - All admin actions logged
- ✅ No AWS account dependency - Global settings not tied to account
Risks & Mitigation
Risk 1: Loss of React Admin UI
- Mitigation: Modern Django admin templates (Unfold already used)
- Mitigation: Build essential monitoring pages in Django admin
- Mitigation: Most admin tasks already work in Django admin
Risk 2: Migration Complexity
- Mitigation: Careful planning and testing
- Mitigation: Gradual rollout (settings first, then UI)
- Mitigation: Rollback plan if issues occur
Risk 3: API Key Management
- Mitigation: Keep global keys secure in Django admin
- Mitigation: Add option for accounts to use own keys
- Mitigation: Track usage per account even with shared keys
Final Recommendation
✅ PROCEED WITH PROPOSED ARCHITECTURE
Reasons:
- Cleaner separation of concerns
- Less code to maintain
- Better security posture
- Proper global settings (not fallbacks)
- Django admin is sufficient for admin tasks
- Frontend becomes pure user interface
Timeline: 4 weeks for complete migration
Risk Level: LOW - Changes are well-defined and testable
Business Impact: POSITIVE - Simpler, more secure, easier to maintain
Next Steps
- ✅ Approval: Review this document and approve approach
- ✅ Plan: Create detailed implementation tickets
- ✅ Build: Implement Phase 1 (global settings)
- ✅ Test: Thorough testing of settings migration
- ✅ Deploy: Phase 1 to production
- ✅ Build: Implement Phase 2 (remove frontend admin)
- ✅ Test: End-to-end testing
- ✅ Deploy: Phase 2 to production
Document Status: Draft for Review
Author: System Architecture Analysis
Date: December 20, 2025
Next Review: After stakeholder feedback
End of Analysis