removed old docs

This commit is contained in:
Abhimanyu Saharan
2026-02-12 02:16:43 +05:30
parent f64e9df120
commit 6548f738cd
24 changed files with 0 additions and 3557 deletions

View File

@@ -1,96 +0,0 @@
# Documentation style guide
This repository aims for a NetBox-like style: clear, technical, and written for working engineers.
## Voice and tone
- **Direct and technical.** Prefer short sentences and specific nouns.
- **Narrative flow.** Describe how the system behaves, not how the doc was produced.
- **Calm, professional tone.** Avoid hype.
- **Assume competence, not context.** Define repo-specific terms once, then reuse them.
## Page structure (default)
Use a consistent, scan-friendly layout.
1. **Title**
2. **13 sentence intro**
- What this page covers and who its for.
3. **Deep dives / Related docs** (optional but common)
- Links to more detailed pages.
4. **Main content**
- Prefer sections that match user intent: “Quickstart”, “How it works”, “Configuration”, “Common workflows”, “Troubleshooting”.
5. **Next steps** (optional)
- Where to go next.
## Headings and conventions
- Prefer **verb-led** headings when describing procedures: “Run migrations”, “Regenerate the client”.
- Prefer **intent-led** headings when describing concepts: “How requests flow”, “Auth model”.
- Use numbered steps when order matters.
- Keep headings short; avoid long parentheticals.
## Cross-linking
- Treat the numbered IA pages in `docs/` as **entrypoints**.
- Link to deep dives instead of duplicating content.
- Use readable link text:
- Good: “Deployment guide” → `docs/deployment/README.md`
- Avoid: ``docs/deployment/README.md``
## Link formatting rules
- Use markdown links: `[Deployment guide](deployment/README.md)`.
- Use relative paths that work in GitHub and typical markdown renderers.
- Keep code formatting for:
- commands (`make check`)
- environment variables (`NEXT_PUBLIC_API_URL`)
- literal file paths when you mean “this exact file on disk” (not as a navigational link)
## Avoided phrases (and what to use instead)
Avoid doc-meta language:
- Avoid: “evidence basis”, “evidence anchors”, “this page is intentionally…”
- Prefer:
- “Source of truth: …” (only when it matters)
- “See also: …”
- Just link the file or section.
Avoid hedging:
- Avoid: “likely”, “probably”, “should” (unless its a policy decision)
- Prefer: state what the code does, and point to the file.
## Preferred patterns
- **Start here** blocks for role-based entry.
- **Common workflows** sections with copy/paste commands.
- **Troubleshooting** sections with symptoms → checks → fixes.
- **Footguns** called out explicitly when they can cause outages or confusing behavior.
## Example rewrites
### Example 1: remove doc-meta “evidence” language
Before:
> Evidence basis: consolidated from repo root `README.md`, `.github/workflows/ci.yml`, `Makefile`.
After:
> This page describes the development workflow that matches CI: setup, checks, and common local loops.
### Example 2: prefer readable links over code-formatted paths
Before:
- See `docs/deployment/README.md` for deployment.
After:
- See the [Deployment guide](deployment/README.md).
### Example 3: replace “first pass” filler with a clear scope boundary
Before:
- Non-goals (first pass)
After:
- Out of scope

View File

@@ -1,43 +0,0 @@
# Mission Control
Mission Control is the **web UI + HTTP API** for operating OpenClaw.
Its the place you go to coordinate work across people and agents, keep an evidence trail, and operate the system safely.
## What problem it solves
OpenClaw can run tools/skills and hold conversations across channels. Whats missing in practice is a control plane that makes this operational:
- **Coordination**: boards + tasks make it explicit whats being worked on, by whom, and whats blocked.
- **Evidence**: task comments capture commands run, links, outputs, and decisions.
- **Risk control**: approvals provide a structured “allow/deny” gate for sensitive actions.
- **Operations**: deployment, configuration, and troubleshooting live in one navigable docs spine.
## Core concepts
- **Board**: a workspace containing tasks, memory, and agents.
- **Task**: a unit of work with a status and evidence (comments).
- **Agent**: an automated worker that executes tasks and posts evidence.
- **Approval**: a review gate for risky steps.
- **Gateway** (optional integration): an OpenClaw runtime host Mission Control can coordinate with.
- **Heartbeat**: periodic agent loop for incremental work.
- **Cron**: scheduled execution (recurring or one-shot).
## What it is not
- A general-purpose project management tool.
- An observability suite (use your existing logs/metrics/tracing; Mission Control links and operationalizes them).
- A secrets manager (keep secrets in your secret store; dont paste them into tasks/docs).
## How to navigate these docs
This repo keeps a small “reader journey” spine under `docs/`:
1. [Quickstart](02-quickstart.md) — run it locally/self-host.
2. [Development](03-development.md) — contributor workflow and CI parity.
3. [Configuration](06-configuration.md) — env vars, precedence, migrations, CORS.
4. [API reference](07-api-reference.md) — route groups + auth model.
5. [Ops / runbooks](09-ops-runbooks.md) — operational checklists.
6. [Troubleshooting](10-troubleshooting.md) — symptom → checks → fixes.
For deeper references, see `docs/architecture/`, `docs/deployment/`, `docs/production/`, `docs/testing/`, and `docs/troubleshooting/`.

View File

@@ -1,61 +0,0 @@
# Quickstart (Docker Compose)
This is the fastest way to run Mission Control locally or on a single host.
## What you get
From `compose.yml` you get three services:
- Postgres (`db`)
- FastAPI backend (`backend`) on `http://localhost:8000`
- Next.js frontend (`frontend`) on `http://localhost:3000`
## Prerequisites
- Docker + Docker Compose v2 (`docker compose`)
## Run
From repo root:
```bash
cp .env.example .env
docker compose -f compose.yml --env-file .env up -d --build
```
Open:
- UI: http://localhost:3000
- Backend health: http://localhost:8000/healthz
## Verify
```bash
curl -f http://localhost:8000/healthz
curl -I http://localhost:3000/
```
## Common gotchas
- `NEXT_PUBLIC_API_URL` must be reachable from your **browser**.
- If its missing/blank/wrong, the UI may load but API calls will fail (e.g. Activity feed blank).
- If you are running locally without Clerk:
- keep `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` unset/blank so Clerk stays gated off in the frontend.
## Useful commands
```bash
# tail logs
docker compose -f compose.yml --env-file .env logs -f --tail=200
# stop (keeps data)
docker compose -f compose.yml --env-file .env down
# reset data (DESTRUCTIVE)
docker compose -f compose.yml --env-file .env down -v
```
## Next
- Want a faster contributor loop? See [Development](03-development.md) (DB via Compose, backend+frontend in dev mode).
- Need to change env vars/migrations/CORS? See [Configuration](06-configuration.md).

View File

@@ -1,121 +0,0 @@
# Development
This page is the contributor workflow for Mission Control.
Its intentionally **CI-aligned**: if you can run these commands locally, you should not be surprised by CI.
## Prerequisites
- Docker + Docker Compose v2 (`docker compose`)
- Python **3.12+** + [`uv`](https://github.com/astral-sh/uv)
- Node.js + npm
- CI pins **Node 20** via `.github/workflows/ci.yml` (`actions/setup-node@v4`, `node-version: "20"`).
## Repo layout
- Backend: `backend/` (FastAPI)
- Frontend: `frontend/` (Next.js)
- Canonical commands: `Makefile`
## Setup (one command)
From repo root:
```bash
make setup
```
What it does (evidence: `Makefile`):
- `make backend-sync`: `cd backend && uv sync --extra dev`
- `make frontend-sync`: verifies node tooling (`scripts/with_node.sh --check`), then `npm install` in `frontend/`
## Run the stack (two recommended loops)
### Loop A (recommended): DB via Compose, app in dev mode
1) Start Postgres:
```bash
cp .env.example .env
docker compose -f compose.yml --env-file .env up -d db
```
2) Backend dev server:
```bash
cd backend
cp .env.example .env
uv sync --extra dev
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```
3) Frontend dev server:
```bash
cd frontend
cp .env.example .env.local
# ensure this is correct for the browser:
# NEXT_PUBLIC_API_URL=http://localhost:8000
npm install
npm run dev
```
### Loop B: all-in-one Compose
```bash
cp .env.example .env
docker compose -f compose.yml --env-file .env up -d --build
```
## Checks (CI parity)
### Run everything
```bash
make check
```
Evidence: `Makefile`.
### Common targeted commands
Backend:
```bash
make backend-lint # flake8
make backend-typecheck # mypy --strict
make backend-test # pytest
make backend-coverage # pytest + scoped 100% coverage gate
make backend-migrate # alembic upgrade head
```
Frontend:
```bash
make frontend-lint # eslint
make frontend-typecheck # tsc
make frontend-test # vitest
make frontend-build # next build
```
## Cypress E2E
Evidence: `docs/testing/README.md`, `.github/workflows/ci.yml`.
- E2E uses Clerks official Cypress integration (`@clerk/testing`).
- Local run pattern:
```bash
# terminal 1
cd frontend
npm run dev -- --hostname 0.0.0.0 --port 3000
# terminal 2
cd frontend
npm run e2e -- --browser chrome
```
## Deep dives
- [Testing guide](testing/README.md)
- [Troubleshooting deep dive](troubleshooting/README.md)

View File

@@ -1,35 +0,0 @@
# Repo tour
High-level map of the codebase so you can quickly find where to change things.
## Top-level
- `backend/` — FastAPI backend (API server)
- `frontend/` — Next.js frontend (web UI)
- `docs/` — documentation
- `compose.yml` — local/self-host stack (db + backend + frontend)
- `scripts/` — helper scripts
## Backend: where to look
- App entrypoint + router wiring: `backend/app/main.py`
- Routers: `backend/app/api/*`
- Settings/config: `backend/app/core/config.py`
- Auth (Clerk + agent token): `backend/app/core/auth.py`, `backend/app/core/agent_auth.py`
- Models: `backend/app/models/*`
- Services/domain logic: `backend/app/services/*`
## Frontend: where to look
- Routes (App Router): `frontend/src/app/*`
- Components: `frontend/src/components/*`
- API utilities: `frontend/src/lib/*` and `frontend/src/api/*`
- Auth (Clerk gating/wrappers): `frontend/src/auth/*`
## Where to change X
| You want to… | Start here |
|---|---|
| Add/modify an API endpoint | `backend/app/api/*` + `backend/app/main.py` |
| Change auth behavior | `backend/app/core/auth.py` + `frontend/src/auth/*` |
| Change a UI page | `frontend/src/app/*` |
| Update Compose topology | `compose.yml` |
Next: see [Architecture](05-architecture.md) for system-level flows.

View File

@@ -1,96 +0,0 @@
# Architecture
## Deep dives
- [Architecture deep dive](architecture/README.md)
- [Gateway protocol](openclaw_gateway_ws.md)
Mission Control is the **web UI + HTTP API** for operating OpenClaw. Its where you manage boards, tasks, agents, approvals, and (optionally) gateway connections.
> Auth note: Mission Control supports two auth modes: `local` (shared bearer token) and `clerk`.
## Components
- **Frontend**: Next.js app used by humans
- Location: `frontend/`
- Routes/pages: `frontend/src/app/*` (Next.js App Router)
- API client: generated + custom fetch (see `frontend/src/api/*`, `frontend/src/lib/api-base.ts`)
- **Backend**: FastAPI service exposing REST endpoints
- Location: `backend/`
- Entrypoint: `backend/app/main.py`
- API prefix: `/api/v1/*`
- **Database**: Postgres (see `compose.yml`)
- **Gateway integration (optional)**: backend may call into OpenClaw Gateways over WebSockets
- Client/protocol list: `backend/app/services/openclaw/gateway_rpc.py`
## Diagram (conceptual)
```mermaid
flowchart LR
U[User / Browser] -->|HTTP| FE[Next.js Frontend :3000]
FE -->|HTTP /api/v1/*| BE[FastAPI Backend :8000]
BE -->|SQL| PG[(Postgres :5432)]
BE -->|WebSocket (optional)| GW[OpenClaw Gateway]
GW --> OC[OpenClaw runtime]
```
## How requests flow
### 1) A human uses the UI
1. Browser loads the Next.js frontend (`frontend/`).
2. Frontend calls backend endpoints using `NEXT_PUBLIC_API_URL`.
3. Backend routes under `/api/v1/*` (`backend/app/main.py`) and reads/writes Postgres.
Common UI-driven data shapes:
- “boards/tasks” views → board/task CRUD + streams.
- “activity feed” → activity/events endpoints.
### 2) Authentication (`local` or Clerk)
- **Frontend**:
- `local`: token entry + token storage (`frontend/src/components/organisms/LocalAuthLogin.tsx`, `frontend/src/auth/localAuth.ts`).
- `clerk`: Clerk wrappers/hooks (`frontend/src/auth/clerk.tsx`).
- **Frontend → backend**:
- API calls attach `Authorization: Bearer <token>` from local mode token or Clerk session token (`frontend/src/api/mutator.ts`).
- **Backend**:
- `local`: validates `LOCAL_AUTH_TOKEN`.
- `clerk`: validates Clerk request state via `clerk_backend_api` + `CLERK_SECRET_KEY`.
- Implementation: `backend/app/core/auth.py`.
### 3) Agent automation surface (`/api/v1/agent/*`)
Agents can call a dedicated API surface:
- Router: `backend/app/api/agent.py` (prefix `/agent` → mounted under `/api/v1/agent/*`).
- Authentication: `X-Agent-Token` header (or agent-only Authorization bearer parsing).
- Implementation: `backend/app/core/agent_auth.py`.
Typical agent flows:
- Heartbeat/presence updates
- Task comment posting (evidence)
- Board memory updates
- Lead coordination actions (if board-lead agent)
### 4) Streaming/feeds (server-sent events)
Some endpoints support streaming via SSE (`text/event-stream`).
Notes:
- Uses `sse-starlette` in backend routes (e.g. task/activity/memory routers).
### 5) Gateway integration (optional)
Mission Control can coordinate with OpenClaw Gateways over WebSockets.
- Protocol methods/events list: `backend/app/services/openclaw/gateway_rpc.py`.
- Operator-facing protocol docs: [Gateway WebSocket protocol](openclaw_gateway_ws.md).
## Where to start reading code
- Backend entrypoint + router wiring: `backend/app/main.py`
- Auth dependencies + access enforcement: `backend/app/api/deps.py`
- User auth: `backend/app/core/auth.py`
- Agent auth: `backend/app/core/agent_auth.py`
- Agent API surface: `backend/app/api/agent.py`

View File

@@ -1,116 +0,0 @@
# Configuration
This page documents **where configuration comes from**, the key **environment variables**, and a couple operational footguns (migrations, CORS).
For deployment/production patterns, see:
- [Deployment](deployment/README.md)
- [Production](production/README.md)
## Configuration sources & precedence
Mission Control is a 3-service stack (`compose.yml`): Postgres (`db`), backend (`backend`), frontend (`frontend`).
### Docker Compose (recommended for local/self-host)
Common pattern:
```bash
cp .env.example .env
docker compose -f compose.yml --env-file .env up -d --build
```
Precedence (high → low):
1. Environment exported in your shell (or `-e NAME=value`)
2. Compose `--env-file .env` (variable interpolation)
3. Defaults in `compose.yml` (e.g. `${BACKEND_PORT:-8000}`)
4. Backend defaults via `env_file: ./backend/.env.example`
5. Frontend optional user-managed `frontend/.env`
> Note: Compose intentionally does **not** load `frontend/.env.example` to avoid placeholder Clerk keys accidentally enabling Clerk.
### Backend env-file loading (non-Compose)
Evidence: `backend/app/core/config.py`.
When running the backend directly (uvicorn), settings are loaded from:
- `backend/.env` (always attempted)
- `.env` (repo root; optional)
- plus process env vars
## Environment variables (grouped)
### Root `.env` (Compose-level)
Template: `.env.example`.
- Ports: `FRONTEND_PORT`, `BACKEND_PORT`, `POSTGRES_PORT`
- Postgres defaults: `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`
- Backend knobs: `CORS_ORIGINS`, `DB_AUTO_MIGRATE`
- Frontend: `NEXT_PUBLIC_API_URL` (required)
### Backend
Template: `backend/.env.example` + settings model `backend/app/core/config.py`.
- `ENVIRONMENT`
- `LOG_LEVEL`
- `DATABASE_URL`
- `CORS_ORIGINS`
- `DB_AUTO_MIGRATE`
Clerk:
- `CLERK_SECRET_KEY` (required; backend enforces non-empty)
- `CLERK_API_URL`, `CLERK_VERIFY_IAT`, `CLERK_LEEWAY`
### Frontend
Template: `frontend/.env.example`.
| Variable | Required? | Purpose | Default / example | Footguns |
|---|---:|---|---|---|
| `NEXT_PUBLIC_API_URL` | **yes** | Backend base URL used by the browser | `http://localhost:8000` | Must be browser-reachable |
| `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` | **yes** | Enables Clerk in the frontend | (none) | Must be a real publishable key |
| `NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL` | optional | Fallback redirect | `/boards` | — |
| `NEXT_PUBLIC_CLERK_AFTER_SIGN_OUT_URL` | optional | Post-logout redirect | `/` | — |
## Minimal dev configuration
### Split-mode dev (fastest contributor loop)
- Start DB via Compose.
- Run backend+frontend dev servers.
See [Development](03-development.md).
## Migrations (`DB_AUTO_MIGRATE`)
Evidence: `backend/app/db/session.py`.
On backend startup:
- if `DB_AUTO_MIGRATE=true` and migrations exist under `backend/migrations/versions/`, backend runs `alembic upgrade head`.
- otherwise it falls back to `SQLModel.metadata.create_all`.
Operational guidance:
- Auto-migrate is convenient on a single host.
- In multi-instance deployments, prefer running migrations as an explicit deploy step to avoid race conditions.
## CORS (`CORS_ORIGINS`)
Evidence: `backend/app/main.py`, `backend/app/core/config.py`.
- `CORS_ORIGINS` is a comma-separated list.
- It must include the frontend origin (e.g. `http://localhost:3000`) or browser requests will fail.
## Common footguns
- **Frontend env template vs runtime env**: `frontend/.env.example` is a template and `compose.yml` intentionally does **not** load it at runtime. Use user-managed `frontend/.env` (for Compose) or `frontend/.env.local` (for Next dev).
- **`NEXT_PUBLIC_API_URL` reachability**: must work from the browsers network context (host), not only from within the Docker network.
## Troubleshooting config issues
- UI loads but API calls fail / Activity feed blank → `NEXT_PUBLIC_API_URL` is missing/incorrect.
- Backend fails at startup → check required env vars (notably `CLERK_SECRET_KEY`) and migrations.
See also: `docs/troubleshooting/README.md`.

View File

@@ -1,115 +0,0 @@
# API / auth
This page documents how Mission Controls API surface is organized and how authentication works.
For deeper backend architecture context, see:
- [Architecture](05-architecture.md)
## Base path
Evidence: `backend/app/main.py`.
- All API routes are mounted under: `/api/v1/*`
## Auth model (two callers)
Mission Control has two primary actor types:
1) **User (Clerk)** — human UI/admin
2) **Agent (`X-Agent-Token`)** — automation
### User auth (Clerk)
Evidence:
- backend: `backend/app/core/auth.py`
- config: `backend/app/core/config.py`
- Frontend calls backend using `Authorization: Bearer <token>`.
- Backend validates requests using the Clerk Backend API SDK with `CLERK_SECRET_KEY`.
### Agent auth (`X-Agent-Token`)
Evidence:
- `backend/app/core/agent_auth.py`
- agent API surface: `backend/app/api/agent.py`
- Agents authenticate with `X-Agent-Token: <token>`.
- Token is verified against the agents stored `agent_token_hash`.
## Route groups (modules)
Evidence: `backend/app/main.py` includes routers from `backend/app/api/*`.
| Module | Prefix (under `/api/v1`) | Purpose |
|---|---|---|
| `activity.py` | `/activity` | Activity listing and task-comment feed endpoints. |
| `agent.py` | `/agent` | Agent-scoped API routes for board operations and gateway coordination. |
| `agents.py` | `/agents` | Thin API wrappers for async agent lifecycle operations. |
| `approvals.py` | `/boards/{board_id}/approvals` | Approval listing, streaming, creation, and update endpoints. |
| `auth.py` | `/auth` | Authentication bootstrap endpoints for the Mission Control API. |
| `board_group_memory.py` | `/board-groups/{group_id}/memory` and `/boards/{board_id}/group-memory` | Board-group memory CRUD and streaming endpoints. |
| `board_groups.py` | `/board-groups` | Board group CRUD, snapshot, and heartbeat endpoints. |
| `board_memory.py` | `/boards/{board_id}/memory` | Board memory CRUD and streaming endpoints. |
| `board_onboarding.py` | `/boards/{board_id}/onboarding` | Board onboarding endpoints for user/agent collaboration. |
| `boards.py` | `/boards` | Board CRUD and snapshot endpoints. |
| `gateway.py` | `/gateways` | Thin gateway session-inspection API wrappers. |
| `gateways.py` | `/gateways` | Thin API wrappers for gateway CRUD and template synchronization. |
| `metrics.py` | `/metrics` | Dashboard metric aggregation endpoints. |
| `organizations.py` | `/organizations` | Organization management endpoints and membership/invite flows. |
| `souls_directory.py` | `/souls-directory` | API routes for searching and fetching souls-directory markdown entries. |
| `tasks.py` | `/boards/{board_id}/tasks` | Task API routes for listing, streaming, and mutating board tasks. |
| `users.py` | `/users` | User self-service API endpoints for profile retrieval and updates. |
## Backend API layer notes (how modules are organized)
Evidence: `backend/app/main.py`, `backend/app/api/*`, `backend/app/api/deps.py`.
### Conventions
- Each file under `backend/app/api/*` typically declares an `APIRouter` (`router = APIRouter(...)`) and defines endpoints with decorators like `@router.get(...)`, `@router.post(...)`, etc.
- Board-scoped modules embed `{board_id}` in the prefix (e.g. `/boards/{board_id}/tasks`).
- Streaming endpoints usually expose **SSE** endpoints at `.../stream` (see `sse-starlette` usage).
### Where key behaviors live
- **Router wiring / base prefix**: `backend/app/main.py` mounts these routers under `/api/v1/*`.
- **Auth / access control** is mostly expressed through dependencies (see `backend/app/api/deps.py`):
- `require_admin_auth` — require an authenticated *admin user*.
- `require_admin_or_agent` — allow either an admin user or an authenticated agent.
- `get_board_for_actor_read` / `get_board_for_actor_write` — enforce board access for the calling actor.
- `require_org_member` / `require_org_admin` — enforce org membership/admin for user callers.
- **Agent-only surface**: `backend/app/api/agent.py` uses `get_agent_auth_context` (X-Agent-Token) and contains board/task/memory endpoints specifically for automation.
### Module-by-module map (prefix, key endpoints, and pointers)
This is a “where to look” index, not a full OpenAPI dump. For exact parameters and response shapes, see:
- route module file (`backend/app/api/<module>.py`)
- schemas (`backend/app/schemas/*`)
- models (`backend/app/models/*`)
- services (`backend/app/services/*`)
| Module | Prefix (under `/api/v1`) | Key endpoints (examples) | Main deps / auth | Pointers (schemas/models/services) |
|---|---|---|---|---|
| `activity.py` | `/activity` | `GET /activity` (events); `GET /activity/task-comments` + `/stream` | `require_admin_or_agent`, `require_org_member` | `app/models/activity_events.py`, `app/schemas/activity_events.py` |
| `agent.py` | `/agent` | agent automation surface: boards/tasks/memory + gateway coordination | `get_agent_auth_context` (X-Agent-Token) | `backend/app/core/agent_auth.py`, `backend/app/services/openclaw/*` |
| `agents.py` | `/agents` | agent lifecycle + SSE stream + heartbeat | org-admin gated for user callers; some endpoints allow agent access via deps | `app/schemas/agents.py`, `app/services/openclaw/provisioning_db.py` |
| `approvals.py` | `/boards/{board_id}/approvals` | list/create/update approvals + `/stream` | `require_admin_or_agent` + board access deps | `app/models/approvals.py`, `app/schemas/approvals.py` |
## Where authorization is enforced
Evidence: `backend/app/api/deps.py`.
Most route modules dont “hand roll” access checks; they declare dependencies:
- `require_admin_auth` — admin user only.
- `require_admin_or_agent` — admin user OR authenticated agent.
- `get_board_for_actor_read` / `get_board_for_actor_write` — board access for user/agent.
- `require_org_member` / `require_org_admin` — org membership/admin for user callers.
## “Start here” pointers for maintainers
- Router wiring: `backend/app/main.py`
- Access dependencies: `backend/app/api/deps.py`
- User auth: `backend/app/core/auth.py`
- Agent auth: `backend/app/core/agent_auth.py`
- Agent automation surface: `backend/app/api/agent.py`

View File

@@ -1,28 +0,0 @@
# Agents & skills
## Deep dives
- [Gateway protocol](openclaw_gateway_ws.md)
- [Gateway base config](openclaw_gateway_base_config.md)
This page explains the automation model as it appears in Mission Control.
## Agent lifecycle (conceptual)
- An **agent** checks in to Mission Control (often on a schedule) and posts work results as task comments.
- In OpenClaw terms, agents can run:
- **heartbeats** (periodic loops)
- **cron jobs** (scheduled runs; better for exact timing / isolation)
## Heartbeats vs cron
- Use **heartbeat** for batched checks and context-aware incremental work.
- Use **cron** for exact timing and isolated, standalone actions.
## Skills (how to think about them)
- A skill is a packaged workflow/tooling instruction set that agents can follow.
- Skills typically define:
- when to use them
- required binaries/services
- command patterns
## Next
- Add repo-specific guidance for authoring skills and where they live (once standardized).

View File

@@ -1,81 +0,0 @@
# Operations
This is the ops/SRE entrypoint.
It aims to answer, quickly:
- “Is the system up?”
- “What changed?”
- “What should I check next?”
Deep dives:
- [Deployment](deployment/README.md)
- [Production](production/README.md)
- [Troubleshooting deep dive](troubleshooting/README.md)
## First 30 minutes (incident checklist)
### 0) Stabilize communications
- Identify incident lead and comms channel.
- Capture last deploy SHA/tag and time window.
- Do not paste secrets into chat/tickets.
### 1) Confirm impact
- UI broken vs API broken vs auth vs DB vs gateway integration.
- All users or subset?
### 2) Health checks
- Backend:
- `curl -f http://<backend-host>:8000/healthz`
- `curl -f http://<backend-host>:8000/readyz`
- Frontend:
- can the UI load?
- in browser devtools, are `/api/v1/*` requests failing?
### 3) Configuration sanity
Common misconfigs that look like outages:
- `NEXT_PUBLIC_API_URL` wrong → UI loads but API calls fail.
- `CORS_ORIGINS` missing frontend origin → browser CORS errors.
- Clerk misconfig → auth redirects/401s.
### 4) Database
- If backend is 5xxing broadly, DB is a top suspect.
- Verify `DATABASE_URL` points at the correct host.
### 5) Logs
Compose:
```bash
docker compose -f compose.yml --env-file .env logs -f --tail=200
```
Targeted:
```bash
docker compose -f compose.yml --env-file .env logs -f --tail=200 backend
```
### 6) Rollback / isolate
- If there was a recent deploy and symptoms align, rollback to last known good.
- If gateway integration is implicated, isolate by disabling gateway-dependent flows.
## Common failure modes
- UI loads, Activity feed blank → `NEXT_PUBLIC_API_URL` wrong/unreachable.
- Repeated auth redirects/errors → Clerk keys/redirects misconfigured.
- Backend 5xx → DB outage/misconfig; migration failure.
- Backend wont start → config validation failure (e.g. empty `CLERK_SECRET_KEY`).
## Backups
Evidence: `docs/production/README.md`.
- Minimum viable: periodic `pg_dump` to off-host storage.
- Treat restore as a drill (quarterly), not a one-time checklist.

View File

@@ -1,38 +0,0 @@
# Troubleshooting
This is the “symptom → checks → likely fixes” page.
For deeper playbooks, see:
- [Troubleshooting deep dive](troubleshooting/README.md)
## Triage map
| Symptom | Fast checks | Likely fix |
|---|---|---|
| UI loads but API calls fail / Activity feed blank | Browser devtools shows `/api/v1/*` failures; check backend `/healthz` | Fix `NEXT_PUBLIC_API_URL` (must be browser-reachable) |
| UI redirects / Clerk errors | Is `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` set? Are Clerk redirects correct? | Unset keys for local dev without Clerk; configure real keys for prod |
| Backend `/healthz` fails | Is backend container/process running? check backend logs | Fix crash loop: env vars, DB connectivity, migrations |
| Backend returns 5xx | Check DB connectivity (`DATABASE_URL`), DB logs | Fix DB outage/misconfig; re-run migrations if needed |
| Browser shows CORS errors | Compare `CORS_ORIGINS` vs frontend origin | Add frontend origin to `CORS_ORIGINS` |
## Common checks
### 1) Verify backend health
```bash
curl -f http://localhost:8000/healthz
```
### 2) Verify frontend can reach backend
- Ensure `NEXT_PUBLIC_API_URL` matches the backend URL the browser can reach.
### 3) Check logs
```bash
docker compose -f compose.yml --env-file .env logs -f --tail=200 backend
```
## Next
If you hit a recurring incident, promote it from the deep-dive page into this triage map.

View File

@@ -1,18 +0,0 @@
# Contributing
## Deep dives
- [Coverage policy](coverage-policy.md)
- [Testing guide](testing/README.md)
## How to contribute
- Follow the repos existing PR and review conventions.
- Prefer small PRs.
- Update docs when behavior changes.
## Adding/changing docs
- Canonical docs live in `docs/`.
- Follow the IA in [Docs landing](README.md).
## Testing expectations
- See [docs/testing/README.md](testing/README.md).

View File

@@ -1,137 +0,0 @@
# Backend core modules (auth/config/logging/errors)
> Evidence basis: repo https://github.com/abhi1693/openclaw-mission-control @ commit `c3490630a4503d9c8142aaa3abf542e0d00b5035`.
This page documents the backend “core” layer under `backend/app/core/*` plus the API dependency module `backend/app/api/deps.py`.
Its written for maintainers who need to answer:
- “Where does configuration come from?”
- “How do user vs agent auth work?”
- “Where are authorization decisions enforced?”
- “Whats the error envelope / request-id behavior?”
- “How is logging structured and how do I get request-context in logs?”
## Start here (reading order)
1. `backend/app/core/config.py` — settings + env file loading
2. `backend/app/core/logging.py` — structured logging + request context
3. `backend/app/core/error_handling.py` — request-id middleware + exception envelope
4. `backend/app/core/auth.py` — Clerk/user auth resolution
5. `backend/app/core/agent_auth.py` — agent token auth resolution
6. `backend/app/api/deps.py` — how routes declare and enforce access
## Configuration: loading & precedence
**Primary file:** `backend/app/core/config.py`
Key facts:
- Uses `pydantic-settings` (`BaseSettings`) to load typed settings from environment.
- Env files are loaded regardless of current working directory:
- `backend/.env` (via `DEFAULT_ENV_FILE`)
- then `.env` (repo root) as an additional source
- See `Settings.model_config.env_file=[DEFAULT_ENV_FILE, ".env"]`.
- Unknown env vars are ignored (`extra="ignore"`).
Notable settings (security-sensitive in **bold**):
- `DATABASE_URL` / `database_url`
- `CORS_ORIGINS` / `cors_origins`
- `DB_AUTO_MIGRATE` / `db_auto_migrate`
- **`CLERK_SECRET_KEY` / `clerk_secret_key`** (must be non-empty; validator enforces it)
- `CLERK_API_URL`, `CLERK_VERIFY_IAT`, `CLERK_LEEWAY`
- logging knobs: `LOG_LEVEL`, `LOG_FORMAT`, `LOG_USE_UTC`, `REQUEST_LOG_SLOW_MS`, `REQUEST_LOG_INCLUDE_HEALTH`
### Deployment implication
- If a deployment accidentally starts the backend with an empty/placeholder `CLERK_SECRET_KEY`, the backend will fail settings validation at startup.
## Auth model split
The backend supports two top-level actor types:
- **User** (human UI / admin) — resolved from the `Authorization: Bearer <token>` header via Clerk.
- **Agent** (automation) — resolved from `X-Agent-Token: <token>` (and optionally `Authorization: Bearer <token>` for agent callers).
### User auth (Clerk) — `backend/app/core/auth.py`
What it does:
- Uses the `clerk_backend_api` SDK to authenticate requests (`authenticate_request(...)`) using `CLERK_SECRET_KEY`.
- Resolves a `AuthContext` containing `actor_type="user"` and a `User` model instance.
- The module includes helpers to fetch user profile details from Clerk (`_fetch_clerk_profile`) and to delete a Clerk user (`delete_clerk_user`).
Security-sensitive notes:
- Treat `CLERK_SECRET_KEY` as a credential; never log it.
- This code calls Clerk API endpoints over the network (timeouts and error handling matter).
### Agent auth (token hash) — `backend/app/core/agent_auth.py`
What it does:
- Requires a token header for protected agent endpoints:
- Primary header: `X-Agent-Token`
- Optional parsing: `Authorization: Bearer ...` (only in `get_agent_auth_context`, and only if `accept_authorization=True`)
- Validates token by comparing it against stored `agent_token_hash` values in the DB (`verify_agent_token`).
- “Touches” agent presence (`last_seen_at`, `status`) on authenticated requests.
- For safe methods (`GET/HEAD/OPTIONS`), it commits immediately so read-only polling still shows the agent as online.
Security-sensitive notes:
- Token verification iterates over agents with a token hash. If this grows large, consider indexing/lookup strategy.
- Never echo full tokens in logs; current code logs only a prefix on invalid tokens.
## Authorization enforcement: `backend/app/api/deps.py`
This module is the primary “policy wiring” for most routes.
Key concepts:
- `require_admin_auth(...)`
- Requires an authenticated *admin user*.
- `require_admin_or_agent(...)` → returns `ActorContext`
- Allows either:
- admin user (user auth via Clerk), or
- authenticated agent (agent auth via X-Agent-Token).
Board/task access patterns:
- `get_board_for_actor_read` / `get_board_for_actor_write`
- Enforces that the caller (user or agent) has the correct access to the board.
- Agent access is restricted if the agent is bound to a specific board (`agent.board_id`).
- `get_task_or_404`
- Loads a task and ensures it belongs to the requested board.
Org access patterns (user callers):
- `require_org_member` and `require_org_admin`
- Resolve/require active org membership.
- Provide an `OrganizationContext` with `organization` + `member`.
Maintainer tip:
- When debugging a “why is this 403/401?”, start by checking the routes dependency stack (in the route module) and trace through the relevant dependency in `deps.py`.
## Logging: structure + request context
**Primary file:** `backend/app/core/logging.py`
Highlights:
- Defines a custom TRACE level (`TRACE_LEVEL = 5`).
- Uses `contextvars` to carry `request_id`, `method`, and `path` across async tasks.
- `AppLogFilter` injects `app`, `version`, and request context into each log record.
- Supports JSON output (`JsonFormatter`) and key=value (`KeyValueFormatter`) formats.
Where request context gets set:
- `backend/app/core/error_handling.py` middleware calls:
- `set_request_id(...)`
- `set_request_route_context(method, path)`
## Error envelope + request-id
**Primary file:** `backend/app/core/error_handling.py`
Key behaviors:
- Installs a `RequestIdMiddleware` (ASGI) that:
- Accepts client-provided `X-Request-Id` or generates one.
- Adds `X-Request-Id` to the response.
- Emits structured “http.request.*” logs, including “slow request” warnings.
- Error responses include `request_id` when available:
- Validation errors (`422`) return `{detail: <errors>, request_id: ...}`.
- Other HTTP errors are wrapped similarly.
Maintainer tip:
- When debugging incidents, ask for the `X-Request-Id` from the client and use it to locate backend logs quickly.

View File

@@ -1,38 +0,0 @@
# Mission Control docs
This folder is the canonical documentation set for Mission Control.
## Start here (by role)
- **Contributor**: start with [Quickstart](../README.md#quick-start-self-host-with-docker-compose) → [Development](development.md) → [Contributing](contributing.md)
- **Maintainer**: start with [Architecture](05-architecture.md) → [Repo tour](04-repo-tour.md) → [API reference](07-api-reference.md)
- **Operator/SRE**: start with [Ops / runbooks](09-ops-runbooks.md) → [Troubleshooting](10-troubleshooting.md)
## Table of contents (IA)
- [Style guide](00-style-guide.md)
1. [Overview](01-overview.md)
2. [Quickstart](02-quickstart.md)
3. [Development](03-development.md)
4. [Repo tour](04-repo-tour.md)
5. [Architecture](05-architecture.md)
6. [Configuration](06-configuration.md)
7. [API reference](07-api-reference.md)
- [Frontend API + auth modules](frontend-api-auth.md)
8. [Agents & skills](08-agents-and-skills.md)
9. [Ops / runbooks](09-ops-runbooks.md)
10. [Troubleshooting](10-troubleshooting.md)
11. [Contributing](11-contributing.md)
## Existing deep-dive docs
These deeper references already exist under `docs/` directories:
- [Architecture deep dive](architecture/README.md)
- [Deployment guide](deployment/README.md)
- [Production notes](production/README.md)
- [Testing guide](testing/README.md)
- [Troubleshooting](troubleshooting/README.md)
- [Gateway WebSocket protocol](openclaw_gateway_ws.md)
- [Gateway base config](openclaw_gateway_base_config.md)

View File

@@ -1,125 +0,0 @@
# Mission Control — Architecture
Mission Control is the **web UI + HTTP API** for operating OpenClaw. Its where you manage boards, tasks, agents, approvals, and (optionally) gateway connections.
> Auth note: Mission Control supports two auth modes: `local` (shared bearer token) and `clerk`.
At a high level:
- The **frontend** is a Next.js app used by humans.
- The **backend** is a FastAPI service that exposes REST endpoints under `/api/v1/*`.
- **Postgres** stores core state (boards/tasks/agents/etc.).
## Components
### Diagram (conceptual)
```mermaid
flowchart LR
U[User / Browser] -->|HTTP| FE[Next.js Frontend :3000]
FE -->|HTTP /api/v1/*| BE[FastAPI Backend :8000]
BE -->|SQL| PG[(Postgres :5432)]
BE -->|WebSocket (optional integration)| GW[OpenClaw Gateway]
GW --> OC[OpenClaw runtime]
```
### Frontend (Next.js)
- Location: `frontend/`
- Routes/pages: `frontend/src/app/*` (Next.js App Router)
- API utilities: `frontend/src/lib/*` and `frontend/src/api/*`
**Auth (`local` or Clerk)**
- `local` mode authenticates a shared bearer token (`LOCAL_AUTH_TOKEN`) and resolves a local user context.
- `clerk` mode verifies Clerk JWTs using `CLERK_SECRET_KEY`.
- Frontend mode switch + wrappers: `frontend/src/auth/clerk.tsx`, `frontend/src/auth/localAuth.ts`, and `frontend/src/components/providers/AuthProvider.tsx`.
- Backend mode switch: `backend/app/core/config.py` and `backend/app/core/auth.py`.
### Backend (FastAPI)
- Location: `backend/`
- App wiring: `backend/app/main.py`
- Health: `/health`, `/healthz`, `/readyz`
- API prefix: `/api/v1`
- Routers: `backend/app/api/*`
**Config**
- Settings: `backend/app/core/config.py`
- Env loading: always reads `backend/.env` (and optionally `.env`) so running from repo root still works.
### Data stores
- **Postgres**: persistence for boards/tasks/agents/approvals/etc.
- Models: `backend/app/models/*`
- Migrations: `backend/migrations/*`
### Gateway integration (optional)
Mission Control can call into an OpenClaw Gateway over WebSockets.
- Client + protocol: `backend/app/services/openclaw/gateway_rpc.py`
- Protocol doc: [Gateway WebSocket protocol](../openclaw_gateway_ws.md)
- Base gateway config (getting started): [Gateway base config](../openclaw_gateway_base_config.md)
## Request flows
### UI → API
1. Browser loads the Next.js frontend.
2. Frontend calls backend endpoints under `/api/v1/*`.
3. Backend reads/writes Postgres.
### Auth (`local` or Clerk)
- **Frontend**:
- `local`: token entry screen + session storage token (`frontend/src/components/organisms/LocalAuthLogin.tsx`, `frontend/src/auth/localAuth.ts`).
- `clerk`: Clerk wrappers/hooks (`frontend/src/auth/clerk.tsx`).
- **Backend**:
- `local`: validates `Authorization: Bearer <LOCAL_AUTH_TOKEN>`.
- `clerk`: validates Clerk request state with SDK + `CLERK_SECRET_KEY`.
### Agent access (X-Agent-Token)
Automation/agents can use the “agent” API surface:
- Endpoints under `/api/v1/agent/*` (router: `backend/app/api/agent.py`).
- Auth via `X-Agent-Token` (see `backend/app/core/agent_auth.py`, referenced from `backend/app/api/deps.py`).
### Background jobs
There is currently no queue runtime configured in this repo.
## Key directories
Repo root:
- `compose.yml` — local/self-host stack
- `.env.example` — compose/local defaults
- `backend/templates/` — shared templates
Backend:
- `backend/app/api/` — REST routers
- `backend/app/core/` — config/auth/logging/errors
- `backend/app/models/` — SQLModel models
- `backend/app/services/` — domain logic
- `backend/app/integrations/` — gateway client/protocol
Frontend:
- `frontend/src/app/` — Next.js routes
- `frontend/src/components/` — UI components
- `frontend/src/auth/` — auth mode helpers (`clerk` and `local`)
- `frontend/src/lib/` — utilities + API base
## Where to start reading code
Backend:
1. `backend/app/main.py` — app + routers
2. `backend/app/core/config.py` — env + defaults
3. `backend/app/core/auth.py` — auth behavior
4. `backend/app/api/tasks.py` and `backend/app/api/agent.py` — core flows
Frontend:
1. `frontend/src/app/*` — main UI routes
2. `frontend/src/lib/api-base.ts` — backend calls
3. `frontend/src/auth/*` — auth mode integration (`local` + Clerk)
## Related docs
- Self-host (Docker Compose): see repo root README: [Quick start (self-host with Docker Compose)](../../README.md#quick-start-self-host-with-docker-compose)
- Production-ish deployment: [Production notes](../production/README.md)
- Testing (Cypress/Clerk): [Testing guide](../testing/README.md)
- Troubleshooting: [Troubleshooting](../troubleshooting/README.md)
## Notes / gotchas
- Mermaid rendering depends on the markdown renderer.
- `NEXT_PUBLIC_API_URL` must be reachable from the browser (host), not just from within Docker.
- If Compose loads `frontend/.env.example` directly, placeholder Clerk keys can accidentally enable Clerk; prefer user-managed env files.

View File

@@ -1,47 +0,0 @@
# Coverage policy (CI gate)
## Why scoped coverage gates?
Today, overall repository coverage is low (especially for API routes and Next pages), but we still want CI to **enforce quality deterministically**.
So we start with a strict gate (100% statements + branches) on a **small, explicitly scoped** set of modules that are:
- unit-testable without external services
- stable and high-signal for regressions
We then expand the gated scope as we add tests.
## Backend scope (100% required)
Enforced in `Makefile` target `backend-coverage`:
- `app.core.error_handling`
- `app.services.mentions`
Command (CI):
```bash
cd backend && uv run pytest \
--cov=app.core.error_handling \
--cov=app.services.mentions \
--cov-branch \
--cov-report=term-missing \
--cov-report=xml:coverage.xml \
--cov-report=json:coverage.json \
--cov-fail-under=100
```
## Frontend scope (100% required)
Enforced in `frontend/vitest.config.ts` coverage settings:
- include: `src/lib/backoff.ts`
- thresholds: 100% for lines/statements/functions/branches
This is intentionally limited to a single pure utility module first. As we add more unit tests in `src/lib/**` and React Testing Library component tests for `src/app/**` + `src/components/**`, we should expand the include list and keep thresholds strict.
## How to expand the gate
- Add tests for the next-highest-signal modules.
- Add them to the gated scope (backend `--cov=` list; frontend `coverage.include`).
- Keep the threshold at 100% for anything included in the gate.

View File

@@ -1,215 +0,0 @@
# Deployment / Self-hosting (Docker Compose)
This guide covers how to self-host **OpenClaw Mission Control** using the repositorys `compose.yml`.
> Scope
> - This is a **dev-friendly self-host** setup intended for local or single-host deployments.
> - For production hardening (TLS, backups, external Postgres, observability), see **Production notes** below.
## What you get
When running Compose, you get:
- **Postgres** database (persistent volume)
- **Backend API** (FastAPI) on `http://localhost:${BACKEND_PORT:-8000}`
- Health check: `GET /healthz`
- **Frontend UI** (Next.js) on `http://localhost:${FRONTEND_PORT:-3000}`
Auth is configurable per deployment:
- `AUTH_MODE=local` (self-host default; shared bearer token)
- `AUTH_MODE=clerk` (Clerk JWT auth; backend requires `CLERK_SECRET_KEY`)
## Requirements
- Docker Engine
- Docker Compose **v2** (`docker compose ...`)
- Recommended: **4GB+ RAM** (frontend build can be memory/CPU intensive)
## Quick start (self-host)
From repo root:
```bash
cp .env.example .env
# REQUIRED for local mode:
# set LOCAL_AUTH_TOKEN in .env to a non-placeholder value with at least 50 characters.
docker compose -f compose.yml --env-file .env up -d --build
```
Check containers:
```bash
docker compose -f compose.yml ps
```
## Sanity checks
Backend health:
```bash
curl -f http://localhost:${BACKEND_PORT:-8000}/healthz
```
Frontend serving:
```bash
curl -I http://localhost:${FRONTEND_PORT:-3000}/
```
## Compose overview
### Services
`compose.yml` defines:
- `db` (Postgres 16)
- `backend` (FastAPI)
- `frontend` (Next.js)
### Ports
By default:
- Postgres: `5432` (`POSTGRES_PORT`)
- Backend: `8000` (`BACKEND_PORT`)
- Frontend: `3000` (`FRONTEND_PORT`)
Ports are sourced from `.env` (passed via `--env-file .env`) and wired into `compose.yml`.
### Volumes (data persistence)
Compose creates named volumes:
- `postgres_data` → Postgres data directory
These persist across `docker compose down`.
## Environment strategy
### Root `.env` (Compose)
- Copy the template: `cp .env.example .env`
- Edit values as needed (ports, auth mode, tokens, API URL, etc.)
Compose is invoked with:
```bash
docker compose -f compose.yml --env-file .env ...
```
### Backend env
The backend container loads `./backend/.env.example` via `env_file` and then overrides the DB URL for container networking.
If you need backend customization, prefer creating a real `backend/.env` and updating compose to use it (optional improvement).
### Frontend env
`compose.yml` intentionally **does not** load `frontend/.env.example` at runtime, because it may contain non-empty placeholders.
Instead, it supports an optional user-managed env file:
- `frontend/.env` (not committed)
If present, Compose will load it.
## Authentication modes
Mission Control supports two deployment auth modes:
- `AUTH_MODE=local`: shared bearer token auth (self-host default)
- `AUTH_MODE=clerk`: Clerk JWT auth
### Local mode (self-host default)
Set in `.env` (repo root):
```env
AUTH_MODE=local
LOCAL_AUTH_TOKEN=replace-with-random-token-at-least-50-characters
```
Set frontend mode (optional override in `frontend/.env`):
```env
NEXT_PUBLIC_AUTH_MODE=local
NEXT_PUBLIC_API_URL=http://localhost:8000
```
Users enter `LOCAL_AUTH_TOKEN` in the local login screen.
### Clerk mode
Set in `.env` (repo root):
```env
AUTH_MODE=clerk
```
Create `backend/.env` with at least:
```env
CLERK_SECRET_KEY=sk_test_your_real_key
CLERK_API_URL=https://api.clerk.com
CLERK_VERIFY_IAT=true
CLERK_LEEWAY=10.0
```
Create `frontend/.env` with at least:
```env
NEXT_PUBLIC_AUTH_MODE=clerk
NEXT_PUBLIC_API_URL=http://localhost:8000
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your_real_key
```
**Security:** treat `LOCAL_AUTH_TOKEN` and `CLERK_SECRET_KEY` like passwords. Do not commit them.
## Troubleshooting
### 1) Check container status
```bash
docker compose -f compose.yml ps
```
### 2) Tail logs
```bash
docker compose -f compose.yml --env-file .env logs -f --tail=200
```
### 3) Common issues
- **Docker permission denied** (`/var/run/docker.sock`)
- Ensure your user is in the `docker` group and your session picked it up (re-login), or use a root/sudo-capable host.
- **Frontend build fails because of missing `public/`**
- If the repo doesnt have `frontend/public`, the Dockerfile should not `COPY public/`.
- **Backend build fails looking for `uv.lock`**
- If backend build context is repo root, Dockerfile must copy `backend/uv.lock` not `uv.lock`.
## Reset / start fresh
Safe (keeps volumes/data):
```bash
docker compose -f compose.yml --env-file .env down
```
Destructive (removes volumes; deletes Postgres data):
```bash
docker compose -f compose.yml --env-file .env down -v
```
## Production notes (future)
If youre running this beyond local dev, consider:
- Run Postgres as a managed service (or on a separate host)
- Add TLS termination (reverse proxy)
- Configure backups for Postgres volume
- Set explicit resource limits and healthchecks
- Pin image versions/tags and consider multi-arch builds

View File

@@ -1,10 +0,0 @@
# E2E auth (Cypress)
Hard requirement: **no auth bypass** for Cypress E2E.
- Cypress tests must use real Clerk sign-in.
- CI should inject Clerk keys into the Cypress job environment.
Test account (non-secret):
- email: `jane+clerk_test@example.com`
- OTP: `424242`

View File

@@ -1,109 +0,0 @@
# Frontend API client and auth integration
This page documents the frontend integration points youll touch when changing how the UI talks to the backend or how auth is applied.
## Related docs
- [Architecture](05-architecture.md)
- [Configuration](06-configuration.md)
- [API reference](07-api-reference.md)
## API base URL
The frontend uses `NEXT_PUBLIC_API_URL` as the single source of truth for where to send API requests.
- Code: `frontend/src/lib/api-base.ts`
- Behavior:
- reads `process.env.NEXT_PUBLIC_API_URL`
- normalizes by trimming trailing slashes
- throws early if missing/invalid
In Docker Compose, `compose.yml` sets `NEXT_PUBLIC_API_URL` both:
- as a **build arg** (for `next build`), and
- as a **runtime env var**.
## API client layout
### Generated client
- Location: `frontend/src/api/generated/*`
- Generator: **Orval**
- Config: `frontend/orval.config.ts`
- Script: `cd frontend && npm run api:gen`
- Convenience target: `make api-gen`
By default, Orval reads the backend OpenAPI schema from:
- `ORVAL_INPUT` (if set), otherwise
- `http://127.0.0.1:8000/openapi.json`
Output details (from `orval.config.ts`):
- Mode: `tags-split`
- Target index: `frontend/src/api/generated/index.ts`
- Schemas: `frontend/src/api/generated/model`
- Client: `react-query`
- All requests go through the custom mutator below.
### Custom fetch / mutator
All generated requests go through:
- Code: `frontend/src/api/mutator.ts`
- What it does:
- resolves `NEXT_PUBLIC_API_URL` and builds the full request URL
- sets `Content-Type: application/json` when theres a body
- injects `Authorization: Bearer <token>` when a Clerk session token is available
- converts non-2xx responses into a typed `ApiError` (status + parsed response)
## Auth enablement and token injection
### Clerk enablement (publishable key gating)
Clerk is enabled in the frontend only when `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` looks valid.
- Gating helper (dependency-free): `frontend/src/auth/clerkKey.ts`
- UI-safe wrappers/hooks: `frontend/src/auth/clerk.tsx`
- provides `SignedIn`, `SignedOut`, `SignInButton`, `SignOutButton`, `useUser`, and `useAuth`
- returns safe fallbacks when Clerk is disabled (to allow secretless builds/prerender)
### Token injection
When the UI makes an API request, the mutator attempts to read a token from the Clerk session:
- Code: `frontend/src/api/mutator.ts` (`resolveClerkToken()`)
- If a token is available, the request includes:
- `Authorization: Bearer <token>`
### Route protection (middleware)
Request-time route protection is implemented via Next.js middleware:
- Code: `frontend/src/proxy.ts`
- Behavior:
- when Clerk is enabled: uses `clerkMiddleware()` to enforce auth on non-public routes
- when Clerk is disabled: passes all requests through
## Common workflows
### Update the backend API and regenerate the client
1. Run the backend so OpenAPI is available:
```bash
# from repo root
cp backend/.env.example backend/.env
make backend-migrate
cd backend && uv run uvicorn app.main:app --reload --port 8000
```
2. Regenerate the client:
```bash
# from repo root
make api-gen
# or from frontend/
ORVAL_INPUT=http://127.0.0.1:8000/openapi.json npm run api:gen
```
3. Review diffs under `frontend/src/api/generated/*`.

View File

@@ -1,167 +0,0 @@
# OpenClaw Gateway Base Config (Local)
This document explains a "base" OpenClaw Gateway config intended for local development and LAN use, and how to connect it to Mission Control.
Related:
- Gateway WebSocket protocol: [Gateway WebSocket protocol](openclaw_gateway_ws.md) (default URL `ws://127.0.0.1:18789`)
- Mission Control architecture (gateway integration): [Architecture deep dive](architecture/README.md)
## Who This Is For
Use this config if you want:
- A gateway listening locally (and optionally on your LAN)
- A predictable workspace location for agents/sessions
- A small, readable starting point you can extend
## Base Config (Template)
Start from this template and change the values in **Required edits**.
```json
{
"agents": {
"defaults": {
"model": {
"primary": "openai-codex/gpt-5.2"
},
"models": {
"openai-codex/gpt-5.2": {}
},
"workspace": "~/.openclaw/workspace",
"compaction": {
"mode": "safeguard"
},
"thinkingDefault": "minimal",
"maxConcurrent": 4,
"subagents": {
"maxConcurrent": 8
}
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "lan",
"controlUi": {
"allowInsecureAuth": true
},
"tailscale": {
"mode": "off",
"resetOnExit": false
},
"reload": {
"mode": "hot",
"debounceMs": 750
}
},
"memory": {
"backend": "qmd",
"citations": "auto",
"qmd": {
"includeDefaultMemory": true,
"update": {
"interval": "15m",
"debounceMs": 15000,
"onBoot": true
},
"limits": {
"maxResults": 6,
"maxSnippetChars": 900,
"maxInjectedChars": 4500,
"timeoutMs": 4000
}
}
},
"skills": {
"install": {
"nodeManager": "npm"
}
}
}
```
### Required Edits
1. `agents.defaults.workspace`
- Set a directory the gateway can read/write.
- Recommended default is `~/.openclaw/workspace` (Mission Control defaults the "workspace root" UI to `~/.openclaw`).
### Optional Edits (Common)
- `gateway.bind`
- `"lan"` is convenient for reaching the gateway from another machine on your network.
- If you want local-only access, configure your gateway to bind only to localhost/loopback (exact values depend on the gateway build) and/or firewall the port.
- `gateway.port`
- Change if `18789` is already in use.
- Mission Control requires the URL to include an explicit port (example: `ws://127.0.0.1:18789`).
- `agents.defaults.model.primary`
- Set your preferred default model identifier.
- `memory.qmd.limits`
- Tune memory query/injection sizes if you see timeouts or overly-large prompts.
## What Each Top-Level Section Does
### `agents.defaults`
Default runtime behavior for agents created/managed by the gateway:
- `model.primary`: default model identifier
- `models`: per-model overrides (empty means "use provider defaults")
- `workspace`: where agent state/files live on disk
- `compaction.mode: "safeguard"`: enables conservative compaction behavior
- `thinkingDefault: "minimal"`: default "thinking" level
- `maxConcurrent`: max concurrent top-level runs
- `subagents.maxConcurrent`: max concurrent subagent runs
### `gateway`
Network/runtime settings for the gateway service itself:
- `port`: TCP port for the WebSocket server (protocol doc defaults to `18789`)
- `mode: "local"`: local mode (vs remote-managed)
- `bind: "lan"`: binds in a way that's reachable from your LAN (treat as "network exposed")
- `controlUi.allowInsecureAuth: true`: convenience for local dev; do not use as-is for production
- `tailscale.mode: "off"`: disables Tailscale integration by default
- `reload.mode: "hot"` + `reload.debounceMs`: enables hot reload of config with a debounce window
### `memory`
Configures the gateway's memory subsystem.
- `backend: "qmd"`: use the QMD backend
- `citations: "auto"`: automatically include citations when supported
- `qmd.includeDefaultMemory`: includes default memory sources
- `qmd.update`: periodic update settings
- `qmd.limits`: bounds for query size/latency and injected context
### `skills.install.nodeManager`
Controls which Node package manager is used for skill installation.
- `"npm"` is the most compatible baseline.
## Connecting Mission Control To The Gateway
Mission Control connects over WebSockets and supports passing a token.
What Mission Control expects:
- Gateway URL must be `ws://...` or `wss://...` and must include an explicit port.
- Token is optional. Empty/whitespace tokens are treated as "no token" by the Mission Control API.
In the Mission Control UI:
1. Go to "Gateways" and add a new gateway.
2. Set URL to something like `ws://127.0.0.1:18789` (or your LAN host/IP + port).
3. If your gateway is configured to require a token, paste it here. Otherwise leave blank.
4. Use the "Check connection" action to confirm reachability.
Implementation note (how Mission Control sends tokens):
- If you provide a token, Mission Control's backend will include it when connecting to the gateway (it attaches it to the URL query string and also sends it in the `connect` params). See `backend/app/services/openclaw/gateway_rpc.py`.
### Workspace Root (Mission Control) vs Workspace (Gateway)
Mission Control stores a `workspace_root` value per gateway (configured in the UI). This is used when generating agent context/templates (for example, to compute a per-agent `workspace_path`). See `backend/app/services/openclaw/provisioning.py`.
The gateway config's `agents.defaults.workspace` is a separate setting that controls where the gateway runtime actually reads/writes agent state on disk.
For the smoothest onboarding, set these so the paths you show agents match what exists on the gateway host.
## Security Notes (Read This If You Expose The Gateway)
- Treat `gateway.bind: "lan"` as "this is reachable by other devices on your network".
- `controlUi.allowInsecureAuth: true` is for convenience in local dev. If you run this beyond your laptop, tighten this setting and prefer TLS (`wss://`) and network-level protections.

File diff suppressed because it is too large Load Diff

View File

@@ -1,209 +0,0 @@
# Production deployment (production-ish)
This document describes **production-ish** deployment patterns for **OpenClaw Mission Control**.
Mission Control is a web app (frontend) + API (backend) + Postgres. The simplest reliable
baseline is Docker Compose plus a reverse proxy with TLS.
> This repo currently ships a developer-friendly `compose.yml`. For real production, you should:
> - put Postgres on a managed service or dedicated host when possible
> - terminate TLS at a reverse proxy
> - set up backups + upgrades
> - restrict network exposure (firewall)
## Recommended baseline
If youre looking for the **dev-friendly self-host** path (single machine, Docker Compose defaults), start with the repo root README:
- [Quick start (self-host with Docker Compose)](../../README.md#quick-start-self-host-with-docker-compose)
- Docker Engine + Docker Compose v2
- Reverse proxy: **Caddy** (simplest) or **nginx**
- TLS via Lets Encrypt
- Persistent storage for Postgres
- Centralized logs (or at least log rotation)
## Single VPS (all-in-one)
### Architecture
On one VM:
- Caddy/nginx (ports 80/443) → routes traffic to:
- frontend container (internal port 3000)
- backend container (internal port 8000)
- Postgres container (internal 5432)
### Ports / firewall
Expose to the internet:
- `80/tcp` and `443/tcp` only
Do **not** expose:
- Postgres 5432
- backend 8000
- frontend 3000
All of those should be reachable only on the docker network / localhost.
### Environment & secrets
Recommended approach:
- Keep a host-level directory (e.g. `/opt/mission-control/`)
- Store runtime env in **non-committed** files:
- `/opt/mission-control/.env` (compose-level vars)
- optionally `/opt/mission-control/backend.env` and `/opt/mission-control/frontend.env`
Secrets guidelines:
- Choose auth mode explicitly:
- `AUTH_MODE=local`: set `LOCAL_AUTH_TOKEN` to a random value with at least 50 characters
- `AUTH_MODE=clerk`: configure Clerk keys
- Never commit `LOCAL_AUTH_TOKEN` or Clerk secret key.
- Prefer passing secrets as environment variables from the host (or use Docker secrets if you later
migrate to Swarm/K8s).
- Rotate secrets if they ever hit logs.
### Compose in production
Clone the repo on the VPS, then:
```bash
cd /opt
sudo git clone https://github.com/abhi1693/openclaw-mission-control.git mission-control
cd mission-control
cp .env.example .env
# edit .env with real values (domains, auth mode + secrets, etc.)
docker compose -f compose.yml --env-file .env up -d --build
```
### Reverse proxy (Caddy example)
Example `Caddyfile` (adjust domain):
```caddyfile
mission-control.example.com {
encode gzip
# Frontend
reverse_proxy /* localhost:3000
# (Optional) If you want to route API separately, use a path prefix:
# reverse_proxy /api/* localhost:8000
}
```
Notes:
- If the frontend calls the backend directly, ensure `NEXT_PUBLIC_API_URL` points to the **public, browser-reachable** API
URL, not `localhost`.
- Example: `NEXT_PUBLIC_API_URL=https://api.mission-control.example.com`
- If you route the backend under a path prefix, ensure backend routing supports it (or put it on a
subdomain like `api.mission-control.example.com`).
### Keep services running (systemd)
Docker restart policies are often enough, but for predictable boot/shutdown and easy ops, use
systemd.
Create `/etc/systemd/system/mission-control.service`:
```ini
[Unit]
Description=Mission Control (docker compose)
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mission-control
ExecStart=/usr/bin/docker compose -f compose.yml --env-file .env up -d
ExecStop=/usr/bin/docker compose -f compose.yml --env-file .env down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
```
Enable:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now mission-control
sudo systemctl status mission-control
```
### Backups
Minimum viable:
- Nightly `pg_dump` to off-host storage
- Or filesystem-level backup of the Postgres volume (requires consistent snapshots)
Example dump:
```bash
docker exec -t openclaw-mission-control-db-1 pg_dump -U postgres mission_control > /opt/backups/mission_control.sql
```
## Multi-VPS (split services)
The main reason to split is reliability and blast-radius reduction.
### Option A: 2 hosts
- Host 1: reverse proxy + frontend + backend
- Host 2: Postgres (or managed)
### Option B: 3 hosts
- Host 1: reverse proxy + frontend
- Host 2: backend
- Host 3: Postgres (or managed)
### Networking / security groups
Minimum rules:
- Public internet → reverse proxy host: `80/443`
- Reverse proxy host → backend host: `8000` (or whatever you publish internally)
- Backend host → DB host: `5432`
Everything else: deny.
### Configuration considerations
- `DATABASE_URL` must point to the DB host (not `localhost`).
- `CORS_ORIGINS` must include the public frontend URL.
- `NEXT_PUBLIC_API_URL` should be the public API base URL.
### Database migrations
The backend currently runs Alembic migrations on startup (see logs). In multi-host setups:
- Decide if migrations should run automatically (one backend instance) or via a manual deploy step.
- Avoid multiple concurrent backend deploys racing on migrations.
## Operational checklist
- [ ] TLS is enabled, HTTP redirects to HTTPS
- [ ] Only 80/443 exposed publicly
- [ ] Postgres not publicly accessible
- [ ] Backups tested (restore drill)
- [ ] Log retention/rotation configured
- [ ] Regular upgrade process (pull latest, rebuild, restart)
## Troubleshooting (production)
- `docker compose ps` and `docker compose logs --tail=200` are your first stops.
- If the UI loads but API calls fail, check:
- `NEXT_PUBLIC_API_URL`
- backend CORS settings (`CORS_ORIGINS`)
- firewall rules between proxy ↔ backend

View File

@@ -1,86 +0,0 @@
# Testing
This repo uses a mix of unit tests and Cypress end-to-end (E2E) tests.
## Cypress E2E: conventions (stories)
Write E2E tests as **user stories** describing what a user does (and does not do):
- Prefer descriptive spec names like:
- `As a signed-in user, I can view my activity feed (happy path)`
- `As a signed-out user, I get redirected to sign-in (negative path)`
- `As a user, invalid API URL shows an error state (negative path)`
- Include **both**:
- **Positive/happy path** (expected successful flow)
- **Negative paths** (missing inputs, unauthenticated access, invalid states)
Keep each spec focused on one story/flow; avoid long “mega specs”.
## Cypress E2E: Clerk auth (official implementation)
Hard requirements:
- **No auth bypass** in E2E.
- Use Clerks **official Cypress support** via `@clerk/testing`.
Implementation in this repo:
- `frontend/cypress.config.ts` calls `clerkSetup()`.
- `frontend/cypress/support/e2e.ts` imports and registers commands:
- `addClerkCommands({ Cypress, cy })`
- Tests can use:
- `cy.clerkLoaded()`
- `cy.clerkSignIn(...)` / `cy.clerkSignOut(...)`
See also: [E2E auth notes](../e2e-auth.md).
### Test user (non-secret)
- Email: `jane+clerk_test@example.com`
- OTP: `424242`
## Required environment variables
### Local E2E (running Cypress yourself)
You typically need:
- `NEXT_PUBLIC_API_URL` (required)
- Must be reachable from the **browser** (host), not just from inside Docker.
- Examples:
- Local backend: `http://localhost:8000`
- CI E2E job (frontend dev server): `http://localhost:3000` (see workflow)
- Clerk env (values should come from your Clerk app; **do not commit secrets**):
- `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` (required for the app)
- `CLERK_SECRET_KEY` (required for Clerk testing tokens)
- Cypress Clerk test user identifier (non-secret, repo default is OK):
- `CYPRESS_CLERK_TEST_EMAIL` (defaults to `jane+clerk_test@example.com` in CI)
Note: Cypress automatically maps `CYPRESS_FOO=bar` into `Cypress.env('FOO')`.
### CI artifacts on E2E failures (required)
For E2E failures, always upload Cypress artifacts so failures are debuggable from CI:
- `frontend/cypress/screenshots/**`
- `frontend/cypress/videos/**`
(Our GitHub Actions workflow already uploads these as an artifact for every E2E run.)
## Running Cypress locally
From repo root:
```bash
make frontend-sync
# in one terminal
cd frontend
npm run dev -- --hostname 0.0.0.0 --port 3000
# in another terminal
cd frontend
npm run e2e -- --browser chrome
```
If you hit Clerk-related bot detection or sign-in failures, re-check the Clerk testing env vars above.

View File

@@ -1,17 +0,0 @@
# Troubleshooting
## Activity feed is blank / frontend API calls fail
**Symptoms**
- Activity feed shows no items.
- The browser console/network tab shows failed requests to `/api/v1/*`.
**Cause**
- `NEXT_PUBLIC_API_URL` is missing/blank/incorrect. The frontend uses this variable to build API URLs.
**Fix**
- Local dev: set `NEXT_PUBLIC_API_URL=http://localhost:8000` in `frontend/.env.local`.
- Docker Compose (self-host): set `NEXT_PUBLIC_API_URL=http://localhost:8000` in the root `.env` used by compose (or update it to match your actual backend host/port).
Notes:
- `NEXT_PUBLIC_API_URL` must be reachable from the browser. If you're using Docker Compose, don't set it to an internal service name like `http://backend:8000` unless the browser can resolve it.