# 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 (1–2 days)

1. **Immediate (today)**: всі фічі chat/voice/projects/sessions/dialog-tree вже працюють — deploy і тестуйте через http://localhost:8002
2. **Quick wins (1–2 дні)**:
   - `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
