snapshot: NODE1 production state 2026-02-09
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>
This commit is contained in:
491
docs/ADR_ARCHITECTURE_VNEXT.md
Normal file
491
docs/ADR_ARCHITECTURE_VNEXT.md
Normal file
@@ -0,0 +1,491 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user