# Runbook: Sofiia Control Console

**Service:** sofiia-console (NODA2 primary)  
**Port:** 8002  
**UI:** http://localhost:8002/

---

## 1. Endpoints

| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/` | — | Console UI (Chat + Ops + Nodes) |
| GET | `/api/health` | — | Aggregated health (first node router) |
| POST | `/api/chat/send` | X-API-Key* | Proxy to router `/v1/agents/sofiia/infer` |
| GET | `/api/ops/actions` | — | List ops action ids |
| POST | `/api/ops/run` | X-API-Key* | Run risk_dashboard / pressure_dashboard / backlog_generate_weekly / release_check |
| GET | `/api/nodes/dashboard` | — | Per-node router health from `config/nodes_registry.yml` |

\* If `SOFIIA_CONSOLE_API_KEY` is set, write endpoints require header `X-API-Key: <key>`.

---

## 2. Environment variables

| Variable | Description | Default |
|----------|-------------|---------|
| `ROUTER_URL` | Default router for health/chat when node not specified | `http://localhost:9102` |
| `CONFIG_DIR` | Directory containing `nodes_registry.yml` (Docker: `/app/config`) | repo `config/` |
| `NODES_<ID>_ROUTER_URL` | Override router URL per node (e.g. `NODES_NODA1_ROUTER_URL`) | from registry |
| `SUPERVISOR_API_KEY` | Sent to router on tool/infer calls (optional) | — |
| `SOFIIA_CONSOLE_API_KEY` | Protects POST /api/chat/send and /api/ops/run | — (no auth if unset) |

---

## 3. Deploy (Docker, NODA2)

```bash
cd /path/to/microdao-daarion
docker compose -f docker-compose.node2-sofiia.yml up -d sofiia-console
```

Ensure `config/nodes_registry.yml` exists and lists `NODA1` / `NODA2` with correct `router_url`.  
Open http://localhost:8002/

---

## 4. Run locally (no Docker)

```bash
cd services/sofiia-console
pip install -r requirements.txt
export ROUTER_URL=http://localhost:8000   # or 9102
uvicorn app.main:app --host 0.0.0.0 --port 8002
```

Then open http://localhost:8002/

---

## 5. API key rotation (NODA2)

Rotate both `SOFIIA_CONSOLE_API_KEY` and `SUPERVISOR_API_KEY` to one new value:

```bash
cd /Users/apple/github-projects/microdao-daarion
NEW_KEY="$(openssl rand -hex 24)"
sed -i '' "s/^SOFIIA_CONSOLE_API_KEY=.*/SOFIIA_CONSOLE_API_KEY=${NEW_KEY}/" .env
sed -i '' "s/^SUPERVISOR_API_KEY=.*/SUPERVISOR_API_KEY=${NEW_KEY}/" .env
docker compose -f docker-compose.node2-sofiia.yml up -d sofiia-console router
```

Quick check in container env:

```bash
docker exec sofiia-console sh -lc 'env | grep -E "^(ENV|SOFIIA_CONSOLE_API_KEY|SUPERVISOR_API_KEY)="'
```

---

## 6. Ops API examples (with key)

```bash
KEY="<SOFIIA_CONSOLE_API_KEY>"
```

```bash
curl -sS -X POST http://localhost:8002/api/ops/run \
  -H "X-API-Key: ${KEY}" -H "Content-Type: application/json" \
  -d '{"action_id":"risk_dashboard","node_id":"NODA2","params":{}}' | jq .
```

```bash
curl -sS -X POST http://localhost:8002/api/ops/run \
  -H "X-API-Key: ${KEY}" -H "Content-Type: application/json" \
  -d '{"action_id":"pressure_dashboard","node_id":"NODA2","params":{}}' | jq .
```

```bash
curl -sS -X POST http://localhost:8002/api/ops/run \
  -H "X-API-Key: ${KEY}" -H "Content-Type: application/json" \
  -d '{"action_id":"release_check","node_id":"NODA2","params":{}}' | jq .
```

---

## 7. Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| Chat "Помилка мережі" | Router unreachable | Check ROUTER_URL and router container |
| Ops run returns 502 | Router or tool error | Check router logs; verify RBAC for agent `sofiia` |
| Nodes dashboard empty | No nodes in registry or CONFIG_DIR wrong | Check `config/nodes_registry.yml` and CONFIG_DIR mount |
| 401 on POST /api/chat/send | API key required but missing/wrong | Set X-API-Key header to SOFIIA_CONSOLE_API_KEY or leave SOFIIA_CONSOLE_API_KEY unset |

---

## 8. Verification

After deploy, run stack verifier (from repo root):

```bash
export ROUTER_URL=http://localhost:8000   # or router:8000 inside Docker network
python3 ops/scripts/verify_sofiia_stack.py
```

See `docs/opencode/sofiia_setup.md` for OpenCode integration and tool contract.
