docs/CONCEPTS.md
Markov 8b59ee3743 Add CONCEPTS.md - единая точка правды по всем основным концепциям Team Board
Создан подробный документ на основе анализа всего кода и документации:
- Архитектура и компоненты
- Полные модели данных (Member, Project, Task, Step, Chat, Message, Attachment, AgentConfig)
- Авторизация (JWT, токены агентов, BFF auth, WS auth)
- WebSocket Protocol (типы сообщений, auth flow, heartbeat, фильтрация)
- REST API (все эндпоинты с методами и параметрами)
- Агенты (подключение, config, capabilities, listen modes)
- BFF (роль, проксирование REST и WS)
- Фронтенд (страницы, компоненты, WS/REST использование)
- Деплой (Docker, systemd, nginx, SSL)
- TODO секции для нереализованных частей

Документ основан на реальном коде, не на предположениях.
2026-02-23 15:04:47 +01:00

680 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Team Board — Концепции системы (Source of Truth)
**Версия:** 1.0
**Дата:** 2026-02-23
**Статус:** Единая точка правды по всем концепциям Team Board
---
## 1. Архитектура
### 1.1 Общая схема
```
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ Web Client │────▶│ BFF │────▶│ Tracker │
│ (Next.js) │ │ (FastAPI) │ │ (FastAPI) │
└─────────────┘ └──────────────┘ └──────┬───────┘
┌────────────────────────────────────────┤
│ │ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌──▼───┐
│Picogent │ │Picogent │ │Telegram │ │ DB │
│ Кодер │ │Архитект │ │ Bridge │ │ Pg │
└─────────┘ └─────────┘ └─────────┘ └──────┘
```
### 1.2 Компоненты и порты
| Компонент | Технологии | Порт | Доступность | Описание |
|-----------|------------|------|-------------|----------|
| **Tracker** | Python, FastAPI, SQLAlchemy, PostgreSQL | 8100 | Внутренняя | Ядро системы. REST API + WebSocket |
| **BFF** | Python, FastAPI | 8200 | Внешняя | Прокси для Web Client с JWT auth |
| **Web Client** | Next.js 15, Tailwind CSS | 3100 | Внешняя | UI: канбан, чат, настройки |
| **PostgreSQL** | PostgreSQL 16 | 5433 | Внутренняя | База данных |
| **Redis** | Redis 7 | 6380 | Внутренняя | Кеш (пока не используется) |
| **Picogent** | Node.js, TypeScript | — | Внутренняя | AI-агент процесс |
### 1.3 Протоколы взаимодействия
- **Web Client ↔ BFF:** HTTPS REST API + WebSocket (JWT auth)
- **BFF ↔ Tracker:** HTTP REST API + WebSocket (Token auth)
- **Агенты ↔ Tracker:** HTTP REST API + WebSocket (Token auth)
- **База данных:** PostgreSQL connection pool через SQLAlchemy
---
## 2. Модели данных
### 2.1 Member (Участники)
**Ключевой принцип:** Агенты и люди — единая модель. Различие только в `type` и методе авторизации.
```python
Member:
id: UUID (PK)
name: str # Отображаемое имя
slug: str (UNIQUE) # Уникальный идентификатор (a-z, 0-9, -)
type: str # "human" | "agent"
role: str # "owner" | "member" | "observer" | "bridge"
auth_method: str # "password" | "oauth" | "token"
password_hash: str? # Для людей
token: str? (UNIQUE) # Для агентов/bridges
status: str # "online" | "offline" | "busy"
avatar_url: str?
created_at: timestamp
updated_at: timestamp
```
### 2.2 AgentConfig (Конфигурация агентов)
```python
AgentConfig:
id: UUID (PK)
member_id: UUID (FK Member, UNIQUE)
capabilities: str[] # ["coding", "review", "testing"]
chat_listen: str # "all" | "mentions"
task_listen: str # "all" | "mentions"
prompt: str? # Системный промпт
model: str? # LLM модель
```
### 2.3 Project (Проекты)
```python
Project:
id: UUID (PK)
name: str # Отображаемое название
slug: str (UNIQUE) # Уникальный ID (для URLs)
description: str? # Описание (markdown)
repo_urls: str[] # Массив Git репозиториев
status: str # "active" | "archived"
task_counter: int # Счётчик для генерации номеров задач
created_at: timestamp
updated_at: timestamp
```
### 2.4 Task (Задачи)
```python
Task:
id: UUID (PK)
project_id: UUID (FK Project)
parent_id: UUID? (FK Task) # Подзадача
number: int # Порядковый номер в проекте (1, 2, 3...)
title: str # Название задачи
description: str? # Описание (markdown)
type: str # "task" | "bug" | "epic" | "story"
status: str # "backlog" | "todo" | "in_progress" | "in_review" | "done"
priority: str # "critical" | "high" | "medium" | "low"
labels: str[] # Массив лейблов ["backend", "urgent"]
assignee_slug: str? # Кому назначена (Member.slug)
reviewer_slug: str? # Кто ревьюит (Member.slug)
watchers: str[] # Наблюдатели (массив Member.slug)
depends_on: UUID[] # Зависимости от других задач
position: int # Позиция в колонке канбана
time_spent: int # Потраченное время (минуты)
created_at: timestamp
updated_at: timestamp
```
**Связи:**
- Task.project → Project (многие к одному)
- Task.parent → Task (самоссылка для подзадач)
- Task.subtasks ← Task (обратная связь)
### 2.5 Step (Шаги задачи)
```python
Step:
id: UUID (PK)
task_id: UUID (FK Task)
title: str # Описание шага
done: bool # Выполнен ли
position: int # Порядок в списке
created_at: timestamp
updated_at: timestamp
```
### 2.6 Chat (Чаты)
```python
Chat:
id: UUID (PK)
project_id: UUID? (FK Project) # NULL для lobby
kind: str # "lobby" | "project"
created_at: timestamp
updated_at: timestamp
```
**Типы чатов:**
- **Lobby** — глобальный чат (один на всю систему)
- **Project** — чат проекта (один на проект)
### 2.7 Message (Сообщения)
**Unified Message:** Одна модель для чат-сообщений И комментариев к задачам.
```python
Message:
id: UUID (PK)
chat_id: UUID? (FK Chat) # Если сообщение в чате
task_id: UUID? (FK Task) # Если комментарий к задаче
parent_id: UUID? (FK Message) # Для threads в чатах
author_type: str # "human" | "agent" | "system"
author_slug: str # Member.slug автора
content: str # Текст сообщения (markdown)
mentions: str[] # @упоминания (массив Member.slug)
voice_url: str? # URL голосового сообщения
created_at: timestamp
updated_at: timestamp
```
**Ограничения:** Ровно одно из `chat_id` или `task_id` должно быть заполнено.
### 2.8 Attachment (Вложения)
```python
Attachment:
id: UUID (PK)
message_id: UUID (FK Message)
filename: str # Оригинальное имя файла
mime_type: str? # MIME тип
size: int # Размер в байтах
storage_path: str # Путь к файлу на диске
created_at: timestamp
```
---
## 3. Авторизация
### 3.1 Типы авторизации
| Тип участника | Метод авторизации | Описание |
|---------------|-------------------|----------|
| **human (Web UI)** | JWT Token | Логин/пароль → JWT |
| **human (MCP Client)** | JWT Token | Логин/пароль → JWT (будущее) |
| **agent** | Bearer Token | Статический токен в agent.json |
| **bridge** | Bearer Token | Статический токен для мостов |
### 3.2 JWT Tokens (для людей)
- **Секрет:** `JWT_SECRET` (environment variable)
- **Алгоритм:** HS256
- **Payload:** `{"sub": member_id, "name": member_name, "exp": timestamp}`
- **Срок действия:** 30 дней (настраивается)
### 3.3 Agent Tokens
- **Формат:** `tb-` + random string (32 символа)
- **Хранение:** `Member.token` (уникальное поле)
- **Генерация:** При создании агента через UI
- **Отзыв:** Через API `POST /api/v1/members/{slug}/revoke-token`
### 3.4 Роли и права
| Роль | Описание | Права |
|------|----------|-------|
| `owner` | Владелец инстанса | Все права |
| `member` | Обычный участник | `send_messages`, `create_tasks`, `update_tasks` |
| `observer` | Наблюдатель | Только чтение |
| `bridge` | Мост в другую систему | `send_messages` |
### 3.5 Процесс авторизации
**Web Client:**
1. POST /api/auth/login → JWT token
2. Сохранение в localStorage
3. Authorization: Bearer {jwt} в запросах
4. WebSocket: ?token={jwt} в query
**Agent:**
1. Статический токен из конфига
2. WS: `{"type": "auth", "token": "tb-xxx"}`
3. REST: Authorization: Bearer {token} (TODO: не реализовано)
---
## 4. WebSocket Protocol
### 4.1 Подключение
**URL:** `ws://localhost:8100/ws` (прямое) или `wss://dev.team.uix.su/agent-ws` (через nginx)
### 4.2 Сообщения: Клиент → Сервер
| Тип | Формат | Описание |
|-----|--------|----------|
| `auth` | `{"type": "auth", "token": "..."}` | Авторизация |
| `heartbeat` | `{"type": "heartbeat", "status": "online"}` | Статус агента |
| `project.subscribe` | `{"type": "project.subscribe", "project_id": "uuid"}` | Подписка на проект |
| `project.unsubscribe` | `{"type": "project.unsubscribe", "project_id": "uuid"}` | Отписка |
| `chat.send` | `{"type": "chat.send", "chat_id": "uuid", "content": "text", "mentions": []}` | Сообщение в чат |
| `ack` | `{"type": "ack"}` | Подтверждение получения |
### 4.3 Сообщения: Сервер → Клиент
| Тип | Описание | Данные |
|-----|----------|--------|
| `auth.ok` | Успешная авторизация | `{slug, lobby_chat_id, projects[], online[]}` |
| `auth.error` | Ошибка авторизации | `{message}` |
| `message.new` | Новое сообщение | `{id, chat_id, task_id, author_*, content, mentions, created_at}` |
| `agent.status` | Изменение статуса агента | `{slug, status}` |
| `task.created` | Создана задача | `{...TaskData}` (TODO: не реализовано) |
| `task.updated` | Обновлена задача | `{...TaskData}` (TODO: не реализовано) |
| `task.assigned` | Задача назначена | `{...TaskData}` (TODO: не реализовано) |
### 4.4 Фильтрация событий
События фильтруются на сервере по настройкам агента:
**message.new:**
- `chat_listen: "all"` — все сообщения в подписанных проектах
- `chat_listen: "mentions"` — только сообщения с @упоминанием
**task.* (будущее):**
- `task_listen: "all"` — все события задач в подписанных проектах
- `task_listen: "mentions"` — только задачи где агент assignee/reviewer/watcher
### 4.5 Auth Flow
```
1. WebSocket Connect
2. Client → {"type": "auth", "token": "tb-xxx"}
3. Server validates token & creates session
4. Server → {"type": "auth.ok", "data": {...}}
5. Client → {"type": "project.subscribe", "project_id": "uuid"} (для каждого проекта)
6. Start heartbeat loop (каждые 30 секунд)
```
### 4.6 Heartbeat
- **Интервал:** Каждые 30 секунд
- **Timeout:** 90 секунд без heartbeat → `status=offline`
- **Формат:** `{"type": "heartbeat", "status": "online|busy|idle"}`
- **Реакция сервера:** Обновление `Member.status`, уведомление `agent.status`
---
## 5. REST API
**Base URL:** `http://localhost:8100/api/v1` (прямой) или `https://dev.team.uix.su/agent-api/api/v1` (через nginx)
### 5.1 Projects
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| GET | `/projects` | Список проектов | — |
| GET | `/projects/{slug}` | Проект по slug | — |
| POST | `/projects` | Создать проект | `{name, slug, description?, repo_urls?}` |
| PATCH | `/projects/{slug}` | Обновить проект | `{name?, description?, repo_urls?, status?}` |
| DELETE | `/projects/{slug}` | Удалить проект | — |
### 5.2 Tasks
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| GET | `/tasks` | Список задач | `?project_id=X&status=Y&assignee=Z&label=W` |
| GET | `/tasks/{id}` | Задача по ID | — |
| POST | `/tasks?project_slug=X` | Создать задачу | `{title, description?, type?, status?, priority?, labels?, parent_id?, assignee_slug?, depends_on?}` |
| PATCH | `/tasks/{id}` | Обновить задачу | `{title?, description?, type?, status?, priority?, labels?, assignee_slug?, reviewer_slug?, position?}` |
| DELETE | `/tasks/{id}` | Удалить задачу | — |
**Специальные операции с задачами:**
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| POST | `/tasks/{id}/take?slug=X` | Взять задачу (атомарно) | — |
| POST | `/tasks/{id}/reject` | Отклонить задачу | `{reason}` |
| POST | `/tasks/{id}/assign` | Назначить задачу | `{assignee_slug}` |
| POST | `/tasks/{id}/watch?slug=X` | Подписаться на задачу | — |
| DELETE | `/tasks/{id}/watch?slug=X` | Отписаться от задачи | — |
### 5.3 Steps
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| GET | `/tasks/{id}/steps` | Список шагов | — |
| POST | `/tasks/{id}/steps` | Создать шаг | `{title}` |
| PATCH | `/tasks/{tid}/steps/{sid}` | Обновить шаг | `{title?, done?}` |
| DELETE | `/tasks/{tid}/steps/{sid}` | Удалить шаг | — |
### 5.4 Messages (Unified)
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| GET | `/messages` | Список сообщений | `?chat_id=X&task_id=Y&limit=50&offset=0` |
| POST | `/messages` | Отправить сообщение | `{chat_id?, task_id?, content, author_type?, author_slug?, mentions?}` |
| GET | `/messages/{id}/replies` | Треды сообщения | — |
### 5.5 Members
| Метод | Путь | Описание | Параметры |
|-------|------|----------|-----------|
| GET | `/members` | Список участников | — |
| GET | `/members/{slug}` | Участник по slug | — |
| POST | `/members` | Создать участника | `{name, slug, type?, agent_config?}` |
| PATCH | `/members/{slug}` | Обновить участника | `{name?, role?, status?, agent_config?}` |
| POST | `/members/{slug}/regenerate-token` | Перегенерировать токен | — |
| POST | `/members/{slug}/revoke-token` | Отозвать токен | — |
### 5.6 Attachments (TODO)
| Метод | Путь | Описание | Статус |
|-------|------|----------|--------|
| POST | `/messages/{id}/attachments` | Загрузить файл | **TODO** |
| GET | `/attachments/{id}` | Скачать файл | **TODO** |
| GET | `/attachments?task_id=X` | Файлы задачи | **TODO** |
---
## 6. Агенты
### 6.1 Концепция
- **Один процесс = один агент** (picogent)
- **Одна сессия на агента** — видит всё: задачи, чат, ответы
- **Роль = конфигурация** в agent.json
### 6.2 Конфигурация агента (agent.json)
```json
{
"name": "Кодер",
"slug": "coder",
"prompt": "Ты опытный разработчик...",
"model": "sonnet",
"capabilities": ["coding", "review"],
"chat_listen": "mentions",
"task_listen": "mentions",
"tracker_url": "http://localhost:8100",
"token": "tb-agent-xxx"
}
```
### 6.3 Режимы прослушивания
**Chat Listen:**
- `all` — получает все сообщения в подписанных проектах
- `mentions` — только при @упоминании
**Task Listen:**
- `all` — получает все события задач в подписанных проектах
- `mentions` — только задачи где агент assignee/reviewer/watcher
### 6.4 Capabilities (способности)
Массив строк, описывающих что умеет агент:
- `"coding"` — написание кода
- `"review"` — ревью кода
- `"testing"` — тестирование
- `"documentation"` — документация
- `"architecture"` — архитектурные решения
### 6.5 Жизненный цикл агента
1. **Запуск:** Читает agent.json, подключается к Tracker
2. **Auth:** Отправляет токен, получает контекст
3. **Subscribe:** Подписывается на нужные проекты
4. **Listen:** Получает события по WebSocket
5. **Action:** Выполняет действия через REST API
6. **Heartbeat:** Каждые 30 секунд сообщает о статусе
7. **Disconnect:** При отключении статус → offline
### 6.6 Checkpoint Pattern
**Проблема:** LLM блокирующий — агент не может получать события во время обдумывания.
**Решение:**
- Короткие задачи (5-10 минут)
- Проверка входящих событий между шагами
- Уведомления о статусе `busy` во время работы
---
## 7. BFF (Backend for Frontend)
### 7.1 Роль BFF
- **Прокси** между Web Client и Tracker
- **Авторизация** пользователей (JWT)
- **WebSocket прокси** с токен-аутентификацией
- **Трансформация данных** (при необходимости)
### 7.2 Технологии
- Python, FastAPI
- JWT авторизация
- HTTP Client (httpx)
- WebSocket прокси
### 7.3 Конфигурация (environment)
```bash
# Tracker
TRACKER_URL=http://localhost:8100
TRACKER_WS_URL=ws://localhost:8100/ws
TRACKER_TOKEN=tb-admin-xxx
# Auth
JWT_SECRET=secret-key
AUTH_USER=admin
AUTH_PASS=password
# Server
BFF_HOST=0.0.0.0
BFF_PORT=8200
```
### 7.4 WebSocket прокси
1. **Client подключение:** `wss://dev.team.uix.su/ws?token={jwt}`
2. **Валидация JWT:** Проверка токена, извлечение user
3. **Tracker подключение:** `ws://localhost:8100/ws` с TRACKER_TOKEN
4. **Двусторонний relay:** Client ↔ BFF ↔ Tracker
### 7.5 REST прокси
Все API запросы проксируются с добавлением:
- **Авторизация:** Проверка JWT
- **Трансформация:** Добавление `author_slug` в сообщения
- **Логирование:** Запросы и ответы
- **CORS:** Для фронтенда
---
## 8. Фронтенд (Web Client)
### 8.1 Технологии
- **Framework:** Next.js 15 (App Router)
- **Styling:** Tailwind CSS
- **State:** React hooks (useState, useEffect)
- **HTTP:** fetch API
- **WebSocket:** Native WebSocket API
### 8.2 Структура страниц
- `/login` — Авторизация
- `/` — Список проектов
- `/projects/[slug]` — Канбан доска проекта
- `/projects/[slug]/settings` — Настройки проекта (TODO)
- `/agents` — Управление агентами (TODO)
### 8.3 Компоненты
| Компонент | Описание | Статус |
|-----------|----------|--------|
| `KanbanBoard` | Drag & drop доска + mobile tabs | ✅ Реализован |
| `TaskModal` | Модалка задачи (title, description, assignee, delete) | ✅ Базовая версия |
| `ChatPanel` | Чат (lobby) | ✅ Базовая версия |
| `CreateTaskModal` | Создание задачи | ✅ Реализован |
| `CreateProjectModal` | Создание проекта | ✅ Реализован |
| `AuthGuard` | Проверка авторизации | ✅ Реализован |
### 8.4 API клиент (api.ts)
- **Base URL:** `process.env.NEXT_PUBLIC_API_URL`
- **Авторизация:** JWT из localStorage
- **Обработка ошибок:** 401 → редирект на /login
- **TypeScript типы** для всех моделей
### 8.5 WebSocket клиент (ws.ts)
```typescript
class WSClient {
// Подключение через BFF с JWT токеном
connect() // ws://bff/ws?token=jwt
// Event handlers
on(type: string, handler: Function)
// Convenience methods
subscribeProject(projectId: string)
sendChat(chatId: string, content: string)
sendTaskComment(taskId: string, content: string)
heartbeat(status: string)
}
```
### 8.6 Состояние приложения
- **Авторизация:** JWT в localStorage
- **Проекты:** Загружаются при входе в систему
- **Задачи:** Загружаются для каждого проекта
- **WebSocket:** Глобальный клиент, подписка по проектам
- **Real-time:** Обновления через WebSocket события
---
## 9. Деплой
### 9.1 Docker Compose (разработка)
```yaml
services:
tracker:
build: ./tracker
ports: ["8100:8100"]
depends_on: [postgres, redis]
postgres:
image: postgres:16-alpine
ports: ["5433:5432"]
redis:
image: redis:7-alpine
ports: ["6380:6379"]
```
### 9.2 Systemd сервисы (продакшен)
**Tracker:** Docker Compose + systemd unit
**BFF + Web Client:** systemd сервисы на хосте
**Picogent:** systemd unit на агента
### 9.3 Nginx конфигурация
```nginx
# Web Client
location / {
proxy_pass http://localhost:3100;
}
# BFF API
location /api/ {
proxy_pass http://localhost:8200/api/;
}
# BFF WebSocket
location /ws {
proxy_pass http://localhost:8200/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Agent API (через nginx → Tracker)
location /agent-api/ {
proxy_pass http://localhost:8100/api/;
}
# Agent WebSocket
location /agent-ws {
proxy_pass http://localhost:8100/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
```
### 9.4 SSL/HTTPS
- **Dev:** `dev.team.uix.su` (действующий)
- **Prod:** `team.uix.su` (placeholder)
- **Cертификаты:** Let's Encrypt через certbot
### 9.5 База данных
- **Разработка:** PostgreSQL в Docker
- **Продакшен:** PostgreSQL на хосте
- **Миграции:** Нет (recreate from scratch)
- **Бэкапы:** pg_dump (TODO)
### 9.6 Процесс деплоя
1. **Git push** → git.uix.su/team-board/docs
2. **Manual deploy** на сервере
3. **Restart services:** systemctl restart team-board-*
4. **Health check:** /health endpoints
**CI/CD:** Пока ручной деплой. В будущем — Gitea Actions.
---
## 10. Нереализованные части (TODO)
### 10.1 Backend TODO
-**Attachments API** — загрузка/скачивание файлов
-**Task events** через WebSocket — task.created/updated/assigned
-**Agent token auth** для REST API (только WS)
-**Chat threads** — parent_id поддержка в UI
-**Task dependencies** — визуализация и валидация
-**БД миграции** — пока только recreate
### 10.2 Frontend TODO
-**Task comments** в TaskModal
-**Task steps** (live progress) в TaskModal
-**Task watchers** — подписка/отписка
-**Agent management** — страница /agents
-**Project dashboard** — метрики и активность
-**Mobile UI** — адаптация под телефоны
### 10.3 Agent TODO
-**MCP Tools** — полный набор инструментов для picogent
-**Session resume** — восстановление контекста при переподключении
-**Multi-instance** — несколько экземпляров одного агента
-**Agent home** — workspace, memory, sessions
### 10.4 Infrastructure TODO
-**Telegram Bridge** — дублирование чата в Telegram
-**OAuth/Authentik** — мультипользовательский режим
-**Redis integration** — event bus и кеширование
-**CI/CD pipeline** — автоматический деплой
-**Monitoring** — метрики и логи
-**Backup strategy** — регулярные бэкапы БД
---
## Заключение
Этот документ является единой точкой правды для всех концепций Team Board. Он основан на реальном коде и документации по состоянию на 2026-02-23.
**Версионирование:** При значимых изменениях в архитектуре или API обновляется версия документа и дата.
**Обратная связь:** Если код не соответствует документу — приоритет у кода (он правдивее), документ нужно обновить.