From b0622f5511641aa7c392be03c8738fee6d568286 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sun, 19 Apr 2026 22:31:03 +0000 Subject: [PATCH] docs(dev-env): rewrite DEV-ENV.md for host-agnostic setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous version was tightly coupled to the Hostinger VPS at 46.202.92.250 — hardcoded IP, Traefik/Let's-Encrypt assumption, specific Docker-volume paths. Rewriting ahead of the Proxmox migration so a fresh clone on any Linux host (LXC, VM, bare metal, VPS) can stand up a working dev environment without pre-baked assumptions about topology. Structural changes: - Introduces Option A (all-in-one host) / Option B (Docker Compose) / Option C (split services) topology choice up front, so readers commit to one shape before touching commands. - Adds a "per-host configuration" template the reader fills in once (DEV_HOST, POSTGRES_PORT, SECRET_KEY, API keys), referenced by name throughout the rest of the doc. No more hardcoded IPs. - Adds an explicit verification section (Section 6) with concrete expected outcomes: alembic head, reversibility, prompt-cache hit, frontend build, /assistant→/pilot redirect, dispatcher routing, CORS. - References the Phase 0 TODO(phase0-verify) in ai_provider.py and the expected alembic head (f07010f17b01) as of the current branch. - Adds a troubleshooting section pulling in CLAUDE.md lessons that bite people repeatedly: stale Vite env vars, RLS policy violations, EACCES on dist/, multi-head alembic state, invisible cache misses. - Documents the structured log events the backend emits (anthropic.cache, mcp.turn, mcp.fallback) so readers know what to grep for during verification. Deliberately excluded: - Production deployment (lives in CLAUDE.md Deployment section). - Reverse-proxy configuration (whatever the reader prefers). - code-server install specifics (Docker vs LXC vs native is reader's choice; once running, this doc applies). - Proxmox-specific instructions — the doc is host-agnostic so it survives the next migration as well. Co-Authored-By: Claude Opus 4.7 (1M context) --- DEV-ENV.md | 633 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 447 insertions(+), 186 deletions(-) diff --git a/DEV-ENV.md b/DEV-ENV.md index 67db033b..a957c9d6 100644 --- a/DEV-ENV.md +++ b/DEV-ENV.md @@ -1,262 +1,523 @@ -# ResolutionFlow Dev Environment Setup & Operations Guide +# ResolutionFlow — Dev Environment Setup & Operations Guide -## Server Overview +> **Scope:** Stand up a working ResolutionFlow dev environment from scratch on any Linux host (VPS, on-prem Proxmox LXC/VM, bare metal). Self-contained — do not read another doc to get the dev stack running. +> **Last rewritten:** April 2026, post-Hostinger-VPS deprecation, ahead of Proxmox migration. +> **Audience:** You (returning to the project), a teammate, or a fresh Claude Code session. -- **Provider:** Hostinger KVM VPS (srv1522117) -- **IP Address:** 46.202.92.250 -- **OS:** Ubuntu 24.04 LTS -- **CPU:** 2 vCPU cores -- **RAM:** 8GB -- **Disk:** 100GB NVMe SSD -- **Swap:** 4GB (`/swapfile`, swappiness=10) +If you're picking up mid-migration and need to know what code state is on the current branch, read `docs/FlowAssist_Migration/MIGRATION-HANDOFF.md` first. -## Architecture +--- -All services run as Docker containers on the host, managed via SSH or from the VS Code Server integrated terminal. +## 1. What this project needs, regardless of host -``` -Host (root@srv1522117) -├── Traefik → reverse proxy + auto SSL (Let's Encrypt) -├── VS Code Server → browser IDE at https://code.resolutionflow.com -└── ResolutionFlow Stack - ├── resolutionflow_frontend → Vite/React on port 5173 - ├── resolutionflow_backend → FastAPI/Uvicorn on port 8000 - └── resolutionflow_postgres → PostgreSQL 16 + pgvector on port 5432 -``` +These are non-negotiable. If your host can't provide them, fix that before anything else. -## Access URLs +| Component | Required version | Notes | +|---|---|---| +| **Linux** | any mainstream distro | Ubuntu 22.04+ / Debian 12+ tested; Alpine fine for containers | +| **Python** | 3.11+ | Backend and migrations | +| **Node.js** | 20.19+ | Vite 7 fails on older versions — CLAUDE.md Lesson 63 | +| **PostgreSQL** | 16 | `gen_random_uuid()` + `jsonb` + RLS are all leaned on | +| **Docker + Docker Compose** | recent | Only if you are running Postgres and/or backend as containers | +| **Git** | recent | | -| Service | URL | +Optional but recommended: + +| Tool | Why | |---|---| -| VS Code Server | https://code.resolutionflow.com | -| Frontend (dev) | http://46.202.92.250:5173 | -| Backend API | http://46.202.92.250:8000 | -| API Docs | http://46.202.92.250:8000/docs | +| **code-server** | Browser-based VS Code; how this project has historically been edited | +| **`gh` CLI** | Mirror repo is on GitHub via Gitea; `gh` reads issues and PRs | +| **bun** | Required for the gstack `/browse` + `/qa` skills (CLAUDE.md Lesson 82) | +| **`npx gitnexus analyze`** | Code-graph for Phase 2+ work that touches `unified_chat_service` | +| **Claude Code CLI** | If you want to run Claude Code locally on the host | -## Docker Layout +--- + +## 2. Architectural shape + +The project is three services plus your editor. Keep these facts in mind regardless of topology: ``` -/docker/ -├── traefik/ -│ ├── docker-compose.yml → Traefik reverse proxy -│ └── .env → ACME_EMAIL for Let's Encrypt -└── vscode/ - ├── docker-compose.yml → VS Code Server - └── .env → CODE_PASSWORD +Your browser + ├─► code-server (editor, optional — usually port 8080 or behind TLS) + ├─► frontend (Vite) (dev server, port 5173) + └─► backend (FastAPI) (dev server, port 8000) + │ + └─► PostgreSQL (port 5432) ``` -Project lives inside the VS Code Server Docker volume: +**The frontend calls the backend by URL at runtime.** The frontend does not proxy through the backend. Whatever URL your browser uses to reach the backend is what `VITE_API_URL` must be set to, **baked in at build time**. Changing `VITE_API_URL` requires rebuilding the frontend. + +**The backend calls the database by URL at runtime.** The URL depends on where Postgres is relative to the backend — Docker service name if both are in the same compose network, `localhost` if Postgres is native on the same host, or a DNS name if they're in separate containers/VMs. + +**CORS is configured explicitly.** The backend's `CORS_ORIGINS` list must include every origin your browser will use to reach the frontend. A missing origin shows up as failed preflight requests. + +--- + +## 3. Topology choices — pick one before you start + +The project is agnostic to topology, but each shape has different setup steps. + +### Option A — all-in-one LXC/VM/host (simplest) + +Postgres, backend, and frontend all run on one Linux host. code-server runs on the same host or a sibling. No Docker required. Best for a single-developer Proxmox LXC. + +### Option B — Docker Compose on one host + +Postgres, backend, and frontend run as Docker containers on one host. code-server runs outside the compose network (on the host or in another container). This is how the old Hostinger VPS was configured. Best if you want reproducible container images. + +### Option C — split services across containers/VMs + +Postgres in one container/VM, backend and frontend in another, code-server in a third. Most complex; requires explicit networking between them. Use only if you have a specific reason. + +**Pick one and stick with it for the entire setup.** Mixing Options A and B halfway through is where setup runs off the rails. + +--- + +## 4. Per-host configuration + +These values are specific to your host. Fill them in once and reference them by name throughout the rest of the doc. + ``` -/var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow/ +DEV_HOST = +DEV_HOST_SCHEME = +FRONTEND_PORT = 5173 +BACKEND_PORT = 8000 +POSTGRES_PORT = 5432 # or 5433 if you're avoiding conflict with a host Postgres +POSTGRES_DB_NAME = resolutionflow +POSTGRES_USER = postgres +POSTGRES_PASSWORD = +SECRET_KEY = +ANTHROPIC_API_KEY = +GOOGLE_AI_API_KEY = ``` -## VS Code Server +Store these somewhere you can copy from during setup. Do not commit them. -- **Container user:** `coder` (UID 1000) -- **Home directory:** `/home/coder` -- **Project location:** `/home/coder/resolutionflow` -- **Host volume path:** `/var/lib/docker/volumes/vscode_vscode-data/_data` -- **Access URL:** `https://code.resolutionflow.com` -- **HTTPS:** Auto-provisioned via Traefik + Let's Encrypt +> **Naming note:** the canonical database name is `resolutionflow`. If you see `patherly` in a config file, that's drift from an earlier rename and is being swept in a separate commit — use `resolutionflow`. CLAUDE.md tracks the live-code files that still reference `patherly`. -### Compose File Location -`/docker/vscode/docker-compose.yml` +--- -## Traefik +## 5. Setup procedure -Handles reverse proxying and automatic SSL for all services. HTTP automatically redirects to HTTPS. +Run these in order. Stop at the first failure and investigate. -### Adding A New Service Behind Traefik - -Add these labels to any new Docker service: - -```yaml -labels: - - "traefik.enable=true" - - "traefik.http.routers..rule=Host(`subdomain.resolutionflow.com`)" - - "traefik.http.routers..entrypoints=websecure" - - "traefik.http.routers..tls.certresolver=letsencrypt" - - "traefik.http.services..loadbalancer.server.port=" -``` - -Also create an A record in DNS pointing the subdomain to `46.202.92.250`. - -## ResolutionFlow Dev Stack - -### Important: No Docker Inside VS Code Container - -The VS Code Server container does NOT have Docker. All `docker compose` commands must be run via SSH as root on the host. - -### Environment Files - -| File | Purpose | -|---|---| -| `.env` | Root — Docker Compose interpolation (`SECRET_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_AI_API_KEY`, `POSTGRES_PORT`) | -| `backend/.env` | Backend source of truth — all FastAPI settings, API keys, DB URLs, CORS | -| `frontend/.env` | Frontend — `VITE_API_URL` pointing to backend | - -### Critical Remote Access Config - -**`frontend/.env`:** -``` -VITE_API_URL=http://46.202.92.250:8000 -``` - -**`backend/.env`:** -``` -CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","http://127.0.0.1:3000","http://127.0.0.1:5173","http://46.202.92.250:5173","http://46.202.92.250:3000","https://resolutionflow.com","https://www.resolutionflow.com"] -FRONTEND_URL=http://46.202.92.250:5173 -DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/resolutionflow -DATABASE_URL_SYNC=postgresql://postgres:postgres@db:5432/resolutionflow -``` - -Note: `DATABASE_URL` uses `@db:5432` (Docker service name), not `@localhost`. - -**`docker-compose.dev.yml`:** -```yaml -- VITE_API_URL=http://46.202.92.250:8000 -``` - -### Starting the Dev Environment - -SSH into host as root: +### 5.1 Install system dependencies ```bash -cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow -docker compose -f docker-compose.dev.yml up -d +# Ubuntu / Debian +sudo apt update && sudo apt install -y \ + git curl build-essential \ + python3.11 python3.11-venv python3-pip \ + postgresql-client # not the server — only if running Postgres natively + +# Node 20 via nvm (survives container rebuilds if stored in a volume) +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +export NVM_DIR="$HOME/.nvm" && source "$NVM_DIR/nvm.sh" +nvm install 20 +nvm alias default 20 ``` -### Running Migrations (Fresh Database) +For Option B (Docker Compose), also: ```bash -cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow +curl -fsSL https://get.docker.com | sh +sudo usermod -aG docker $USER # log out and back in for this to take effect +``` + +### 5.2 Clone the repo + +```bash +git clone https://gitea.resolutionflow.com/chihlasm/resolutionflow.git +# or the GitHub mirror: +# git clone https://github.com/chihlasm/resolutionflow.git +cd resolutionflow + +# Check out the working branch if you're continuing mid-migration. +git fetch origin +git checkout feat/flowpilot-migration +``` + +### 5.3 Start PostgreSQL + +**Option A (native Postgres on the host):** + +```bash +sudo apt install -y postgresql-16 +sudo -u postgres psql -c "CREATE DATABASE resolutionflow;" +sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" +# Adjust pg_hba.conf if you need non-local connections. +``` + +**Option B (Postgres via Docker Compose):** The repo has a `docker-compose.dev.yml` at the root. Check its Postgres service for the container name, port mapping, and volume. CLAUDE.md Lesson 65 notes the local compose defaults use container name `resolutionflow_postgres`, database `resolutionflow`, port `5433` mapped to the host. Confirm what the compose file actually says on your branch before trusting those values. + +```bash +docker compose -f docker-compose.dev.yml up -d db +docker compose -f docker-compose.dev.yml logs db # wait for "ready to accept connections" +``` + +**Verify:** + +```bash +# From the host (Option A) or the backend container/LXC (Option B): +psql -h -p -U postgres -d resolutionflow -c "SELECT now();" +``` + +### 5.4 Write the `.env` files + +The repo expects three env files. Create each one: + +**`backend/.env`** — backend source of truth: + +```bash +APP_NAME=ResolutionFlow +DEBUG=true + +# DB URLs — `` is `localhost` for Option A, the Docker service name +# (e.g. `db`) for Option B, or the DB container/VM hostname for Option C. +DATABASE_URL=postgresql+asyncpg://postgres:postgres@:/resolutionflow +DATABASE_URL_SYNC=postgresql://postgres:postgres@:/resolutionflow + +# Auth +SECRET_KEY= +ACCESS_TOKEN_EXPIRE_MINUTES=5 +REFRESH_TOKEN_EXPIRE_DAYS=7 +REQUIRE_INVITE_CODE=true + +# AI providers +AI_PROVIDER=anthropic +ANTHROPIC_API_KEY= +GOOGLE_AI_API_KEY= + +# FlowPilot MCP telemetry — leave on so the Phase 0.5 baseline data keeps accruing +ENABLE_MCP_MICROSOFT_LEARN=true + +# CORS + frontend URL +FRONTEND_URL=://: +CORS_ORIGINS=["http://localhost:5173","http://127.0.0.1:5173","://:"] +``` + +**`frontend/.env.local`** — frontend build-time config: + +```bash +VITE_API_URL=://: +``` + +Optional PostHog (CLAUDE.md Lesson 64 — enables product analytics locally): + +```bash +VITE_PUBLIC_POSTHOG_KEY= +VITE_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com +``` + +**Repo root `.env`** — only needed for Option B (Docker Compose interpolation): + +```bash +SECRET_KEY= +ANTHROPIC_API_KEY= +GOOGLE_AI_API_KEY= +POSTGRES_PORT= +``` + +> **Never commit any `.env` file.** The `.gitignore` already covers this. + +### 5.5 Run the backend setup + +**Option A (native):** + +```bash +cd backend +python3.11 -m venv venv +source venv/bin/activate +pip install -r requirements.txt + +# Migrate the DB to head. +alembic upgrade head +``` + +**Option B (Docker):** + +```bash +docker compose -f docker-compose.dev.yml up -d backend docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head ``` -### Seeding Test Users +**Expected alembic head** (as of `feat/flowpilot-migration`): `f07010f17b01`. If `alembic current` shows anything else after `upgrade head`, something has gone wrong — stop and investigate. + +### 5.6 Seed test users ```bash +# Option A +cd backend && source venv/bin/activate +python -m scripts.seed_test_users + +# Option B docker exec resolutionflow_backend python -m scripts.seed_test_users ``` -Test accounts (password: `TestPass123!`): +Test users (all share password `TestPass123!`): -| Email | Role | Plan | -|---|---|---| -| admin@resolutionflow.example.com | Owner | Team | -| pro@resolutionflow.example.com | Owner | Pro | -| teamadmin@resolutionflow.example.com | Owner | Team | -| engineer@resolutionflow.example.com | Engineer | Shared | +| Email | Role | +|---|---| +| `admin@resolutionflow.example.com` | super admin | +| `teamadmin@resolutionflow.example.com` | team admin | +| `engineer@resolutionflow.example.com` | engineer | +| `pro@resolutionflow.example.com` | solo pro | -### Rebuilding After Config Changes +### 5.7 Run the backend + +**Option A:** + +```bash +cd backend && source venv/bin/activate +uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload +``` + +**Option B:** Already running from `docker compose up -d backend`. Tail logs: + +```bash +docker compose -f docker-compose.dev.yml logs -f backend +``` + +**Verify:** `curl ://:/api/docs` — OpenAPI docs page loads. + +### 5.8 Run the frontend + +**Option A:** + +```bash +cd frontend +npm install +npm run dev -- --host 0.0.0.0 --port 5173 +``` + +**Option B:** -**Frontend** (Vite bakes env vars at build time — requires rebuild): ```bash -cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow docker compose -f docker-compose.dev.yml up -d --build frontend ``` -**Backend** (restart only): +**Verify:** Open `://:` in your browser. Log in with one of the test users. Navigate to `/pilot` — the FlowPilot session page should render. + +--- + +## 6. Verification — proof the env actually works + +Run these after setup. Every item has a concrete expected outcome. + +### 6.1 Database schema is at the right version + ```bash +# Option A +cd backend && source venv/bin/activate && alembic current +# Option B +docker compose -f docker-compose.dev.yml run --rm backend alembic current +``` + +Expected: `f07010f17b01 (head)` on the `feat/flowpilot-migration` branch. On `main`, expected: `074 (head)`. + +### 6.2 Alembic reversibility + +```bash +alembic downgrade -1 # should complete cleanly +alembic upgrade head # should return to f07010f17b01 +``` + +If either step fails, the migration has a bug and Phase 2 cannot start. + +### 6.3 Prompt-cache hit verification (the deferred Phase 0 TODO) + +`backend/app/core/ai_provider.py` module docstring has a `TODO(phase0-verify)` note describing this. Procedure: + +1. Confirm `AI_PROVIDER=anthropic` and `ANTHROPIC_API_KEY` is set in `backend/.env`. +2. Start the backend with log level INFO or lower. +3. In the UI, open `/pilot` and send a chat message. Wait a few seconds for the response. +4. Send a second chat message in the same session, within 5 minutes of the first. +5. In backend logs, grep for lines containing `anthropic.cache`: + + ```bash + # Option A + grep 'anthropic.cache' + # Option B + docker compose -f docker-compose.dev.yml logs backend | grep 'anthropic.cache' + ``` + +6. Expected: two `anthropic.cache` log events. First has `cache_creation_input_tokens > 0`. Second has `cache_read_input_tokens > 0`. +7. If the second shows zero reads, inspect the prompt prefix for silent invalidators (timestamps, unsorted JSON keys, varying tool list ordering). Fix before proceeding with any Phase 2 work. + +### 6.4 Frontend build is TypeScript-clean + +```bash +cd frontend +npx tsc -b # no errors +npm run build # no errors +``` + +CLAUDE.md Lesson 105 notes that `npm run build` may fail with an `EACCES` on `dist/` inside code-server — that is a Docker filesystem permission issue, not a real build error. Use `npx tsc -b` to verify TypeScript cleanliness in that case. + +### 6.5 `/assistant` → `/pilot` redirect + +Open `://:/assistant/` in the browser. Expected: URL changes to `/pilot/`; the FlowPilot session page renders. Bare `/assistant` redirects to bare `/pilot`. + +### 6.6 Dispatcher de-branching + +Navigate to the dashboard. Click a session in `ActiveFlowPilotSessions` or `RecentFlowPilotSessions`. Expected: routes to `/pilot/:id` regardless of the session's `session_type` value. (Check the browser URL bar.) + +### 6.7 CORS + +Open the browser DevTools Network tab, navigate to any backend-hitting page. Expected: no CORS errors. If you see "blocked by CORS policy," the missing origin needs adding to `backend/.env`'s `CORS_ORIGINS`. + +--- + +## 7. Runbook + +Day-to-day commands after setup is complete. + +### Restart services + +```bash +# Option A +# backend — Ctrl-C and re-run uvicorn +# frontend — Ctrl-C and re-run npm run dev + +# Option B docker compose -f docker-compose.dev.yml restart backend +docker compose -f docker-compose.dev.yml up -d --build frontend # rebuild required if VITE_* changed +docker compose -f docker-compose.dev.yml down && docker compose -f docker-compose.dev.yml up -d # full restart ``` -**Full restart:** -```bash -docker compose -f docker-compose.dev.yml down -docker compose -f docker-compose.dev.yml up -d -``` - -## Installed Tools (Inside VS Code Server Container) - -Installed in `/home/coder` — persists via Docker volume: - -- **nvm** — Node version manager -- **Node.js 20.x** — via nvm, default alias set -- **npm** — latest -- **GitHub CLI (gh)** — authenticated via personal access token -- **Claude Code CLI** — `@anthropic-ai/claude-code` (global npm) - -### Permanent Tool Installs - -Tools installed via `apt` inside the container do NOT survive container rebuilds. To add permanently, modify the VS Code Server Docker image and rebuild. - -Temporary (session only): -```bash -sudo apt update && sudo apt install -y -``` - -## SSH Access +### Apply a new migration ```bash -ssh root@46.202.92.250 +# Option A +cd backend && source venv/bin/activate && alembic upgrade head +# Option B +docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head ``` -Key auth configured via `~/.ssh/authorized_keys` on host. +### Create a new migration -## Useful Commands - -### Check all running containers ```bash -docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" +# Option A +cd backend && source venv/bin/activate +alembic revision -m "short description" # manual, preferred per CLAUDE.md Lesson 77 +# OR +alembic revision --autogenerate -m "description" # pulls in drift; review carefully ``` -### View container logs +Never pass `--rev-id` — let Alembic generate the hex hash. + +### Inspect the database + ```bash -docker logs --tail 30 -f +# Option A (native Postgres) +psql -h localhost -p 5432 -U postgres -d resolutionflow + +# Option B (Docker) +docker exec -it resolutionflow_postgres psql -U postgres -d resolutionflow ``` -### Restart VS Code Server +### Run tests + ```bash -cd /docker/vscode && docker compose restart +# Option A +cd backend && source venv/bin/activate +pytest --override-ini="addopts=" + +# Option B +docker compose -f docker-compose.dev.yml run --rm backend pytest --override-ini="addopts=" ``` -### Restart Traefik +First time only, create the test database: + ```bash -cd /docker/traefik && docker compose restart +# Option A +sudo -u postgres psql -c "CREATE DATABASE resolutionflow_test;" + +# Option B +docker exec -it resolutionflow_postgres psql -U postgres -c "CREATE DATABASE resolutionflow_test;" ``` -### Restart dev stack +### View backend logs + ```bash -cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow -docker compose -f docker-compose.dev.yml down -docker compose -f docker-compose.dev.yml up -d +# Option A: wherever you ran uvicorn +# Option B +docker compose -f docker-compose.dev.yml logs -f --tail=100 backend ``` -### Check swap +Structured events to grep for: +- `anthropic.cache` — prompt-cache hit/creation telemetry (Phase 0.1) +- `mcp.turn` — per-turn MCP availability/invocation (Phase 0.5) +- `mcp.fallback` — MCP silent-retry fallback fired (Phase 0.5) + +--- + +## 8. Troubleshooting + +### CORS errors in the browser + +The backend did not accept the origin your browser used. Check `backend/.env`'s `CORS_ORIGINS` — it must include the exact scheme + host + port the browser sent. Restart the backend after editing. + +### `VITE_API_URL` points at the wrong place + +The frontend was built with a stale value. Rebuild the frontend. Option B: `docker compose up -d --build frontend`. Option A: restart `npm run dev`. + +### `alembic upgrade head` fails with "target database is not up to date" + +Your DB migration chain is out of sync with the code. On a dev box, the safe recovery is to drop the DB and re-migrate from scratch: + ```bash -free -h && swapon --show +# Option A +sudo -u postgres psql -c "DROP DATABASE resolutionflow;" -c "CREATE DATABASE resolutionflow;" +cd backend && source venv/bin/activate && alembic upgrade head + +# Option B +docker exec resolutionflow_postgres psql -U postgres -c "DROP DATABASE resolutionflow;" -c "CREATE DATABASE resolutionflow;" +docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head ``` -### Check disk -```bash -df -h -``` +Only do this on a dev box — it destroys all local data. -### Check memory + container usage -```bash -free -h && docker stats --no-stream -``` +### `alembic heads` shows more than one head -## DNS Records (resolutionflow.com) +Only on a local branch that has diverged from `origin/main`. Production `main` has a single head. If this happens on a fresh clone, one of your local migration files has the wrong `down_revision`. Inspect each file's `down_revision` and reconnect the chain. -| Type | Name | Value | Purpose | -|---|---|---|---| -| A | code | 46.202.92.250 | VS Code Server | +### Frontend build fails with "EACCES: permission denied" on `dist/` -## Security Notes +Filesystem permission issue inside the code-server container (CLAUDE.md Lesson 105). TypeScript compilation itself completes — use `npx tsc -b` to verify cleanliness without needing to write to `dist/`. -- UFW is inactive — Traefik and Docker manage port exposure -- All public-facing services run through Traefik with valid HTTPS certs -- PostgreSQL port 5432 is exposed on all interfaces — restrict if needed in production -- Rotate API keys (Anthropic, Voyage) if ever exposed in logs or chat -- Never commit `.env` files to Git +### `docker` command not found inside code-server -## VS Code Server Browser Tips +If your code-server is itself inside a container, Docker is probably not exposed to it. CLAUDE.md Lesson 103 was written for this case on the old VPS. On Proxmox, the fix depends on topology — either SSH to the host to run Docker commands, or mount the host's Docker socket into the code-server container. -- **Command Palette:** `F1` -- **Terminal:** Ctrl+` -- **Rename file:** `F2` -- **Go to definition:** `F12` -- **Find references:** `Shift+F12` -- **Context Menu:** `Alt + Right Click` \ No newline at end of file +### Backend returns 500 with `InsufficientPrivilegeError: new row violates row-level security policy` + +RLS is enabled on a table your code wrote to without the right `account_id`. CLAUDE.md Lessons 107, 108, 110 cover this family of bugs. The fix is always at the service layer: make sure every model creation passes `account_id=` explicitly, and that startup routines that touch tenant-isolated tables use `_admin_session_factory()` rather than `get_db()`. + +### Anthropic cache reads are zero on the second turn + +Something in the cached prefix is changing between turns. Inspect the system-block list and the first N history messages for timestamps, `datetime.now()`, unsorted dict keys in JSON prompts, or varying tool-list order. The `anthropic.cache` telemetry shows exactly how many tokens were read vs created — use it to narrow down the invalidator. + +--- + +## 9. Security posture for dev environments + +This doc is about dev, not production. But: + +- Never commit `.env` files. The `.gitignore` covers this. +- `SECRET_KEY` should be generated per-host, not reused across environments. +- `ANTHROPIC_API_KEY` is billable — rotate if leaked into logs or chat. +- Postgres on a dev host should not be exposed to the internet. Bind it to `127.0.0.1` or to a private network interface only. +- If you expose the frontend or backend publicly (for teammates to test against), put it behind TLS with a real certificate. Do not let dev credentials travel over plain HTTP on the public internet. + +--- + +## 10. What's not in this doc + +- **Production deployment.** This is a dev-env doc. Production lives on Railway — see `CLAUDE.md`'s Deployment section. +- **How to set up Traefik or any particular reverse proxy.** Whichever proxy you use is your choice; the dev stack just needs something that routes `:5173` and `:8000` to the right services. +- **How to configure code-server itself.** Install it however you prefer (native, Docker, LXC); point it at the repo, and the rest of this doc applies. +- **Where to host the Proxmox instance.** Up to you. + +If something in this doc turns out to be wrong on your host, fix the doc. This is a living document — the whole point of rewriting it from the Hostinger-specific version was to make it survive host changes.