docs(platform): add policy configs, runbooks, ops scripts and platform documentation

Config policies (16 files): alert_routing, architecture_pressure, backlog,
cost_weights, data_governance, incident_escalation, incident_intelligence,
network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix,
release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout

Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard,
deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice,
cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule),
task_registry, voice alerts/ha/latency/policy

Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks,
NODA1/NODA2 status and setup, audit index and traces, backlog, incident,
supervisor, tools, voice, opencode, release, risk, aistalk, spacebot

Made-with: Cursor
This commit is contained in:
Apple
2026-03-03 07:14:53 -08:00
parent 129e4ea1fc
commit 67225a39fa
102 changed files with 20060 additions and 0 deletions

View File

@@ -0,0 +1,477 @@
# Sofiia CTO Agent — Gaps & Recovery Plan (E)
> Generated: 2026-02-26 | P0 = блокуюче | P1 = критичне для vNext | P2 = покращення
---
## Критичне резюме
**Що вже готово і може йти в UI:** Chat, Voice, Projects CRUD, File upload, Sessions, Dialog Map tree, Ops actions, Node health.
**Що не готово і блокує vNext:** Tasks/Kanban, Meetings, Dialog Map canvas + Postgres schema, Doc versions, CTO Repo/Ops flow, Supervisor через BFF, Semantic search.
---
## Таблиця прогалин з пріоритетами
| # | Gap | Пріоритет | Складність | Блокує |
|---|-----|-----------|-----------|--------|
| G1 | `dialog_nodes`/`dialog_edges` Postgres tables + API | P0 | Medium | Dialog Map vNext |
| G2 | `tasks` table + CRUD API + Kanban UI | P0 | Medium | Projects Board |
| G3 | `meetings` table + CRUD API | P0 | Medium | Projects Meetings tab |
| G4 | Supervisor не проксюється через BFF | P0 | Low | CTO workflow access |
| G5 | `docs_versions` table + API | P1 | Low | Doc history/rollback |
| G6 | `entity_links` table + API | P1 | Low | Cross-entity linking |
| G7 | `repo_changesets` + `repo_patches` + PR flow | P1 | High | CTO code workflow |
| G8 | `ops_runs` job system (not one-shot) | P1 | Medium | CTO ops audit trail |
| G9 | Semantic search (Qdrant/Meilisearch) | P1 | Medium | Doc/Project search |
| G10 | NATS `attachment.created` on upload | P1 | Low | Parser pipeline hook |
| G11 | `DELETE` endpoints (projects/docs) | P1 | Low | CRUD completeness |
| G12 | Real-time WS events for map/tasks | P1 | Medium | Live UI updates |
| G13 | E2EE / confidential mode | P2 | Very High | Privacy |
| G14 | 2-step Plan → Apply for dangerous actions | P2 | High | Safe ops flow |
| G15 | `agent_id="l"` vs `"sofiia"` inconsistency | P1 | Low | Config correctness |
| G16 | `dialog_views` saved views | P2 | Low | UX |
| G17 | NODA3 integration | P2 | Medium | AI/ML workstation |
| G18 | Meilisearch deployment | P2 | Low | Full-text search |
| G19 | Privacy Gate middleware (Router) | P2 | High | Confidential mode |
| G20 | Wiki Markdown editor UI | P2 | Medium | Docs/Wiki experience |
| G21 | `doc_index_state` table + reindex jobs | P2 | Low | AI doc indexing |
| G22 | Meeting reminders (push/WS) | P2 | Medium | Meetings UX |
| G23 | `DELETE /api/nodes/{id}` | P2 | Low | Node management |
| G24 | S3/MinIO для file storage | P2 | High | Scale (replace volume) |
---
## P0 — Блокуючі прогалини (потрібні для vNext)
### G1: Dialog Map — Postgres schema + API
**Що зроблено:** SQLite tree via `parent_msg_id`. Works for conversation branching.
**Чого не вистачає:**
- Postgres tables: `dialog_nodes`, `dialog_edges`, `dialog_views`
- API: `GET /api/projects/{id}/dialog-map`, `POST /api/links`
- WS event: `dialog_map.updated`
- Auto-edge creation from NATS events
**Recovery plan:**
```sql
-- Step 1: Add to sofiia-console db.py (SQLite first, Postgres later)
CREATE TABLE IF NOT EXISTS dialog_nodes (
node_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
node_type TEXT NOT NULL CHECK(node_type IN ('message','task','doc','meeting','agent_run','decision','goal')),
ref_id TEXT NOT NULL, -- FK to actual entity
title TEXT DEFAULT '',
created_at TEXT NOT NULL,
created_by TEXT DEFAULT 'system'
);
CREATE TABLE IF NOT EXISTS dialog_edges (
edge_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
from_node_id TEXT NOT NULL REFERENCES dialog_nodes(node_id),
to_node_id TEXT NOT NULL REFERENCES dialog_nodes(node_id),
edge_type TEXT NOT NULL CHECK(edge_type IN ('references','resolves','derives_task','updates_doc','schedules','summarizes')),
created_at TEXT NOT NULL,
props TEXT DEFAULT '{}' -- JSON
);
CREATE TABLE IF NOT EXISTS dialog_views (
view_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
name TEXT NOT NULL,
filters TEXT DEFAULT '{}',
layout TEXT DEFAULT '{}'
);
```
```python
# Step 2: New endpoint in docs_router.py
@router.get("/api/projects/{project_id}/dialog-map")
async def get_project_dialog_map(project_id: str):
nodes = await db.get_dialog_nodes(project_id)
edges = await db.get_dialog_edges(project_id)
return {"nodes": nodes, "edges": edges}
@router.post("/api/links")
async def create_link(body: LinkCreate):
# Creates dialog_edge between two entities
...
```
**Оцінка:** 46 годин роботи.
---
### G2: Tasks + Kanban
**Що зроблено:** Немає.
**Recovery plan:**
```sql
CREATE TABLE IF NOT EXISTS tasks (
task_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL REFERENCES projects(project_id),
title TEXT NOT NULL,
description TEXT DEFAULT '',
status TEXT DEFAULT 'backlog' CHECK(status IN ('backlog','in_progress','review','done')),
priority TEXT DEFAULT 'medium',
assignee_id TEXT DEFAULT '',
labels TEXT DEFAULT '[]', -- JSON
due_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
msg_id TEXT -- Optional: link to originating message
);
```
- API: `GET/POST /api/projects/{id}/tasks`, `PATCH /api/tasks/{id}`, `DELETE /api/tasks/{id}`
- UI: Kanban board з drag-drop (можна почати з простим list + status buttons)
- Dialog Map auto-edge: `POST /api/links` after task creation
**Оцінка:** 12 дні (backend + basic UI).
---
### G3: Meetings
**Recovery plan:**
```sql
CREATE TABLE IF NOT EXISTS meetings (
meeting_id TEXT PRIMARY KEY,
project_id TEXT NOT NULL REFERENCES projects(project_id),
title TEXT NOT NULL,
starts_at TEXT NOT NULL,
duration_min INTEGER DEFAULT 60,
attendees TEXT DEFAULT '[]', -- JSON
location TEXT DEFAULT '',
agenda TEXT DEFAULT '',
created_at TEXT NOT NULL
);
```
- API: `GET/POST /api/projects/{id}/meetings`, `PATCH /api/meetings/{id}`
- UI: simple form (title, date/time, duration, attendees)
- Reminders: Phase 2 (WS push)
**Оцінка:** 1 день.
---
### G4: Supervisor → BFF proxy
**Що зроблено:** Supervisor API exists at `http://sofiia-supervisor:8080` (або port 9400).
**Recovery plan:**
```python
# Add to services/sofiia-console/app/main.py:
SUPERVISOR_URL = os.getenv("SUPERVISOR_URL", "http://sofiia-supervisor:8080")
@app.post("/api/supervisor/runs")
async def run_supervisor_graph(body: dict, _auth: str = Depends(require_auth)):
async with httpx.AsyncClient() as c:
resp = await c.post(f"{SUPERVISOR_URL}/v1/graphs/{body['graph']}/runs",
json=body, timeout=60)
return resp.json()
@app.get("/api/supervisor/runs/{run_id}")
async def get_supervisor_run(run_id: str, _auth: str = Depends(require_auth)):
async with httpx.AsyncClient() as c:
resp = await c.get(f"{SUPERVISOR_URL}/v1/runs/{run_id}", timeout=10)
return resp.json()
```
**Оцінка:** 30 хвилин.
---
## P1 — Критичні для vNext
### G5: Doc versions
```sql
CREATE TABLE IF NOT EXISTS doc_versions (
version_id TEXT PRIMARY KEY,
doc_id TEXT NOT NULL REFERENCES documents(doc_id),
content TEXT NOT NULL, -- full text
author_id TEXT DEFAULT 'system',
created_at TEXT NOT NULL
);
```
```python
# New endpoints in docs_router.py:
# GET /api/projects/{pid}/documents/{did}/versions
# POST /api/projects/{pid}/documents/{did}/restore
```
**Оцінка:** 2 години.
---
### G7: Repo Changesets (CTO Code Flow)
Це найскладніша частина. **Рекомендація:** почати з mock endpoints, потім реалізувати реальну логіку.
**Mock endpoint (30 хв):**
```python
@app.post("/api/repo/changesets")
async def create_changeset_mock(body: dict, _auth=Depends(require_auth)):
# Mock: store in SQLite, return changeset_id
cs_id = str(uuid.uuid4())
# await db.save_changeset(cs_id, body)
return {"changeset_id": cs_id, "status": "draft", "mock": True}
```
**Реальна реалізація (23 дні):**
```sql
CREATE TABLE repo_changesets (
cs_id TEXT PRIMARY KEY,
project_id TEXT,
repo TEXT NOT NULL, -- e.g., "github.com/IvanTytar/microdao-daarion"
base_ref TEXT NOT NULL, -- branch/commit
intent TEXT NOT NULL,
risk_level TEXT DEFAULT 'low',
status TEXT DEFAULT 'draft',
created_by TEXT,
created_at TEXT NOT NULL
);
CREATE TABLE repo_patches (
patch_id TEXT PRIMARY KEY,
cs_id TEXT NOT NULL REFERENCES repo_changesets(cs_id),
file_path TEXT NOT NULL,
patch_text TEXT NOT NULL, -- unified diff
created_at TEXT NOT NULL
);
CREATE TABLE pull_requests (
pr_id TEXT PRIMARY KEY,
cs_id TEXT NOT NULL REFERENCES repo_changesets(cs_id),
provider TEXT DEFAULT 'github', -- github/gitlab/gitea
pr_url TEXT,
pr_number INTEGER,
status TEXT DEFAULT 'draft',
created_at TEXT NOT NULL
);
```
---
### G8: Ops Runs (Job System)
Поточний `/api/ops/run` — one-shot dispatch. Потрібен job tracking.
```sql
CREATE TABLE ops_runs (
run_id TEXT PRIMARY KEY,
project_id TEXT,
node_id TEXT NOT NULL, -- noda1/noda2
action TEXT NOT NULL, -- з allowlist
params TEXT DEFAULT '{}', -- JSON
dry_run INTEGER DEFAULT 1,
status TEXT DEFAULT 'pending', -- pending/running/success/failed
result TEXT DEFAULT '',
started_at TEXT,
finished_at TEXT,
created_by TEXT
);
```
**API:**
- `POST /api/ops/runs` (створити job, dry_run=true за замовч.)
- `GET /api/ops/runs/{id}` (статус)
- `GET /api/ops/runs?project_id=&limit=20` (список)
**Оцінка:** 4 години (backend) + 2 год (UI list).
---
### G10: NATS attachment.created
Одна зміна в `docs_router.py`:
```python
# After successful file save:
try:
import nats
nc = await nats.connect(NATS_URL)
await nc.publish(f"attachment.created.{mime_category}",
json.dumps({"file_id": file_id, "doc_id": doc_id, ...}).encode())
await nc.close()
except Exception:
pass # best-effort
```
**Оцінка:** 1 година.
---
### G15: agent_id "l" vs "sofiia"
У `services/router/router-config.yml` для NODA2:
```yaml
# Check if there's "l:" entry that should be "sofiia:"
```
**Action:** знайти і замінити `"l"``"sofiia"` у router-config відповідної ноди.
**Оцінка:** 15 хвилин.
---
## P2 — Покращення
### G13: E2EE (confidential mode)
**Складність:** Дуже висока. Потребує:
1. Client-side key generation (WebCrypto API)
2. Server-side: store only ciphertext + key_id
3. Router Privacy Gate middleware
4. Dialog Map: тільки user-created edges (не semantic auto-edges)
5. Search: тільки metadata, не plaintext
**Рекомендація:** Не реалізовувати до завершення Projects + Dialog Map. Спочатку `mode=public` тільки.
---
### G20: Wiki Markdown Editor
Потрібна бібліотека (CodeMirror / Monaco / Tiptap). Для Phase 1 — textarea з preview.
```html
<!-- Simple Phase 1 wiki editor -->
<div id="wikiEditor">
<textarea id="wikiContent" placeholder="# Сторінка wiki..."></textarea>
<div id="wikiPreview" class="markdown-preview"></div>
</div>
```
---
## Quick Wins (до 2 годин кожен)
| # | Quick Win | Час | Цінність |
|---|-----------|-----|---------|
| QW1 | `DELETE /api/projects/{id}` | 15 хв | CRUD completeness |
| QW2 | `DELETE /api/projects/{id}/documents/{did}` | 15 хв | CRUD completeness |
| QW3 | BFF proxy до Supervisor (G4) | 30 хв | CTO workflow access |
| QW4 | Mock `/api/repo/changesets` | 30 хв | UI CTO panel development |
| QW5 | Mock `/api/ops/runs` | 30 хв | UI CTO panel development |
| QW6 | `docs_versions` table + API (G5) | 2 год | Doc history |
| QW7 | `USE_EMBEDDINGS=true` + Qdrant ingest | 1 год | Semantic search |
| QW8 | `agent_id "l"``"sofiia"` fix | 15 хв | Config consistency |
| QW9 | NATS `attachment.created` on upload | 1 год | Parser pipeline |
| QW10 | WS `dialog_map.updated` basic event | 1 год | Live map refresh |
---
## Повний план відновлення (поетапно)
### Тиждень 1: Stabilize & Quick Wins
```
Day 12:
- QW1, QW2, QW3, QW8 (CRUD + Supervisor proxy + agent_id fix)
- Деплой на NODA2, verify через http://localhost:8002
Day 34:
- G2: tasks table + basic API + simple list UI
- G3: meetings table + basic form UI
Day 5:
- G5: docs_versions + API
- G10: NATS attachment.created
- QW4, QW5: mock changeset/ops_run endpoints for UI
```
### Тиждень 2: Dialog Map + CTO Panel
```
Day 12:
- G1: dialog_nodes/edges tables + API
- WS event: dialog_map.updated
Day 34:
- UI: Dialog Map canvas (D3 tree → force graph)
- Entity links UI (drag edge between nodes)
Day 5:
- G8: ops_runs job system
- UI: CTO Ops panel (list + status)
```
### Тиждень 3: Advanced Features
```
- G7: Repo changesets (real implementation)
- G9: USE_EMBEDDINGS=true + semantic search
- G12: Full real-time WS events (tasks, docs, meetings)
- Kanban drag-drop UI
- Doc versions diff viewer
```
### Тиждень 4+: Scale & Polish
```
- G14: 2-step Plan → Apply
- G20: Wiki Markdown editor
- G22: Meeting reminders
- G24: S3/MinIO for file storage
- G13: E2EE (only when everything else is stable)
```
---
## 5 Найбільш Критичних Прогалин
1. **`dialog_nodes/edges` + project-level Dialog Map API** — без цього vNext граф неможливий
2. **Tasks/Kanban** — Projects без задач = тільки файлосховище
3. **Meetings** — Projects без зустрічей = неповний workflow
4. **Supervisor не проксюється через BFF** — CTO не може запускати LangGraph runs з UI
5. **Repo changesets / CTO code flow** — Sofiia не може "пропонувати PR" як structured artifact
---
## 5 Найбільш Готових Частин для UI
1. **Chat + Voice** — повністю готово, production-grade (Phase 2 streaming, HA, SLO, alerts)
2. **Projects + Documents + File Upload** — CRUD, search, sessions — все є
3. **Dialog Map tree**`GET /api/sessions/{id}/map` повертає nodes/edges
4. **Ops Actions** — risk/pressure/backlog/notion/release — все є через `/api/ops/run`
5. **Node Health Dashboard** — multi-node, SSH, WebSocket realtime — все є
---
## 3 Рекомендації "Зробити Негайно"
### 1. Зберегти контекст у Dialog Map
Найпростіший спосіб не "загубити" поточний дизайн — додати `dialog_nodes/edges` tables у `db.py` прямо зараз (схема вже описана вище). Навіть якщо UI ще не готовий, дані почнуть накопичуватись від поточних повідомлень.
### 2. Proxy Supervisor через BFF
30 хвилин роботи, але це дасть Sofiia доступ до `alert_triage`, `incident_triage`, `postmortem_draft`, `release_check` прямо з UI Console — не тільки через Telegram.
### 3. Нормалізувати `agent_id`
Знайти і виправити `"l"``"sofiia"` у конфігурації NODA2. Це унеможливить silent routing failures де Router не знаходить агента і тихо fallbacks до дефолту.
---
## Next Actions for UI Team (12 days)
1. **Розгорнути і протестувати** поточний стек на NODA2 — `http://localhost:8002/` вже повністю робочий
2. **Реалізувати QW1QW5** (прості DELETE + Supervisor proxy + mock endpoints) — 23 год
3. **Додати `tasks` і `meetings` tables** у `db.py` та відповідні endpoints у `docs_router.py`
4. **Додати `dialog_nodes/edges`** у `db.py` (DDL вище) і endpoint `GET /api/projects/{id}/dialog-map`
5. **Тестувати** через `tests/test_sofiia_docs.py` — всі 28 тестів мають пройти
6. **Оновити** `docker-compose.node2-sofiia.yml` з `SUPERVISOR_URL` env var
7. **Перевірити** що `ops/voice_ha_smoke.sh` проходить після деплою
8. **Прочитати** `docs/architecture_inventory/` (7 файлів) для повного контексту поточного стеку
9. **Використовувати** `ops/fabric_preflight.sh` перед кожним деплоєм (preflight-first policy)
10. **Щотижня**: запускати `ops/fabric_snapshot.py --save` і commit результат — щоб мати baseline для drift detection

View File

@@ -0,0 +1,216 @@
# Sofiia CTO Agent — Audit Index (A)
> Generated: 2026-02-26 | Scope: Full repository scan | Author: Cursor Auditor
---
## 1. Canonical Files (Топ-10 "Sources of Truth")
| # | File | Тип | Статус | Короткий опис |
|---|------|-----|--------|---------------|
| 1 | `AGENTS.md` | Identity/Capabilities | ✅ Актуальний | Головний identity файл Sofiia. CTO-агент, 3 ноди, всі можливості, toolchain |
| 2 | `config/agent_registry.yml` | Config Registry | ✅ Актуальний | Single Source of Truth для конфігурації. Sofiia entry ~рядки 12761330 |
| 3 | `services/sofiia-console/app/main.py` | BFF Implementation | ✅ Актуальний | FastAPI BFF v0.3.0. Всі endpoint-и Control Console |
| 4 | `services/sofiia-console/static/index.html` | UI | ✅ Актуальний | 1600+ рядків SPA. Чат, Projects, Ops, Hub, Nodes, Memory |
| 5 | `docs/ADR_ARCHITECTURE_VNEXT.md` | Architecture ADR | ✅ Актуальний (2026-01-19) | Control Plane + Data Plane архітектура, Privacy Gate, NATS standards |
| 6 | `services/router/router-config.yml` | Router Config | ✅ Актуальний | LLM profiles, voice policies, agent routing |
| 7 | `config/rbac_tools_matrix.yml` | Security | ✅ Актуальний | `agent_cto` роль з 39 дозволами |
| 8 | `docs/OPENAPI_CONTRACTS.md` | API Contracts | ✅ Актуальний | Gateway→Router, Router→Memory контракти |
| 9 | `docs/architecture_inventory/` | Inventory (7 файлів) | ✅ Актуальний (2026-02-16) | Повний каталог сервісів, інструментів, NATS, безпека |
| 10 | `gateway-bot/sofiia_prompt.txt` | System Prompt | ✅ Актуальний | 138KB+ Telegram-промпт Sofiia як Chief AI Architect |
---
## 2. Повна Карта Файлів
### 2.1 Identity та промпти
| Файл | Опис | Розмір | Стан |
|------|------|--------|------|
| `AGENTS.md` | Sofiia identity: CTO-агент, NODA1/NODA2/NODA3, інструменти, стиль | ~400 рядків | ✅ Канонічний |
| `gateway-bot/sofiia_prompt.txt` | Telegram system prompt (великий, детальний) | ~138KB | ✅ Production |
| `services/sofiia-console/app/main.py` lines 138177 | Console embedded system prompt (BFF) | ~1KB | ✅ Production |
| `docs/consolidation/_node1_runtime_docs/gateway-bot/sofiia_prompt.txt` | Копія промпту (NODA1 backup) | ~138KB | ⚠️ Backup copy |
### 2.2 Core Implementation — sofiia-console
| Файл | Опис | Рядків |
|------|------|--------|
| `services/sofiia-console/app/main.py` | BFF FastAPI: всі endpoints, voice, telemetry, degradation SM | ~1800 |
| `services/sofiia-console/app/docs_router.py` | Projects/Documents/Sessions/Dialog Map router | ~380 |
| `services/sofiia-console/app/db.py` | SQLite async CRUD: projects, documents, sessions, messages, dialog map | ~320 |
| `services/sofiia-console/app/auth.py` | API key authentication | ~50 |
| `services/sofiia-console/app/config.py` | Node registry, URLs, feature flags | ~100 |
| `services/sofiia-console/app/monitor.py` | Multi-node health polling | ~150 |
| `services/sofiia-console/app/nodes.py` | Nodes dashboard | ~80 |
| `services/sofiia-console/app/ops.py` | Ops actions dispatcher | ~200 |
| `services/sofiia-console/app/router_client.py` | Proxy до Router (infer, tools, health) | ~100 |
| `services/sofiia-console/app/voice_utils.py` | Voice sanitize, chunk split, think-block clean | ~150 |
| `services/sofiia-console/app/adapters/aistalk.py` | AISTALK adapter | ~80 |
| `services/sofiia-console/static/index.html` | SPA UI: chat, projects, ops, hub, nodes, memory | ~1600 |
| `services/sofiia-console/requirements.txt` | aiosqlite, pypdf, python-docx, fastapi, httpx | 10 рядків |
| `services/sofiia-console/Dockerfile` | Docker build | ~25 |
### 2.3 Sofiia Supervisor (LangGraph)
| Файл | Опис |
|------|------|
| `services/sofiia-supervisor/app/main.py` | FastAPI: `/v1/graphs/{name}/runs` API |
| `services/sofiia-supervisor/app/graphs/alert_triage_graph.py` | Alert triage LangGraph |
| `services/sofiia-supervisor/app/graphs/incident_triage_graph.py` | Incident triage LangGraph |
| `services/sofiia-supervisor/app/graphs/postmortem_draft_graph.py` | Postmortem LangGraph |
| `services/sofiia-supervisor/app/graphs/release_check_graph.py` | Release check LangGraph |
| `services/sofiia-supervisor/app/alert_routing.py` | Routing policy matcher |
| `services/sofiia-supervisor/app/gateway_client.py` | RBAC-enforced gateway client |
| `services/sofiia-supervisor/app/models.py` | Pydantic models |
| `services/sofiia-supervisor/app/state_backend.py` | Redis/in-memory state |
| `docker-compose.node2-sofiia-supervisor.yml` | Supervisor Docker Compose |
| `services/sofiia-supervisor/tests/` | 6 test files |
### 2.4 Router та Tools
| Файл | Опис |
|------|------|
| `services/router/main.py` | Main router: всі API endpoints, voice HA, capabilities |
| `services/router/tool_manager.py` | 20+ інструментів: CRUD, exec, governance |
| `services/router/agent_tools_config.py` | Per-agent tool allowlists |
| `services/router/router-config.yml` | LLM profiles, voice policies, agent routing |
| `services/router/fabric_metrics.py` | Prometheus metrics |
| `services/router/offload_client.py` | NATS offload client |
| `services/router/risk_engine.py` | Risk assessment engine |
| `services/router/backlog_generator.py` | Backlog generation |
| `services/router/incident_intelligence.py` | Incident correlation |
| `services/router/cost_analyzer.py` | Cost analysis tool |
| `services/router/data_governance.py` | Data governance |
| `services/router/dependency_scanner.py` | Dependency scanner |
| `services/router/drift_analyzer.py` | Infrastructure drift |
| `services/router/architecture_pressure.py` | Architecture pressure analysis |
### 2.5 Memory Service
| Файл | Опис |
|------|------|
| `services/memory-service/app/main.py` | FastAPI: threads, events, memories, facts, agent memory |
| `services/memory-service/app/vector_store.py` | Qdrant integration |
| `services/memory-service/app/voice_endpoints.py` | STT/TTS endpoints з Prometheus metrics |
| `services/memory-service/app/integration_endpoints.py` | Integration webhooks |
| `services/memory-service/app/integrations.py` | External integrations |
### 2.6 Configuration
| Файл | Опис |
|------|------|
| `config/agent_registry.yml` | Всі 13+ агентів + sofiia entry |
| `config/rbac_tools_matrix.yml` | RBAC ролі: `agent_cto` (39 permissions) |
| `config/slo_policy.yml` | SLO для voice fast/quality profiles |
| `config/risk_policy.yml` | Risk scoring policy |
| `config/release_gate_policy.yml` | Release gate rules |
| `config/incident_escalation_policy.yml` | Escalation policy |
| `config/alert_routing_policy.yml` | Alert routing |
| `config/observability_sources.yml` | Prometheus/Loki/Tempo sources |
| `config/tool_limits.yml` | Tool rate limits |
| `config/tools_rollout.yml` | Tools rollout configuration |
| `config/cost_weights.yml` | Cost scoring weights |
| `config/network_allowlist.yml` | Network access allowlist |
| `config/nodes_registry.yml` | NODA1/NODA2 node registry |
| `config/data_governance_policy.yml` | Data governance policy |
| `config/backlog_policy.yml` | Backlog generation policy |
| `services/router/router-config.yml` | Voice profiles, agent routing |
### 2.7 Docker Compose (NODA2 Sofiia Stack)
| Файл | Опис |
|------|------|
| `docker-compose.node2-sofiia.yml` | Main: sofiia-console + router + node-worker + memory + qdrant |
| `docker-compose.node2-sofiia-supervisor.yml` | Sofiia Supervisor + Redis |
| `docker-compose.memory-node2.yml` | Memory stack: Postgres + Qdrant + Neo4j + Memory Service |
| `docker-compose.node2.yml` | Full NODA2 stack |
### 2.8 Документація (docs/)
| Файл/Dir | Опис | Стан |
|----------|------|------|
| `docs/ADR_ARCHITECTURE_VNEXT.md` | Основний ADR: vNext архітектура | ✅ |
| `docs/OPENAPI_CONTRACTS.md` | API контракти Gateway↔Router↔Memory | ✅ |
| `docs/ARCHITECTURE_DIAGRAM.md` | Діаграма архітектури | ✅ |
| `docs/architecture_inventory/` | 7 файлів: exec summary, service catalog, tool catalog, dataflows, security, observability, open questions | ✅ 2026-02-16 |
| `docs/fabric_contract.md` | Fabric multi-node contract, Voice HA | ✅ |
| `docs/sofiia_ui_vnext_audit.md` | vNext UI audit | ✅ |
| `docs/supervisor/langgraph_supervisor.md` | Supervisor архітектура | ✅ |
| `docs/supervisor/postmortem_draft_graph.md` | Postmortem граф | ✅ |
| `docs/runbook/sofiia-control-plane.md` | Operations runbook | ✅ |
| `docs/NODA1-NODA2-STATUS.md` | Статус нод | ✅ |
| `docs/MULTINODE_ARCHITECTURE.md` | Multi-node архітектура | ✅ |
| `docs/NATS_SUBJECTS.md` | NATS subject map | ✅ |
| `docs/voice_phase2_cutover.md` | Voice Phase 2 cutover plan | ✅ |
| `docs/voice_streaming_phase2.md` | Voice Phase 2 spec | ✅ |
| `docs/PRIVACY_GATE.md` | Privacy gate policy | ✅ |
| `docs/DATA_RETENTION_POLICY.md` | Data retention | ✅ |
| `docs/MEMORY_API_POLICY.md` | Memory API policy | ✅ |
| `docs/AGENT_RUNTIME_POLICY.md` | Agent runtime policy | ✅ |
| `docs/SECURITY_HARDENING_SUMMARY.md` | Security hardening | ✅ |
| `docs/backlog/backlog.md` | Поточний беклог | ✅ |
| `docs/incident/` | Incident tracking docs | ✅ |
| `docs/risk/risk_index.md` | Risk index | ✅ |
### 2.9 Тести
| Файл | Що тестує |
|------|-----------|
| `tests/test_voice_ha.py` | Voice HA: 35 tests |
| `tests/test_voice_policy.py` | Voice routing policy: 23 tests |
| `tests/test_voice_stream.py` | Voice Phase 2 streaming: 22 tests |
| `tests/test_sofiia_docs.py` | Projects/Documents/Sessions/Dialog Map: 28 tests |
| `tests/test_tool_governance.py` | Tool RBAC (agent_cto role) |
| `tests/test_risk_attribution.py` | Risk engine |
| `tests/test_drift_analyzer.py` | Drift analyzer |
| `tests/test_cost_analyzer.py` | Cost analyzer |
| `tests/test_incident_escalation.py` | Escalation |
| `tests/test_backlog_*.py` | Backlog generation/store |
| `services/sofiia-supervisor/tests/` | 6 supervisor graph tests |
### 2.10 Ops Scripts
| Файл | Опис |
|------|------|
| `ops/fabric_preflight.sh` | Preflight checks: models, canary, voice |
| `ops/voice_ha_smoke.sh` | Voice HA acceptance smoke test |
| `ops/voice_latency_audit.sh` | Multi-scenario latency audit |
| `ops/voice_policy_update.py` | Auto-update voice policy від audit results |
| `ops/scripts/voice_canary.py` | Voice health canary (preflight + runtime) |
| `ops/runbook-voice-incidents.md` | Voice incident runbook |
| `ops/runbook-sofiia-docs.md` | Projects/Docs runbook |
| `ops/grafana_voice_dashboard.json` | Grafana dashboard |
| `ops/voice_alerts.yml` | Prometheus alerting rules |
---
## 3. Відсутні файли (NOT FOUND — очікувались)
| Очікуваний файл | Чому очікувався | Статус |
|-----------------|-----------------|--------|
| `services/projects-service/` | ADR_ARCHITECTURE_VNEXT згадує окремий projects-service | ❌ НЕ ЗНАЙДЕНО |
| `services/docs-service/` | ADR згадує окремий docs-service з версіями | ❌ НЕ ЗНАЙДЕНО |
| `services/dialogmap-service/` | vNext design, описаний у chat | ❌ НЕ ЗНАЙДЕНО |
| `services/ingest-service/` | ADR 2.2 Ingest Service | ❌ НЕ ЗНАЙДЕНО (тільки stub reference) |
| `openapi.yml` / `swagger.yml` | Формальна OpenAPI специфікація | ❌ НЕ ЗНАЙДЕНО |
| `migrations/` (Postgres DDL для sofiia) | Versioned DB migrations | ⚠️ Є `migrations/046, 049, 052` для memory-service, але не для sofiia-console |
| `docs/audit/` (5 аудит-файлів) | Запит цього сеансу | ✅ Створюються зараз |
| `docs_versions` table | vNext DDL план | ❌ НЕ РЕАЛІЗОВАНО |
| `dialog_nodes` / `dialog_edges` tables (Postgres) | vNext Dialog Map | ⚠️ SQLite-тільки, tree-based |
| `entity_links` / `repo_changesets` / `ops_runs` | CTO DDL заготовки | ❌ НЕ ЗНАЙДЕНО |
---
## Next Actions for UI Team (12 days)
1. **Ознайомитись з `docs/architecture_inventory/` (7 файлів)** — там повний каталог поточного стеку
2. **Перевірити `services/sofiia-console/app/docs_router.py`** — Projects/Documents/Sessions API вже є, потрібно тільки вмикати USE_EMBEDDINGS/USE_FABRIC_OCR
3. **`config/agent_registry.yml` Sofiia entry** — перевірити `telegram_mode: whitelist` і `allowed_users: []`
4. **Впевнитись що `docker-compose.node2-sofiia.yml`** має `sofiia-data` volume з правильним path
5. **Протестувати UI** через `http://localhost:8002/` — відкрити вкладку "📁 Проєкти" і перевірити sidebar
6. **Перевірити Dialog Map** через `GET /api/sessions/{sid}/map` — tree view реалізований
7. **НОВА ПОТРЕБА**: визначити де буде Dialog Map на Postgres (`dialog_nodes/edges`) — поки SQLite tree-only
8. **Пріоритет для UI**: mock endpoints для `repo_changesets` і `ops_runs` (CTO panel) поки не реалізовано
9. **Додати `docs_versions` endpoint** в `docs_router.py` (колонка `extracted_text` є, потрібна таблиця версій)
10. **Перевірити NATS subjects** в `docs/NATS_SUBJECTS.md` і зіставити з поточними з `docs/ADR_ARCHITECTURE_VNEXT.md §5`

View File

@@ -0,0 +1,441 @@
# Sofiia CTO Agent — Intelligence System Trace (C)
> Generated: 2026-02-26 | Реконструкція "інтелектуальної системи" Sofiia
---
## Загальна схема мислення
```
User Input (Telegram / Console / Voice)
[BFF: sofiia-console]
Auth + Rate limit + Session
├─── Voice turn? ──► STT (memory-service) → sanitize_for_voice() → voice_fast_uk
└─── Text turn? ──► [Router /v1/agents/sofiia/infer]
┌────────────┴────────────┐
│ │
LLM selection Tool call?
(profile-based) (tool_manager)
│ │
[LLM response] [Tool execution]
│ │
<think> strip RBAC check
│ │
Memory save Evidence
│ │
└────────┬────────────────┘
[Dialog Map update]
(SQLite tree / future Postgres graph)
[Response to User]
[TTS if voice mode]
```
---
## 1. Intent → Plan → Execute (Canonical CTO Flow)
### 1.1 Документовано
- **Docs:** `AGENTS.md` §Example Commands, `docs/ADR_ARCHITECTURE_VNEXT.md` §3.1 CrewAI Workers
- **Concept:** "Chat/Intent → Plan (Artifacts) → Execute as Job → Evidence → Dialog Map"
- **vNext Design:** вся концепція описана в цьому сеансі розмови
### 1.2 Реалізовано
- **Intent → Plan:** ✅ LLM inference через Router (`/v1/agents/sofiia/infer`)
- **Plan → Execute (Ops):** ✅ `/api/ops/run` dispatches pre-defined actions
- **Execute → Evidence:** ⚠️ частково — ops повертає result, але не зберігає як artifact
- **Evidence → Dialog Map:** ❌ ops artifacts не зшиваються в dialog_nodes
### 1.3 Розриви
- Немає загального **Job System** (тільки pre-defined ops actions)
- Немає `repo_changesets` / `ops_runs` як артефактів у DB
- Dialog Map не оновлюється автоматично від ops actions
---
## 2. Модулі Архітектури
### 2.1 BFF (sofiia-console)
**Документовано тут:**
- `docs/runbook/sofiia-control-plane.md`
- `docs/sofiia_ui_vnext_audit.md`
- `docs/fabric_contract.md`
**Реалізовано тут:**
- `services/sofiia-console/app/main.py` — FastAPI v0.3.0
- `services/sofiia-console/app/config.py` — node registry, ENV loading
- `docker-compose.node2-sofiia.yml` — deployment config
**Що BFF робить:**
```
1. API Gateway для UI (chat/voice/projects/ops/nodes)
2. Session management (SQLite sofiia.db)
3. Multi-provider LLM proxy (ollama/router/glm/grok)
4. Voice pipeline (STT→LLM→TTS, Phase 2 streaming)
5. Ops dispatcher (risk/pressure/backlog/notion/release)
6. Multi-node health monitor (polling + WebSocket fan-out)
7. Memory save (SQLite first, then Memory Service best-effort)
```
**Розриви:**
- Відсутній єдиний Job tracking (кожен ops action — one-shot, без persist)
- Відсутній `repo_changesets` flow
- `ops.html`, `chat.html`, `nodes.html` — fallback HTML, не окремі файли
---
### 2.2 LLM Routing
**Документовано тут:**
- `services/router/router-config.yml`
- `docs/architecture_inventory/01_SERVICE_CATALOG.md`
- `docs/OPENAPI_CONTRACTS.md`
**Реалізовано тут:**
- `services/router/main.py``/v1/agents/{agent_id}/infer`
- `services/router/router-config.yml``sofiia:` entry
**Конфігурація Sofiia (router-config.yml):**
```yaml
sofiia:
primary: cloud_grok # Grok API (Telegram mode)
fallback: cloud_deepseek # DeepSeek API
# Console mode може override через ollama
```
**Voice profiles:**
```yaml
voice_fast_uk:
prefer_models: [gemma3:latest, qwen3.5:35b-a3b, qwen3:14b]
deadline_ms: 9000
max_tokens: 256
voice_quality_uk:
prefer_models: [qwen3.5:35b-a3b, qwen3:14b]
deadline_ms: 12000
max_tokens: 256
```
**Розриви:**
- Відсутній профіль для `repo_changeset` (long-form, structured output)
- Відсутній профіль для `plan_generation` (CTO structured plans)
---
### 2.3 Tool System
**Документовано тут:**
- `AGENTS.md` §Tool List
- `docs/architecture_inventory/02_TOOL_CATALOG.md`
- `config/rbac_tools_matrix.yml`
**Реалізовано тут:**
- `services/router/tool_manager.py` — TOOL_DEFINITIONS + execution
- `services/router/agent_tools_config.py` — per-agent allowlists
**RBAC роль `agent_cto`** (39 permissions):
```
docs: read ops: read/exec_safe
repo: read jobs: smoke/drift/backup/deploy
kb: read risk: read/write
pr_review: use pressure: read/write
contract: use backlog: read/write/admin
config_lint: use deps: read/gate
threatmodel: use cost: read/gate
observability drift: read/gate
incidents: write alerts: ingest/read/ack/claim
```
**Sofiia спеціалізовані tools (agent_tools_config.py):**
```python
AGENT_SPECIALIZED_TOOLS["sofiia"] = [
"comfy_generate_image",
"comfy_generate_video",
"risk_engine_tool",
"architecture_pressure_tool",
"backlog_tool",
"job_orchestrator_tool",
"dependency_scanner_tool",
"incident_intelligence_tool",
"cost_analyzer_tool",
"pieces_tool",
"notion_tool",
]
```
**FULL_STANDARD_STACK** (16 tools available to all agents):
```
memory_search, graph_query, web_search, web_extract, crawl4ai_scrape,
remember_fact, image_generate, tts_speak, presentation_create/status/download,
file_tool, repo_tool, pr_reviewer_tool, contract_tool, oncall_tool,
observability_tool, config_linter_tool, threatmodel_tool, job_orchestrator_tool,
kb_tool, drift_analyzer_tool, pieces_tool
```
**Розриви:**
- Відсутній `repo_changeset_tool` (create/patch/plan/pr)
- Відсутній `ops_job_tool` (start/status/cancel з job tracking)
- `job_orchestrator_tool` є, але не пов'язаний з Dialog Map artifact creation
---
### 2.4 Memory System
**Документовано тут:**
- `docs/ADR_ARCHITECTURE_VNEXT.md` §2.5 Memory Service
- `docs/MEMORY_API_POLICY.md`
- `docs/AGENT-MEMORY-STANDARD.md`
**Реалізовано тут:**
- `services/memory-service/app/main.py` — threads/events/memories/facts/agents
- `services/memory-service/app/vector_store.py` — Qdrant
- `docker-compose.memory-node2.yml` — Postgres + Qdrant + Neo4j
**3 рівні пам'яті (згідно ADR):**
| Рівень | Qdrant | Neo4j | Postgres |
|--------|--------|-------|----------|
| Personal | `user_{id}_*` | `:User` nodes | `user_facts`, `user_sessions` |
| Team/DAO | `team_{id}_*` | `:Team`, `:Project` | `team_facts`, `team_quotas` |
| Public | `public_*` | `:Public` | `indexed_content` |
**Реальні колекції (NODA2):**
- `sofiia_messages` — 1183+ points
- `sofiia_summaries`
- Memory Service Postgres (port 5433, db `daarion_memory`)
**Console-рівень пам'яті (SQLite `sofiia.db`):**
```sql
projects, documents, sessions, messages
```
**Розриви:**
- Team/DAO namespace: описаний в ADR, реалізований лише для Personal
- E2EE для confidential: тільки в ADR, не реалізовано
- BFF і Memory Service "знають" одне про одного, але sync неповний
---
### 2.5 Planning System (Supervisor)
**Документовано тут:**
- `docs/supervisor/langgraph_supervisor.md`
- `docs/supervisor/postmortem_draft_graph.md`
**Реалізовано тут:**
- `services/sofiia-supervisor/app/main.py`
- `services/sofiia-supervisor/app/graphs/`
**Доступні LangGraph графи:**
```
alert_triage → класифікація/ескалація алертів
incident_triage → тріаж інцидентів (SLO, labels, owners)
postmortem_draft → автогенерація postmortem документа
release_check → pre-release gate checks
```
**Архітектура (загальна):**
```
Event/Trigger → LangGraph Node → State update → Next Node
↓ ↓
NATS event Tool calls (via gateway_client)
Memory writes
Structured output (JSON)
```
**Розриви:**
- Немає `cto_intent_graph` (intent → plan → execute)
- Немає `repo_changeset_graph` (diff → plan → PR)
- Немає `dialog_map_builder_graph` (events → nodes/edges)
- Supervisor ізольований від BFF (не інтегрований у `/api/ops/run`)
---
## 3. Policies (Безпека, Дозволи, Approval)
### 3.1 Документовано
- `docs/PRIVACY_GATE.md` — Privacy Gate middleware
- `docs/ADR_ARCHITECTURE_VNEXT.md` §4 Privacy Gate
- `docs/AGENT_RUNTIME_POLICY.md`
- `config/rbac_tools_matrix.yml`
- `config/data_governance_policy.yml`
- `config/risk_policy.yml`
### 3.2 Реалізовано
- RBAC tool allowlist: ✅ `agent_tools_config.py`
- API key auth: ✅ `auth.py`
- Rate limiting: ✅ per-endpoint
- Upload sanitization: ✅ mime + filename + size
- Voice guardrails: ✅ `sanitize_for_voice()`
- Config linter (secrets detection): ✅ `tool_manager.py`
### 3.3 Не реалізовано
- **Privacy Gate middleware** (перевірка `mode=confidential` в Router): 📄 описаний, не реалізований
- **2-step Plan → Apply flow**: 📄 описаний як "dangerous actions", не реалізований
- **E2EE client-side encryption**: 📄 тільки ADR, не реалізований
- **Confidential doc indexing block**: 📄 тільки ADR, не реалізований
---
## 4. Event Model
### 4.1 Документовано
- `docs/ADR_ARCHITECTURE_VNEXT.md` §5 NATS Standards
- `docs/NATS_SUBJECTS.md`
- `docs/NATS_SUBJECT_MAP.md`
### 4.2 NATS Subjects (ADR canonical)
```
message.created.{channel_id} # chat messages
attachment.created.{type} # uploaded files
agent.run.requested.{agent_id} # agent activation
agent.run.completed.{agent_id}
quota.consumed.{user_id}
audit.{service}.{action} # append-only audit
ops.health.{service}
ops.alert.{severity}
```
### 4.3 Fabric Subjects (реалізовані у node-worker)
```
node.{id}.llm.request # LLM offload
node.{id}.tts.request # TTS offload
node.{id}.stt.request # STT offload
node.{id}.voice.llm.request # Voice LLM (dedicated)
node.{id}.voice.tts.request # Voice TTS (dedicated)
node.{id}.voice.stt.request # Voice STT (dedicated)
node.{id}.ocr.request # OCR offload
node.{id}.crawl.request # Crawl offload
node.{id}.image.request # Image generation
```
### 4.4 Розриви
- `attachment.created` — реалізований частково (upload зберігає файл, але не публікує у NATS)
- `task_create`, `doc_upsert`, `meeting_create` — не реалізовані (потрібні для Dialog Map auto-edge)
- `agent.run.requested` → legacy flat subject ще може бути в деяких шляхах (відомий drift)
- Dialog Map не підписаний на NATS events
---
## 5. Memory Architecture (деталізована)
```
┌──────────────────────────────────────────────────────────┐
│ Sofiia Memory Layers │
├──────────────────────────────────────────────────────────┤
│ Layer 0: Working Context (per-turn) │
│ - history[-12:] in BFF request │
│ - sanitize_for_voice() for voice turns │
├──────────────────────────────────────────────────────────┤
│ Layer 1: Session Memory (sofiia-console SQLite) │
│ Tables: projects, documents, sessions, messages │
│ TTL: indefinite (volume-backed) │
│ Fork: parent_msg_id для branching │
├──────────────────────────────────────────────────────────┤
│ Layer 2: Long-term Memory (Memory Service) │
│ Qdrant: sofiia_messages (1183+ vectors) │
│ sofiia_summaries │
│ Postgres: daarion_memory DB (facts, threads, events) │
│ Neo4j: agent memory graph (infrastructure ready) │
├──────────────────────────────────────────────────────────┤
│ Layer 3: Factual Memory (Key-Value) │
│ /facts/upsert, /facts/{key} │
│ Rolling summaries via /threads/{id}/summarize │
└──────────────────────────────────────────────────────────┘
```
**Namespaces (implemented):**
- `sofiia_messages` — agent-specific collection
- Загальний: `{agent_id}_{type}` pattern
**Sync між Layer 1 і Layer 2:**
- `_do_save_memory()` у `main.py`: спочатку SQLite, потім Memory Service (best-effort)
- Немає зворотнього sync (Memory Service → SQLite)
- Немає конфліктів (append-only обидва)
---
## 6. Dialog Map Intelligence
### Поточна реалізація (Phase 1)
```
SQLite messages table (parent_msg_id = branching)
GET /api/sessions/{sid}/map
Python: build_tree(messages) → nodes/edges
UI: <details><summary> tree
```
### Цільова реалізація (vNext Phase 2)
```
NATS events (task_create, doc_upsert, meeting_create)
Dialog Map Builder (новий сервіс або Supervisor граф)
Postgres: dialog_nodes + dialog_edges
GET /projects/{id}/dialog-map
UI: D3/Cytoscape canvas + live WS updates
```
**Node types (vNext):**
- `message` — chat message
- `task` — задача
- `doc` — документ/wiki
- `meeting` — зустріч
- `agent_run` — виклик агента
- `decision` — ADR/рішення
- `goal` — ціль/OKR
**Edge types (vNext):**
- `references` — A посилається на B
- `resolves` — A вирішує B
- `derives_task` — повідомлення → задача
- `updates_doc` — action → doc version
- `schedules` — message → meeting
- `summarizes` — rollup вузол
---
## 7. Preflight-First Policy
**Документовано тут:**
- `ops/fabric_preflight.sh`
- `docs/fabric_contract.md`
**Принцип:** "Zero assumptions" — перед будь-яким deploy/change:
1. Запустити `ops/fabric_preflight.sh`
2. Перевірити моделі (VOICE_REQUIRED_MODELS fail / VOICE_PREFERRED_MODELS warn)
3. Перевірити `ops/fabric_snapshot.py --save`
4. Тільки потім deploy
**Реалізовано:**
- `ops/fabric_preflight.sh` — перевірки моделей, voice health, canary
- `ops/scripts/voice_canary.py` — runtime canary (кожні 510 хв)
- `ops/voice_latency_audit.sh` — 10-сценарний latency audit
---
## Next Actions for UI Team (12 days)
1. **Ознайомитись із Supervisor API** (`/v1/graphs/{name}/runs`) — це готовий "job runner" для CTO workflows
2. **Розширити Supervisor**: додати `cto_intent_graph` на базі `release_check_graph` (спільна структура)
3. **NATS attachment events**: при upload в `docs_router.py` — публікувати `attachment.created` (1 рядок коду)
4. **Dialog Map NATS listener**: простий consumer що upsert-ить SQLite nodes при events
5. **`docs_versions` table**: ALTER TABLE + endpoint — 12 год роботи
6. **Privacy Gate stub**: додати перевірку `mode` поля в BFF, навіть якщо без шифрування
7. **Plan → Apply pattern**: для ops actions — показувати "план" перед запуском
8. **`agent_id` нормалізація**: замінити `"l"` на `"sofiia"` в node2 router-config.yml
9. **Memory sync**: додати endpoint для завантаження Sofiia memory з Memory Service у SQLite
10. **CTO Panel**: mock `/api/repo/changesets` і `/api/ops/runs` endpoints для UI розробки

View File

@@ -0,0 +1,192 @@
# Sofiia CTO Agent — State of Implementation (B)
> Generated: 2026-02-26 | Legend: ✅ Implemented | ⚠️ Partial | 📄 Documented Only | ❌ Not Found
---
## 1. Identity & System Prompt
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| Sofiia identity (AGENTS.md) | ✅ Implemented | `AGENTS.md` — CTO-агент, NODA1/2/3, capabilities | — |
| Telegram system prompt | ✅ Implemented | `gateway-bot/sofiia_prompt.txt` (138KB) | — |
| Control Console system prompt | ✅ Implemented | `services/sofiia-console/app/main.py` lines 138177 | — |
| Voice turn prompt suffix | ✅ Implemented | `main.py` `SOFIIA_VOICE_PROMPT_SUFFIX` — max 2 sentences, no markdown | — |
| Agent ID consistency | ⚠️ Partial | `"sofiia"` у production, `"l"` у node2-конфігурації та тестах | ⚠️ Confusion risk |
| NODA3 integration | 📄 Documented Only | `AGENTS.md` описує NODA3 (IP, GPU, models), але немає compose/config | 🔴 Blocking |
---
## 2. Control Console (BFF)
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| FastAPI BFF основа | ✅ Implemented | `sofiia-console/app/main.py` v0.3.0, 1800 рядків | — |
| Chat: Ollama/Router/GLM/Grok | ✅ Implemented | `/api/chat/send`, providers: ollama, router, glm, grok | — |
| Chat: history (client-side) | ✅ Implemented | `body.history[-12:]` передається клієнтом | — |
| Chat: session persist (SQLite) | ✅ Implemented | `_do_save_memory``db.save_message`, `db.upsert_session` | — |
| Chat: session restore on page reload | ✅ Implemented | `GET /api/chat/history`, localStorage session_id | — |
| Ops: risk/pressure/backlog/release | ✅ Implemented | `/api/ops/run` + `ops.py` dispatcher | — |
| Ops: Notion actions | ✅ Implemented | notion_status/create_task/create_page/create_database | — |
| Hub: integrations status | ✅ Implemented | `/api/integrations/status` — Router, Memory, OpenWebUI, Pieces, OpenCode, Notion | — |
| Nodes: dashboard | ✅ Implemented | `/api/nodes/dashboard` з caching, multi-node poll | — |
| Nodes: SSH status | ✅ Implemented | `/api/nodes/ssh/status` (strict auth) | — |
| Nodes: add node | ✅ Implemented | `/api/nodes/add` | — |
| Nodes: remove node | ❌ Not Found | Тільки add, без delete | ⚠️ Minor gap |
| Memory: status | ✅ Implemented | `/api/memory/status` | — |
| Memory: context | ✅ Implemented | `/api/memory/context` | — |
| WebSocket event bus | ✅ Implemented | `/ws/events` — nodes.status, chat.reply, voice.*, ops.run | — |
| Rate limiting | ✅ Implemented | per-endpoint limiters: 30/min chat, 15/min stream, 30/min TTS | — |
| API key auth | ✅ Implemented | `auth.py` + strict mode | — |
---
## 3. Voice Layer
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| STT proxy | ✅ Implemented | `POST /api/voice/stt` → memory-service | — |
| TTS proxy | ✅ Implemented | `POST /api/voice/tts` (legacy + HA path) | — |
| Voice streaming Phase 2 | ✅ Implemented | `POST /api/voice/chat/stream` — split → first TTS | — |
| Voice policy (voice_fast_uk/quality_uk) | ✅ Implemented | `router-config.yml`, `test_voice_policy.py` 23/23 | — |
| Voice guardrails (2 sentences) | ✅ Implemented | `SOFIIA_VOICE_PROMPT_SUFFIX`, `sanitize_for_voice()` | — |
| `<think>` stripping | ✅ Implemented | `voice_utils.py` + Router `_clean_think_blocks` | — |
| Degradation state machine | ✅ Implemented | `_VoiceDegradationSM` (ok/degraded_tts/degraded_llm/fast_lock/emergency) | — |
| TTFA telemetry | ✅ Implemented | `POST /api/telemetry/voice` + Prometheus metrics | — |
| Voice HA (multi-node routing) | ✅ Implemented | `VOICE_HA_ENABLED` flag, Router `/v1/capability/voice_*` | — |
| Remote voice badge | ✅ Implemented | `X-Voice-Mode: remote` header → `🌐 noda1` badge | — |
| Voice canary | ✅ Implemented | `ops/scripts/voice_canary.py` (preflight + runtime mode) | — |
| Grafana voice dashboard | ✅ Implemented | `ops/grafana_voice_dashboard.json` | — |
| Voice alerts (Prometheus) | ✅ Implemented | `ops/voice_alerts.yml` (6 rules) | — |
| SLO definitions | ✅ Implemented | `config/slo_policy.yml` voice_fast_uk / voice_quality_uk | — |
| Rate limit / DoS guard | ✅ Implemented | semaphore, per-IP limiter, `rest_chunks ≤ 8` cap | — |
---
## 4. Projects, Documents, Sessions
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| Projects CRUD | ✅ Implemented | `docs_router.py`: GET/POST/PATCH `/api/projects` | — |
| Documents CRUD | ✅ Implemented | upload, list, get, keyword search | — |
| File upload (multipart) | ✅ Implemented | `POST /api/files/upload` — sha256, mime detect, size limit | — |
| Text extraction (PDF/DOCX/TXT) | ✅ Implemented | `_extract_text_simple()` у docs_router | — |
| Sessions persistence | ✅ Implemented | `upsert_session`, `save_message`, SQLite `sofiia.db` | — |
| Chat history restore | ✅ Implemented | `GET /api/chat/history?session_id=...` | — |
| Dialog Map (tree) | ✅ Implemented | `GET /api/sessions/{sid}/map` → nodes/edges | — |
| Dialog Map (canvas/D3) | ❌ Not Found | Поточний — `<details>` collapsible tree тільки | Phase 2 |
| Session fork | ✅ Implemented | `POST /api/sessions/{sid}/fork` | — |
| Projects sidebar (chat UI) | ✅ Implemented | `#sidebarProjectList` у `index.html` | — |
| Projects section (full UI) | ✅ Implemented | `#section-projects` з tabs: docs, sessions, map | — |
| Fabric OCR для uploaded images | ⚠️ Feature Flag Off | `USE_FABRIC_OCR=false` за замовч. | Low risk |
| Qdrant embeddings для docs | ⚠️ Feature Flag Off | `USE_EMBEDDINGS=false` за замовч. | Low risk |
| Docs versions (history) | ❌ Not Found | `docs_versions` таблиця відсутня | 🔴 vNext gap |
| Docs backlinks (entity_links) | ❌ Not Found | `docs_links`/`entity_links` таблиця відсутня | 🔴 vNext gap |
| `doc_index_state` table | ❌ Not Found | Відсутня | 🔴 vNext gap |
| Semantic search (Meilisearch) | ❌ Not Found | Тільки SQL LIKE keyword search | 📄 ADR describes it |
---
## 5. CTO-specific Capabilities (Repo/Ops)
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| `repo_tool` (read-only) | ✅ Implemented | `tool_manager.py` — tree/read/search/metadata | — |
| `pr_reviewer_tool` | ✅ Implemented | `tool_manager.py` — blocking_only/full_review | — |
| `contract_tool` (OpenAPI) | ✅ Implemented | `tool_manager.py` — lint_openapi/diff_openapi/generate_client_stub | — |
| `oncall_tool` | ✅ Implemented | services_list/health/runbook_search/incident_log | — |
| `observability_tool` | ✅ Implemented | Prometheus/Loki/Tempo queries | — |
| `config_linter_tool` | ✅ Implemented | Secrets detection, policy violations | — |
| `threatmodel_tool` | ✅ Implemented | STRIDE-based threat modeling | — |
| `job_orchestrator_tool` | ✅ Implemented | smoke/drift/backup/deploy tasks | — |
| `kb_tool` | ✅ Implemented | ADR/docs search | — |
| `drift_analyzer_tool` | ✅ Implemented | Infrastructure drift detection | — |
| `risk_engine_tool` | ✅ Implemented | Risk scoring | — |
| `architecture_pressure_tool` | ✅ Implemented | Architecture health analysis | — |
| `backlog_tool` | ✅ Implemented | Backlog generation/management | — |
| `dependency_scanner_tool` | ✅ Implemented | Dependency security scan | — |
| `incident_intelligence_tool` | ✅ Implemented | Incident correlation | — |
| `cost_analyzer_tool` | ✅ Implemented | Cost analysis | — |
| `notion_tool` | ✅ Implemented | Notion pages/tasks/databases | — |
| **`repo_changesets`** (CTO workflow) | ❌ Not Found | Тільки описано в vNext design | 🔴 Blocking |
| **`ops_runs` API** | ❌ Not Found | Тільки `ops.py` dispatcher (не як job system) | 🔴 Blocking |
| **`pull_requests` API** | ❌ Not Found | PR Review tool є, але PR object як артефакт — немає | 🔴 vNext gap |
| **`entity_links`** | ❌ Not Found | Concept described, not implemented | 🔴 vNext gap |
| Direct NODA3 integration | ❌ Not Found | Описано в AGENTS.md, відсутній docker-compose/router config | 🔴 |
---
## 6. Supervisor (LangGraph)
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| Alert triage graph | ✅ Implemented | `alert_triage_graph.py` + tests | — |
| Incident triage graph | ✅ Implemented | `incident_triage_graph.py` + tests | — |
| Postmortem draft graph | ✅ Implemented | `postmortem_draft_graph.py` + tests | — |
| Release check graph | ✅ Implemented | `release_check_graph.py` + tests | — |
| Supervisor API | ✅ Implemented | `/v1/graphs/{name}/runs` | — |
| **CTO workflow graph** (intent→plan→execute) | ❌ Not Found | Описано в vNext design, немає реалізації | 🔴 vNext gap |
| **Repo changeset graph** | ❌ Not Found | Тільки в дизайн-доці | 🔴 vNext gap |
---
## 7. Memory System
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| Short-term memory (threads/events) | ✅ Implemented | Memory Service `/threads`, `/events` | — |
| Long-term memory (Qdrant) | ✅ Implemented | `/memories` + semantic search | — |
| Facts store | ✅ Implemented | `/facts/upsert`, `/facts/{key}` | — |
| Agent memory (Postgres + Neo4j) | ✅ Implemented | `/agents/{id}/memory` | — |
| Rolling summaries | ✅ Implemented | `/threads/{id}/summarize` | — |
| Neo4j graph memory | ✅ Infrastructure Ready | docker-compose.memory-node2.yml | Не тестований |
| **Personal namespace** | ⚠️ Partial | ADR описує `user_{id}_*` collections, реалізація через `user_id` param | — |
| **Team/DAO namespace** | 📄 Documented Only | ADR, не реалізовано в code | 🔴 vNext gap |
| **E2EE (confidential docs)** | 📄 Documented Only | ADR + PRIVACY_GATE.md, не реалізовано | 🔴 vNext gap |
---
## 8. Infrastructure
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| NODA2 Docker stack | ✅ Implemented | `docker-compose.node2-sofiia.yml` | — |
| NODA1 health + SSH | ✅ Implemented | nodes.py + SSH key auth | — |
| Prometheus metrics | ✅ Implemented | fabric_metrics.py (router + node-worker), voice metrics | — |
| NATS subjects | ✅ Implemented | Fabric node.{id}.*.request subjects | — |
| Voice HA semaphores | ✅ Implemented | node-worker separate voice semaphores | — |
| sofiia-data volume | ✅ Implemented | docker-compose.node2-sofiia.yml sofiia-data:/app/data | — |
| Postgres для sofiia docs | ⚠️ SQLite Only | Phase 1: SQLite у sofiia-console, Postgres для Memory Service | Phase 2 needed |
| S3/MinIO storage | ❌ Not Found | ADR описує, upload зараз у volume | 🔴 Phase 2 |
| Meilisearch | ❌ Not Found | ADR описує для search, не розгорнутий | 🔴 vNext |
| Control Plane service | ❌ Not Found | ADR 1.1-1.3, reference у security audit | 🔴 vNext |
---
## 9. Security
| Feature | Status | Evidence | Risk |
|---------|--------|----------|------|
| RBAC per agent | ✅ Implemented | `rbac_tools_matrix.yml` agent_cto (39 permissions) | — |
| Tool allowlist per agent | ✅ Implemented | `agent_tools_config.py` AGENT_SPECIALIZED_TOOLS["sofiia"] | — |
| API key auth | ✅ Implemented | `auth.py` — console + strict modes | — |
| Upload sanitization (filename/mime) | ✅ Implemented | `_safe_filename()`, `_detect_mime()` у docs_router | — |
| Rate limiting | ✅ Implemented | per-endpoint + semaphore + `rest_chunks ≤ 8` | — |
| **E2EE (confidential)** | ❌ Not Found | Privacy Gate описаний в ADR, не реалізований | 🔴 |
| **2-step approval для dangerous actions** | ❌ Not Found | ADR описує Plan → Apply flow | 🔴 vNext |
| Audit log (append-only) | ⚠️ Partial | audit.py у agromatrix crew, `audit.{service}.{action}` NATS — частково | 🔴 |
---
## Next Actions for UI Team (12 days)
1. **Зверніть увагу**: `repo_changesets`, `ops_runs`, `entity_links`**не існують**. UI CTO panel потребує mock endpoints
2. **Quick win**: `docs_versions` таблиця — 30хв роботи (ALTER TABLE + endpoint у docs_router.py)
3. **Quick win**: увімкнути `USE_EMBEDDINGS=true` в docker-compose для реального vector search
4. **Перевірити** соfiia agent_id у тестах: `"l"` vs `"sofiia"` — потрібна нормалізація
5. **Postgres migration**: коли sofiia-console готова до Postgres, потрібен `DATABASE_URL` env + аналогічний `init_db()`
6. **E2EE**: перед вмиканням confidential docs — треба спроєктувати ключі (client-side only)
7. **Dialog Map Phase 2**: canvas rendering (D3/Cytoscape) — `<details>` tree є, але не масштабується
8. **Meilisearch**: поки `LIKE` search, але коли кількість docs зросте — потрібен реальний search index
9. **NODA3**: додати до `nodes_registry.yml` і `docker-compose.node2-sofiia.yml` (якщо NODA3 реально доступна)
10. **CTO workflow graph**: перший крок — alert_triage граф вже є, на його основі зробити `cto_intent_graph`

View File

@@ -0,0 +1,248 @@
# Sofiia UI vNext — Dependency Map (D)
> Generated: 2026-02-26 | Карта залежностей UI → Backend → DB → Events
---
## Легенда
| Символ | Значення |
|--------|----------|
| ✅ | Endpoint/Model реалізований |
| ⚠️ | Частково реалізований або за feature flag |
| ❌ | Відсутній, потрібна реалізація |
| 🔧 | Потрібне виправлення/доопрацювання |
| 📄 | Тільки документований |
---
## Таблиця 1: Chat & Voice
| UI Feature | Expected API/Event | Found? | Evidence | Action |
|-----------|-------------------|--------|----------|--------|
| Text chat | `POST /api/chat/send` | ✅ | `main.py` | — |
| Voice STT (WebM) | `POST /api/voice/stt` | ✅ | `main.py` → memory-service | — |
| Voice TTS | `POST /api/voice/tts` | ✅ | `main.py` (legacy + HA) | — |
| Voice Phase 2 stream | `POST /api/voice/chat/stream` | ✅ | `main.py` | — |
| Voice stop/abort | AbortController + `POST /api/voice/tts` cancel | ✅ | `index.html` JS | — |
| TTFA telemetry | `POST /api/telemetry/voice` | ✅ | `main.py` | — |
| Batch telemetry | `POST /api/telemetry/voice/batch` | ✅ | `main.py` | — |
| Degradation badge | `GET /api/voice/degradation_status` | ✅ | `main.py` | — |
| Remote voice badge | `X-Voice-Mode: remote` header | ✅ | `main.py` + `index.html` | — |
| Model selector UI | inline models list | ✅ | `index.html` (hardcoded) | 🔧 Should come from `/api/models` |
| Chat history restore | `GET /api/chat/history?session_id=` | ✅ | `docs_router.py` | — |
| Session persistence | localStorage `session_id` | ✅ | `index.html` | — |
| Memory status | `GET /api/memory/status` | ✅ | `main.py` | — |
---
## Таблиця 2: Projects
| UI Feature | Expected API/Event | Found? | Evidence | Action |
|-----------|-------------------|--------|----------|--------|
| Projects list | `GET /api/projects` | ✅ | `docs_router.py` | — |
| Create project | `POST /api/projects` | ✅ | `docs_router.py` | — |
| Get project | `GET /api/projects/{id}` | ✅ | `docs_router.py` | — |
| Update project | `PATCH /api/projects/{id}` | ✅ | `docs_router.py` | — |
| Delete project | `DELETE /api/projects/{id}` | ❌ | Not found | implement |
| Projects sidebar | `GET /api/projects` (on load) | ✅ | `index.html` `loadSidebarProjects()` | — |
| Project switcher | localStorage `project_id` | ✅ | `index.html` | — |
| **Board (Kanban)** | `GET /api/projects/{id}/tasks` | ❌ | Not found | implement or mock |
| **Tasks CRUD** | `/api/projects/{id}/tasks` | ❌ | Not found | implement |
| **Meetings** | `GET /api/projects/{id}/meetings` | ❌ | Not found | implement or mock |
| **Meeting create** | `POST /api/meetings` | ❌ | Not found | implement |
| **Meeting reminders** | NATS `meeting.reminder.*` | ❌ | Not found | Phase 2 |
| Project settings | `PATCH /api/projects/{id}` | ✅ | `docs_router.py` | — |
---
## Таблиця 3: Documents DB
| UI Feature | Expected API/Event | Found? | Evidence | Action |
|-----------|-------------------|--------|----------|--------|
| Upload file | `POST /api/files/upload` (multipart) | ✅ | `docs_router.py` | — |
| List documents | `GET /api/projects/{id}/documents` | ✅ | `docs_router.py` | — |
| Get document | `GET /api/projects/{id}/documents/{doc_id}` | ✅ | `docs_router.py` | — |
| Download file | `GET /api/files/{file_id}/download` | ✅ | `docs_router.py` | — |
| Search docs | `POST /api/projects/{id}/search` | ✅ | `docs_router.py` (SQL LIKE) | 🔧 Needs semantic search |
| Delete document | `DELETE /api/projects/{id}/documents/{doc_id}` | ❌ | Not found | implement |
| **Doc versioning** | `GET /docs/{id}/versions` | ❌ | Not found | implement (DDL needed) |
| **Restore version** | `POST /docs/{id}/restore` | ❌ | Not found | implement |
| **Doc diff** | `GET /docs/{id}/diff?from=&to=` | ❌ | Not found | Phase 2 |
| **Backlinks (entity_links)** | `POST /docs/{id}/links` | ❌ | Not found | implement |
| **"Index for AI" toggle** | `POST /docs/{id}/index` | ❌ | Not found (USE_EMBEDDINGS flag) | implement |
| **doc_index_state** | status tracking | ❌ | Not found | implement |
| **Wiki Markdown editor** | Frontend only | ❌ | Not in index.html | implement (Phase 2) |
| **Docs tree navigation** | Frontend only | ❌ | Not in index.html | implement (Phase 2) |
| Fabric OCR on upload | `POST /v1/capability/ocr` | ⚠️ | `USE_FABRIC_OCR=false` | enable flag |
| Embeddings on upload | Qdrant ingest via Router | ⚠️ | `USE_EMBEDDINGS=false` | enable flag |
| NATS event on upload | `attachment.created` | ❌ | Not published | add to upload handler |
---
## Таблиця 4: Sessions & Dialog Map
| UI Feature | Expected API/Event | Found? | Evidence | Action |
|-----------|-------------------|--------|----------|--------|
| Sessions list | `GET /api/sessions?project_id=` | ✅ | `docs_router.py` | — |
| Resume session | `GET /api/chat/history?session_id=` | ✅ | `docs_router.py` | — |
| Session title update | `PATCH /api/sessions/{id}/title` | ✅ | `docs_router.py` | — |
| Session fork | `POST /api/sessions/{id}/fork` | ✅ | `docs_router.py` | — |
| Dialog Map (tree) | `GET /api/sessions/{id}/map` | ✅ | `docs_router.py` | — |
| **Dialog Map (canvas)** | D3/Cytoscape rendering | ❌ | `<details>` tree only in UI | Phase 2 |
| **Project-level map** | `GET /api/projects/{id}/dialog-map` | ❌ | Not found | implement (Postgres needed) |
| **Node types** (task/doc/meeting) | NATS consumers | ❌ | Not found | Phase 2 |
| **Edge creation UI** | `POST /api/links` | ❌ | Not found | implement |
| **Pin important node** | `PATCH /api/sessions/{id}/pin/{msg_id}` | ❌ | Not found | implement |
| Real-time map updates | WS `dialog_map.updated` event | ❌ | Not found | implement |
| **Saved views** | `dialog_views` table | ❌ | Not found | implement |
---
## Таблиця 5: CTO Panel (Repo + Ops)
| UI Feature | Expected API/Event | Found? | Evidence | Action |
|-----------|-------------------|--------|----------|--------|
| Ops actions (risk/backlog/etc.) | `GET /api/ops/actions` | ✅ | `main.py` | — |
| Run ops action | `POST /api/ops/run` | ✅ | `main.py` + `ops.py` | — |
| Node health dashboard | `GET /api/nodes/dashboard` | ✅ | `main.py` | — |
| Node SSH status | `GET /api/nodes/ssh/status` | ✅ | `main.py` | — |
| Add node | `POST /api/nodes/add` | ✅ | `main.py` | — |
| Integrations status | `GET /api/integrations/status` | ✅ | `main.py` | — |
| **Repo changesets list** | `GET /api/repo/changesets` | ❌ | Not found | implement or mock |
| **Create changeset** | `POST /api/repo/changesets` | ❌ | Not found | implement |
| **Add patch** | `POST /api/repo/changesets/{id}/patches` | ❌ | Not found | implement |
| **Execution plan** | `POST /api/repo/changesets/{id}/plan` | ❌ | Not found | implement |
| **Create PR** | `POST /api/repo/changesets/{id}/pr` | ❌ | Not found | implement |
| **Run checks** | `POST /api/repo/pr/{id}/checks:run` | ❌ | Not found | implement |
| **Ops runs list** | `GET /api/ops/runs` | ❌ | Not found (only one-shot dispatch) | implement |
| **Ops run create** | `POST /api/ops/runs` (job-based) | ❌ | Not found | implement |
| **Ops run status** | `GET /api/ops/runs/{id}` | ❌ | Not found | implement |
| LangGraph runs | `POST /v1/graphs/{name}/runs` (Supervisor) | ✅ | `sofiia-supervisor` | 🔧 Not exposed via BFF |
| LangGraph status | `GET /v1/runs/{id}` | ✅ | `sofiia-supervisor` | 🔧 Not exposed via BFF |
| **repo_tool (read)** | via chat tools | ✅ | `tool_manager.py` | — |
| **pr_reviewer_tool** | via chat tools | ✅ | `tool_manager.py` | — |
---
## Таблиця 6: Database Model Dependency
| UI Screen | Required DB Table | Status | Storage | Action |
|-----------|------------------|--------|---------|--------|
| Chat history | `messages` | ✅ | SQLite | — |
| Projects | `projects` | ✅ | SQLite | — |
| Documents | `documents` | ✅ | SQLite | — |
| Sessions | `sessions` | ✅ | SQLite | — |
| Dialog Map (messages) | `messages.parent_msg_id` | ✅ | SQLite | — |
| **Dialog Map (graph)** | `dialog_nodes` + `dialog_edges` | ❌ | None | ADD TABLES |
| **Saved map views** | `dialog_views` | ❌ | None | ADD TABLE |
| **Doc versions** | `docs_versions` | ❌ | None | ADD TABLE |
| **Entity links** | `entity_links` | ❌ | None | ADD TABLE |
| **Tasks** | `tasks` | ❌ | None | ADD TABLE |
| **Meetings** | `meetings` | ❌ | None | ADD TABLE |
| **Repo changesets** | `repo_changesets` | ❌ | None | ADD TABLE |
| **Repo patches** | `repo_patches` | ❌ | None | ADD TABLE |
| **Pull requests** | `pull_requests` | ❌ | None | ADD TABLE |
| **Ops runs** | `ops_runs` | ❌ | None | ADD TABLE |
| Embeddings | Qdrant `sofiia_docs_*` | ⚠️ | Qdrant (disabled) | ENABLE FLAG |
| Long-term memory | Qdrant `sofiia_messages` | ✅ | Qdrant | — |
| Facts | Postgres `daarion_memory` | ✅ | Postgres | — |
---
## Таблиця 7: Real-time Events (WebSocket)
| Event | Direction | Status | Evidence |
|-------|-----------|--------|----------|
| `nodes.status` | Server → UI | ✅ | `main.py` WebSocket fan-out |
| `chat.reply` | Server → UI | ✅ | `main.py` |
| `voice.stt.result` | Server → UI | ✅ | `main.py` |
| `voice.tts.ready` | Server → UI | ✅ | `main.py` |
| `voice.stream.chunk` | Server → UI | ✅ | `main.py` |
| `ops.run.status` | Server → UI | ✅ | `main.py` |
| `error` | Server → UI | ✅ | `main.py` |
| `dialog_map.updated` | Server → UI | ❌ | Not found |
| `task.created` | Server → UI | ❌ | Not found |
| `doc.updated` | Server → UI | ❌ | Not found |
| `meeting.reminder` | Server → UI | ❌ | Not found |
| `repo.pr.status` | Server → UI | ❌ | Not found |
| `ops_run.completed` | Server → UI | ❌ | Not found |
---
## Таблиця 8: Security & Access Control
| Feature | Status | Evidence |
|---------|--------|----------|
| API key auth (console) | ✅ | `auth.py` |
| Strict auth (SSH/admin) | ✅ | `auth.py` strict mode |
| Rate limiting per endpoint | ✅ | `main.py` limiters |
| Upload sanitize (filename/mime) | ✅ | `docs_router.py` |
| Upload size limits (env-based) | ✅ | `UPLOAD_MAX_*_MB` env |
| RBAC tool allowlist | ✅ | `agent_tools_config.py` |
| `mode=confidential` check | ❌ | Not in BFF or Router |
| E2EE for docs | ❌ | Not implemented |
| Audit log for actions | ⚠️ | Partial (router audit.py) |
| 2-step Plan → Apply for risky ops | ❌ | Not implemented |
| CORS config | ⚠️ | Check `main.py` |
---
## Граф залежностей (логічний)
```
[index.html SPA]
┌───────────────┼───────────────┐
│ │ │
[chat+voice] [projects] [ops+nodes]
│ │ │
▼ ▼ ▼
/api/chat/send /api/projects /api/ops/run
/api/voice/* /api/files/* /api/nodes/*
/api/telemetry /api/sessions/* /api/integrations/*
│ │ │
▼ ▼ ▼
[Router BFF] [SQLite sofiia.db] [nodes health poll]
│ │ │
▼ ▼ ▼
[Router DAGI] [Memory Service] [SSH + node-worker]
/v1/agents/ /threads /events /caps
/v1/tools/ /memories /facts /voice/health
[LLM + Tools]
Grok / qwen3 / DeepSeek
+ 20+ tools (repo/pr/kb/etc.)
```
**Відсутні зв'язки (vNext):**
```
[index.html] → [Kanban Board] ←→ /api/projects/{id}/tasks
[index.html] → [Dialog Map canvas] ←→ /api/projects/{id}/dialog-map
[index.html] → [CTO Repo Panel] ←→ /api/repo/changesets
[index.html] → [CTO Ops Panel] ←→ /api/ops/runs (job-based)
[docs_router] → NATS attachment.created
[Supervisor] → BFF (not proxied)
```
---
## Next Actions for UI Team (12 days)
1. **Immediate (today)**: всі фічі chat/voice/projects/sessions/dialog-tree вже працюють — deploy і тестуйте через http://localhost:8002
2. **Quick wins (12 дні)**:
- `DELETE /api/projects/{id}` — 10 рядків коду
- `DELETE /api/projects/{id}/documents/{doc_id}` — 10 рядків
- BFF proxy до Supervisor: `POST /api/supervisor/runs``sofiia-supervisor:8080/v1/graphs/{name}/runs`
3. **Phase 2 UI (mock-first)**:
- Kanban board: спочатку in-memory tasks → `tasks` table
- Meetings: спочатку form → `meetings` table
- Dialog Map canvas: `<details>` tree → D3 tree → D3 force graph
4. **CTO Panel mock**: додати mock handlers для `/api/repo/changesets` і `/api/ops/runs`
5. **Увімкнути USE_EMBEDDINGS=true**: після перевірки що Qdrant доступний
6. **Expose Supervisor API через BFF**: один proxy endpoint в main.py
7. **NATS attachment.created**: додати до upload handler у docs_router.py
8. **`dialog_nodes/edges` tables**: DDL + API + WS events (найважливіше для vNext graph)
9. **`docs_versions` table**: ALTER + endpoint (для wiki history)
10. **Перевірити WebSocket**: всі voice/ops events реально приходять до UI