---
auto_generated: true
created: 2026-05-18
manual_updated_at: 2026-05-18
modified: 2026-05-19
name: Developer_Manual
status: active
tags:
- client/oliver
- domain/ai
- domain/devops
- domain/security
- tech/azure-ad
- tech/docker
- tech/fastapi
- tech/gemini
- tech/postgresql
- tech/react
- tech/typescript
- type/reference
type: reference
---

# AC Tool Developer Manual

## Architecture Overview

AC Tool follows a three-tier architecture:
1. **Frontend**: React + Vite + TailwindCSS, managed via Zustand for state.
2. **Backend**: Python FastAPI (implied by docker-compose and typical patterns), serving REST API and WebSockets.
3. **Database**: PostgreSQL 16, stored in a Docker volume.

### Communication Flow
- **HTTP**: REST API for CRUD operations (clients, sheets, jobs, auth).
- **WebSocket**: Real-time job progress updates.
- **Storage**: Local filesystem for uploaded files (`./data` in Docker), PostgreSQL for metadata.

## Tech Stack

- **Frontend**: React, TypeScript, Vite, TailwindCSS, Zustand, MSAL.js (implied by Azure config)
- **Backend**: Python, FastAPI (inferred), Uvicorn (inferred), MSAL (Azure Auth), OpenAI/Gemini/Anthropic SDKs
- **Database**: PostgreSQL 16
- **Infrastructure**: Docker Compose, Apache Reverse Proxy (production), Vite Dev Server (local)

## Local Setup

### Prerequisites
- Node.js 18+
- Python 3.10+
- Docker & Docker Compose
- Git

### Steps
1. **Clone the repository**
   ```bash
   git clone <repo-url>
   cd ac-tool
   ```

2. **Set up environment variables**
   ```bash
   cp .env.example .env
   # Edit .env with your Azure AD, API keys, and DB password
   ```

3. **Start Backend & Database**
   ```bash
   docker-compose up -d postgres app
   ```

4. **Install Frontend Dependencies**
   ```bash
   cd frontend
   npm install
   ```

5. **Run Frontend Dev Server**
   ```bash
   npm run dev
   ```
   The app will be available at `http://localhost:5173` and proxied to `http://localhost:8000` for API/WS.

## Environment Variables

### Critical Variables (.env)
- `POSTGRES_PASSWORD`: Database password (default: `achelper_secret`)
- `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_REDIRECT_URI`: For SSO
- `OPENAI_API_KEY`, `GEMINI_API_KEY`, `ANTHROPIC_API_KEY`: AI provider keys
- `EMERGENCY_TOKEN`: For bypassing SSO (leave blank to disable)
- `APP_PORT`: Host port for the backend (default: 8100)

### Azure AD Configuration
- The app uses MSAL with PKCE flow (no client secret).
- Redirect URI must match `AZURE_REDIRECT_URI` in Azure Portal.

## Key Services & Entry Points

### Frontend Stores (Zustand)
- `useAuthStore`: Handles authentication state and token management.
- `useClientStore`: Manages client CRUD operations.
- `useJobStore`: Handles job creation, deletion, and real-time updates.
- `useSheetStore`: Manages spreadsheet data and deliverables.
- `useDropdownStore`: Fetches and caches category/media type data.

### Backend Entry Points (Inferred)
- `/auth/me`: GET - Fetch current user info.
- `/api/clients`: CRUD for clients.
- `/api/sheets`: CRUD for sheets and deliverables.
- `/api/jobs`: POST (create job), GET (list), WebSocket connection.
- `/api/dropdowns`: GET categories for dropdowns.

### AI Providers
- **OpenAI**: Configured via `OPENAI_API_KEY`, model `gpt-4.1`.
- **Google Gemini**: Configured via `GEMINI_API_KEY`, model `gemini-2.0-flash-exp`.
- **Anthropic Claude**: Configured via `ANTHROPIC_API_KEY`, models `claude-opus-4-5-20251101` and `claude-sonnet-4-5-20250929`.

## API Reference

### Auth
- `GET /auth/me`: Returns `User` object.

### Clients
- `GET /api/clients`: List all clients.
- `POST /api/clients`: Create client (name).
- `PUT /api/clients/{id}`: Update client.
- `DELETE /api/clients/{id}`: Delete client.

### Sheets
- `GET /api/sheets`: List sheets.
- `POST /api/sheets`: Create sheet (name).
- `GET /api/sheets/{id}`: Load sheet data.
- `PUT /api/sheets/{id}`: Save sheet data.
- `DELETE /api/sheets/{id}`: Delete sheet.
- `POST /api/sheets/{id}/duplicate`: Duplicate sheet.

### Jobs
- `POST /api/jobs`: Upload files and start job.
- `GET /api/jobs`: List jobs.
- `DELETE /api/jobs/{id}`: Cancel/delete job.
- `GET /ws`: WebSocket endpoint for real-time job updates.

### Dropdowns
- `GET /api/dropdowns/{clientId?}`: Get categories and media types.

## Deployment

### Production Environment
1. **Apache Configuration**: Use the provided Apache VirtualHost snippet in `docker-compose.yml` to proxy requests.
2. **SSL**: Ensure SSL termination is handled by Apache or the load balancer.
3. **Database**: Use a managed PostgreSQL service or ensure the Docker volume is backed up.
4. **Environment Variables**: Set all required `.env` variables on the host.
5. **Docker**: Run `docker-compose up -d` to start services.

### Nginx Alternative
If using Nginx instead of Apache, configure:
```nginx
location /ac-helper/api/ {
    proxy_pass http://127.0.0.1:8100/api/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}
location /ac-helper/ws {
    proxy_pass http://127.0.0.1:8100/ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
location /ac-helper/ {
    alias /var/www/html/ac-helper/;
    index index.html;
}
```

## Known Gotchas

1. **Azure AD Redirect URI**: Must exactly match the configured `AZURE_REDIRECT_URI` including trailing slashes.
2. **Emergency Token**: Must be a long random string (use `secrets.token_hex(32)`). Leaving it blank disables emergency login.
3. **WebSocket Path**: The frontend strips `/ac-helper` before proxying. Ensure backend WebSocket path is `/ws`.
4. **CORS**: Vite dev server handles CORS via proxy. In production, rely on Apache/Nginx reverse proxy; do not use CORS headers from the backend.
5. **Database Connection**: The backend uses `DATABASE_URL` with `postgres:5432` (internal Docker hostname), not `localhost`.
6. **Model Costs**: AI processing costs accumulate quickly. Monitor `costUsdTotal` in job summaries and set `minimum_success_threshold` if needed.
7. **File Uploads**: Large files may timeout if `OPENAI_TIMEOUT` or similar is too low. Default is 3600s.
8. **State Hydration**: Frontend stores do not persist across refreshes except for `activeSheetId` in localStorage. Users may need to re-login or reload data.

## Related

- [[01 Projects/ac-helper/DEVELOPER_MANUAL]]
- [[01 Projects/cc-dashboard/DEVELOPER_MANUAL]]
- [[01 Projects/oliver-sales-ops-platform/DEVELOPER_MANUAL]]
- [[01 Projects/ppt-tool/DEVELOPER_MANUAL]]
- [[01 Projects/ac-tool/DEVELOPER_MANUAL.md]]
- [[01 Projects/ac-helper/DEVELOPER_MANUAL.md]]
- [[01 Projects/oliver-sales-ops-platform/DEVELOPER_MANUAL.md]]
- [[01 Projects/modcomms/DEVELOPER_MANUAL.md]]