# Deployment Guide

## Requirements

- Docker and Docker Compose
- PostgreSQL 16 with pgvector extension (included in pgvector/pgvector:pg16 image)
- Reverse proxy (Nginx, Caddy, or Traefik) for HTTPS termination
- At least one AI provider configured

## Docker Deployment

### 1. Configure Environment

```bash
cp .env.example .env
```

Required settings:

```env
AI_PROVIDER=litellm              # or bedrock, azure, vertex, openrouter
JWT_SECRET=<64-char random>      # openssl rand -hex 32
DB_PASSWORD=<strong password>
APP_URL=https://your-domain.com  # used for CORS, emails, verification links
```

### 2. Build and Start

```bash
docker compose up -d --build
```

This starts two containers:
- `pediatric-ai-scribe` -- Node.js app on port 3552 (mapped to container port 3000)
- `pedscribe-db` -- PostgreSQL 16 with pgvector

### 3. Verify

```bash
docker compose ps
curl http://localhost:3552/api/health
```

### 4. First User

Navigate to `https://your-domain.com` and register. The first user is automatically promoted to admin.

## Reverse Proxy

The app binds to `127.0.0.1:3552` by default. You need a reverse proxy for HTTPS.

### Nginx

```nginx
server {
    listen 443 ssl http2;
    server_name scribe.example.com;

    ssl_certificate     /etc/ssl/certs/scribe.example.com.pem;
    ssl_certificate_key /etc/ssl/private/scribe.example.com.key;

    client_max_body_size 100M;

    location / {
        proxy_pass http://127.0.0.1:3552;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

### Caddy

```
scribe.example.com {
    reverse_proxy localhost:3552
}
```

### Trust Proxy

If you see `X-Forwarded-For` warnings in logs, add `trust proxy` to Express. The app currently runs behind a local reverse proxy, so rate limiting uses the direct connection IP.

## Volumes

| Volume | Purpose | Backup Priority |
|--------|---------|----------------|
| `pgdata` | PostgreSQL data (all user data, settings, content) | Critical |
| `scribe-logs` | Application log files (YYYY-MM-DD.log) | Low |

### Backup PostgreSQL

```bash
docker exec pedscribe-db pg_dump -U pedscribe pedscribe > backup.sql
```

### Restore

```bash
cat backup.sql | docker exec -i pedscribe-db psql -U pedscribe pedscribe
```

## Updating

```bash
git pull
docker compose build --no-cache
docker compose up -d
```

Database migrations run automatically on startup (CREATE TABLE IF NOT EXISTS, ALTER TABLE ADD COLUMN IF NOT EXISTS patterns).

## Health Check

The container includes a built-in health check:

```
wget --spider -q http://localhost:3000/api/health
```

Runs every 30 seconds with a 20-second start period. Docker marks the container as healthy/unhealthy automatically.

## Resource Requirements

- Memory: 256MB minimum, 512MB recommended
- Disk: ~200MB for Docker image (includes self-hosted Whisper WASM models)
- PostgreSQL: depends on usage (audio backups use BYTEA storage, auto-deleted after 24h)

## Environment-Specific Notes

### Production Checklist

- Set a strong `JWT_SECRET` (64+ characters)
- Set a strong `DB_PASSWORD`
- Set `APP_URL` to your actual domain (required for CORS, email links)
- Configure SMTP for email verification and password reset
- Use a HIPAA-eligible AI provider if handling PHI (Bedrock, Azure, Vertex)
- Enable Cloudflare Turnstile for bot protection
- Set up regular PostgreSQL backups
- Configure OIDC/SSO for enterprise environments

### Development

```bash
npm install
cp .env.example .env
# Start PostgreSQL separately or use docker compose for just the DB:
docker compose up -d postgres
node server.js
```

The app runs on port 3000 by default. Without `APP_URL` set, CORS allows all origins.

## Ports

| Service | Internal | External (default) |
|---------|----------|--------------------|
| Node.js app | 3000 | 127.0.0.1:3552 |
| PostgreSQL | 5432 | Not exposed |

To change the external port, edit `docker-compose.yml`:

```yaml
ports:
  - "127.0.0.1:YOUR_PORT:3000"
```

## Logs

Application logs are written to:
- Console (visible via `docker compose logs`)
- `/app/data/logs/YYYY-MM-DD.log` inside the container (mapped to `scribe-logs` volume)
- Database tables: `audit_log`, `api_log`, `access_log`

View logs:

```bash
docker compose logs -f pediatric-scribe
docker compose logs --since=1h pediatric-scribe
```

## Auto-Cleanup

The application automatically cleans up expired data:
- Saved encounters: deleted after 7 days (configurable via `site.auto_delete_days`)
- Audio backups: deleted after 24 hours
- Cleanup runs hourly and 10 seconds after startup
