> ## Documentation Index
> Fetch the complete documentation index at: https://rapidreview.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Operations

> Day-two tasks for a self-hosted brain: readiness sweeps, cleanup, the client version floor, backups, and moving the database.

## Readiness sweep

After a deploy or restart:

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
RP_DOCTOR_BEARER_TOKEN=mk_… python3 deploy/doctor.py --control-url http://127.0.0.1:8787
```

## Cleanup

The sandbox expiry reaper runs inside control and reconciles active rows on restart. Broader cleanup is **not** scheduled — call it from a trusted cron or sidecar:

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
curl -X POST -H "X-Admin-Token: $MERV_ADMIN_TOKEN" https://your-brain.example.com/api/admin/cleanup
```

Unset `MERV_ADMIN_TOKEN` denies every caller.

It handles registered stale sandbox state, blob TTLs, storage leases, and stale provisioning records. It does not discover or terminate provider VMs that have no ledger row.

## Client version floor

Clients send `X-RP-Client-Version`; anything below the floor published by `/api/meta` (`min_proxy_version`) gets HTTP **426**. The check runs before auth so stale clients see "upgrade", not "login".

## Logs

HTTP request logs go to stdout. Diagnostic activity and tool-call rings are process-local and bounded — they reset on restart.

## Backups

Scheduled logical backups (`pg_dump`) plus tested restores. A Docker named-volume snapshot alone is not a backup policy. On hosted Supabase, verify the data project's backup/PITR plan.

## Move the database

Changing overlays changes where new writes go; it does not copy data. Controlled cutover:

1. Create the empty target and run its bootstrap; don't start Merv against it yet.
2. Run the preflight; take a target baseline backup; verify the source's latest backup restores.
3. Stop all source writers, then export with a matching-or-newer `pg_dump`:
   ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
   pg_dump --dbname="$MERV_SOURCE_DB_URL" --format=custom --no-owner --no-acl --file=merv-cutover.dump
   ```
4. Restore as `merv_app`:
   ```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
   pg_restore --dbname="$MERV_TARGET_DB_URL" --no-owner --no-acl --single-transaction merv-cutover.dump
   ```
5. Point one control replica at the target and start it (migrations apply under the advisory lock). Compare table counts and the max `schema_migrations.version`; then start the rest.
6. Keep the source read-only and the dump through the rollback window. Rollback = stop target writers, restore the original DSN. Don't merge divergent writes.

## Security boundary, restated

Plain HTTP on 8787 behind your TLS proxy; open stacks (`MERV_REQUIRE_AUTH=0`) only on a trusted operator network; `/api/admin/*` network-restricted; UI deployed separately with explicit CORS origins. Byte transfers — artifact, storage, feed uploads, sandbox output pulls — run agent-side over presigned or token URLs, so the brain never serves live checkout files.
