Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.
Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles
Excluded from snapshot: venv/, .env, data/, backups, .tgz archives
Co-authored-by: Cursor <cursoragent@cursor.com>
492 lines
17 KiB
Markdown
492 lines
17 KiB
Markdown
# ADR: Improved microdao-daarion Architecture vNext
|
||
|
||
**Дата:** 2026-01-19
|
||
**Статус:** Прийнято (Phased Rollout)
|
||
**Версія:** 1.0
|
||
|
||
---
|
||
|
||
## Контекст
|
||
|
||
Поточний стек (Gateway → Router → Swapper → Memory Layer + NATS) працює для MVP, але має обмеження при масштабуванні на багато нод. Потрібно:
|
||
1. Легше масштабувати на багато нод
|
||
2. Не "розмити" межі сервісів
|
||
3. Зробити приватність/аудит/квоти системними, а не точковими
|
||
|
||
---
|
||
|
||
## Рішення: Control Plane + Data Plane Architecture
|
||
|
||
### Загальна схема
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ CONTROL PLANE │
|
||
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
|
||
│ │ RBAC/PDP │ │ Config │ │ Observability │ │
|
||
│ │ Service │ │ Registry │ │ + Audit │ │
|
||
│ └─────────────┘ └──────────────┘ └──────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│
|
||
[Policy Cache + Config Sync]
|
||
│
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ DATA PLANE │
|
||
│ │
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ BFF │ │ Ingest │ │ DAGI │ │ Swapper │ │
|
||
│ │ Gateway │───▶│ Service │ │ Router │───▶│ Runtime │ │
|
||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||
│ │ │ │ │ │
|
||
│ │ │ │ │ │
|
||
│ └───────────────┴───────────────┴───────────────┘ │
|
||
│ │ │
|
||
│ ┌─────────▼─────────┐ │
|
||
│ │ NATS Cluster │ │
|
||
│ │ (Events + Jobs) │ │
|
||
│ └─────────┬─────────┘ │
|
||
│ │ │
|
||
│ ┌──────────────────────┼──────────────────────┐ │
|
||
│ │ │ │ │
|
||
│ ┌────▼────┐ ┌─────▼─────┐ ┌─────▼─────┐ │
|
||
│ │ Memory │ │ CrewAI │ │ Parser │ │
|
||
│ │ Service │ │ Workers │ │ Pipeline │ │
|
||
│ └─────────┘ └───────────┘ └───────────┘ │
|
||
│ │ │
|
||
│ ┌────▼────────────────────────────────────────┐ │
|
||
│ │ Postgres │ Qdrant │ Neo4j │ Redis │ S3 │ │
|
||
│ └─────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 1. Control Plane (повільніша, керує правилами)
|
||
|
||
### 1.1 RBAC/PDP Service
|
||
- Policy Decision Point — окремий сервіс
|
||
- Кешований на Data Plane рівні
|
||
- Обробляє: entitlements, scopes, modes, quotas
|
||
|
||
### 1.2 Config Registry
|
||
- Версії системних промптів
|
||
- Routing rules (версійовані)
|
||
- Quotas per user/team/agent
|
||
- Feature flags
|
||
- Allowlists/blocklists
|
||
|
||
### 1.3 Observability + Audit
|
||
- Незмінні журнали (append-only)
|
||
- Prometheus метрики
|
||
- Grafana dashboards
|
||
- Alerting (PagerDuty/Slack)
|
||
|
||
---
|
||
|
||
## 2. Data Plane (шлях запиту, низька латентність)
|
||
|
||
### 2.1 BFF Gateway (замість монолітного Gateway)
|
||
|
||
**Відповідальність:**
|
||
- Auth, sessions, throttling
|
||
- Webhook signature verification
|
||
- Request validation & shaping
|
||
- Rate limiting (per user/IP/team)
|
||
- TLS termination
|
||
|
||
**НЕ відповідальність:**
|
||
- Обробка мультимедіа (винесено в Ingest)
|
||
- Бізнес-логіка (винесено в Router)
|
||
|
||
### 2.2 Ingest Service (НОВИЙ)
|
||
|
||
**Відповідальність:**
|
||
- Прийом файлів (фото/відео/аудіо/документи)
|
||
- Virus scan / size limits
|
||
- Upload до Object Storage (S3/MinIO)
|
||
- Публікація події `attachment.created`
|
||
|
||
**Переваги:**
|
||
- Gateway не блокується важкими операціями
|
||
- Формалізований потік: файл → подія → обробка
|
||
- Outbox pattern для надійності
|
||
|
||
### 2.3 DAGI Router (stateless)
|
||
|
||
**Залишається:**
|
||
- Routing rules (версійовані з Config Registry)
|
||
- Tool registry (дозволені інструменти)
|
||
- Policy checks (mode/confidential, scopes, budgets)
|
||
- Privacy Gate (mode-aware middleware)
|
||
|
||
**Виноситься:**
|
||
- Довгі workflow → CrewAI Workers
|
||
- Стани задач → NATS + Memory
|
||
- Проміжні артефакти → Object Storage
|
||
|
||
**Статус:** Повністю stateless, горизонтально масштабується
|
||
|
||
### 2.4 Swapper Runtime
|
||
|
||
**Відповідальність:**
|
||
- LLM inference (local/cloud)
|
||
- Vision processing
|
||
- OCR
|
||
- STT/TTS
|
||
- Image generation
|
||
- Lazy loading/unloading моделей
|
||
|
||
**Статус:** Capability runtime, не має бізнес-логіки
|
||
|
||
### 2.5 Memory Service
|
||
|
||
**Відповідальність:**
|
||
- CRUD для всіх data stores
|
||
- Інкапсуляція Postgres/Qdrant/Neo4j/Redis
|
||
- Без бізнес-логіки продукту
|
||
|
||
**3 рівні пам'яті:**
|
||
|
||
| Scope | Qdrant | Neo4j | Postgres |
|
||
|-------|--------|-------|----------|
|
||
| **Personal** | `user_{id}_*` collections | `:User` nodes + ACL | `user_facts`, `user_sessions` |
|
||
| **Team/DAO** | `team_{id}_*` collections | `:Team`, `:Project` nodes | `team_facts`, `team_quotas` |
|
||
| **Public** | `public_*` collections | `:Public` nodes | `indexed_content` |
|
||
|
||
**Правило:** Індексація plaintext дозволена лише для `scope=public + indexed=true`. Для confidential — тільки шифротекст/метадані.
|
||
|
||
---
|
||
|
||
## 3. Async Workers (через NATS)
|
||
|
||
### 3.1 CrewAI Workers
|
||
|
||
**Позиціонування:** Workflow/Job runtime, НЕ в лінії запиту
|
||
|
||
**Принципи:**
|
||
- Бере задачі з NATS JetStream
|
||
- Ідемпотентність (idempotency key)
|
||
- Пише результат у Memory Service
|
||
- Повертає статус подією
|
||
|
||
**Синхронно (в лінії запиту):** Тільки короткі задачі (LLM answer ≤ N секунд)
|
||
**Асинхронно (job):** Все інше
|
||
|
||
### 3.2 Parser Pipeline
|
||
|
||
**Тригер:** `attachment.created` подія
|
||
|
||
**Потік:**
|
||
```
|
||
attachment.created → Parser Worker →
|
||
→ extraction/chunking →
|
||
→ артефакти для RAG →
|
||
→ attachment.parsed подія
|
||
```
|
||
|
||
### 3.3 RAG Indexer
|
||
|
||
**Тригер:** `attachment.parsed` або `content.updated`
|
||
|
||
**Потік:**
|
||
```
|
||
content.updated → Embeddings →
|
||
→ Qdrant upsert →
|
||
→ content.indexed подія
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Privacy Gate (обов'язковий middleware)
|
||
|
||
### Правило
|
||
|
||
Якщо `mode=confidential`:
|
||
- Router передає в агентний шар тільки **узагальнений контекст / embedding / features**
|
||
- Або контент тільки з **явної згоди**
|
||
- Логи без контенту (тільки метрики)
|
||
|
||
### Реалізація
|
||
|
||
```python
|
||
class PrivacyGate:
|
||
def check(self, request: Request) -> GateResult:
|
||
if request.mode == "confidential":
|
||
if not request.user_consent:
|
||
return GateResult(
|
||
allow=False,
|
||
transform=self.sanitize_context,
|
||
log_content=False
|
||
)
|
||
return GateResult(allow=True, log_content=True)
|
||
|
||
def sanitize_context(self, context: str) -> str:
|
||
# Повертає тільки узагальнений summary
|
||
return summarize(context, max_tokens=100)
|
||
```
|
||
|
||
---
|
||
|
||
## 5. NATS Standards
|
||
|
||
### 5.1 Subject Naming Convention
|
||
|
||
```
|
||
# Messages
|
||
message.created.{channel_id}
|
||
message.edited.{channel_id}
|
||
message.deleted.{channel_id}
|
||
|
||
# Attachments
|
||
attachment.created.{type} # type: image/video/audio/document
|
||
attachment.parsed.{type}
|
||
attachment.indexed.{type}
|
||
|
||
# Agent Operations
|
||
agent.run.requested.{agent_id}
|
||
agent.run.started.{agent_id}
|
||
agent.run.completed.{agent_id}
|
||
agent.run.failed.{agent_id}
|
||
|
||
# Handoff (orchestration)
|
||
agent.handoff.requested.{from}.{to}
|
||
agent.handoff.completed.{from}.{to}
|
||
|
||
# Quota
|
||
quota.consumed.{user_id}
|
||
quota.blocked.{user_id}
|
||
quota.reset.{user_id}
|
||
|
||
# Audit (append-only)
|
||
audit.{service}.{action}
|
||
|
||
# Ops
|
||
ops.health.{service}
|
||
ops.alert.{severity}
|
||
```
|
||
|
||
### 5.2 Outbox Pattern
|
||
|
||
```sql
|
||
CREATE TABLE outbox (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
aggregate_type VARCHAR(255) NOT NULL,
|
||
aggregate_id VARCHAR(255) NOT NULL,
|
||
event_type VARCHAR(255) NOT NULL,
|
||
payload JSONB NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
published_at TIMESTAMPTZ,
|
||
status VARCHAR(20) DEFAULT 'pending'
|
||
);
|
||
|
||
CREATE INDEX idx_outbox_pending ON outbox(status, created_at)
|
||
WHERE status = 'pending';
|
||
```
|
||
|
||
### 5.3 Dead Letter Queue (DLQ)
|
||
|
||
- Всі невдалі обробки йдуть у DLQ
|
||
- Retry policy: exponential backoff
|
||
- Alert після N retries
|
||
|
||
---
|
||
|
||
## 6. Observability: AgentOps Layer
|
||
|
||
### 6.1 Per-Agent Metrics
|
||
|
||
```yaml
|
||
agent_latency_seconds{agent_id, operation}
|
||
agent_tokens_in_total{agent_id, model}
|
||
agent_tokens_out_total{agent_id, model}
|
||
agent_error_rate{agent_id, error_type}
|
||
agent_tool_calls_total{agent_id, tool}
|
||
agent_budget_consumed{agent_id, user_id}
|
||
```
|
||
|
||
### 6.2 Per-Channel Metrics
|
||
|
||
```yaml
|
||
channel_rag_hit_rate{channel_id}
|
||
channel_index_lag_seconds{channel_id}
|
||
channel_ws_fanout_latency_seconds{channel_id}
|
||
```
|
||
|
||
### 6.3 Per-Node Metrics
|
||
|
||
```yaml
|
||
node_gpu_utilization{node_id, gpu_id}
|
||
node_vram_used_bytes{node_id, gpu_id}
|
||
node_queue_lag_seconds{node_id, queue}
|
||
node_nats_stream_lag{node_id, stream}
|
||
```
|
||
|
||
### 6.4 Auto-Routing Rules
|
||
|
||
```yaml
|
||
# Якщо GPU зайнятий > 80%, переключити на API модель
|
||
routing_rules:
|
||
- condition: node_gpu_utilization > 0.8
|
||
action: route_to_cloud_llm
|
||
|
||
- condition: agent_error_rate > 0.1
|
||
action: fallback_to_backup_agent
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Multi-Node Topology
|
||
|
||
### 7.1 Global Entry
|
||
|
||
```
|
||
gateway.daarion.city (TLS/WAF)
|
||
│
|
||
▼
|
||
[Load Balancer]
|
||
│
|
||
┌────┴────┐
|
||
│ │
|
||
Node1 Node2 ...
|
||
```
|
||
|
||
### 7.2 Per-Node Stack
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ NODE 1 │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ Local Edge Ingress │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ Local DAGI Router │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ Local Swapper (GPU) │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ NATS Leafnode │ │
|
||
│ └───────────────────────────────┘ │
|
||
│ ┌───────────────────────────────┐ │
|
||
│ │ Redis Cache │ │
|
||
│ └───────────────────────────────┘ │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 7.3 Data Layer
|
||
|
||
| Component | Topology |
|
||
|-----------|----------|
|
||
| **Postgres** | Primary + Read Replicas (або per-DAO sharding пізніше) |
|
||
| **Qdrant** | Replication/Sharding |
|
||
| **Neo4j** | Central + Read Replicas (або domain separation) |
|
||
| **NATS** | Supercluster / Leafnodes |
|
||
|
||
---
|
||
|
||
## 8. Phased Rollout Plan
|
||
|
||
### Phase 1: Foundation (2-3 тижні)
|
||
|
||
**Пріоритет:** Не ламати MVP
|
||
|
||
- [ ] Створити Config Registry (версії промптів, routing rules)
|
||
- [ ] Додати Privacy Gate middleware в Router
|
||
- [ ] Стандартизувати NATS subjects
|
||
- [ ] Додати Outbox pattern в Memory Service
|
||
- [ ] AgentOps метрики (базові)
|
||
|
||
### Phase 2: Separation (3-4 тижні)
|
||
|
||
**Пріоритет:** Розділити responsibilities
|
||
|
||
- [ ] Виділити Ingest Service з Gateway
|
||
- [ ] Зробити Router повністю stateless
|
||
- [ ] Винести CrewAI в async workers
|
||
- [ ] Додати Parser Pipeline
|
||
- [ ] Audit append-only stream
|
||
|
||
### Phase 3: Scale (4-6 тижнів)
|
||
|
||
**Пріоритет:** Multi-node готовність
|
||
|
||
- [ ] NATS leafnodes topology
|
||
- [ ] Per-node stack template (k3s)
|
||
- [ ] Auto-routing rules (GPU/load based)
|
||
- [ ] DLQ та retry policies
|
||
- [ ] Full observability dashboard
|
||
|
||
### Phase 4: Production (ongoing)
|
||
|
||
- [ ] Load testing
|
||
- [ ] Chaos engineering
|
||
- [ ] DR (disaster recovery) runbooks
|
||
- [ ] SLA monitoring
|
||
|
||
---
|
||
|
||
## 9. Migration Notes
|
||
|
||
### 9.1 Backward Compatibility
|
||
|
||
- Gateway endpoints залишаються незмінними
|
||
- Внутрішня структура змінюється поступово
|
||
- Feature flags для поступового rollout
|
||
|
||
### 9.2 Breaking Changes
|
||
|
||
| Change | Impact | Mitigation |
|
||
|--------|--------|------------|
|
||
| Ingest Service | File upload latency | Async processing + webhooks |
|
||
| Stateless Router | Session state | Move to NATS/Redis |
|
||
| Async CrewAI | Response time | Progress events + SSE |
|
||
|
||
---
|
||
|
||
## 10. Files to Create/Modify
|
||
|
||
### Нові сервіси:
|
||
- `/services/ingest/` — Ingest Service
|
||
- `/services/config-registry/` — Config Registry
|
||
- `/services/audit/` — Audit Service
|
||
|
||
### Модифікації:
|
||
- `/gateway-bot/` → BFF Gateway (спростити)
|
||
- `/services/router/` → Stateless + Privacy Gate
|
||
- `/services/swapper/` → Capability Runtime (без змін)
|
||
- `/services/memory-service/` → + Outbox pattern
|
||
|
||
### Документація:
|
||
- `/docs/ADR_ARCHITECTURE_VNEXT.md` — цей документ
|
||
- `/docs/NATS_SUBJECTS.md` — стандарти subjects
|
||
- `/docs/PRIVACY_GATE.md` — правила приватності
|
||
|
||
---
|
||
|
||
## Альтернативи (відхилені)
|
||
|
||
1. **Монолітний підхід** — не масштабується
|
||
2. **Full microservices одразу** — занадто складно для команди
|
||
3. **Serverless (Lambda/Cloud Functions)** — cold start, vendor lock-in
|
||
|
||
---
|
||
|
||
## Наслідки
|
||
|
||
### Позитивні:
|
||
- Горизонтальне масштабування
|
||
- Чіткі межі сервісів
|
||
- Системна приватність та аудит
|
||
- Multi-node ready
|
||
|
||
### Негативні:
|
||
- Більше сервісів = більше operational complexity
|
||
- Потрібен час на міграцію
|
||
- Потрібен моніторинг distributed system
|
||
|
||
---
|
||
|
||
**Версія:** 1.0
|
||
**Автор:** Architecture Team
|
||
**Останнє оновлення:** 2026-01-19
|