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>
17 KiB
ADR: Improved microdao-daarion Architecture vNext
Дата: 2026-01-19
Статус: Прийнято (Phased Rollout)
Версія: 1.0
Контекст
Поточний стек (Gateway → Router → Swapper → Memory Layer + NATS) працює для MVP, але має обмеження при масштабуванні на багато нод. Потрібно:
- Легше масштабувати на багато нод
- Не "розмити" межі сервісів
- Зробити приватність/аудит/квоти системними, а не точковими
Рішення: 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
- Або контент тільки з явної згоди
- Логи без контенту (тільки метрики)
Реалізація
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
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
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
channel_rag_hit_rate{channel_id}
channel_index_lag_seconds{channel_id}
channel_ws_fanout_latency_seconds{channel_id}
6.3 Per-Node Metrics
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
# Якщо 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— правила приватності
Альтернативи (відхилені)
- Монолітний підхід — не масштабується
- Full microservices одразу — занадто складно для команди
- Serverless (Lambda/Cloud Functions) — cold start, vendor lock-in
Наслідки
Позитивні:
- Горизонтальне масштабування
- Чіткі межі сервісів
- Системна приватність та аудит
- Multi-node ready
Негативні:
- Більше сервісів = більше operational complexity
- Потрібен час на міграцію
- Потрібен моніторинг distributed system
Версія: 1.0
Автор: Architecture Team
Останнє оновлення: 2026-01-19