diff --git a/CONCEPTS.md b/CONCEPTS.md new file mode 100644 index 0000000..9cdcc0e --- /dev/null +++ b/CONCEPTS.md @@ -0,0 +1,680 @@ +# 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 обновляется версия документа и дата. + +**Обратная связь:** Если код не соответствует документу — приоритет у кода (он правдивее), документ нужно обновить. \ No newline at end of file