PDF documents with Mermaid diagrams, styled with purple theme. Includes build script for regenerating PDFs from Markdown sources. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1333 lines
41 KiB
Markdown
1333 lines
41 KiB
Markdown
---
|
||
pdf_options:
|
||
format: A4
|
||
margin: 25mm 20mm
|
||
headerTemplate: '<div style="font-size:8px;color:#999;width:100%;text-align:right;margin-right:20mm;">Oliver DeckForge — System Administration Guide</div>'
|
||
footerTemplate: '<div style="font-size:8px;color:#999;width:100%;text-align:center;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>'
|
||
displayHeaderFooter: true
|
||
stylesheet:
|
||
- https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.5.1/github-markdown.min.css
|
||
body_class: markdown-body
|
||
css: |-
|
||
body { font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; }
|
||
.markdown-body { max-width: 100%; }
|
||
h1 { color: #5146E5; border-bottom: 3px solid #5146E5; padding-bottom: 8px; }
|
||
h2 { color: #3b3494; border-bottom: 1px solid #E9E8F8; padding-bottom: 6px; margin-top: 2em; }
|
||
h3 { color: #4a4a4a; }
|
||
h4 { color: #555; }
|
||
table { width: 100%; }
|
||
th { background: #5146E5; color: white; }
|
||
td, th { padding: 8px 12px; }
|
||
code { background: #f0eff8; color: #5146E5; padding: 2px 6px; border-radius: 4px; }
|
||
pre code { background: #1e1e2e; color: #cdd6f4; display: block; padding: 16px; border-radius: 8px; }
|
||
blockquote { border-left: 4px solid #5146E5; background: #f8f7ff; padding: 12px 16px; margin: 16px 0; }
|
||
.tip { border-left: 4px solid #22c55e; background: #f0fdf4; padding: 12px 16px; margin: 16px 0; border-radius: 0 8px 8px 0; }
|
||
.warning { border-left: 4px solid #f59e0b; background: #fffbeb; padding: 12px 16px; margin: 16px 0; border-radius: 0 8px 8px 0; }
|
||
.danger { border-left: 4px solid #ef4444; background: #fef2f2; padding: 12px 16px; margin: 16px 0; border-radius: 0 8px 8px 0; }
|
||
img { max-width: 100%; max-height: 280px; object-fit: contain; display: block; margin: 16px auto; }
|
||
---
|
||
|
||
# Oliver DeckForge — System Administration Guide
|
||
|
||
**Version 1.0** | Complete Setup, Configuration & Operations Reference
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
1. [Architecture Overview](#1-architecture-overview)
|
||
2. [Installation & Deployment](#2-installation--deployment)
|
||
3. [Environment Variables Reference](#3-environment-variables-reference)
|
||
4. [Authentication Configuration](#4-authentication-configuration)
|
||
5. [Role-Based Access Control](#5-role-based-access-control)
|
||
6. [Admin Panel Operations](#6-admin-panel-operations)
|
||
7. [Template Pipeline](#7-template-pipeline)
|
||
8. [AI Provider Configuration](#8-ai-provider-configuration)
|
||
9. [Database Administration](#9-database-administration)
|
||
10. [Background Jobs & Workers](#10-background-jobs--workers)
|
||
11. [Nginx & Networking](#11-nginx--networking)
|
||
12. [Storage & File Management](#12-storage--file-management)
|
||
13. [Monitoring & Logging](#13-monitoring--logging)
|
||
14. [Backup & Recovery](#14-backup--recovery)
|
||
15. [Security Hardening](#15-security-hardening)
|
||
16. [Scaling & Performance](#16-scaling--performance)
|
||
17. [Troubleshooting](#17-troubleshooting)
|
||
18. [API Reference](#18-api-reference)
|
||
|
||
---
|
||
|
||
|
||
## 1. Architecture Overview
|
||
|
||
### 1.1 System Architecture
|
||
|
||
```mermaid
|
||
graph LR
|
||
Browser([Browser]) --> NG[nginx :80]
|
||
NG --> NX[Next.js :3000]
|
||
NG --> FA[FastAPI :8000]
|
||
FA --> PG[(PostgreSQL)]
|
||
FA --> RD[(Redis)]
|
||
FA --> VOL[/app_data/]
|
||
ARQ[ARQ Worker] --> PG
|
||
ARQ --> RD
|
||
ARQ --> VOL
|
||
FA --> AI{AI APIs}
|
||
ARQ --> AI
|
||
```
|
||
|
||
### 1.2 Service Overview
|
||
|
||
| Service | Technology | Port | Purpose |
|
||
|---------|-----------|------|---------|
|
||
| **nginx** | nginx:alpine | 80 | Reverse proxy, static file serving, SSL termination |
|
||
| **web** | Next.js 14 | 3000 | Frontend SPA, Puppeteer-based export |
|
||
| **api** | FastAPI + SQLModel | 8000 | REST API, authentication, RBAC |
|
||
| **worker** | ARQ (Python) | — | Background AI generation, parsing, retention |
|
||
| **postgres** | PostgreSQL 16 | 5432 | Primary relational database |
|
||
| **redis** | Redis 7 | 6379 | Job queue, caching |
|
||
|
||
### 1.3 Request Flow
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant B as Browser
|
||
participant N as nginx
|
||
participant W as Next.js
|
||
participant A as FastAPI
|
||
participant M as Middleware
|
||
participant DB as PostgreSQL
|
||
|
||
B->>N: HTTP Request
|
||
alt /api/v1/*
|
||
N->>A: Proxy to backend
|
||
A->>M: Auth + RBAC check
|
||
M->>DB: Validate session
|
||
DB-->>M: User context
|
||
M-->>A: request.state.user
|
||
A-->>N: JSON response
|
||
else /* (all other)
|
||
N->>W: Proxy to frontend
|
||
W-->>N: HTML/JS/CSS
|
||
end
|
||
N-->>B: Response
|
||
```
|
||
|
||
### 1.4 Data Flow: Presentation Generation
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Submit] --> B[Decompose] --> C[Outline] --> D[Template]
|
||
D --> E[Job Queue] --> F[Worker]
|
||
F --> G[AI Content] --> H[Images] --> I[Save DB]
|
||
I --> J[SSE Notify] --> K[Editor]
|
||
```
|
||
|
||
---
|
||
|
||
|
||
## 2. Installation & Deployment
|
||
|
||
### 2.1 Prerequisites
|
||
|
||
| Requirement | Minimum | Recommended |
|
||
|-------------|---------|-------------|
|
||
| Docker | 20.10+ | 24.0+ |
|
||
| Docker Compose | v2.0+ | v2.20+ |
|
||
| RAM | 4 GB | 8 GB+ |
|
||
| Disk | 10 GB | 50 GB+ (for generated assets) |
|
||
| CPU | 2 cores | 4+ cores |
|
||
|
||
### 2.2 Quick Start
|
||
|
||
```bash
|
||
# 1. Clone repository
|
||
git clone <repository-url>
|
||
cd ppt-tool
|
||
|
||
# 2. Configure environment
|
||
cp .env.example .env
|
||
# Edit .env — set ANTHROPIC_API_KEY at minimum
|
||
|
||
# 3. Build and start
|
||
make dev
|
||
|
||
# 4. Run migrations
|
||
make migrate
|
||
|
||
# 5. Seed default data
|
||
make seed
|
||
```
|
||
|
||
The application is available at:
|
||
- **http://localhost** — Full application (via nginx)
|
||
- **http://localhost:3000** — Frontend directly
|
||
- **http://localhost:8000** — API directly
|
||
- **http://localhost/docs** — Swagger API documentation
|
||
|
||
### 2.3 Makefile Commands
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `make dev` | Build and start all services with logs |
|
||
| `make build` | Build Docker images only |
|
||
| `make up` | Start services in background (detached) |
|
||
| `make down` | Stop and remove all containers |
|
||
| `make migrate` | Run Alembic database migrations |
|
||
| `make seed` | Seed default admin user and team |
|
||
| `make test` | Run backend pytest suite |
|
||
| `make test-e2e` | Run Cypress E2E tests |
|
||
| `make test-all` | Run all tests |
|
||
| `make logs` | Follow all container logs |
|
||
| `make shell-api` | Open bash shell in API container |
|
||
| `make shell-db` | Open psql shell in PostgreSQL |
|
||
|
||
### 2.4 Local Development (Without Docker)
|
||
|
||
#### Backend
|
||
|
||
```bash
|
||
cd backend
|
||
python -m venv venv && source venv/bin/activate
|
||
pip install -r requirements.txt
|
||
|
||
export DATABASE_URL="postgresql+asyncpg://deckforge:deckforge@localhost:5432/deckforge"
|
||
export REDIS_URL="redis://localhost:6379/0"
|
||
export APP_DATA_DIRECTORY="./data"
|
||
export ANTHROPIC_API_KEY="sk-ant-..."
|
||
|
||
# Start API
|
||
uvicorn api.main:app --reload --port 8000
|
||
|
||
# Start worker (separate terminal)
|
||
python -m arq workers.main.WorkerSettings
|
||
```
|
||
|
||
#### Frontend
|
||
|
||
```bash
|
||
cd frontend
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
The Next.js dev server proxies `/api/v1/` requests to `http://localhost:8000` via rewrites in `next.config.mjs`.
|
||
|
||
### 2.5 Docker Image Details
|
||
|
||
**Backend Dockerfile** (multi-stage):
|
||
- **Builder stage**: `python:3.11-slim-bookworm` + `uv` package manager
|
||
- **Runtime stage**: Includes LibreOffice (PDF conversion), Chromium (browser automation), fontconfig, ONNX models
|
||
- Exposes port 8000
|
||
|
||
**Frontend Dockerfile**:
|
||
- **Base**: `node:20-alpine`
|
||
- Includes Chromium for server-side Puppeteer PDF/PPTX export
|
||
- Environment: `PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser`
|
||
- Exposes port 3000
|
||
|
||
---
|
||
|
||
|
||
## 3. Environment Variables Reference
|
||
|
||
### 3.1 Database & Infrastructure
|
||
|
||
| Variable | Required | Default | Description |
|
||
|----------|----------|---------|-------------|
|
||
| `POSTGRES_PASSWORD` | No | `deckforge` | PostgreSQL password |
|
||
| `DATABASE_URL` | Auto | Set by docker-compose | Full async connection string |
|
||
| `REDIS_URL` | No | `redis://redis:6379/0` | Redis connection string |
|
||
| `APP_DATA_DIRECTORY` | No | `/app_data` | Path for images, exports, uploads |
|
||
| `TEMP_DIRECTORY` | No | `/tmp/deckforge` | Temporary file storage |
|
||
|
||
### 3.2 Authentication
|
||
|
||
| Variable | Required | Default | Description |
|
||
|----------|----------|---------|-------------|
|
||
| `JWT_SECRET_KEY` | **Yes** | `change-me-...` | Secret for JWT signing (256-bit+) |
|
||
| `AZURE_AD_TENANT_ID` | No | — | Azure AD tenant ID (blank = dev mode) |
|
||
| `AZURE_AD_CLIENT_ID` | No | — | Azure AD app client ID |
|
||
| `AZURE_AD_CLIENT_SECRET` | No | — | Azure AD app secret |
|
||
| `AZURE_AD_REDIRECT_URI` | No | `http://localhost/api/v1/auth/callback` | OAuth callback URL |
|
||
| `DEV_AUTH_PASSWORD` | No | `devpass123` | Dev bypass login password |
|
||
|
||
### 3.3 AI Providers
|
||
|
||
| Variable | Required | Default | Description |
|
||
|----------|----------|---------|-------------|
|
||
| `LLM` | No | `anthropic` | Primary LLM provider |
|
||
| `ANTHROPIC_API_KEY` | **Yes*** | — | Claude API key |
|
||
| `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Claude model ID |
|
||
| `OPENAI_API_KEY` | No | — | OpenAI API key |
|
||
| `OPENAI_MODEL` | No | — | OpenAI model ID |
|
||
| `GOOGLE_API_KEY` | No | — | Google Gemini API key |
|
||
| `GOOGLE_MODEL` | No | — | Google model ID |
|
||
| `OLLAMA_URL` | No | — | Ollama server URL |
|
||
| `OLLAMA_MODEL` | No | — | Ollama model name |
|
||
| `IMAGE_PROVIDER` | No | `nanobanana_pro` | Image generation provider |
|
||
| `DISABLE_IMAGE_GENERATION` | No | — | Set to disable image gen |
|
||
|
||
*Required if using Anthropic (default provider)
|
||
|
||
### 3.4 Application Settings
|
||
|
||
| Variable | Required | Default | Description |
|
||
|----------|----------|---------|-------------|
|
||
| `CAN_CHANGE_KEYS` | No | `false` | Allow runtime API key changes |
|
||
| `DISABLE_ANONYMOUS_TRACKING` | No | `true` | Disable analytics tracking |
|
||
| `SETTINGS_ENCRYPTION_KEY` | No | — | Fernet key for encrypting stored API keys |
|
||
| `EXTENDED_REASONING` | No | — | Enable LLM extended thinking |
|
||
| `TOOL_CALLS` | No | — | Enable LLM tool use |
|
||
| `WEB_GROUNDING` | No | — | Enable web search in generation |
|
||
| `NEXT_INTERNAL_URL` | No | `http://web:3000` | Backend → frontend URL (Docker) |
|
||
|
||
### 3.5 Supported AI Providers
|
||
|
||
**LLM Providers:**
|
||
|
||
| Provider | Value | Models |
|
||
|----------|-------|--------|
|
||
| Anthropic | `anthropic` | claude-opus-4-6, claude-sonnet-4-6, claude-sonnet-4-5, claude-haiku-4-5 |
|
||
| OpenAI | `openai` | gpt-4.1, gpt-4.1-mini, gpt-4o, o3, o4-mini |
|
||
| Google | `google` | gemini-2.5-flash, gemini-2.5-pro, gemini-2.0-flash |
|
||
| Ollama | `ollama` | Any locally installed model |
|
||
| Custom | `custom` | Any OpenAI-compatible endpoint |
|
||
|
||
**Image Providers:**
|
||
|
||
| Provider | Value | Requirements |
|
||
|----------|-------|-------------|
|
||
| NanoBanana Pro | `nanobanana_pro` | Google API key |
|
||
| Gemini Flash | `gemini_flash` | Google API key |
|
||
| DALL-E 3 | `dall-e-3` | OpenAI API key |
|
||
| GPT Image 1.5 | `gpt-image-1.5` | OpenAI API key |
|
||
| Pexels | `pexels` | Pexels API key |
|
||
| Pixabay | `pixabay` | Pixabay API key |
|
||
| ComfyUI | `comfyui` | Local ComfyUI instance |
|
||
|
||
---
|
||
|
||
|
||
## 4. Authentication Configuration
|
||
|
||
### 4.1 Authentication Flow
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Login Page] --> B{Azure AD?}
|
||
B -->|Yes| C[SSO] --> D[Callback] --> E{User exists?}
|
||
B -->|No| F[Dev Login] --> E
|
||
E -->|Yes| G[Update login]
|
||
E -->|No| H[Create user]
|
||
G --> I[JWT Cookie]
|
||
H --> I
|
||
```
|
||
|
||
### 4.2 Azure AD Setup (Production)
|
||
|
||
1. **Register an application** in Azure Portal > Azure AD > App Registrations
|
||
2. Set the **Redirect URI** to: `https://your-domain.com/api/v1/auth/callback`
|
||
3. Create a **client secret** under Certificates & Secrets
|
||
4. Configure environment variables:
|
||
|
||
```env
|
||
AZURE_AD_TENANT_ID=your-tenant-id
|
||
AZURE_AD_CLIENT_ID=your-client-id
|
||
AZURE_AD_CLIENT_SECRET=your-client-secret
|
||
AZURE_AD_REDIRECT_URI=https://your-domain.com/api/v1/auth/callback
|
||
```
|
||
|
||
5. Grant API permissions: `User.Read` (delegated)
|
||
|
||
### 4.3 Development Mode
|
||
|
||
When `AZURE_AD_TENANT_ID` is empty or not set, the system enables development authentication:
|
||
|
||
- Login form with email + password fields
|
||
- Password validated against `DEV_AUTH_PASSWORD` environment variable
|
||
- Users are auto-created on first login
|
||
- Default role: `user`
|
||
|
||
<div class="danger">
|
||
|
||
**Security Warning:** Development mode should never be used in production. Always configure Azure AD or another SSO provider for production deployments.
|
||
|
||
</div>
|
||
|
||
### 4.4 JWT Configuration
|
||
|
||
| Parameter | Value |
|
||
|-----------|-------|
|
||
| Algorithm | HS256 |
|
||
| Expiry | 24 hours |
|
||
| Storage | `session_token` HTTP cookie |
|
||
| Payload | `sub` (user UUID), `email`, `role`, `exp`, `iat` |
|
||
|
||
<div class="warning">
|
||
|
||
**Critical:** Change `JWT_SECRET_KEY` from the default value in production. Use a cryptographically random 256-bit key. All active sessions are invalidated when this key changes.
|
||
|
||
</div>
|
||
|
||
---
|
||
|
||
|
||
## 5. Role-Based Access Control
|
||
|
||
### 5.1 Role Hierarchy
|
||
|
||
```mermaid
|
||
graph LR
|
||
SA[Super Admin] --> CA[Client Admin] --> U[User]
|
||
SA -.->|Full access| ALL[All Clients]
|
||
CA -.->|Scoped| CLIENT[Assigned Clients]
|
||
U -.->|Basic| OWN[Own Data]
|
||
```
|
||
|
||
### 5.2 Permission Matrix
|
||
|
||
| Feature | Super Admin | Client Admin | User |
|
||
|---------|:-----------:|:------------:|:----:|
|
||
| **Presentations** | All | Client-scoped | Own only |
|
||
| **Admin Panel** | Full | Limited | None |
|
||
| **User Management** | CRUD all | View team members | — |
|
||
| **Client Management** | CRUD all | View/edit assigned | — |
|
||
| **Team Management** | All teams | Assigned client teams | — |
|
||
| **Master Decks** | All | Client-scoped | — |
|
||
| **Storage** | All clients | Client-scoped | — |
|
||
| **Analytics** | Global + per-client | Client-scoped | — |
|
||
| **Audit Logs** | All | Client-scoped | — |
|
||
| **System Settings** | Full access | — | — |
|
||
| **Brand Config** | All clients | Client-scoped | — |
|
||
|
||
### 5.3 Multi-Tenant Data Isolation
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Request] --> B[Auth] --> C[RBAC] --> D{Role}
|
||
D -->|super_admin| E[No filter]
|
||
D -->|client_admin| F[Team lookup → client_ids]
|
||
D -->|user| G[Own data + team clients]
|
||
```
|
||
|
||
The `_resolve_client_filter()` pattern is used throughout:
|
||
- **Super Admin with no client_id param** → Returns `None` (no filter, see all)
|
||
- **Super Admin with client_id param** → Filters to specific client
|
||
- **Client Admin** → Auto-scoped to accessible clients via `TeamMembershipModel`
|
||
- **User** → Scoped to own data within accessible clients
|
||
|
||
### 5.4 Admin Panel Navigation
|
||
|
||
The sidebar dynamically shows menu items based on role:
|
||
|
||
| Menu Item | Super Admin | Client Admin |
|
||
|-----------|:-----------:|:------------:|
|
||
| Users | Yes | — |
|
||
| Clients | Yes | Yes |
|
||
| Storage | Yes | Yes |
|
||
| Audit Log | Yes | Yes |
|
||
| Analytics | Yes | Yes |
|
||
| Settings | Yes | — |
|
||
|
||
---
|
||
|
||
|
||
## 6. Admin Panel Operations
|
||
|
||
### 6.1 User Management
|
||
|
||
**Path:** Admin > Users (Super Admin only)
|
||
|
||
#### Listing Users
|
||
- Table with columns: Name, Email, Role, Status, Last Login
|
||
- Filterable by active status and role
|
||
|
||
#### Changing User Roles
|
||
1. Find the user in the list
|
||
2. Click the role dropdown
|
||
3. Select new role: `super_admin`, `client_admin`, or `user`
|
||
|
||
<div class="warning">
|
||
|
||
You cannot change your own role. This prevents accidental lockout.
|
||
|
||
</div>
|
||
|
||
#### Deactivating Users
|
||
1. Click **Deactivate** on the user row
|
||
2. Confirm the action
|
||
3. User's `is_active` is set to false — they can no longer log in
|
||
4. Their presentations remain in the system
|
||
|
||
#### Transferring Ownership
|
||
Before deactivating a user (e.g., for GDPR compliance):
|
||
1. Use the transfer ownership endpoint to move all presentations to another user
|
||
2. Then deactivate the original user
|
||
|
||
### 6.2 Client Management
|
||
|
||
**Path:** Admin > Clients
|
||
|
||
#### Creating a Client
|
||
1. Click **"+ New Client"**
|
||
2. Enter the client name
|
||
3. A URL-safe slug is auto-generated
|
||
4. A default team is auto-created for the client
|
||
|
||
#### Client Settings
|
||
Each client has configurable:
|
||
|
||
| Setting | Description |
|
||
|---------|-------------|
|
||
| **Name** | Display name |
|
||
| **Slug** | URL-safe identifier (unique) |
|
||
| **Review Policy** | `self_approve` or `require_reviewer` |
|
||
| **Retention Days** | Auto-delete presentations after N days (optional) |
|
||
|
||
### 6.3 Team Management
|
||
|
||
**Path:** Admin > Clients > [Client] > Teams
|
||
|
||
Teams group users within a client:
|
||
- Each client has a **default team** (cannot be deleted)
|
||
- Users can belong to multiple teams
|
||
- Team membership determines client access for non-admin users
|
||
|
||
#### Adding Team Members
|
||
1. Navigate to the client's team page
|
||
2. Click **"+ Add Member"**
|
||
3. Search and select a user from the dropdown
|
||
4. The user now has access to this client's data
|
||
|
||
### 6.4 Brand Configuration
|
||
|
||
**Path:** Admin > Clients > [Client] > Brand Config
|
||
|
||
Configure branding per client:
|
||
|
||
| Setting | Description |
|
||
|---------|-------------|
|
||
| **Primary Colors** | Color picker, add/remove multiple colors |
|
||
| **Secondary Colors** | Color picker, add/remove multiple colors |
|
||
| **Fonts** | Heading, Body, and Accent font names |
|
||
| **Logos** | Upload multiple logo images |
|
||
| **Voice Rules** | Text guidelines for AI tone and style |
|
||
| **Voice Examples** | Good/bad example pairs for AI training |
|
||
| **Brand Guideline** | Upload a PDF/DOCX brand guide |
|
||
|
||
Brand configuration is injected into AI prompts during presentation generation to ensure brand consistency.
|
||
|
||
### 6.5 Storage Management
|
||
|
||
**Path:** Admin > Storage
|
||
|
||
#### Summary Dashboard
|
||
Four cards show:
|
||
- **Presentations** count
|
||
- **Export Files** count
|
||
- **Master Decks** count
|
||
- **Total Size** (formatted)
|
||
|
||
#### Client Selector (Super Admin)
|
||
Dropdown to filter by specific client or view all clients combined.
|
||
|
||
#### Presentation Table
|
||
- Columns: Title, Status, Created, Files, Size
|
||
- Checkboxes for bulk selection
|
||
- Per-row actions: Download PPTX, Delete
|
||
|
||
#### Bulk Operations
|
||
- Select multiple presentations via checkboxes
|
||
- Click **"Delete Selected"** for bulk soft-delete
|
||
|
||
#### Purge Files (Super Admin Only)
|
||
- Amber banner shows count of soft-deleted presentations
|
||
- **"Purge Files"** permanently removes files from disk
|
||
- Returns statistics: files purged, bytes freed
|
||
|
||
### 6.6 Analytics Dashboard
|
||
|
||
**Path:** Admin > Analytics
|
||
|
||
#### Overview Metrics
|
||
- Total Presentations (all-time)
|
||
- This Month / This Week (30/7-day counts)
|
||
- Active Users (distinct users, last 30 days)
|
||
- Approval Rate (% approved or in_review)
|
||
|
||
#### Usage Metrics
|
||
- **Presentations per Day** — 14-day bar chart
|
||
- **Top 10 Users** — ranked by presentation count
|
||
|
||
#### Quality Metrics
|
||
- **Status Distribution** — draft/in_review/approved breakdown
|
||
- **Presentations with Comments** — count
|
||
|
||
#### Performance Metrics
|
||
- **Average Generation Time** — job completion duration
|
||
- **Total Jobs** — all-time count
|
||
- **Error Rate** — % failed jobs
|
||
|
||
#### AI Usage (if tracking enabled)
|
||
- Total AI Calls, Input/Output Tokens
|
||
- Usage by Provider (bar chart)
|
||
- Usage by Model (top 10)
|
||
- Daily Usage Trend
|
||
|
||
### 6.7 Audit Logs
|
||
|
||
**Path:** Admin > Audit Log
|
||
|
||
All mutating API requests are logged automatically.
|
||
|
||
#### Query Filters
|
||
- **Action** — text search (e.g., "admin_delete")
|
||
- **User ID** — filter by specific user
|
||
- **Resource Type** — e.g., "presentation", "storage"
|
||
- **Client ID** — scope to a client
|
||
- **Date Range** — from/to date pickers
|
||
|
||
#### Export
|
||
- Click **"Export Audit Log"**
|
||
- Choose format: CSV or JSON
|
||
- Downloads up to 10,000 entries
|
||
|
||
#### Logged Actions
|
||
| Action | Trigger |
|
||
|--------|---------|
|
||
| `admin_delete` | Single presentation soft-delete |
|
||
| `admin_bulk_delete` | Bulk presentation delete |
|
||
| `admin_purge` | Hard-delete purged files |
|
||
| Role changes, team membership updates, etc. | Various admin operations |
|
||
|
||
---
|
||
|
||
|
||
## 7. Template Pipeline
|
||
|
||
### 7.1 Master Deck → Template Flow
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Upload PPTX] --> B[Enqueue Job]
|
||
B --> C{Parse Mode}
|
||
C -->|layouts| D[slideLayouts XML]
|
||
C -->|slides| E[slides XML]
|
||
D --> F[PDF → Screenshots]
|
||
E --> F
|
||
F --> G[LLM Vision: Screenshot+XML → TSX]
|
||
G --> H[Store Layouts] --> I[Register Template]
|
||
```
|
||
|
||
### 7.2 Upload & Parse
|
||
|
||
1. Navigate to **Admin > Clients > [Client] > Master Decks**
|
||
2. Click **"Upload PPTX"** and select a `.pptx` file
|
||
3. The deck enters **"pending"** status, then **"processing"**
|
||
4. Auto-polling every 5 seconds shows current status
|
||
5. On completion, status changes to **"completed"** and layouts appear
|
||
|
||
### 7.3 Parse Modes
|
||
|
||
| Mode | Source | Best For |
|
||
|------|--------|----------|
|
||
| **slides** (default) | Actual slides (`ppt/slides/`) | Decks with unique slide designs; 1:1 screenshot match |
|
||
| **layouts** | Slide layouts (`ppt/slideLayouts/`) | Decks with reusable layout templates; may produce more layouts |
|
||
|
||
### 7.4 Layout Management
|
||
|
||
After parsing, manage layouts in the expanded deck view:
|
||
|
||
**Filtering & Search:**
|
||
- Text search by layout name
|
||
- Type filter dropdown (auto-detected from layout types)
|
||
- Code filter: All / Has Code / Missing Code
|
||
|
||
**Individual Actions:**
|
||
- **Edit** — modify name, type, or React TSX code
|
||
- **Delete** — remove with confirmation dialog
|
||
|
||
**Bulk Actions:**
|
||
- Toggle **Select Mode** to show checkboxes
|
||
- **Select All** / **Deselect All**
|
||
- **Delete Selected** — bulk remove
|
||
|
||
<div class="tip">
|
||
|
||
After deleting layouts, the system automatically re-registers the template by recreating `PresentationLayoutCodeModel` records for the remaining layouts.
|
||
|
||
</div>
|
||
|
||
### 7.5 Reparsing
|
||
|
||
If layouts need to be regenerated (e.g., after an LLM model upgrade):
|
||
1. Click the reparse dropdown on the deck card
|
||
2. Choose **"Reparse (slides)"** or **"Reparse (layouts)"**
|
||
3. All existing layouts are replaced with freshly parsed versions
|
||
|
||
---
|
||
|
||
|
||
## 8. AI Provider Configuration
|
||
|
||
### 8.1 Settings Page
|
||
|
||
**Path:** Admin > Settings (Super Admin only)
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Select LLM Provider] --> B[Fetch Available Models]
|
||
B --> C[Select Model]
|
||
C --> D[Enter API Key]
|
||
D --> E[Test Connection]
|
||
E -->|OK| F[Save Settings]
|
||
E -->|Fail| G[Check Key / Network]
|
||
```
|
||
|
||
### 8.2 Configuring LLM Provider
|
||
|
||
1. Open **Admin > Settings**
|
||
2. Select the **LLM Provider** from the dropdown
|
||
3. The **Model** dropdown auto-populates with available models
|
||
4. Enter the **API Key** if not already set (shown as "Set" badge if configured)
|
||
5. Click **"Test"** to verify connectivity
|
||
6. Click **"Save Changes"**
|
||
|
||
### 8.3 Configuring Image Provider
|
||
|
||
1. Select the **Image Provider** from the dropdown
|
||
2. Ensure the required API key is set (e.g., Google API key for NanoBanana Pro)
|
||
3. Save changes
|
||
|
||
### 8.4 Connection Testing
|
||
|
||
The **"Test"** button performs a lightweight API call to validate the key:
|
||
|
||
| Result | Display |
|
||
|--------|---------|
|
||
| Success | Green check + latency in ms |
|
||
| Failure | Red X + error message |
|
||
|
||
### 8.5 Settings Persistence
|
||
|
||
Settings are persisted to the database via `KeyValueSqlModel`:
|
||
- Survive container restarts
|
||
- API keys optionally encrypted at rest (if `SETTINGS_ENCRYPTION_KEY` is set)
|
||
- Environment variables serve as defaults — database values override them
|
||
|
||
---
|
||
|
||
|
||
## 9. Database Administration
|
||
|
||
### 9.1 Schema Overview
|
||
|
||
```mermaid
|
||
erDiagram
|
||
UserModel ||--o{ TeamMembershipModel : "belongs to"
|
||
TeamModel ||--o{ TeamMembershipModel : "has"
|
||
ClientModel ||--o{ TeamModel : "owns"
|
||
ClientModel ||--o{ BrandConfigModel : "has"
|
||
ClientModel ||--o{ MasterDeckModel : "has"
|
||
|
||
UserModel ||--o{ PresentationModel : "creates"
|
||
ClientModel ||--o{ PresentationModel : "scopes"
|
||
PresentationModel ||--o{ SlideModel : "contains"
|
||
PresentationModel ||--o{ JobModel : "tracks"
|
||
|
||
UserModel ||--o{ AuditLogModel : "generates"
|
||
UserModel ||--o{ AIUsageModel : "tracks"
|
||
|
||
MasterDeckModel ||--o{ TemplateModel : "registers as"
|
||
TemplateModel ||--o{ PresentationLayoutCodeModel : "has layouts"
|
||
```
|
||
|
||
### 9.2 Core Tables
|
||
|
||
| Table | Purpose | Key Fields |
|
||
|-------|---------|------------|
|
||
| `usermodel` | User accounts | id, email, role, azure_oid, is_active |
|
||
| `clientmodel` | Tenant organizations | id, name, slug, retention_days, review_policy |
|
||
| `teammodel` | Team groupings | id, name, client_id, is_default |
|
||
| `teammembershipmodel` | User↔Team links | user_id, team_id, assigned_by |
|
||
| `presentationmodel` | Presentations | id, title, owner_id, client_id, status, content |
|
||
| `slidemodel` | Individual slides | id, presentation, index, content, layout |
|
||
| `jobmodel` | Background jobs | id, job_type, status, progress, error_message |
|
||
| `masterdeck` | Master PPTX decks | id, client_id, layouts (JSON), parse_status |
|
||
| `templatemodel` | Registered templates | id, name, description |
|
||
| `presentationlayoutcodemodel` | Layout TSX code | presentation, layout_name, layout_code |
|
||
| `brandconfigmodel` | Brand settings | client_id, colors, fonts, logos, voice_rules |
|
||
| `auditlogmodel` | Audit trail | user_id, action, resource_type, ip_address |
|
||
| `aiusagemodel` | AI usage metrics | provider, model, tokens, duration_ms |
|
||
| `keyvaluesqlmodel` | KV settings store | key, value (JSON) |
|
||
| `imageasset` | Generated images | id, path, is_uploaded |
|
||
|
||
### 9.3 Alembic Migrations
|
||
|
||
```bash
|
||
# View migration history
|
||
docker compose exec api alembic history
|
||
|
||
# Apply all pending migrations
|
||
make migrate
|
||
# or: docker compose exec api alembic upgrade head
|
||
|
||
# Generate new migration after model changes
|
||
docker compose exec api alembic revision --autogenerate -m "description"
|
||
|
||
# Rollback last migration
|
||
docker compose exec api alembic downgrade -1
|
||
|
||
# View current revision
|
||
docker compose exec api alembic current
|
||
```
|
||
|
||
<div class="warning">
|
||
|
||
Always review auto-generated migrations before applying. SQLAlchemy may miss rename operations (interpreting them as drop + create) or produce incorrect defaults.
|
||
|
||
</div>
|
||
|
||
### 9.4 Direct Database Access
|
||
|
||
```bash
|
||
# Interactive psql
|
||
make shell-db
|
||
|
||
# Common queries
|
||
SELECT COUNT(*) FROM usermodel;
|
||
SELECT COUNT(*) FROM presentationmodel WHERE deleted_at IS NULL;
|
||
SELECT status, COUNT(*) FROM jobmodel GROUP BY status;
|
||
SELECT provider, SUM(total_tokens) FROM aiusagemodel GROUP BY provider;
|
||
```
|
||
|
||
---
|
||
|
||
|
||
## 10. Background Jobs & Workers
|
||
|
||
### 10.1 ARQ Worker Configuration
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
RD[(Redis)] --> W[ARQ Worker]
|
||
W --> A[generate_presentation]
|
||
W --> B[parse_master_deck]
|
||
W --> C[Cron: cleanup 2AM / purge Mon 3AM]
|
||
```
|
||
|
||
| Setting | Value | Description |
|
||
|---------|-------|-------------|
|
||
| `max_jobs` | 5 | Maximum concurrent background jobs |
|
||
| `job_timeout` | 1800s (30 min) | Per-job timeout |
|
||
| `max_tries` | 3 | Retry attempts on failure |
|
||
| `health_check_interval` | 30s | Health check frequency |
|
||
|
||
### 10.2 Job Types
|
||
|
||
#### Presentation Generation (`generate_presentation_task`)
|
||
1. Load request from PresentationModel
|
||
2. Fetch brand context (colors, fonts, voice rules)
|
||
3. Generate outlines via LLM
|
||
4. Generate per-slide structure and content
|
||
5. Run image generation for each slide
|
||
6. Save results to database
|
||
7. Update JobModel progress (0–100%)
|
||
|
||
#### Master Deck Parsing (`parse_master_deck_task`)
|
||
1. Extract XML layouts/slides from PPTX
|
||
2. Convert PPTX to PDF via LibreOffice
|
||
3. Split PDF into per-page screenshots
|
||
4. Send each screenshot + XML to LLM vision
|
||
5. Store generated React TSX code
|
||
6. Register as template
|
||
|
||
#### Retention Cleanup (Cron — Daily)
|
||
- Soft-deletes presentations exceeding client's `retention_days`
|
||
- Runs at 2:00 AM UTC
|
||
|
||
#### Retention Purge (Cron — Weekly)
|
||
- Permanently deletes files for presentations soft-deleted 30+ days ago
|
||
- Runs Monday 3:00 AM UTC
|
||
|
||
### 10.3 Monitoring Jobs
|
||
|
||
```bash
|
||
# View worker logs
|
||
docker compose logs -f worker
|
||
|
||
# Check job status in database
|
||
make shell-db
|
||
# Then: SELECT id, job_type, status, progress, error_message FROM jobmodel ORDER BY created_at DESC LIMIT 20;
|
||
```
|
||
|
||
### 10.4 Common Job Issues
|
||
|
||
| Issue | Cause | Solution |
|
||
|-------|-------|----------|
|
||
| Job stuck at 0% | Worker crashed or no workers running | Restart worker: `docker compose restart worker` |
|
||
| Job times out | LLM response too slow | Increase `job_timeout` in WorkerSettings |
|
||
| Job fails repeatedly | Invalid API key or model | Check Settings page, test connection |
|
||
| Queue backed up | Too many concurrent requests | Scale workers horizontally |
|
||
|
||
---
|
||
|
||
|
||
## 11. Nginx & Networking
|
||
|
||
### 11.1 Routing Rules
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Request :80] --> B{Path}
|
||
B -->|/api/v1/*| C[FastAPI :8000]
|
||
B -->|/app_data/*| D[Static files]
|
||
B -->|/static/*| D
|
||
B -->|/* catch-all| E[Next.js :3000]
|
||
```
|
||
|
||
### 11.2 Key Configuration
|
||
|
||
| Setting | Value | Purpose |
|
||
|---------|-------|---------|
|
||
| `client_max_body_size` | 100M | Allow large PPTX uploads |
|
||
| `proxy_read_timeout` | 30m | Long-running LLM operations |
|
||
| `proxy_connect_timeout` | 30m | Connection establishment |
|
||
| `proxy_buffering` | off | SSE streaming support |
|
||
| `chunked_transfer_encoding` | off | SSE streaming support |
|
||
|
||
### 11.3 SSL/TLS (Production)
|
||
|
||
The default `nginx.conf` serves HTTP only. For production, add SSL:
|
||
|
||
```nginx
|
||
server {
|
||
listen 443 ssl http2;
|
||
ssl_certificate /etc/ssl/certs/your-cert.pem;
|
||
ssl_certificate_key /etc/ssl/private/your-key.pem;
|
||
# ... existing location blocks ...
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
```
|
||
|
||
### 11.4 Inter-Service Communication
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
API["api :8000"] -->|DATABASE_URL| PG["postgres :5432"]
|
||
API -->|REDIS_URL| RD["redis :6379"]
|
||
API -->|NEXT_INTERNAL_URL| WEB["web :3000"]
|
||
WORKER["worker"] -->|DATABASE_URL| PG
|
||
WORKER -->|REDIS_URL| RD
|
||
WEB -->|API_INTERNAL_URL| API
|
||
NG["nginx :80"] --> API
|
||
NG --> WEB
|
||
```
|
||
|
||
All services communicate via Docker Compose's internal network. No ports need to be exposed to the host except:
|
||
- **80** (nginx) — user access
|
||
- **5432** (postgres) — optional, for direct DB access
|
||
- **6379** (redis) — optional, for debugging
|
||
|
||
---
|
||
|
||
|
||
## 12. Storage & File Management
|
||
|
||
### 12.1 Directory Structure
|
||
|
||
```
|
||
/app_data/
|
||
├── images/ # AI-generated images (UUID-named PNG files)
|
||
├── exports/ # Generated PPTX/PDF export files
|
||
├── uploads/ # User-uploaded documents (DOCX, PDF, TXT)
|
||
├── fonts/ # Custom font files
|
||
└── master_decks/ # Master deck PPTX files and screenshots
|
||
└── {deck_id}/
|
||
├── original.pptx
|
||
├── screenshots/
|
||
│ ├── page_1.png
|
||
│ ├── page_2.png
|
||
│ └── ...
|
||
└── pdf/
|
||
└── deck.pdf
|
||
```
|
||
|
||
### 12.2 File Serving
|
||
|
||
| Context | Serving Method |
|
||
|---------|---------------|
|
||
| **Docker (production)** | nginx serves `/app_data/` directly from volume |
|
||
| **Local development** | FastAPI `StaticFiles` mount on `/app_data` |
|
||
| **Frontend access** | Next.js rewrites `/app_data/*` to backend |
|
||
|
||
### 12.3 Retention Policy
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Presentation Created] -->|retention_days exceeded| B[Soft Delete<br/>deleted_at = now]
|
||
B -->|30 days later| C[Hard Purge<br/>Files removed from disk]
|
||
```
|
||
|
||
- **Retention days** configured per client in `ClientModel.retention_days`
|
||
- **Soft delete** runs daily at 2:00 AM UTC (sets `deleted_at` timestamp)
|
||
- **Hard purge** runs weekly Monday at 3:00 AM UTC (removes files for items soft-deleted 30+ days ago)
|
||
- **Manual purge** available via Admin > Storage > "Purge Files" button
|
||
|
||
### 12.4 Disk Space Monitoring
|
||
|
||
Monitor the `app_data` volume:
|
||
|
||
```bash
|
||
# Check volume usage
|
||
docker compose exec api du -sh /app_data/*
|
||
|
||
# Check available disk space
|
||
docker compose exec api df -h /app_data
|
||
```
|
||
|
||
---
|
||
|
||
|
||
## 13. Monitoring & Logging
|
||
|
||
### 13.1 Log Access
|
||
|
||
```bash
|
||
# All services
|
||
make logs
|
||
|
||
# Specific service
|
||
docker compose logs -f api
|
||
docker compose logs -f worker
|
||
docker compose logs -f postgres
|
||
docker compose logs -f web
|
||
|
||
# Last N lines
|
||
docker compose logs --tail=100 api
|
||
```
|
||
|
||
### 13.2 Audit Trail
|
||
|
||
The `AuditMiddleware` automatically logs all mutating API requests:
|
||
|
||
| Field | Content |
|
||
|-------|---------|
|
||
| `user_id` | Authenticated user's UUID |
|
||
| `action` | Operation name (e.g., "admin_delete") |
|
||
| `resource_type` | Entity type (e.g., "presentation") |
|
||
| `resource_id` | Entity UUID |
|
||
| `client_id` | Tenant context |
|
||
| `details` | JSON with request/response metadata |
|
||
| `ip_address` | Client IP address |
|
||
| `created_at` | Timestamp (indexed for fast queries) |
|
||
|
||
Audit logging is fire-and-forget (non-blocking) via `asyncio.create_task()`.
|
||
|
||
### 13.3 AI Usage Tracking
|
||
|
||
The `AIUsageModel` tracks all LLM API calls:
|
||
|
||
| Metric | Description |
|
||
|--------|-------------|
|
||
| Provider | anthropic, openai, google, ollama |
|
||
| Model | Specific model ID |
|
||
| Call Type | outline, content, vision, etc. |
|
||
| Input Tokens | Tokens sent to the model |
|
||
| Output Tokens | Tokens received |
|
||
| Duration (ms) | Call latency |
|
||
| Error Details | Error message if failed |
|
||
|
||
View aggregated metrics at **Admin > Analytics > AI Usage**.
|
||
|
||
### 13.4 Health Checks
|
||
|
||
| Service | Method | Interval | Timeout |
|
||
|---------|--------|----------|---------|
|
||
| PostgreSQL | `pg_isready` | 5s | 5s, 5 retries |
|
||
| Redis | `redis-cli ping` | 5s | 5s, 5 retries |
|
||
| API | Lifespan startup | At boot | — |
|
||
| Worker | ARQ health check | 30s | — |
|
||
|
||
---
|
||
|
||
## 14. Backup & Recovery
|
||
|
||
### 14.1 Backup Components
|
||
|
||
| Component | Location | Strategy |
|
||
|-----------|----------|----------|
|
||
| Database | `postgres_data` volume | `pg_dump` to file |
|
||
| Redis | `redis_data` volume | Optional (transient queue data) |
|
||
| Files | `app_data` volume | File-level backup or snapshot |
|
||
| Settings | Database (KeyValueSqlModel) | Included in pg_dump |
|
||
| Migrations | `backend/migrations/` | In git repository |
|
||
|
||
### 14.2 Database Backup
|
||
|
||
```bash
|
||
# Full database dump
|
||
docker compose exec postgres pg_dump -U deckforge deckforge > backup_$(date +%Y%m%d).sql
|
||
|
||
# Compressed backup
|
||
docker compose exec postgres pg_dump -U deckforge deckforge | gzip > backup_$(date +%Y%m%d).sql.gz
|
||
|
||
# Restore from backup
|
||
docker compose exec -T postgres psql -U deckforge deckforge < backup.sql
|
||
```
|
||
|
||
### 14.3 File Backup
|
||
|
||
```bash
|
||
# Backup app_data volume
|
||
docker run --rm -v ppt-tool_app_data:/data -v $(pwd):/backup alpine \
|
||
tar czf /backup/app_data_$(date +%Y%m%d).tar.gz -C /data .
|
||
|
||
# Restore app_data
|
||
docker run --rm -v ppt-tool_app_data:/data -v $(pwd):/backup alpine \
|
||
tar xzf /backup/app_data_YYYYMMDD.tar.gz -C /data
|
||
```
|
||
|
||
### 14.4 Disaster Recovery
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Deploy Stack] --> B[Restore DB] --> C[alembic upgrade] --> D[Restore app_data] --> E[Start Services] --> F[Verify]
|
||
```
|
||
|
||
1. Deploy fresh Docker Compose stack
|
||
2. Start PostgreSQL and Redis first
|
||
3. Restore database from latest `pg_dump`
|
||
4. Run `alembic upgrade head` to ensure schema is current
|
||
5. Restore `app_data` volume from backup
|
||
6. Start remaining services
|
||
7. Verify data integrity via Admin Panel
|
||
|
||
---
|
||
|
||
|
||
## 15. Security Hardening
|
||
|
||
### 15.1 Production Checklist
|
||
|
||
<div class="danger">
|
||
|
||
Before deploying to production, complete every item:
|
||
|
||
</div>
|
||
|
||
| Item | Action | Priority |
|
||
|------|--------|----------|
|
||
| JWT Secret | Change `JWT_SECRET_KEY` to a random 256-bit key | Critical |
|
||
| Dev Auth | Set `AZURE_AD_TENANT_ID` to disable dev bypass | Critical |
|
||
| CORS | Restrict `allow_origins` from `*` to your domain | High |
|
||
| SSL/TLS | Configure nginx with SSL certificates | High |
|
||
| Database Password | Use a strong `POSTGRES_PASSWORD` | High |
|
||
| API Keys | Set `SETTINGS_ENCRYPTION_KEY` for at-rest encryption | High |
|
||
| Port Exposure | Remove host port mappings for postgres/redis | Medium |
|
||
| Secrets | Move `.env` to Docker secrets or vault | Medium |
|
||
| Rate Limiting | Add nginx rate limiting rules | Medium |
|
||
| Monitoring | Set up external monitoring and alerting | Medium |
|
||
|
||
### 15.2 CORS Configuration
|
||
|
||
The default CORS configuration allows all origins. For production, modify `backend/api/main.py`:
|
||
|
||
```python
|
||
origins = [
|
||
"https://your-domain.com",
|
||
"https://app.your-domain.com",
|
||
]
|
||
```
|
||
|
||
### 15.3 API Key Encryption
|
||
|
||
Enable at-rest encryption for stored API keys:
|
||
|
||
```bash
|
||
# Generate a Fernet key
|
||
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
|
||
# Add to .env
|
||
SETTINGS_ENCRYPTION_KEY=your-generated-fernet-key
|
||
```
|
||
|
||
### 15.4 Middleware Execution Order
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[Request] --> B[1.CORS] --> C[2.Auth] --> D[3.Audit] --> E[4.UserConfig] --> F[Handler]
|
||
```
|
||
|
||
Middlewares are added in reverse order in FastAPI (last added = first executed).
|
||
|
||
---
|
||
|
||
## 16. Scaling & Performance
|
||
|
||
### 16.1 Horizontal Scaling
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
LB[Load Balancer] --> API[API x N]
|
||
API --> PG[(Managed PostgreSQL)]
|
||
API --> RD[(Managed Redis)]
|
||
W[Workers x N] --> PG
|
||
W --> RD
|
||
API --> S3[S3 / CDN]
|
||
W --> S3
|
||
```
|
||
|
||
| Component | Scaling Strategy |
|
||
|-----------|-----------------|
|
||
| **API** | Run multiple replicas behind load balancer |
|
||
| **Worker** | Run multiple instances (ARQ handles job locking) |
|
||
| **PostgreSQL** | Use managed service (RDS, Cloud SQL) with read replicas |
|
||
| **Redis** | Use managed service (ElastiCache) with clustering |
|
||
| **Files** | Replace local volume with S3 + CDN |
|
||
| **nginx** | Replace with cloud load balancer (ALB, Cloud Load Balancing) |
|
||
|
||
### 16.2 Vertical Scaling
|
||
|
||
| Setting | Location | Effect |
|
||
|---------|----------|--------|
|
||
| `max_jobs` | `WorkerSettings` | More concurrent background jobs |
|
||
| `job_timeout` | `WorkerSettings` | Allow longer-running LLM operations |
|
||
| `worker_connections` | `nginx.conf` | More concurrent connections |
|
||
| `client_max_body_size` | `nginx.conf` | Larger file uploads |
|
||
|
||
### 16.3 Performance Optimization
|
||
|
||
- **Database indexes** already exist on:
|
||
- `auditlogmodel.created_at`
|
||
- `teammembershipmodel(user_id, team_id)` (unique)
|
||
- `usermodel.email` (unique)
|
||
- `clientmodel.slug` (unique)
|
||
|
||
- **Async operations**: All database queries use `asyncpg` (async PostgreSQL driver)
|
||
- **Sync LLM calls**: Wrapped in `asyncio.to_thread()` to avoid blocking the event loop
|
||
- **SSE streaming**: Server-Sent Events for real-time progress (no polling overhead)
|
||
- **Fire-and-forget audit**: Audit logs don't block request processing
|
||
|
||
---
|
||
|
||
|
||
## 17. Troubleshooting
|
||
|
||
### 17.1 Common Issues
|
||
|
||
| Issue | Cause | Solution |
|
||
|-------|-------|----------|
|
||
| API won't start | PostgreSQL not ready | Wait for health check (15–25s) |
|
||
| Worker jobs not processing | Redis down or worker crashed | `docker compose restart worker` |
|
||
| Auth failures after restart | JWT_SECRET_KEY changed | All users must re-login |
|
||
| File uploads fail | Disk full or wrong permissions | Check `du -sh /app_data/*` and permissions |
|
||
| PPTX export 500 | Puppeteer / Chromium issue | Restart web service, check memory |
|
||
| Slide edit timeout | LLM response too slow | Check provider status, increase timeouts |
|
||
| Master deck stuck "processing" | Worker died during parse | Restart worker, reparse the deck |
|
||
| Images not showing | Static files not served | Check FastAPI mounts and nginx config |
|
||
| SSE not working | Proxy buffering enabled | Ensure nginx `proxy_buffering off` |
|
||
|
||
### 17.2 Diagnostic Commands
|
||
|
||
```bash
|
||
# Service health
|
||
docker compose ps
|
||
|
||
# Container resource usage
|
||
docker stats
|
||
|
||
# API application logs
|
||
docker compose logs --tail=50 api
|
||
|
||
# Worker job processing logs
|
||
docker compose logs --tail=50 worker
|
||
|
||
# Database connection check
|
||
docker compose exec postgres pg_isready -U deckforge
|
||
|
||
# Redis connectivity
|
||
docker compose exec redis redis-cli ping
|
||
|
||
# Database query — check failed jobs
|
||
docker compose exec postgres psql -U deckforge -c \
|
||
"SELECT id, job_type, status, error_message FROM jobmodel WHERE status='failed' ORDER BY created_at DESC LIMIT 10;"
|
||
|
||
# Disk usage
|
||
docker compose exec api du -sh /app_data/*
|
||
```
|
||
|
||
### 17.3 Resetting the System
|
||
|
||
```bash
|
||
# Full reset (WARNING: destroys all data)
|
||
docker compose down -v
|
||
docker compose up --build -d
|
||
make migrate
|
||
make seed
|
||
```
|
||
|
||
---
|
||
|
||
## 18. API Reference
|
||
|
||
### 18.1 Authentication Endpoints
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| GET | `/api/v1/auth/login` | Redirect to Azure AD login |
|
||
| GET | `/api/v1/auth/callback` | OAuth callback handler |
|
||
| POST | `/api/v1/auth/dev-login` | Dev mode authentication |
|
||
| GET | `/api/v1/auth/dev-status` | Check if dev mode is enabled |
|
||
| POST | `/api/v1/auth/logout` | Clear session |
|
||
| GET | `/api/v1/auth/me` | Current user info |
|
||
|
||
### 18.2 Admin Endpoints
|
||
|
||
| Method | Path | Access |
|
||
|--------|------|--------|
|
||
| GET/PUT/DELETE | `/api/v1/admin/users/*` | Super Admin |
|
||
| POST/GET/PUT/DELETE | `/api/v1/admin/clients/*` | Admin |
|
||
| POST/GET/DELETE | `/api/v1/admin/teams/*` | Admin |
|
||
| GET/PUT | `/api/v1/admin/settings` | Super Admin |
|
||
| GET/POST | `/api/v1/admin/settings/models` | Super Admin |
|
||
| POST | `/api/v1/admin/settings/test-connection` | Super Admin |
|
||
| GET/DELETE/POST | `/api/v1/admin/storage/*` | Admin |
|
||
| GET | `/api/v1/admin/analytics/*` | Admin |
|
||
| GET | `/api/v1/admin/audit-log` | Admin |
|
||
| GET/PUT/POST/DELETE | `/api/v1/admin/master-decks/*` | Admin |
|
||
| GET/PUT/POST/DELETE | `/api/v1/admin/brand-config/*` | Admin |
|
||
|
||
### 18.3 Presentation Endpoints
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| POST | `/api/v1/ppt/presentation/create` | Create new presentation |
|
||
| GET | `/api/v1/ppt/presentation/all` | List presentations |
|
||
| GET | `/api/v1/ppt/presentation/{id}` | Get presentation detail |
|
||
| PUT | `/api/v1/ppt/presentation/{id}` | Update presentation |
|
||
| DELETE | `/api/v1/ppt/presentation/{id}` | Delete presentation |
|
||
| POST | `/api/v1/ppt/presentation/decompose` | Decompose content |
|
||
| POST | `/api/v1/ppt/presentation/prepare` | Prepare for generation |
|
||
| GET | `/api/v1/ppt/presentation/{id}/review` | Get review status |
|
||
| PUT | `/api/v1/ppt/presentation/{id}/status` | Change review status |
|
||
| POST | `/api/v1/ppt/presentation/{id}/comment` | Add review comment |
|
||
| POST | `/api/v1/ppt/jobs/generate` | Start generation job |
|
||
| GET | `/api/v1/ppt/jobs/{id}/status` | Job status (SSE) |
|
||
| POST | `/api/v1/ppt/export/pptx` | Export as PPTX |
|
||
| POST | `/api/v1/ppt/export/pdf` | Export as PDF |
|
||
|
||
---
|
||
|
||
<div style="text-align: center; margin-top: 60px; color: #999;">
|
||
|
||
**Oliver DeckForge** | System Administration Guide
|
||
|
||
Version 1.0 | © 2026 All Rights Reserved
|
||
|
||
</div>
|