Phase 3 (#38): Fix reset_in_ms=0 bug - Add _oldest_active_ts() to find oldest session timestamp in 5h window - _build_window() now anchors fallback to oldest_event_ts + 5h instead of now - 5h - Add _parse_rate_limit_reset_value() and _extract_rate_limit_reset_at() for proper rate-limit reset parsing - Source/confidence labeling now based on reset provenance Phase 2 (#37): Provider-native usage windows - ParsedClaudeUsageWindow dataclass with section-aware parsing - Frontend ProviderNativeUsageWindow interface and provider-native usage section - sessions.list call now has 8s timeout to avoid gateway blocking Phase 5 (#40): Pricing fixes - Opus cache_write corrected .75 → .75 - Added GPT-4.1/mini/nano, GPT-4.5 pricing - Pricing override loader supports both shapes (rates_usd_per_million wrapper and direct dict) |
||
|---|---|---|
| .. | ||
| .learnings/neo | ||
| app | ||
| migrations | ||
| scripts | ||
| templates | ||
| tests | ||
| .coveragerc | ||
| .env.example | ||
| .env.test | ||
| .flake8 | ||
| .gitignore | ||
| Dockerfile | ||
| README.md | ||
| alembic.ini | ||
| pyproject.toml | ||
| uv.lock | ||
README.md
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(recommended; used by this repo)- Postgres (local or Docker)
Quick start (local backend + Docker Postgres)
From the repo root:
# 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:
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:
backend/.env(preferred).env(current working directory)
A starter file exists at backend/.env.example.
Core
ENVIRONMENT(default:dev)- In
dev, if you don’t explicitly setDB_AUTO_MIGRATE, the backend defaults it totrue.
- In
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
- Default:
CORS_ORIGINS(comma-separated)- Example:
http://localhost:3000
- Example:
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.
- If
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:
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://...becomespostgresql+psycopg://....
Running tests / lint / typecheck
From repo root (recommended):
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/:
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:
make backend-format
make backend-format-check
Scripts
Backend scripts live in backend/scripts/:
export_openapi.py– export OpenAPI schemaseed_demo.py– seed demo data (if applicable)sync_gateway_templates.py– sync repo templates to an existing gateway
Run with:
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:
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_URLshould usually point atlocalhost.
CORS issues from the frontend
- Set
CORS_ORIGINS=http://localhost:3000(or a comma-separated list) inbackend/.env. - Restart the backend after changing env vars.
Alembic / migrations not applying
-
If you want deterministic behavior, run migrations manually:
cd backend uv run alembic upgrade head -
If
DB_AUTO_MIGRATE=false, the backend may usecreate_allinstead of Alembic.