# Mission Control Backend (FastAPI)

This directory contains the **Mission Control backend API** (FastAPI + SQLModel) and its database migrations (Alembic).

- Default API base URL: http://localhost:8000
- Health endpoints: `/healthz`, `/readyz`
- API routes: `/api/v1/*`

## Requirements

- Python **3.12+**
- [`uv`](https://github.com/astral-sh/uv) (recommended; used by this repo)
- Postgres (local or Docker)

## Quick start (local backend + Docker Postgres)

From the repo root:

```bash
# start dependencies
cp .env.example .env
docker compose -f compose.yml --env-file .env up -d db

# run backend
cd backend
cp .env.example .env

uv sync --extra dev
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```

Verify:

```bash
curl -f http://localhost:8000/healthz
```

## Configuration / environment variables

Backend settings are defined in `app/core/config.py` via `pydantic-settings`.

The backend loads env files in this order:

1. `backend/.env` (preferred)
2. `.env` (current working directory)

A starter file exists at `backend/.env.example`.

### Core

- `ENVIRONMENT` (default: `dev`)
  - In `dev`, if you **don’t** explicitly set `DB_AUTO_MIGRATE`, the backend defaults it to `true`.
- `LOG_LEVEL` (default: `INFO`)
- `DATABASE_URL`
  - Default: `postgresql+psycopg://postgres:postgres@localhost:5432/openclaw_agency`
  - Recommended local/dev default (matches `backend/.env.example`):
    `postgresql+psycopg://postgres:postgres@localhost:5432/mission_control`
- `CORS_ORIGINS` (comma-separated)
  - Example: `http://localhost:3000`
- `BASE_URL` (required for gateway provisioning/agent heartbeat templates; no fallback)

### Database lifecycle

- `DB_AUTO_MIGRATE`
  - If `true`: on startup, the backend attempts to run Alembic migrations (`alembic upgrade head`).
  - If there are **no** Alembic revision files yet, it falls back to `SQLModel.metadata.create_all`.

### Forgejo scheduled sync

- `FORGEJO_SYNC_ENABLED` (default: `true`)
  - When enabled, the API seeds a periodic Forgejo issue-cache sync task into the RQ queue on startup.
- `FORGEJO_SYNC_INTERVAL_SECONDS` (default: `3600`)
  - How often the worker syncs all active Forgejo repositories.
- `FORGEJO_SYNC_STARTUP_DELAY_SECONDS` (default: `60`)
  - Initial delay before the first scheduled sync after API startup.

### Security headers

Security response headers added to every API response. Set any variable to blank to disable the corresponding header.

- `SECURITY_HEADER_X_CONTENT_TYPE_OPTIONS` (default: `nosniff`)
- `SECURITY_HEADER_X_FRAME_OPTIONS` (default: `DENY`)
- `SECURITY_HEADER_REFERRER_POLICY` (default: `strict-origin-when-cross-origin`)
- `SECURITY_HEADER_PERMISSIONS_POLICY` (default: blank — disabled)

### Auth (Clerk)

Clerk is used for user authentication (optional for local/self-host in many setups).

- `CLERK_SECRET_KEY` (required)
  - Used to fetch user profile fields (email/name) from Clerk when JWT claims are minimal.
- `CLERK_API_URL` (default: `https://api.clerk.com`)
- `CLERK_VERIFY_IAT` (default: `true`)
- `CLERK_LEEWAY` (default: `10.0`)

## Database migrations (Alembic)

Migrations live in `backend/migrations/versions/*`.

Common commands:

```bash
cd backend

# apply migrations
uv run alembic upgrade head

# create a new migration (example)
uv run alembic revision --autogenerate -m "add foo"
```

Notes:

- The backend can also auto-run migrations on startup when `DB_AUTO_MIGRATE=true`.
- The database URL is normalized so `postgresql://...` becomes `postgresql+psycopg://...`.

## Running tests / lint / typecheck

From repo root (recommended):

```bash
make backend-lint
make backend-test
make backend-coverage
```

`make backend-lint` runs backend format checks (`isort`, `black`), lint (`flake8`), and typecheck (`mypy`) in one command.

Or from `backend/`:

```bash
cd backend
uv run pytest
uv run isort . --check-only --diff
uv run black . --check --diff
uv run flake8 --config .flake8
uv run mypy
```

Formatting:

```bash
make backend-format
make backend-format-check
```

## Scripts

Backend scripts live in `backend/scripts/`:

- `export_openapi.py` – export OpenAPI schema
- `seed_demo.py` – seed demo data (if applicable)
- `sync_gateway_templates.py` – sync repo templates to an existing gateway

Run with:

```bash
cd backend
uv run python scripts/export_openapi.py
```

## Troubleshooting

### Backend can’t connect to Postgres

- If you started Postgres via compose, make sure it is healthy:

  ```bash
  docker compose -f compose.yml --env-file .env ps
  docker compose -f compose.yml --env-file .env logs -f --tail=200 db
  ```

- If backend runs **locally** (not in compose), `DATABASE_URL` should usually point at `localhost`.

### CORS issues from the frontend

- Set `CORS_ORIGINS=http://localhost:3000` (or a comma-separated list) in `backend/.env`.
- Restart the backend after changing env vars.

### Alembic / migrations not applying

- If you want deterministic behavior, run migrations manually:

  ```bash
  cd backend
  uv run alembic upgrade head
  ```

- If `DB_AUTO_MIGRATE=false`, the backend may use `create_all` instead of Alembic.
