diff --git a/docs/01-User-Manual.md b/docs/01-User-Manual.md new file mode 100644 index 0000000..5c6e6df --- /dev/null +++ b/docs/01-User-Manual.md @@ -0,0 +1,492 @@ +--- +pdf_options: + format: A4 + margin: 25mm 20mm + headerTemplate: '
Oliver DeckForge — User Manual
' + footerTemplate: '
/
' + 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; } + 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; } + img { max-width: 100%; max-height: 280px; object-fit: contain; display: block; margin: 16px auto; } +--- + +# Oliver DeckForge User Manual + +**Version 1.0** | Enterprise AI Presentation Generator + +--- + +## Table of Contents + +1. [Getting Started](#1-getting-started) +2. [Dashboard](#2-dashboard) +3. [Creating a Presentation](#3-creating-a-presentation) +4. [Working with the Outline](#4-working-with-the-outline) +5. [Selecting a Template](#5-selecting-a-template) +6. [Generation Progress](#6-generation-progress) +7. [Editing Slides](#7-editing-slides) +8. [Review Workflow](#8-review-workflow) +9. [Exporting Presentations](#9-exporting-presentations) +10. [Keyboard Shortcuts & Tips](#10-keyboard-shortcuts--tips) + +--- + +## 1. Getting Started + +### 1.1 Logging In + +Oliver DeckForge supports two authentication methods: + +```mermaid +flowchart LR + A[Open App] --> B{Auth Mode?} + B -->|Production| C[Azure AD SSO] + B -->|Development| D[Email + Password] + C --> E[Microsoft Login] + E --> F[Dashboard] + D --> F +``` + +**Production Mode (Azure AD SSO):** +Click **"Sign in with Microsoft"** and authenticate with your organization's Microsoft 365 credentials. + +**Development Mode:** +When Azure AD is not configured, a development login form appears. Enter: +- **Email:** Your email address (e.g., `admin@deckforge.dev`) +- **Password:** The development password (default: `devpass123`) + +> After successful authentication, you are redirected to the Dashboard. + +### 1.2 User Interface Overview + +The application has two main areas: + +| Area | Access | Purpose | +|------|--------|---------| +| **Presentation Generator** | All users | Create, edit, and export presentations | +| **Admin Panel** | Admins only | Manage users, clients, templates, settings | + +--- + +## 2. Dashboard + +The dashboard is your home screen after logging in. What you see depends on your account configuration. + +### 2.1 Client Grid View + +If your account is associated with one or more clients, you see a grid of **client cards**: + +- Each card displays the client's **name** and **logo** +- Click a card to view that client's templates and presentations +- Click **"New Presentation"** to start creating + +### 2.2 Client Detail View + +After selecting a client, two tabs appear: + +**Templates Tab** +- Shows all available master deck templates for this client +- Each template card shows a **thumbnail**, **name**, **layout count**, and **status** +- Click a template to start a new presentation with that template pre-selected + +**Presentations Tab** +- Lists all presentations created under this client +- Each card shows: + - Presentation **title** + - **Status badge**: Draft (yellow), In Review (blue), Approved (green) + - **Last updated** date +- Click any card to open it in the editor + +### 2.3 Quick Actions + +| Action | How | +|--------|-----| +| Create new presentation | Click **"New Presentation"** button (top-right) | +| Open existing presentation | Click on any presentation card | +| Switch client | Click breadcrumb "All Clients" to go back to client grid | + +--- + +## 3. Creating a Presentation + +### 3.1 Workflow Overview + +```mermaid +flowchart LR + A[Upload Page] --> B{Input} + B -->|Topic| C[Text] + B -->|File| D[DOCX/PDF/PPTX] + B -->|URL| E[Web] + C --> F[Configure] + D --> F + E --> F + F --> G[Outline] --> H[Template] --> I[Generate] --> J[Edit] --> K[Export] +``` + +### 3.2 The Upload Page + +Navigate to **Create Presentation** to see the upload page. You have three ways to provide content: + +#### Option A: Topic or Text Prompt +Type your presentation topic or detailed content in the large text area: + +> **Example:** "Quarterly business review for Q3 2026, focusing on revenue growth, customer acquisition, and product roadmap milestones" + +#### Option B: Upload Documents +Drag and drop files into the upload zone, or click **"Choose Files"**: + +| Format | Notes | +|--------|-------| +| `.docx` | Word documents — structured content with tables extracted | +| `.pptx` | PowerPoint files — existing slides used as reference | +| `.pdf` | PDF documents — text and layout extracted (max 1 PDF) | +| `.txt` | Plain text files — raw content | + +Multiple files can be uploaded simultaneously (except PDFs — only one allowed). + +#### Option C: Paste a URL +Enter a web URL to extract content from a web page. The system fetches and processes the page content automatically. + +### 3.3 Configuration Options + +Before generating, configure these settings: + +**Slide Count** +- Choose from presets: 5, 8, 10, 12, 15, or 20 slides +- Or enter a custom number + +**Language** +- Select the output language from a searchable dropdown +- Default: English + +**Advanced Settings** (click the sliders icon): + +| Setting | Options | Default | +|---------|---------|---------| +| **Tone** | Default, Professional, Casual, Funny, Academic | Default | +| **Verbosity** | Concise, Standard, Detailed | Standard | +| **Table of Contents** | On/Off | Off | +| **Title Slide** | On/Off | On | +| **Web Search** | On/Off — allows AI to search the web for fresh data | Off | +| **Custom Instructions** | Free text to guide the AI | — | + +> **Tip:** Custom instructions are powerful. Use them to specify audience, emphasize particular topics, or set formatting preferences. + +### 3.4 Document Preview + +If you uploaded documents, a **Document Preview** page appears next: + +- **Left sidebar** lists all uploaded files +- Click a file to preview its extracted content in the main area +- Content is rendered as formatted Markdown +- Click **"Next"** to proceed to the outline + +--- + +## 4. Working with the Outline + +The outline page shows the AI-generated structure for your presentation. + +### 4.1 Outline View + +Each slide appears as an editable card with: + +- **Slide number** badge (left side) +- **Content editor** — editable Markdown content +- **Attached files** — badges showing which uploaded documents are linked to this slide +- **Drag handle** — reorder slides by dragging +- **Delete button** — remove a slide (trash icon, right side) + +### 4.2 Editing the Outline + +| Action | How | +|--------|-----| +| **Edit slide content** | Click into the text area and modify | +| **Reorder slides** | Drag the handle (dots icon) on the left | +| **Delete a slide** | Click the trash icon on the right | +| **Add a new slide** | Click **"+ Add Slide"** at the bottom | + +### 4.3 Streaming Indicator + +While the AI is generating the outline: +- A **"Thinking"** spinner appears +- Content streams in real-time with animation +- The active slide auto-scrolls into view +- Editing is disabled until streaming completes + +> **Note:** Wait for streaming to finish before making edits to avoid conflicts. + +--- + +## 5. Selecting a Template + +Switch to the **"Select Template"** tab on the outline page. + +### 5.1 Built-in Templates + +Pre-configured templates ship with the system. Each card shows: +- Template **name** and **description** +- Preview images of 4 sample layouts +- A **"Selected"** badge on the active choice + +### 5.2 Custom AI Templates + +If your organization has uploaded master decks (PPTX files parsed by AI), they appear under **"Custom AI Templates"**: +- Shows the master deck **thumbnail** and **name** +- Contains layouts specifically designed for your brand + +### 5.3 Generating the Presentation + +1. Select a template (border turns blue) +2. Click **"Generate Presentation"** at the bottom +3. You are redirected to the progress page + +> **Important:** You must select a template before the Generate button becomes active. + +--- + +## 6. Generation Progress + +### 6.1 Progress Screen + +```mermaid +stateDiagram-v2 + [*] --> Processing + Processing --> Completed: All slides generated + Processing --> Failed: Error occurred + Completed --> Editor: Auto-redirect (1.5s) + Failed --> Outline: User clicks Retry +``` + +The progress page shows: +- **Status icon**: Animated hamster wheel (processing), green check (done), or red X (failed) +- **Progress bar** with percentage +- **Status message** describing the current step + +### 6.2 Actions During Generation + +| Status | Available Actions | +|--------|-------------------| +| **Processing** | **Cancel** — stops the job, returns to outline | +| **Completed** | **Open Presentation** — auto-opens after 1.5 seconds | +| **Failed** | **Retry** — returns to outline to try again | + +### 6.3 Connection Method + +The progress page uses **Server-Sent Events (SSE)** for real-time updates. If SSE fails, it falls back to **polling** every 3 seconds. + +--- + +## 7. Editing Slides + +### 7.1 Editor Layout + +```mermaid +flowchart LR + subgraph Editor + A[Left Sidebar
Slide Thumbnails] --- B[Main Content
Slide Preview] + end + subgraph Header + C[Logo] --- D[Actions
Undo/Redo/Export] + end +``` + +The presentation editor has: +- **Header bar** (purple) with actions +- **Left sidebar** with slide thumbnails +- **Main area** with full-size slide previews + +### 7.2 Sidebar Navigation + +Toggle between two views: +- **Grid view** — thumbnail previews of all slides +- **List view** — slide numbers and titles + +Click any slide to navigate to it. Drag to reorder. + +### 7.3 Slide Actions + +Hover over any slide to reveal action overlays: + +| Position | Action | Description | +|----------|--------|-------------| +| **Top-left** | Update slide | Opens prompt input — describe changes and AI regenerates | +| **Top-right** | Delete slide | Removes the slide | +| **Top-right** | Speaker notes | View/edit speaker notes for this slide | +| **Bottom-center** | Add slide | Insert a new slide below this one | + +### 7.4 AI-Powered Slide Updates + +1. Hover over a slide +2. Click the **magic wand** icon (top-left) +3. Enter your update prompt (e.g., "Add a chart showing quarterly revenue") +4. Click **"Update"** +5. The AI regenerates the slide content based on your instructions + +> **Note:** Updates may take 30–120 seconds depending on content complexity and image generation. + +### 7.5 Auto-Save + +The editor automatically saves your changes. A spinning icon in the header indicates a save is in progress. + +--- + +## 8. Review Workflow + +### 8.1 Status Flow + +```mermaid +stateDiagram-v2 + direction LR + Draft --> InReview: Submit for Review + InReview --> Approved: Approve + InReview --> Draft: Return to Draft + Approved --> Draft: Reopen +``` + +Every presentation has a review status: + +| Status | Badge Color | Meaning | +|--------|-------------|---------| +| **Draft** | Yellow | Work in progress — not reviewed | +| **In Review** | Blue | Submitted for review — awaiting approval | +| **Approved** | Green | Reviewed and approved — ready for use | + +### 8.2 Changing Status + +1. Click the **status badge** in the editor header +2. A popover appears with: + - Current status display + - Last review comment (if any) + - Available status transition buttons + - Comment text area + +### 8.3 Adding Review Comments + +1. Open the status popover +2. Type a comment in the text area +3. Click **"Add Comment"** + +Comments are saved and visible to all users who access the presentation. + +### 8.4 Status Transitions + +| Current Status | Available Actions | +|----------------|-------------------| +| **Draft** | Submit to **In Review** | +| **In Review** | **Approve** or return to **Draft** | +| **Approved** | Return to **Draft** | + +--- + +## 9. Exporting Presentations + +### 9.1 Export Options + +Click **"Export"** in the editor header to see options: + +| Format | Description | +|--------|-------------| +| **PDF** | High-quality PDF document, one slide per page | +| **PPTX** | PowerPoint file, editable in Microsoft PowerPoint | + +### 9.2 Export Process + +```mermaid +sequenceDiagram + participant U as User + participant E as Editor + participant S as Server + participant P as Puppeteer + + U->>E: Click Export + E->>E: Auto-save presentation + E->>S: Request export + S->>P: Render slides in headless browser + P->>S: Return rendered output + S->>E: File ready + E->>U: Download starts +``` + +1. Click **"Export as PDF"** or **"Export as PPTX"** +2. The system auto-saves your latest changes +3. A loading overlay appears: **"Exporting presentation..."** +4. The rendered file downloads automatically + +> **Note:** Export may take 15–60 seconds depending on slide count and image complexity. + +--- + +## 10. Keyboard Shortcuts & Tips + +### 10.1 Tips for Better Presentations + +
+ +**Be specific in your prompt.** Instead of "Make a sales presentation," try: "Create a 12-slide sales pitch for enterprise CRM software targeting Fortune 500 IT directors, emphasizing ROI and integration capabilities." + +
+ +
+ +**Use Custom Instructions wisely.** Add rules like: "Use bullet points, not paragraphs. Keep each slide to 3-4 key points. Include data visualizations where possible." + +
+ +
+ +**Upload reference documents.** The AI produces significantly better content when given source material like reports, briefs, or existing presentations to draw from. + +
+ +
+ +**Image generation may fail silently.** If a slide shows a placeholder instead of a generated image, check the slide content for an image error indicator. Try updating the slide with a more specific image description. + +
+ +### 10.2 Troubleshooting + +| Problem | Solution | +|---------|----------| +| Export fails | Refresh the page and try again. Ensure the presentation has been saved. | +| Slide update hangs | Wait up to 2 minutes. If still loading, refresh and retry. | +| Outline won't generate | Check that you've entered content or uploaded at least one document. | +| Template not showing | Ask your admin to verify the master deck has been fully parsed. | +| Images missing | Image generation may be disabled or the provider API key may be invalid. Contact your admin. | +| Cannot log in | Verify your credentials. In dev mode, check the `DEV_AUTH_PASSWORD` setting. | + +### 10.3 Browser Requirements + +Oliver DeckForge works best with: +- **Google Chrome** 90+ +- **Microsoft Edge** 90+ +- **Firefox** 90+ +- **Safari** 15+ + +> JavaScript must be enabled. A stable internet connection is required for AI generation. + +--- + +
+ +**Oliver DeckForge** | Enterprise AI Presentation Generator + +Version 1.0 | © 2026 All Rights Reserved + +
diff --git a/docs/01-User-Manual.pdf b/docs/01-User-Manual.pdf new file mode 100644 index 0000000..6964dab Binary files /dev/null and b/docs/01-User-Manual.pdf differ diff --git a/docs/02-System-Administration-Guide.md b/docs/02-System-Administration-Guide.md new file mode 100644 index 0000000..6998b11 --- /dev/null +++ b/docs/02-System-Administration-Guide.md @@ -0,0 +1,1333 @@ +--- +pdf_options: + format: A4 + margin: 25mm 20mm + headerTemplate: '
Oliver DeckForge — System Administration Guide
' + footerTemplate: '
/
' + 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 +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` + +
+ +**Security Warning:** Development mode should never be used in production. Always configure Azure AD or another SSO provider for production deployments. + +
+ +### 4.4 JWT Configuration + +| Parameter | Value | +|-----------|-------| +| Algorithm | HS256 | +| Expiry | 24 hours | +| Storage | `session_token` HTTP cookie | +| Payload | `sub` (user UUID), `email`, `role`, `exp`, `iat` | + +
+ +**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. + +
+ +--- + + +## 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` + +
+ +You cannot change your own role. This prevents accidental lockout. + +
+ +#### 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 + +
+ +After deleting layouts, the system automatically re-registers the template by recreating `PresentationLayoutCodeModel` records for the remaining layouts. + +
+ +### 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 +``` + +
+ +Always review auto-generated migrations before applying. SQLAlchemy may miss rename operations (interpreting them as drop + create) or produce incorrect defaults. + +
+ +### 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
deleted_at = now] + B -->|30 days later| C[Hard Purge
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 + +
+ +Before deploying to production, complete every item: + +
+ +| 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 | + +--- + +
+ +**Oliver DeckForge** | System Administration Guide + +Version 1.0 | © 2026 All Rights Reserved + +
diff --git a/docs/02-System-Administration-Guide.pdf b/docs/02-System-Administration-Guide.pdf new file mode 100644 index 0000000..7aa71ba Binary files /dev/null and b/docs/02-System-Administration-Guide.pdf differ diff --git a/docs/build-pdfs.mjs b/docs/build-pdfs.mjs new file mode 100644 index 0000000..7c3c8c7 --- /dev/null +++ b/docs/build-pdfs.mjs @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/** + * Build script for Oliver DeckForge documentation PDFs. + * + * 1. Renders Mermaid diagrams to PNG via @mermaid-js/mermaid-cli (mmdc) + * 2. Converts the resulting Markdown (with images) to styled PDFs via md-to-pdf + * 3. Cleans up intermediate files + * + * Usage: node docs/build-pdfs.mjs + */ + +import { execSync } from 'child_process'; +import { readdirSync, unlinkSync, existsSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const sources = [ + '01-User-Manual.md', + '02-System-Administration-Guide.md', +]; + +for (const file of sources) { + const input = join(__dirname, file); + const rendered = join(__dirname, file.replace('.md', '-rendered.md')); + const renderedPdf = rendered.replace('.md', '.pdf'); + const finalPdf = join(__dirname, file.replace('.md', '.pdf')); + + console.log(`\n=== ${file} ===`); + + // 1. Pre-render Mermaid diagrams → PNG, output modified markdown + console.log(' [1/3] Rendering Mermaid diagrams...'); + execSync( + `npx -y @mermaid-js/mermaid-cli -i "${input}" -o "${rendered}" -e png --scale 2`, + { cwd: __dirname, stdio: 'inherit' }, + ); + + // 2. Convert rendered markdown → PDF + console.log(' [2/3] Converting to PDF...'); + execSync(`npx -y md-to-pdf "${rendered}"`, { + cwd: __dirname, + stdio: 'inherit', + }); + + // 3. Move PDF to final name and clean up temp files + console.log(' [3/3] Cleaning up...'); + execSync(`mv "${renderedPdf}" "${finalPdf}"`); + + // Remove rendered markdown + if (existsSync(rendered)) unlinkSync(rendered); + + // Remove generated diagram PNGs + const prefix = file.replace('.md', '-rendered-'); + readdirSync(__dirname) + .filter((f) => f.startsWith(prefix) && f.endsWith('.png')) + .forEach((f) => unlinkSync(join(__dirname, f))); + + console.log(` -> ${file.replace('.md', '.pdf')} created`); +} + +console.log('\nDone.');