temproary docs uplaoded
This commit is contained in:
346
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/ARCHITECTURE.md
Normal file
346
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/ARCHITECTURE.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# System Architecture
|
||||
|
||||
**Last Verified:** January 20, 2026
|
||||
**Version:** 1.8.4
|
||||
**Backend Path:** `backend/igny8_core/`
|
||||
**Frontend Path:** `frontend/src/`
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology | Version | Purpose |
|
||||
|-------|------------|---------|---------|
|
||||
| **Backend Framework** | Django | 5.1 | Web framework |
|
||||
| **API Layer** | Django REST Framework | 3.15 | REST API |
|
||||
| **Database** | PostgreSQL | 16 | Primary data store |
|
||||
| **Cache/Queue** | Redis | 7 | Caching, Celery broker |
|
||||
| **Task Queue** | Celery | 5.4 | Async task processing |
|
||||
| **Frontend Framework** | React | 19 | UI framework |
|
||||
| **Build Tool** | Vite | 5 | Frontend bundler |
|
||||
| **Styling** | Tailwind CSS | 3 | Utility CSS |
|
||||
| **State Management** | Zustand | 4 | React state |
|
||||
| **Language** | TypeScript | 5 | Frontend typing |
|
||||
| **Web Server** | Caddy | 2 | Reverse proxy, SSL |
|
||||
| **Containerization** | Docker | - | Deployment |
|
||||
|
||||
---
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CLIENTS │
|
||||
│ React SPA (app.igny8.com) │ WordPress Plugin │ Admin │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CADDY (Reverse Proxy) │
|
||||
│ SSL termination, routing, static files │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ DJANGO REST FRAMEWORK │
|
||||
│ │
|
||||
│ Middleware Stack: │
|
||||
│ SecurityMiddleware → WhiteNoise → CORS → Session → CSRF → │
|
||||
│ DjangoAuth → RequestIDMiddleware → AccountContextMiddleware → │
|
||||
│ ResourceTrackingMiddleware │
|
||||
│ │
|
||||
│ API: /api/v1/* → ViewSets → Services → Models │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────┐ ┌─────────────────────────────────────┐
|
||||
│ PostgreSQL │ │ Redis │
|
||||
│ Primary Database │ │ Sessions, Cache, Celery Broker │
|
||||
└─────────────────────┘ └─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CELERY WORKERS │
|
||||
│ AI Tasks, Automation, Publishing, Background Jobs │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ EXTERNAL SERVICES │
|
||||
│ OpenAI │ Anthropic │ Runware │ Bria │ WordPress Sites │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend Structure
|
||||
|
||||
```
|
||||
backend/igny8_core/
|
||||
├── settings.py # Django settings, all config
|
||||
├── urls.py # Root URL routing
|
||||
├── celery.py # Celery configuration
|
||||
├── wsgi.py / asgi.py # WSGI/ASGI entry points
|
||||
│
|
||||
├── auth/ # Authentication & tenancy
|
||||
│ ├── models.py # User, Account, Site, Sector, Plan
|
||||
│ ├── views.py # Login, register, password reset
|
||||
│ ├── middleware.py # AccountContextMiddleware
|
||||
│ └── urls.py # /api/v1/auth/*
|
||||
│
|
||||
├── api/ # API infrastructure
|
||||
│ ├── base.py # AccountModelViewSet, SiteSectorModelViewSet
|
||||
│ ├── authentication.py # JWT, API key auth classes
|
||||
│ └── pagination.py # Unified pagination
|
||||
│
|
||||
├── ai/ # AI engine
|
||||
│ ├── engine.py # AIEngine orchestrator
|
||||
│ ├── functions/ # AutoCluster, GenerateIdeas, GenerateContent, etc.
|
||||
│ ├── registry.py # Function registry
|
||||
│ ├── model_registry.py # Model Registry service (v1.3.0)
|
||||
│ └── progress.py # Progress tracking
|
||||
│
|
||||
├── modules/ # Feature modules (API layer)
|
||||
│ ├── planner/ # Keywords, Clusters, Ideas
|
||||
│ ├── writer/ # Tasks, Content, Images
|
||||
│ ├── billing/ # Credits, usage, transactions
|
||||
│ ├── integration/ # WordPress integration
|
||||
│ ├── system/ # Settings, prompts, AI config
|
||||
│ ├── linker/ # Internal linking (inactive)
|
||||
│ ├── optimizer/ # Content optimization (inactive)
|
||||
│ └── publisher/ # Publishing pipeline
|
||||
│
|
||||
├── business/ # Business logic (services)
|
||||
│ ├── automation/ # 7-stage automation pipeline
|
||||
│ ├── billing/ # Credit service, payment processing
|
||||
│ ├── content/ # Content generation orchestration
|
||||
│ ├── integration/ # Sync services
|
||||
│ ├── linking/ # Link processing
|
||||
│ ├── notifications/ # Notification system (v1.2.0)
|
||||
│ ├── optimization/ # Content optimization
|
||||
│ ├── planning/ # Clustering, idea generation
|
||||
│ └── publishing/ # Publishing orchestration
|
||||
│
|
||||
├── middleware/ # Custom middleware
|
||||
│ ├── request_id.py # X-Request-ID header
|
||||
│ └── resource_tracker.py # Resource tracking for admins
|
||||
│
|
||||
└── tasks/ # Celery tasks
|
||||
└── *.py # Background job definitions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Structure
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── main.tsx # Entry point
|
||||
├── App.tsx # Root component, routing
|
||||
├── index.css # Global styles, Tailwind
|
||||
│
|
||||
├── api/ # API clients
|
||||
│ ├── linker.api.ts
|
||||
│ ├── optimizer.api.ts
|
||||
│ └── ...
|
||||
│
|
||||
├── services/
|
||||
│ ├── api.ts # Main API service (2500+ lines)
|
||||
│ └── notifications.api.ts # Notification API (v1.2.0)
|
||||
│
|
||||
├── store/ # Zustand stores
|
||||
│ ├── authStore.ts # Authentication state
|
||||
│ ├── siteStore.ts # Active site
|
||||
│ ├── sectorStore.ts # Active sector
|
||||
│ ├── billingStore.ts # Billing state
|
||||
│ ├── moduleStore.ts # Module enable/disable
|
||||
│ ├── notificationStore.ts # Notifications (v1.2.0)
|
||||
│ └── ...
|
||||
│
|
||||
├── pages/ # Route pages
|
||||
│ ├── Dashboard/
|
||||
│ ├── Planner/
|
||||
│ ├── Writer/
|
||||
│ ├── Automation/
|
||||
│ ├── Linker/
|
||||
│ ├── Optimizer/
|
||||
│ ├── Settings/
|
||||
│ ├── Billing/
|
||||
│ └── Auth/
|
||||
│
|
||||
├── components/ # Reusable components
|
||||
│ ├── common/
|
||||
│ │ ├── ProgressModal.tsx # AI progress display
|
||||
│ │ ├── SearchModal.tsx # Global search (v1.1.9)
|
||||
│ │ └── ...
|
||||
│ ├── dashboard/ # Dashboard widgets (v1.2.0)
|
||||
│ │ ├── WorkflowPipelineWidget.tsx
|
||||
│ │ ├── AIOperationsWidget.tsx
|
||||
│ │ ├── RecentActivityWidget.tsx
|
||||
│ │ ├── ContentVelocityWidget.tsx
|
||||
│ │ ├── AutomationStatusWidget.tsx
|
||||
│ │ ├── ThreeWidgetFooter.tsx
|
||||
│ │ └── ...
|
||||
│ └── header/
|
||||
│ └── NotificationDropdown.tsx
|
||||
│
|
||||
├── context/ # React contexts (v1.1.9)
|
||||
│ └── PageContext.tsx # Page-level state
|
||||
│
|
||||
├── layout/ # Layout components
|
||||
│ ├── AppLayout.tsx
|
||||
│ ├── AppHeader.tsx
|
||||
│ └── AppSidebar.tsx
|
||||
│
|
||||
├── hooks/ # Custom hooks
|
||||
│ └── useWorkflowStats.ts # Automation stats hook (v1.3.0)
|
||||
├── context/ # React contexts
|
||||
└── utils/ # Utility functions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Design Patterns
|
||||
|
||||
### 1. Multi-Tenant Data Isolation
|
||||
|
||||
All data is scoped to Account, with optional Site and Sector filtering:
|
||||
|
||||
```
|
||||
Account (Tenant)
|
||||
└── Site (e.g., myblog.com)
|
||||
└── Sector (e.g., Technology, Health)
|
||||
└── Keywords/Clusters/Ideas/Content
|
||||
```
|
||||
|
||||
**Implementation:**
|
||||
- `AccountBaseModel` - Base class for account-scoped models
|
||||
- `SiteSectorBaseModel` - Base class for site/sector-scoped models
|
||||
- `AccountModelViewSet` - Auto-filters queryset by request.account
|
||||
- `SiteSectorModelViewSet` - Auto-filters by account + site + sector
|
||||
|
||||
### 2. Middleware-First Tenant Resolution
|
||||
|
||||
```python
|
||||
# Order in settings.py MIDDLEWARE
|
||||
1. SecurityMiddleware
|
||||
2. WhiteNoiseMiddleware
|
||||
3. CorsMiddleware
|
||||
4. SessionMiddleware
|
||||
5. DjangoAuthenticationMiddleware
|
||||
6. RequestIDMiddleware # Assigns X-Request-ID
|
||||
7. AccountContextMiddleware # Sets request.account from session/JWT
|
||||
8. ResourceTrackingMiddleware # Optional admin profiling
|
||||
```
|
||||
|
||||
### 3. Unified API Responses
|
||||
|
||||
All API responses follow this structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": { ... },
|
||||
"message": "Optional message"
|
||||
}
|
||||
```
|
||||
|
||||
Error responses:
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Error message",
|
||||
"code": "ERROR_CODE"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Credit-Based Operations
|
||||
|
||||
All AI operations check and deduct credits:
|
||||
1. Pre-check: `CreditService.check_credits()`
|
||||
2. Execute: AI function runs
|
||||
3. Post-deduct: `CreditService.deduct_credits_for_operation()`
|
||||
|
||||
---
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
Key environment variables (from `settings.py`):
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `DATABASE_URL` | PostgreSQL connection |
|
||||
| `REDIS_URL` | Redis connection |
|
||||
| `SECRET_KEY` | Django secret |
|
||||
| `JWT_SECRET_KEY` | JWT signing key |
|
||||
| `CORS_ALLOWED_ORIGINS` | Allowed frontend origins |
|
||||
| `CELERY_BROKER_URL` | Celery broker (Redis) |
|
||||
|
||||
AI keys are stored in `GlobalIntegrationSettings` (database), not env vars.
|
||||
|
||||
---
|
||||
|
||||
## Deployment Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Docker Compose │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Frontend │ │ Backend │ │ Worker │ │
|
||||
│ │ (Caddy) │ │ (Django) │ │ (Celery) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └────────────────┼────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ PostgreSQL │ │ Redis │ │
|
||||
│ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Model Registry (v1.3.0)
|
||||
|
||||
The Model Registry provides centralized AI model configuration with database-stored pricing and settings:
|
||||
|
||||
```python
|
||||
# backend/igny8_core/ai/model_registry.py
|
||||
from igny8_core.modules.system.models import AIModelConfig
|
||||
|
||||
class ModelRegistry:
|
||||
"""Centralized AI model configuration service"""
|
||||
|
||||
@classmethod
|
||||
def get_model(cls, model_id: str) -> AIModelConfig:
|
||||
"""Get model config by ID"""
|
||||
return AIModelConfig.objects.get(model_id=model_id)
|
||||
|
||||
@classmethod
|
||||
def get_active_models_by_type(cls, model_type: str) -> QuerySet:
|
||||
"""Get all active models for a type (text, image, etc.)"""
|
||||
return AIModelConfig.objects.filter(
|
||||
model_type=model_type,
|
||||
is_active=True
|
||||
)
|
||||
```
|
||||
|
||||
**Supported Providers:**
|
||||
| Provider | Types | Integration |
|
||||
|----------|-------|-------------|
|
||||
| OpenAI | Text, Image | GPT-4o, GPT-4-turbo, DALL-E 3 |
|
||||
| Anthropic | Text | Claude 3.5 Sonnet, Claude 3 Opus |
|
||||
| Runware | Image | RunwareFLUX, SD 3.5 |
|
||||
| Bria | Image | Bria 2.3 |
|
||||
|
||||
---
|
||||
|
||||
## Planned Changes
|
||||
|
||||
| Feature | Status | Description |
|
||||
|---------|--------|-------------|
|
||||
| ~~AIModelConfig Database~~ | ✅ v1.3.0 | ~~Move AI model pricing from constants to database~~ |
|
||||
| ~~Multi-provider AI~~ | ✅ v1.3.0 | ~~Support for Anthropic, Bria~~ |
|
||||
| Module Guard Extension | 🔜 Planned | Extend linker/optimizer disable to all pages (currently sidebar only) |
|
||||
| Google AI Integration | 🔜 Planned | Support for Gemini models |
|
||||
255
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/AUTH-FLOWS.md
Normal file
255
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/AUTH-FLOWS.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Authentication & Authorization
|
||||
|
||||
**Last Verified:** January 20, 2026
|
||||
**Version:** 1.8.4
|
||||
**Backend Path:** `backend/igny8_core/auth/`
|
||||
**Frontend Path:** `frontend/src/store/authStore.ts`
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| What | File | Key Functions |
|
||||
|------|------|---------------|
|
||||
| User Model | `auth/models.py` | `User`, `Account`, `Plan` |
|
||||
| Auth Views | `auth/views.py` | `LoginView`, `RegisterView`, `RefreshTokenView` |
|
||||
| Middleware | `auth/middleware.py` | `AccountContextMiddleware` |
|
||||
| JWT Auth | `api/authentication.py` | `JWTAuthentication`, `CookieJWTAuthentication` |
|
||||
| API Key Auth | `api/authentication.py` | `APIKeyAuthentication` |
|
||||
| Frontend Store | `store/authStore.ts` | `useAuthStore` |
|
||||
|
||||
---
|
||||
|
||||
## Authentication Methods
|
||||
|
||||
### 1. JWT Token Authentication (Primary)
|
||||
|
||||
**Flow:**
|
||||
1. User logs in via `/api/v1/auth/login/`
|
||||
2. Backend returns `access_token` (15 min) + `refresh_token` (7 days)
|
||||
3. Frontend stores tokens in localStorage and Zustand store
|
||||
4. All API requests include `Authorization: Bearer <access_token>`
|
||||
5. Token refresh via `/api/v1/auth/token/refresh/`
|
||||
|
||||
**Token Payload:**
|
||||
```json
|
||||
{
|
||||
"user_id": 123,
|
||||
"account_id": 456,
|
||||
"email": "user@example.com",
|
||||
"exp": 1735123456,
|
||||
"iat": 1735122456
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Session Authentication (Admin/Fallback)
|
||||
|
||||
- Used by Django Admin interface
|
||||
- Cookie-based session with CSRF protection
|
||||
- Redis-backed sessions (prevents user swapping bug)
|
||||
|
||||
### 3. API Key Authentication (WordPress Bridge)
|
||||
|
||||
**Flow:**
|
||||
1. Account generates API key in settings
|
||||
2. WordPress plugin uses `Authorization: ApiKey <key>`
|
||||
3. Backend validates key, sets `request.account` and `request.site`
|
||||
|
||||
**Use Cases:**
|
||||
- WordPress content sync
|
||||
- External integrations
|
||||
- Headless CMS connections
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
| Method | Path | Handler | Purpose |
|
||||
|--------|------|---------|---------|
|
||||
| POST | `/api/v1/auth/register/` | `RegisterView` | Create new user + account |
|
||||
| POST | `/api/v1/auth/login/` | `LoginView` | Authenticate, return tokens |
|
||||
| POST | `/api/v1/auth/logout/` | `LogoutView` | Invalidate tokens |
|
||||
| POST | `/api/v1/auth/token/refresh/` | `RefreshTokenView` | Refresh access token |
|
||||
| POST | `/api/v1/auth/password/change/` | `ChangePasswordView` | Change password |
|
||||
| POST | `/api/v1/auth/password/reset/` | `RequestPasswordResetView` | Request reset email |
|
||||
| POST | `/api/v1/auth/password/reset/confirm/` | `ResetPasswordView` | Confirm reset with token |
|
||||
|
||||
---
|
||||
|
||||
## User Roles
|
||||
|
||||
| Role | Code | Permissions |
|
||||
|------|------|-------------|
|
||||
| **Developer** | `developer` | Full access across ALL accounts (superuser) |
|
||||
| **Owner** | `owner` | Full access to own account (account creator) |
|
||||
| **Admin** | `admin` | Full access to own account, billing, team management |
|
||||
| **Editor** | `editor` | Content creation and editing only |
|
||||
| **Viewer** | `viewer` | Read-only access to content |
|
||||
| **System Bot** | `system_bot` | System automation (internal) |
|
||||
|
||||
**Role Hierarchy:**
|
||||
```
|
||||
developer > owner > admin > editor > viewer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Middleware: AccountContextMiddleware
|
||||
|
||||
**File:** `auth/middleware.py`
|
||||
|
||||
**Purpose:** Injects `request.account` on every request
|
||||
|
||||
**Flow:**
|
||||
1. Check for JWT token → extract account_id
|
||||
2. Check for session → get account from session
|
||||
3. Check for API key → get account from key
|
||||
4. Validate account exists and is active
|
||||
5. Validate plan exists and is active
|
||||
6. Set `request.account`, `request.user`
|
||||
|
||||
**Error Responses:**
|
||||
- No account: 403 with JSON error
|
||||
- Inactive plan: 402 with JSON error
|
||||
|
||||
---
|
||||
|
||||
## Frontend Auth Store
|
||||
|
||||
**File:** `store/authStore.ts`
|
||||
|
||||
**State:**
|
||||
```typescript
|
||||
{
|
||||
user: User | null;
|
||||
token: string | null;
|
||||
refreshToken: string | null;
|
||||
isAuthenticated: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
**Actions:**
|
||||
- `login(email, password)` - Authenticate and store tokens
|
||||
- `register(data)` - Create account and store tokens
|
||||
- `logout()` - Clear tokens and reset stores
|
||||
- `refreshToken()` - Refresh access token
|
||||
- `checkAuth()` - Verify current auth state
|
||||
|
||||
**Critical Implementation:**
|
||||
```typescript
|
||||
// Tokens are written synchronously to localStorage
|
||||
// This prevents race conditions where API calls happen before persist
|
||||
localStorage.setItem('auth-storage', JSON.stringify(authState));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Session Security (Redis-Backed)
|
||||
|
||||
**Problem Solved:** User swapping / random logout issues
|
||||
|
||||
**Implementation:**
|
||||
```python
|
||||
# settings.py
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
|
||||
SESSION_CACHE_ALIAS = 'default' # Redis
|
||||
|
||||
# auth/backends.py
|
||||
class NoCacheModelBackend(ModelBackend):
|
||||
"""Authentication backend without user caching"""
|
||||
pass
|
||||
```
|
||||
|
||||
**Session Integrity:**
|
||||
- Stores `account_id` and `user_id` in session
|
||||
- Validates on every request
|
||||
- Prevents cross-request contamination
|
||||
|
||||
---
|
||||
|
||||
## API Key Management
|
||||
|
||||
**Model:** `APIKey` in `auth/models.py`
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| key | CharField | Hashed API key |
|
||||
| account | ForeignKey | Owner account |
|
||||
| site | ForeignKey | Optional: specific site |
|
||||
| name | CharField | Key name/description |
|
||||
| is_active | Boolean | Enable/disable |
|
||||
| created_at | DateTime | Creation time |
|
||||
| last_used_at | DateTime | Last usage time |
|
||||
|
||||
**Generation:**
|
||||
- 32-character random key
|
||||
- Stored hashed (SHA-256)
|
||||
- Shown once on creation
|
||||
|
||||
---
|
||||
|
||||
## Permission Checking
|
||||
|
||||
**In ViewSets:**
|
||||
```python
|
||||
class MyViewSet(AccountModelViewSet):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
# Automatically filtered by request.account
|
||||
return super().get_queryset()
|
||||
```
|
||||
|
||||
**Role Checks:**
|
||||
```python
|
||||
if request.user.is_admin_or_developer:
|
||||
# Admin/developer access
|
||||
pass
|
||||
elif request.user.role == 'editor':
|
||||
# Editor access
|
||||
pass
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logout Flow
|
||||
|
||||
**Backend:**
|
||||
1. Blacklist refresh token (if using token blacklist)
|
||||
2. Clear session
|
||||
|
||||
**Frontend (Critical):**
|
||||
```typescript
|
||||
logout: () => {
|
||||
// NEVER use localStorage.clear() - breaks Zustand persist
|
||||
const authKeys = ['auth-storage', 'site-storage', 'sector-storage', 'billing-storage'];
|
||||
authKeys.forEach(key => localStorage.removeItem(key));
|
||||
|
||||
// Reset dependent stores
|
||||
useSiteStore.setState({ activeSite: null });
|
||||
useSectorStore.setState({ activeSector: null, sectors: [] });
|
||||
|
||||
set({ user: null, token: null, isAuthenticated: false });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| 403 after login | Tokens not persisted before API call | Write to localStorage synchronously |
|
||||
| User swapping | DB-backed sessions with user caching | Redis sessions + NoCacheModelBackend |
|
||||
| Token refresh loop | Refresh token expired | Redirect to login |
|
||||
| API key not working | Missing site scope | Check API key has correct site assigned |
|
||||
|
||||
---
|
||||
|
||||
## Planned Changes
|
||||
|
||||
| Feature | Status | Description |
|
||||
|---------|--------|-------------|
|
||||
| Token blacklist | 🔜 Planned | Proper refresh token invalidation |
|
||||
| 2FA | 🔜 Planned | Two-factor authentication |
|
||||
| SSO | 🔜 Planned | Google/GitHub OAuth |
|
||||
383
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/IGNY8-APP.md
Normal file
383
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/IGNY8-APP.md
Normal file
@@ -0,0 +1,383 @@
|
||||
# IGNY8 - AI-Powered SEO Content Platform
|
||||
|
||||
**Version:** 1.8.4
|
||||
**Last Updated:** January 20, 2026
|
||||
**Status:** Production Ready
|
||||
|
||||
---
|
||||
|
||||
## What is IGNY8?
|
||||
|
||||
IGNY8 is an enterprise-grade AI content platform that transforms keyword research into published, SEO-optimized articles at scale. The platform automates the entire content lifecycle—from discovering keywords to publishing polished articles with AI-generated images—reducing what typically takes days of manual work into hours.
|
||||
|
||||
**The Problem:** Creating SEO content at scale requires keyword research, content planning, writing, image creation, optimization, and publishing—a process that's labor-intensive and inconsistent.
|
||||
|
||||
**The Solution:** IGNY8 provides an end-to-end automated pipeline where AI handles clustering, ideation, writing, and image generation while you maintain editorial control.
|
||||
|
||||
---
|
||||
|
||||
## Platform Architecture
|
||||
|
||||
| Aspect | Details |
|
||||
|--------|---------|
|
||||
| **Type** | Full-stack SaaS Platform |
|
||||
| **Architecture** | Multi-tenant with complete data isolation |
|
||||
| **Target Users** | Content marketers, SEO agencies, digital publishers |
|
||||
| **Deployment** | Docker-based, cloud-hosted |
|
||||
| **Pricing Model** | Credits + Monthly subscription plans |
|
||||
|
||||
---
|
||||
|
||||
## Core Workflow
|
||||
|
||||
IGNY8 follows a structured 8-stage content pipeline:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ SETUP WORKFLOW │
|
||||
│ ───── ──────── │
|
||||
│ Sites → Keywords → Clusters → Ideas → Tasks → Content → Images → Published │
|
||||
│ ↑ ↑ ↑ │
|
||||
│ Configure AI Groups AI Writes │
|
||||
│ WordPress Related Full Articles │
|
||||
│ Keywords + SEO Meta │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Manual Mode
|
||||
Walk through each stage with full control—review and edit at every step.
|
||||
|
||||
### Automation Mode
|
||||
Configure once, let IGNY8 process all 7 stages automatically on a schedule (daily, weekly, or monthly). Content lands in your review queue ready for approval.
|
||||
|
||||
---
|
||||
|
||||
## Feature Deep-Dive
|
||||
|
||||
### 1. Keyword Management (Planner)
|
||||
|
||||
**Import Options:**
|
||||
- Upload CSV with thousands of keywords
|
||||
- Browse 50+ industries of pre-curated seed keywords
|
||||
- Filter by country, difficulty, search volume
|
||||
|
||||
**AI Clustering:**
|
||||
- GPT-4 analyzes keyword intent and relationships
|
||||
- Groups related keywords into topical clusters
|
||||
- Enables one comprehensive article per cluster (instead of keyword stuffing)
|
||||
|
||||
**Metrics Tracked:**
|
||||
- Search volume (monthly)
|
||||
- Keyword difficulty (0-100)
|
||||
- CPC (cost-per-click)
|
||||
- Intent classification (informational, commercial, transactional)
|
||||
|
||||
---
|
||||
|
||||
### 2. Content Ideation (Planner)
|
||||
|
||||
**AI-Generated Ideas:**
|
||||
- Each cluster becomes a content brief
|
||||
- Suggested titles, angles, and outlines
|
||||
- Word count recommendations based on competition
|
||||
- Priority scoring by SEO potential
|
||||
|
||||
**Bulk Operations:**
|
||||
- Generate ideas for multiple clusters at once
|
||||
- Queue ideas directly to Writer module
|
||||
- Batch status updates
|
||||
|
||||
---
|
||||
|
||||
### 3. Content Generation (Writer)
|
||||
|
||||
**AI Writing Engine:**
|
||||
- Powered by GPT-4/GPT-4 Turbo
|
||||
- Produces structured articles (H2s, H3s, lists, paragraphs)
|
||||
- SEO-optimized meta titles and descriptions
|
||||
- Configurable length: 500 to 5,000+ words
|
||||
|
||||
**Content Types:**
|
||||
- Blog posts and articles
|
||||
- How-to guides
|
||||
- Product comparisons
|
||||
- Reviews and roundups
|
||||
|
||||
**Customization:**
|
||||
- Custom prompt additions (append to all AI prompts)
|
||||
- Default tone selection (professional, casual, authoritative, etc.)
|
||||
- Default article length preferences
|
||||
|
||||
**Workflow States:**
|
||||
- Queue → Draft → Review → Published
|
||||
- Each stage has dedicated management views
|
||||
|
||||
---
|
||||
|
||||
### 4. Image Generation (Writer)
|
||||
|
||||
**Dual AI Providers:**
|
||||
| Provider | Quality Tier | Best For |
|
||||
|----------|--------------|----------|
|
||||
| DALL-E 2 | Standard | Fast, economical |
|
||||
| DALL-E 3 | Premium | High quality, detailed |
|
||||
| Runware | Best | Alternative variety |
|
||||
|
||||
**Image Types:**
|
||||
- Featured images (hero/thumbnail)
|
||||
- In-article images (embedded in content)
|
||||
- Desktop and mobile sizes (responsive)
|
||||
|
||||
**Smart Features:**
|
||||
- AI extracts image prompts from article content
|
||||
- Negative prompts for style control
|
||||
- Multiple format support (WebP, JPG, PNG)
|
||||
- Configurable max images per article
|
||||
|
||||
---
|
||||
|
||||
### 5. Automation Pipeline
|
||||
|
||||
**7-Stage Automated Workflow:**
|
||||
```
|
||||
Stage 1: Process new keywords
|
||||
Stage 2: AI cluster keywords
|
||||
Stage 3: Generate content ideas
|
||||
Stage 4: Create writer tasks
|
||||
Stage 5: Generate article content
|
||||
Stage 6: Extract image prompts
|
||||
Stage 7: Generate images → Review queue
|
||||
```
|
||||
|
||||
**Configuration:**
|
||||
- Schedule: Daily, weekly, or monthly runs
|
||||
- Run controls: Start, pause, resume
|
||||
- Credit estimation before running
|
||||
- Real-time progress tracking
|
||||
- Activity log and run history
|
||||
|
||||
---
|
||||
|
||||
### 6. WordPress Integration
|
||||
|
||||
**Publishing:**
|
||||
- One-click publish from Review tab
|
||||
- Direct WordPress REST API integration
|
||||
- Supports multiple WordPress sites per account
|
||||
|
||||
**Synchronization:**
|
||||
- Two-way content sync (import/export)
|
||||
- Category and tag mapping
|
||||
- Featured image upload
|
||||
- Post type configuration (posts, pages, custom)
|
||||
|
||||
**Setup:**
|
||||
- Site URL and REST API authentication
|
||||
- Content type mapping in Site Settings
|
||||
- Auto-publish toggle (skip review step)
|
||||
- Auto-sync toggle (keep WordPress updated)
|
||||
|
||||
---
|
||||
|
||||
### 7. Team & Account Management
|
||||
|
||||
**User Roles:**
|
||||
| Role | Permissions |
|
||||
|------|-------------|
|
||||
| Admin | Full access, billing, team management |
|
||||
| Manager | Content + billing view, no team management |
|
||||
| Editor | AI content, clusters, tasks |
|
||||
| Viewer | Read-only dashboards |
|
||||
|
||||
**Team Features:**
|
||||
- Invite team members by email
|
||||
- Remove members
|
||||
- Role display (editing roles coming soon)
|
||||
|
||||
**Account Settings:**
|
||||
- Organization name and billing address
|
||||
- Tax ID / VAT number
|
||||
- Billing email
|
||||
|
||||
---
|
||||
|
||||
### 8. Usage & Billing
|
||||
|
||||
**Credit System:**
|
||||
| Operation | Typical Credits |
|
||||
|-----------|-----------------|
|
||||
| Keyword clustering (batch) | 10 |
|
||||
| Content idea generation | 2 |
|
||||
| Article (per 100 words) | 5 |
|
||||
| Image (standard) | 3 |
|
||||
| Image (premium/best) | 5 |
|
||||
|
||||
**Usage Tracking:**
|
||||
- Real-time credit balance
|
||||
- Monthly usage vs. limits
|
||||
- Transaction history
|
||||
- Hard limits (sites, users, keywords, clusters)
|
||||
- Monthly limits (ideas, words, images)
|
||||
|
||||
**Subscription Plans:**
|
||||
| Plan | Sites | Users | Credits/Month | Best For |
|
||||
|------|-------|-------|---------------|----------|
|
||||
| Free | 1 | 1 | 100 | Trial/Evaluation |
|
||||
| Starter | 3 | 3 | 1,000 | Individual creators |
|
||||
| Growth | 10 | 10 | 5,000 | Small teams |
|
||||
| Scale | Unlimited | Unlimited | 25,000 | Agencies |
|
||||
|
||||
---
|
||||
|
||||
## Module Status
|
||||
|
||||
| Module | Status | Location |
|
||||
|--------|--------|----------|
|
||||
| **Dashboard** | ✅ Active | `/` |
|
||||
| **Add Keywords** | ✅ Active | `/setup/add-keywords` |
|
||||
| **Content Settings** | ✅ Active | `/account/content-settings` |
|
||||
| **Sites** | ✅ Active | `/sites` |
|
||||
| **Thinker** | ✅ Active (Admin) | `/thinker/prompts` |
|
||||
| **Planner** | ✅ Active | `/planner/keywords` |
|
||||
| **Writer** | ✅ Active | `/writer/tasks` |
|
||||
| **Automation** | ✅ Active | `/automation` |
|
||||
| **Account Settings** | ✅ Active | `/account/settings` |
|
||||
| **Plans & Billing** | ✅ Active | `/account/plans` |
|
||||
| **Usage** | ✅ Active | `/account/usage` |
|
||||
| **AI Models** | ✅ Active (Admin) | `/settings/integration` |
|
||||
| **Help** | ✅ Active | `/help` |
|
||||
| **SiteBuilder** | ❌ Deprecated | Removed - was for site structure generation |
|
||||
| **Linker** | ⏸️ Phase 2 | Internal linking suggestions (disabled by default) |
|
||||
| **Optimizer** | ⏸️ Phase 2 | Content optimization (disabled by default) |
|
||||
|
||||
### Module Status Details
|
||||
|
||||
| Module | Status | Notes |
|
||||
|--------|--------|-------|
|
||||
| **SiteBuilder** | ❌ Deprecated | Code exists but feature is removed. Marked for cleanup. |
|
||||
| **Linker** | ⏸️ Phase 2 | Feature flag: `linker_enabled`. Available but disabled by default. |
|
||||
| **Optimizer** | ⏸️ Phase 2 | Feature flag: `optimizer_enabled`. Available but disabled by default. |
|
||||
|
||||
To enable Phase 2 modules, update via Django Admin:
|
||||
- `GlobalModuleSettings` (pk=1) for platform-wide settings
|
||||
- `ModuleEnableSettings` for per-account settings
|
||||
|
||||
---
|
||||
|
||||
## Navigation Structure
|
||||
|
||||
```
|
||||
Sidebar Menu
|
||||
├── Dashboard
|
||||
├── SETUP
|
||||
│ ├── Add Keywords
|
||||
│ ├── Content Settings
|
||||
│ ├── Sites (if enabled)
|
||||
│ └── Thinker (admin only, if enabled)
|
||||
├── WORKFLOW
|
||||
│ ├── Planner (Keywords → Clusters → Ideas)
|
||||
│ ├── Writer (Queue → Drafts → Images → Review → Published)
|
||||
│ ├── Automation
|
||||
│ ├── Linker (if enabled)
|
||||
│ └── Optimizer (if enabled)
|
||||
├── ACCOUNT
|
||||
│ ├── Account Settings (Account → Profile → Team)
|
||||
│ ├── Plans & Billing (Plan → Upgrade → History)
|
||||
│ ├── Usage (Limits → Credit History → API Activity)
|
||||
│ └── AI Models (admin only)
|
||||
└── HELP
|
||||
└── Help & Docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technical Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|------------|
|
||||
| **Backend** | Django 5.x, Django REST Framework, Python 3.11+ |
|
||||
| **Frontend** | React 19, TypeScript, Vite, TailwindCSS |
|
||||
| **Database** | PostgreSQL 15+ |
|
||||
| **Cache/Sessions** | Redis |
|
||||
| **Task Queue** | Celery + Celery Beat |
|
||||
| **AI Services** | OpenAI GPT-4, DALL-E 3, Runware |
|
||||
| **Deployment** | Docker, Docker Compose |
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
- **Data Isolation:** Complete multi-tenant separation at database level
|
||||
- **Authentication:** JWT tokens with Redis session management
|
||||
- **Encryption:** Data encrypted at rest and in transit
|
||||
- **Access Control:** Role-based permissions per account
|
||||
- **Session Security:** Secure cookie handling, session integrity checks
|
||||
|
||||
---
|
||||
|
||||
## Current Limitations & Known Issues
|
||||
|
||||
**Payment Processing:**
|
||||
- Stripe/PayPal pending production credentials
|
||||
- Manual payment methods available
|
||||
|
||||
**Pending Backend Implementation:**
|
||||
- Content Generation settings (append prompt, tone, length) - UI exists, API pending
|
||||
- Publishing settings (auto-publish, sync) - UI exists, API pending
|
||||
- Profile settings save - UI exists, API pending
|
||||
- Password change functionality
|
||||
- API Activity tracking (currently placeholder data)
|
||||
|
||||
**Disabled Modules:**
|
||||
- Linker (internal linking) - Available but disabled
|
||||
- Optimizer (content optimization) - Available but disabled
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### For New Users
|
||||
1. Create account and verify email
|
||||
2. Create your first site (industry + sectors)
|
||||
3. Connect WordPress (optional)
|
||||
4. Add keywords from seed database or import CSV
|
||||
5. Run AI clustering on keywords
|
||||
6. Generate content ideas from clusters
|
||||
7. Queue ideas to Writer
|
||||
8. Generate content and images
|
||||
9. Review and publish
|
||||
|
||||
### For Admins
|
||||
1. Configure AI Models (OpenAI API key, Runware key)
|
||||
2. Customize prompts in Thinker module
|
||||
3. Set up global module settings
|
||||
4. Configure automation schedules
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
| Document | Location |
|
||||
|----------|----------|
|
||||
| Technical Docs | `/docs/INDEX.md` |
|
||||
| API Reference | `/docs/20-API/` |
|
||||
| Pre-Launch Audit | `/PRE-LAUNCH-AUDIT.md` |
|
||||
| Changelog | `/CHANGELOG.md` |
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Highlights |
|
||||
|---------|------|------------|
|
||||
| **1.1.0** | Dec 25, 2025 | UX overhaul, page consolidation, pre-launch audit |
|
||||
| 1.0.5 | Dec 12, 2025 | Purchase Credits tab |
|
||||
| 1.0.4 | Dec 12, 2025 | Credit Activity tab |
|
||||
| 1.0.3 | Dec 12, 2025 | Usage Limits improvements |
|
||||
| 1.0.2 | Dec 12, 2025 | Design system enforcement |
|
||||
| 1.0.1 | Dec 12, 2025 | Plan limits UI |
|
||||
| 1.0.0 | Dec 12, 2025 | Initial production release |
|
||||
|
||||
---
|
||||
|
||||
*For detailed technical implementation, see the `/docs` folder. For known issues and improvement roadmap, see `/PRE-LAUNCH-AUDIT.md`.*
|
||||
@@ -0,0 +1,268 @@
|
||||
# Repository Structure (App Repo)
|
||||
|
||||
**Last Verified:** January 20, 2026
|
||||
**Scope:** `/data/app/igny8` (app repo)
|
||||
**Excluded from tree:** `.git/`, `node_modules/`, `dist/`, `staticfiles/`, `backups/`, `__pycache__/`
|
||||
|
||||
---
|
||||
|
||||
## Root
|
||||
|
||||
```
|
||||
/data/app/igny8
|
||||
├── backend/
|
||||
├── docs/
|
||||
├── frontend/
|
||||
├── KW_DB/
|
||||
├── plugins/
|
||||
├── scripts/
|
||||
├── .claude/
|
||||
├── .gitignore
|
||||
├── .rules
|
||||
├── CHANGELOG.md
|
||||
├── CLEANUP_SUMMARY_20260113.md
|
||||
├── content_generation.md
|
||||
├── docker-compose.app.yml
|
||||
├── git-credential-helper.sh
|
||||
├── idea_genration.md
|
||||
├── last-session.md
|
||||
├── README.md
|
||||
└── test_routes.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend
|
||||
|
||||
```
|
||||
backend/
|
||||
├── igny8_core/
|
||||
├── migrations/
|
||||
├── logs/
|
||||
├── scripts/
|
||||
├── Dockerfile
|
||||
├── container_startup.sh
|
||||
├── create_groups.py
|
||||
├── manage.py
|
||||
├── requirements.txt
|
||||
└── seed_keywords_import_template.csv
|
||||
```
|
||||
|
||||
### Django App Core
|
||||
|
||||
```
|
||||
backend/igny8_core/
|
||||
├── admin/
|
||||
├── ai/
|
||||
├── api/
|
||||
├── auth/
|
||||
├── business/
|
||||
├── common/
|
||||
├── management/
|
||||
├── middleware/
|
||||
├── migrations/
|
||||
├── modules/
|
||||
├── plugins/
|
||||
├── static/
|
||||
├── tasks/
|
||||
├── templates/
|
||||
├── urls/
|
||||
├── utils/
|
||||
├── __init__.py
|
||||
├── asgi.py
|
||||
├── celery.py
|
||||
├── settings.py
|
||||
├── tasks.py
|
||||
├── urls.py
|
||||
└── wsgi.py
|
||||
```
|
||||
|
||||
### Feature Modules
|
||||
|
||||
```
|
||||
backend/igny8_core/modules/
|
||||
├── billing/
|
||||
├── integration/
|
||||
├── linker/
|
||||
├── optimizer/
|
||||
├── planner/
|
||||
├── publisher/
|
||||
├── system/
|
||||
└── writer/
|
||||
```
|
||||
|
||||
### Business Services
|
||||
|
||||
```
|
||||
backend/igny8_core/business/
|
||||
├── automation/
|
||||
├── billing/
|
||||
├── content/
|
||||
├── integration/
|
||||
├── linking/
|
||||
├── notifications/
|
||||
├── optimization/
|
||||
├── planning/
|
||||
└── publishing/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── public/
|
||||
├── src/
|
||||
├── audit-results/
|
||||
├── eslint/
|
||||
├── Caddyfile
|
||||
├── Caddyfile.marketing
|
||||
├── Dockerfile
|
||||
├── Dockerfile.dev
|
||||
├── Dockerfile.marketing
|
||||
├── Dockerfile.marketing.dev
|
||||
├── LICENSE.md
|
||||
├── README.md
|
||||
├── container_startup.sh
|
||||
├── eslint.config.js
|
||||
├── index.html
|
||||
├── marketing.html
|
||||
├── package.json
|
||||
├── package-lock.json
|
||||
├── postcss.config.js
|
||||
├── tsconfig.app.json
|
||||
├── tsconfig.json
|
||||
├── tsconfig.node.json
|
||||
├── vite.config.ts
|
||||
└── vitest.config.ts
|
||||
```
|
||||
|
||||
### Frontend Source
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── api/
|
||||
├── components/
|
||||
├── config/
|
||||
├── constants/
|
||||
├── context/
|
||||
├── hooks/
|
||||
├── icons/
|
||||
├── layout/
|
||||
├── marketing/
|
||||
├── modules/
|
||||
├── pages/
|
||||
├── services/
|
||||
├── store/
|
||||
├── styles/
|
||||
├── templates/
|
||||
├── types/
|
||||
├── utils/
|
||||
├── App.tsx
|
||||
├── main.tsx
|
||||
├── svg.d.ts
|
||||
└── vite-env.d.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
```
|
||||
docs/
|
||||
├── 00-SYSTEM/
|
||||
├── 10-MODULES/
|
||||
├── 20-API/
|
||||
├── 30-FRONTEND/
|
||||
├── 40-WORKFLOWS/
|
||||
├── 50-DEPLOYMENT/
|
||||
├── 60-PLUGINS/
|
||||
├── 90-REFERENCE/
|
||||
├── audits/
|
||||
├── plans/
|
||||
├── FILTER_GUIDELINES.md
|
||||
└── INDEX.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugins
|
||||
|
||||
```
|
||||
plugins/
|
||||
└── wordpress/
|
||||
├── dist/
|
||||
├── source/
|
||||
│ └── igny8-wp-bridge/
|
||||
│ ├── admin/
|
||||
│ ├── data/
|
||||
│ ├── docs/
|
||||
│ ├── includes/
|
||||
│ ├── languages/
|
||||
│ ├── sync/
|
||||
│ ├── templates/
|
||||
│ ├── tests/
|
||||
│ ├── igny8-bridge.php
|
||||
│ └── uninstall.php
|
||||
└── UI-REDESIGN-v1.2.0.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## KW_DB (Seed Keyword CSV Library)
|
||||
|
||||
Top-level categories and subcategories (CSV files omitted for brevity):
|
||||
|
||||
```
|
||||
KW_DB/
|
||||
├── Advertising_&_Media/
|
||||
│ └── Printing_Services/
|
||||
├── Apparel_&_Fashion/
|
||||
│ ├── Jewelery/
|
||||
│ ├── Menswear/
|
||||
│ └── Womens_Wear/
|
||||
├── Automotive/
|
||||
│ ├── Car_Accessories/
|
||||
│ ├── Cars_General/
|
||||
│ └── Tyres_&_Wheels/
|
||||
├── Beauty_&_Personal_Care/
|
||||
│ ├── Haircare/
|
||||
│ ├── Makeup_&_Cosmetics/
|
||||
│ └── Skincare/
|
||||
├── Finance_&_Insurance/
|
||||
│ ├── Insurance/
|
||||
│ ├── Investment_&_Weallth_Management/
|
||||
│ └── Loans_&_Lending/
|
||||
├── Food_&_Beverage/
|
||||
│ ├── Food Delivery/
|
||||
│ └── Restaurants/
|
||||
├── HealthCare_Medical/
|
||||
│ ├── Health_Practitioners/
|
||||
│ ├── Massage_&_Therapy/
|
||||
│ ├── Physiotherapy_Rehabilitation/
|
||||
│ ├── Relaxation_Devices/
|
||||
│ └── Wellness_&_Fitness/
|
||||
├── Home_&_Garden/
|
||||
│ ├── Bedding_&_Mattress/
|
||||
│ ├── Furniture/
|
||||
│ ├── Home_Decor/
|
||||
│ └── Storage_&_Organization/
|
||||
├── management/
|
||||
├── Real_Estate_&_Construction/
|
||||
└── Technology_&_IT_Services/
|
||||
├── AI/
|
||||
├── cloud_services/
|
||||
├── DIgital_Marketing_&_SEO/
|
||||
├── SAAS/
|
||||
└── Web_Development_&_Design/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scripts
|
||||
|
||||
```
|
||||
scripts/
|
||||
└── package_app.sh
|
||||
```
|
||||
302
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/TENANCY.md
Normal file
302
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/TENANCY.md
Normal file
@@ -0,0 +1,302 @@
|
||||
# Multi-Tenancy Architecture
|
||||
|
||||
**Last Verified:** January 20, 2026
|
||||
**Version:** 1.8.4
|
||||
**Backend Path:** `backend/igny8_core/auth/models.py`
|
||||
|
||||
---
|
||||
|
||||
## Data Hierarchy
|
||||
|
||||
```
|
||||
Account (Tenant)
|
||||
├── Users (team members)
|
||||
├── Subscription (plan binding)
|
||||
├── Sites
|
||||
│ ├── Sectors
|
||||
│ │ ├── Keywords
|
||||
│ │ ├── Clusters
|
||||
│ │ ├── ContentIdeas
|
||||
│ │ ├── Tasks
|
||||
│ │ ├── Content
|
||||
│ │ └── Images
|
||||
│ └── Integrations (WordPress)
|
||||
└── Billing (credits, transactions)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Models
|
||||
|
||||
### Account
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| name | CharField | Account/organization name |
|
||||
| is_active | Boolean | Enable/disable account |
|
||||
| credits | Decimal | Plan credits (reset on renewal) |
|
||||
| bonus_credits | Decimal | Purchased credits (never expire) |
|
||||
| account_timezone | CharField | IANA timezone (e.g., America/New_York) |
|
||||
| stripe_customer_id | CharField | Stripe integration |
|
||||
| paypal_customer_id | CharField | PayPal integration |
|
||||
| created_at | DateTime | Registration date |
|
||||
|
||||
> **Two-Pool Credit System (v1.8.3):** Plan credits consumed first, bonus credits only when plan = 0. Bonus credits never expire.
|
||||
|
||||
### Plan
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| name | CharField | Plan name (Free, Starter, Growth, Scale) |
|
||||
| included_credits | Integer | Monthly credit allocation |
|
||||
| max_sites | Integer | Site limit (hard limit) |
|
||||
| max_users | Integer | User limit (hard limit) |
|
||||
| max_keywords | Integer | Keyword limit (hard limit) |
|
||||
| max_ahrefs_queries | Integer | Monthly Ahrefs queries (monthly limit) |
|
||||
| is_active | Boolean | Available for purchase |
|
||||
| is_internal | Boolean | Internal/test plan |
|
||||
|
||||
> **Note (v1.5.0+):** Operation limits like `max_clusters`, `max_content_words`, `max_images_basic`, `max_images_premium` were removed. All AI operations are now credit-based.
|
||||
|
||||
### Site
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| account | ForeignKey | Owner account |
|
||||
| name | CharField | Site name |
|
||||
| domain | CharField | Primary domain |
|
||||
| is_active | Boolean | Enable/disable |
|
||||
|
||||
### Sector
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| site | ForeignKey | Parent site |
|
||||
| account | ForeignKey | Owner account |
|
||||
| industry | ForeignKey | Industry template |
|
||||
| name | CharField | Sector name |
|
||||
| is_active | Boolean | Enable/disable |
|
||||
|
||||
---
|
||||
|
||||
## Base Model Classes
|
||||
|
||||
### AccountBaseModel
|
||||
|
||||
**File:** `auth/models.py`
|
||||
|
||||
All account-scoped models inherit from this:
|
||||
|
||||
```python
|
||||
class AccountBaseModel(models.Model):
|
||||
account = models.ForeignKey(Account, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
```
|
||||
|
||||
**Used by:** Billing records, Settings, API keys
|
||||
|
||||
### SiteSectorBaseModel
|
||||
|
||||
**File:** `auth/models.py`
|
||||
|
||||
All content models inherit from this:
|
||||
|
||||
```python
|
||||
class SiteSectorBaseModel(AccountBaseModel):
|
||||
site = models.ForeignKey(Site, on_delete=models.CASCADE)
|
||||
sector = models.ForeignKey(Sector, on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
```
|
||||
|
||||
**Used by:** Keywords, Clusters, Ideas, Tasks, Content, Images
|
||||
|
||||
---
|
||||
|
||||
## ViewSet Base Classes
|
||||
|
||||
### AccountModelViewSet
|
||||
|
||||
**File:** `api/base.py`
|
||||
|
||||
Automatically filters queryset by account:
|
||||
|
||||
```python
|
||||
class AccountModelViewSet(ModelViewSet):
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
if not self.request.user.is_admin_or_developer:
|
||||
qs = qs.filter(account=self.request.account)
|
||||
return qs
|
||||
```
|
||||
|
||||
### SiteSectorModelViewSet
|
||||
|
||||
**File:** `api/base.py`
|
||||
|
||||
Filters by account + site + sector:
|
||||
|
||||
```python
|
||||
class SiteSectorModelViewSet(AccountModelViewSet):
|
||||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
site_id = self.request.query_params.get('site_id')
|
||||
sector_id = self.request.query_params.get('sector_id')
|
||||
if site_id:
|
||||
qs = qs.filter(site_id=site_id)
|
||||
if sector_id:
|
||||
qs = qs.filter(sector_id=sector_id)
|
||||
return qs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Where Tenancy Applies
|
||||
|
||||
### Uses Site/Sector Filtering
|
||||
|
||||
| Module | Filter |
|
||||
|--------|--------|
|
||||
| Planner (Keywords, Clusters, Ideas) | site + sector |
|
||||
| Writer (Tasks, Content, Images) | site + sector |
|
||||
| Linker | site + sector |
|
||||
| Optimizer | site + sector |
|
||||
| Setup/Add Keywords | site + sector |
|
||||
|
||||
### Account-Level Only (No Site/Sector)
|
||||
|
||||
| Module | Filter |
|
||||
|--------|--------|
|
||||
| Billing/Plans | account only |
|
||||
| Account Settings | account only |
|
||||
| Team Management | account only |
|
||||
| User Profile | user only |
|
||||
| System Settings | account only |
|
||||
|
||||
---
|
||||
|
||||
## Frontend Implementation
|
||||
|
||||
### Site Selection
|
||||
|
||||
**Store:** `store/siteStore.ts`
|
||||
|
||||
```typescript
|
||||
const useSiteStore = create({
|
||||
activeSite: Site | null,
|
||||
sites: Site[],
|
||||
loadSites: () => Promise<void>,
|
||||
setActiveSite: (site: Site) => void,
|
||||
});
|
||||
```
|
||||
|
||||
### Sector Selection
|
||||
|
||||
**Store:** `store/sectorStore.ts`
|
||||
|
||||
```typescript
|
||||
const useSectorStore = create({
|
||||
activeSector: Sector | null,
|
||||
sectors: Sector[],
|
||||
loadSectorsForSite: (siteId: number) => Promise<void>,
|
||||
setActiveSector: (sector: Sector) => void,
|
||||
});
|
||||
```
|
||||
|
||||
### Sector Loading Pattern
|
||||
|
||||
Sectors are loaded by `PageHeader` component, not `AppLayout`:
|
||||
|
||||
```typescript
|
||||
// PageHeader.tsx
|
||||
useEffect(() => {
|
||||
if (hideSiteSector) return; // Skip for account pages
|
||||
|
||||
if (activeSite?.id && activeSite?.is_active) {
|
||||
loadSectorsForSite(activeSite.id);
|
||||
}
|
||||
}, [activeSite?.id, hideSiteSector]);
|
||||
```
|
||||
|
||||
**Pages with `hideSiteSector={true}`:**
|
||||
- `/account/*` (settings, team, billing)
|
||||
- User profile pages
|
||||
|
||||
---
|
||||
|
||||
## Global Resources (No Tenancy)
|
||||
|
||||
These are system-wide, not tenant-specific:
|
||||
|
||||
| Model | Purpose |
|
||||
|-------|---------|
|
||||
| Industry | Global industry taxonomy |
|
||||
| IndustrySector | Sub-categories within industries |
|
||||
| SeedKeyword | Global keyword database |
|
||||
| GlobalIntegrationSettings | Platform API keys |
|
||||
| GlobalAIPrompt | Default prompt templates |
|
||||
| GlobalAuthorProfile | Author persona templates |
|
||||
|
||||
---
|
||||
|
||||
## Tenant Data vs System Data
|
||||
|
||||
### System Data (KEEP on reset)
|
||||
|
||||
- Plans, CreditPackages
|
||||
- Industries, IndustrySectors
|
||||
- GlobalIntegrationSettings
|
||||
- GlobalAIPrompt, GlobalAuthorProfile
|
||||
- CreditCostConfig
|
||||
- PaymentMethodConfig
|
||||
|
||||
### Tenant Data (CLEAN on reset)
|
||||
|
||||
- Accounts, Users, Sites, Sectors
|
||||
- Keywords, Clusters, Ideas, Tasks, Content, Images
|
||||
- Subscriptions, Invoices, Payments
|
||||
- CreditTransactions, CreditUsageLogs
|
||||
- SiteIntegrations, SyncEvents
|
||||
- AutomationConfigs, AutomationRuns
|
||||
|
||||
---
|
||||
|
||||
## Admin/Developer Bypass
|
||||
|
||||
Admin and developer users can access all tenants:
|
||||
|
||||
```python
|
||||
# In auth/models.py
|
||||
class User:
|
||||
@property
|
||||
def is_admin_or_developer(self):
|
||||
return self.role in ['admin', 'developer']
|
||||
```
|
||||
|
||||
**Bypass Rules:**
|
||||
- Admin: Full access to own account
|
||||
- Developer: Full access to ALL accounts
|
||||
- System accounts protected from deletion
|
||||
|
||||
---
|
||||
|
||||
## Common Issues
|
||||
|
||||
| Issue | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| Data leak between accounts | Missing account filter | Use AccountModelViewSet |
|
||||
| Wrong site data | Site not validated for account | Validate site.account == request.account |
|
||||
| Sector not loading | Site changed but sector not reset | Clear activeSector when activeSite changes |
|
||||
| Admin can't see all data | Incorrect role check | Check is_admin_or_developer |
|
||||
|
||||
---
|
||||
|
||||
## Planned Changes
|
||||
|
||||
| Feature | Status | Description |
|
||||
|---------|--------|-------------|
|
||||
| Account switching | 🔜 Planned | Allow users to switch between accounts |
|
||||
| Sub-accounts | 🔜 Planned | Hierarchical account structure |
|
||||
66
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/TIMEZONE.md
Normal file
66
v2/Live Docs on Server/igny8-app-docs/00-SYSTEM/TIMEZONE.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Timezone Standard
|
||||
|
||||
## Purpose
|
||||
This document defines the single-source timezone standard for IGNY8 and how all future time-related features must use it.
|
||||
|
||||
## Single Source of Truth
|
||||
- **Account timezone** is the canonical timezone for all user-visible times and scheduling UI.
|
||||
- The value is stored on the Account model as `account_timezone` (IANA name, e.g., `America/New_York`).
|
||||
- Selection modes:
|
||||
- **Country-derived**: timezone is derived from billing country.
|
||||
- **Manual**: user picks an IANA timezone that maps to a UTC offset list.
|
||||
|
||||
## Storage Rules
|
||||
- **Persist timestamps in UTC** in the database.
|
||||
- **Never store local times** without timezone context.
|
||||
- Store user selection in `Account.account_timezone` and (when needed) `timezone_mode` and `timezone_offset` for UI display.
|
||||
|
||||
## Display Rules (Frontend)
|
||||
- All UI formatting must use the account timezone.
|
||||
- Use shared helpers:
|
||||
- `getAccountTimezone()` for the active timezone.
|
||||
- `formatDate()`, `formatDateTime()`, `formatRelativeDate()` for consistent formatting.
|
||||
- **Do not** call `toLocaleDateString()` or `toLocaleTimeString()` without passing the account timezone.
|
||||
|
||||
## Scheduling Rules
|
||||
- All scheduling inputs in UI are **account timezone**.
|
||||
- Convert to UTC before sending to the backend.
|
||||
- All API payloads for scheduling must send ISO-8601 with timezone offset.
|
||||
- The backend stores scheduled datetimes in UTC.
|
||||
|
||||
## Backend API Contract
|
||||
- Endpoints that return timestamps should return UTC ISO strings.
|
||||
- Endpoints that return “server time” should return **account-local time** for display, plus the account timezone identifier.
|
||||
- If the account timezone is invalid or missing, fall back to `UTC`.
|
||||
|
||||
## Country List Source
|
||||
- Country list must be fetched from `/v1/auth/countries/`.
|
||||
- No hardcoded country lists in UI or backend responses.
|
||||
|
||||
## Implementation Checklist (New Features)
|
||||
1. **Input**: confirm user inputs are in account timezone.
|
||||
2. **Conversion**: convert to UTC before persistence or scheduling.
|
||||
3. **Storage**: store in UTC only.
|
||||
4. **Output**: format all timestamps with account timezone helpers.
|
||||
5. **API**: ensure responses include timezone-aware context when needed.
|
||||
|
||||
## Guardrails
|
||||
- Never introduce a second timezone source per user/site.
|
||||
- Do not mix server timezone with account timezone in UI.
|
||||
- Avoid timezone math in the UI; prefer helpers and backend-provided values when possible.
|
||||
|
||||
## Examples
|
||||
- **Display date in UI**:
|
||||
- Use `formatDateTime(timestamp)` to render in account timezone.
|
||||
- **Schedule content**:
|
||||
- User selects date/time in account timezone → convert to ISO → send to `/schedule/`.
|
||||
|
||||
## Troubleshooting
|
||||
- If times appear “off”:
|
||||
- Check account timezone is set.
|
||||
- Confirm UI uses helpers.
|
||||
- Confirm backend converts to UTC before save.
|
||||
|
||||
---
|
||||
Owner: Platform
|
||||
Last updated: 2026-01-19
|
||||
Reference in New Issue
Block a user