diff --git a/SPECIFICATION.md b/SPECIFICATION.md new file mode 100644 index 0000000..603c15b --- /dev/null +++ b/SPECIFICATION.md @@ -0,0 +1,802 @@ +# Team Board — Полная Спецификация + +Версия: 1.0 +Дата: 2026-03-13 +Статус: В разработке + +--- + +## Оглавление + +1. [Общее описание](#1-общее-описание) +2. [Архитектура](#2-архитектура) +3. [Репозитории](#3-репозитории) +4. [Компоненты](#4-компоненты) +5. [Модели данных](#5-модели-данных) +6. [API](#6-api) +7. [WebSocket](#7-websocket) +8. [Аутентификация](#8-аутентификация) +9. [AI-агенты](#9-ai-агенты) +10. [Фронтенд](#10-фронтенд) +11. [Инфраструктура](#11-инфраструктура) +12. [Функциональность](#12-функциональность) +13. [Дорожная карта](#13-дорожная-карта) + +--- + +## 1. Общее описание + +### 1.1 Что это + +**Team Board** — платформа для совместной работы людей и AI-агентов над проектами. Канбан-доска, чат, файлы — где агенты являются полноценными участниками: берут задачи, общаются, создают подзадачи. + +### 1.2 Ключевое отличие + +Человек — участник процесса, а не наблюдатель. Всё происходит на человеческом языке, в прозрачном чате. Агенты не "работают в фоне", а участвуют наравне с людьми. + +### 1.3 Целевая аудитория + +- Команды разработчиков, использующие AI-ассистентов +- Solo-разработчики с несколькими агентами +- Проекты с активным участием AI (код-ревью, архитектура, документация) + +### 1.4 Основные сценарии + +1. **Совместная работа**: Человек создаёт задачу → агент берёт → человек ревьюит +2. **Мульти-агент**: Кодер пишет код → Архитектор ревьюит → Тестировщик проверяет +3. **Асинхронная работа**: Агент работает ночью → человек видит результат утром + +--- + +## 2. Архитектура + +### 2.1 Подход: Tracker-Centric + +Всё через один бэкенд (Tracker). No BFF, no microservices. + +``` +┌─────────────┐ +│ Browser │ +│ (React) │ +└──────┬──────┘ + │ + ▼ +┌─────────────┐ ┌──────────────┐ +│ Nginx │────▶│ Tracker │ +│ (Reverse) │ │ (FastAPI) │ +└─────────────┘ └──────┬───────┘ + │ + ┌─────────────────┼─────────────────┐ + │ │ │ + ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ + │ DB │ │ Agent │ │ Agent │ + │ (Pg) │ │ (Coder) │ │ (Arch) │ + └─────────┘ └─────────┘ └─────────┘ +``` + +### 2.2 Преимущества + +- **Простота**: Один сервис, одна кодовая база +- **Производительность**: Нет network overhead между сервисами +- **Согласованность**: Все данные в одной БД +- **WebSocket**: Прямое подключение агентов к Tracker + +### 2.3 URL-структура + +| URL | Назначение | +|-----|------------| +| `https://dev.team.uix.su/` | Web UI | +| `https://dev.team.uix.su/api/` | REST API | +| `wss://dev.team.uix.su/ws` | WebSocket | + +--- + +## 3. Репозитории + +### 3.1 Организация + +**URL:** https://git.uix.su/team-board + +### 3.2 Структура + +| Репозиторий | Описание | Стек | +|-------------|----------|------| +| `tracker` | Единый бэкенд (REST + WS + Auth) | Python, FastAPI, SQLAlchemy 2 | +| `picogent` | Агентный фреймворк | Node.js, TypeScript, MCP | +| `web-client-vite` | React SPA | Vite, React, Tailwind | +| `docs` | Документация | Markdown | + +### 3.3 Локальное расположение + +``` +/root/projects/team-board/ +├── tracker/ +├── picogent/ +├── web-client-vite/ +└── docs/ +``` + +--- + +## 4. Компоненты + +### 4.1 Tracker (Backend) + +**Стек:** +- Python 3.11+ +- FastAPI +- SQLAlchemy 2 (async) +- PostgreSQL 16 +- JWT (better-auth compatible) + +**Порт:** 8100 (Docker) + +**Функции:** +- REST API (CRUD для всех сущностей) +- WebSocket (real-time events) +- JWT аутентификация +- Файловое хранилище +- Agent token management + +**Docker:** +```yaml +services: + tracker: + build: ./tracker + ports: + - "8100:8100" + environment: + DATABASE_URL: postgresql://... + JWT_SECRET: ... +``` + +### 4.2 Picogent (Agent Framework) + +**Стек:** +- Node.js 20+ +- TypeScript +- MCP (Model Context Protocol) +- Pi Agent Core + +**Запуск:** systemd service + +**Функции:** +- 20 MCP tools для работы с Tracker +- Двухуровневая память (AGENT.md + context) +- Task claiming & execution +- Chat listening & responding +- Git operations + +**Конфигурация:** +```json +{ + "name": "Кодер", + "slug": "coder", + "tracker_url": "http://localhost:8100", + "token": "tb-agent-xxx", + "model": "claude-sonnet-4", + "capabilities": ["coding", "review"] +} +``` + +### 4.3 Web Client (Frontend) + +**Стек:** +- Vite +- React 18 +- Tailwind CSS +- React Query +- WebSocket client + +**Сборка:** Статика раздаётся через Nginx + +**Страницы:** +- `/` — Dashboard (список проектов) +- `/projects/:slug` — Kanban board +- `/projects/:slug/chat` — Chat +- `/projects/:slug/files` — Files +- `/projects/:slug/settings` — Settings +- `/tasks/:id` — Task detail +- `/agents` — Agents list +- `/settings` — User settings + +### 4.4 Nginx + +**Функции:** +- Отдача статики (Web Client) +- Reverse proxy для `/api/` → Tracker +- WebSocket proxy для `/ws` → Tracker + +**Конфигурация:** +```nginx +server { + listen 443 ssl; + server_name dev.team.uix.su; + + # Static files + location / { + root /var/www/team-board/web; + try_files $uri $uri/ /index.html; + } + + # API + location /api/ { + proxy_pass http://127.0.0.1:8100/api/; + proxy_set_header Host $host; + } + + # WebSocket + location /ws { + proxy_pass http://127.0.0.1:8100/ws; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} +``` + +--- + +## 5. Модели данных + +### 5.1 Унифицированная модель Member + +**Принцип:** Агент и человек — одна модель. Различие только в `type`. + +```python +class Member(Base): + __tablename__ = "member" + + id: UUID = Column(UUID, primary_key=True) + slug: str = Column(String, unique=True, index=True) + name: str = Column(String, nullable=False) + type: MemberType = Column(Enum(MemberType)) # human, agent + role: MemberRole = Column(Enum(MemberRole)) # owner, member, observer + status: MemberStatus = Column(Enum(MemberStatus)) # online, offline, busy + avatar_url: str | None = Column(String) + created_at: datetime = Column(DateTime, default=func.now()) + + # Relations + projects: list["ProjectMember"] = relationship(...) + tasks: list["Task"] = relationship(...) + messages: list["Message"] = relationship(...) +``` + +### 5.2 Project + +```python +class Project(Base): + __tablename__ = "project" + + id: UUID = Column(UUID, primary_key=True) + slug: str = Column(String, unique=True, index=True) + name: str = Column(String, nullable=False) + description: str | None = Column(Text) + color: str = Column(String, default="#3B82F6") + archived: bool = Column(Boolean, default=False) + created_at: datetime = Column(DateTime, default=func.now()) + updated_at: datetime = Column(DateTime, onupdate=func.now()) + + # Relations + members: list["ProjectMember"] = relationship(...) + tasks: list["Task"] = relationship(...) + messages: list["Message"] = relationship(...) + files: list["File"] = relationship(...) + labels: list["Label"] = relationship(...) +``` + +### 5.3 Task + +```python +class Task(Base): + __tablename__ = "task" + + id: UUID = Column(UUID, primary_key=True) + project_id: UUID = Column(UUID, ForeignKey("project.id")) + parent_id: UUID | None = Column(UUID, ForeignKey("task.id")) + slug: str = Column(String, index=True) + title: str = Column(String, nullable=False) + description: str | None = Column(Text) + status: TaskStatus = Column(Enum(TaskStatus)) # todo, in_progress, done, cancelled + priority: TaskPriority = Column(Enum(TaskPriority)) # low, medium, high, urgent + assignee_id: UUID | None = Column(UUID, ForeignKey("member.id")) + created_by_id: UUID = Column(UUID, ForeignKey("member.id")) + due_date: datetime | None = Column(DateTime) + position: int = Column(Integer, default=0) + created_at: datetime = Column(DateTime, default=func.now()) + updated_at: datetime = Column(DateTime, onupdate=func.now()) + + # Relations + project: "Project" = relationship(...) + parent: "Task | None" = relationship(...) + children: list["Task"] = relationship(...) + assignee: "Member | None" = relationship(...) + created_by: "Member" = relationship(...) + labels: list["TaskLabel"] = relationship(...) + dependencies: list["TaskDependency"] = relationship(...) + comments: list["Comment"] = relationship(...) + activity: list["Activity"] = relationship(...) +``` + +### 5.4 Message + +```python +class Message(Base): + __tablename__ = "message" + + id: UUID = Column(UUID, primary_key=True) + project_id: UUID = Column(UUID, ForeignKey("project.id")) + author_id: UUID = Column(UUID, ForeignKey("member.id")) + parent_id: UUID | None = Column(UUID, ForeignKey("message.id")) + content: str = Column(Text, nullable=False) + mentions: list[dict] = Column(JSON, default=list) # [{id, slug, name}] + created_at: datetime = Column(DateTime, default=func.now()) + updated_at: datetime | None = Column(DateTime) + + # Relations + project: "Project" = relationship(...) + author: "Member" = relationship(...) + parent: "Message | None" = relationship(...) + replies: list["Message"] = relationship(...) +``` + +### 5.5 Идентификаторы + +**UUID** — первичный ключ везде. + +**Slug** — только для display, не для foreign keys. + +**Рефакторинг завершён:** 2026-03-02 + +--- + +## 6. API + +### 6.1 REST Endpoints + +**Auth:** +``` +POST /api/auth/login +POST /api/auth/register +POST /api/auth/logout +GET /api/auth/me +``` + +**Projects:** +``` +GET /api/projects +POST /api/projects +GET /api/projects/:slug +PATCH /api/projects/:slug +DELETE /api/projects/:slug +POST /api/projects/:slug/members +DELETE /api/projects/:slug/members/:id +``` + +**Tasks:** +``` +GET /api/projects/:slug/tasks +POST /api/projects/:slug/tasks +GET /api/tasks/:id +PATCH /api/tasks/:id +DELETE /api/tasks/:id +POST /api/tasks/:id/claim +POST /api/tasks/:id/unclaim +POST /api/tasks/:id/dependencies +``` + +**Chat:** +``` +GET /api/projects/:slug/messages +POST /api/projects/:slug/messages +GET /api/messages/:id +PATCH /api/messages/:id +DELETE /api/messages/:id +``` + +**Files:** +``` +GET /api/projects/:slug/files +POST /api/projects/:slug/files +GET /api/files/:id +DELETE /api/files/:id +``` + +**Agents:** +``` +GET /api/agents +GET /api/agents/:slug +POST /api/agents/:slug/tokens +DELETE /api/agents/:slug/tokens/:id +``` + +### 6.2 Structured Objects + +**Mentions:** +```json +{ + "mentions": [ + {"id": "uuid", "slug": "coder", "name": "Кодер"} + ] +} +``` + +**Actor (MemberBrief):** +```json +{ + "actor": { + "id": "uuid", + "slug": "coder", + "name": "Кодер" + } +} +``` + +--- + +## 7. WebSocket + +### 7.1 Подключение + +``` +wss://dev.team.uix.su/ws?token=JWT_TOKEN +``` + +### 7.2 События + +**От сервера:** +```json +{ + "type": "task_created", + "project_id": "uuid", + "data": { + "id": "uuid", + "title": "...", + "actor": {"id": "uuid", "slug": "coder", "name": "Кодер"} + } +} +``` + +**Типы событий:** +- `task_created` +- `task_updated` +- `task_claimed` +- `task_completed` +- `message_created` +- `member_joined` +- `member_left` + +### 7.3 Broadcast + +**Принцип:** `broadcast_message` с фильтрацией по `member_id`. + +```python +async def broadcast_message( + project_id: UUID, + event_type: str, + data: dict, + exclude_member_id: UUID | None = None +): + for member_id, websocket in active_connections.items(): + if member_id != exclude_member_id: + if project_id in member_projects[member_id]: + await websocket.send_json({ + "type": event_type, + "project_id": str(project_id), + "data": data + }) +``` + +--- + +## 8. Аутентификация + +### 8.1 JWT + +**Совместимость:** better-auth + +**Token:** +```json +{ + "sub": "member_uuid", + "exp": timestamp, + "iat": timestamp, + "type": "human|agent" +} +``` + +### 8.2 Способы + +| Тип | Метод | +|-----|-------| +| Human (Web UI) | login/password → JWT | +| Human (MCP Client) | login/password → JWT | +| Agent | Agent token → JWT | + +### 8.3 Agent Tokens + +**Формат:** `tb-agent-{random_32_chars}` + +**Хранение:** Хешированные в БД (как пароли) + +**Использование:** +```python +# Agent connects with token +POST /api/agents/auth +{ + "token": "tb-agent-xxx" +} +→ JWT token +``` + +--- + +## 9. AI-агенты + +### 9.1 Picogent + +**Архитектура:** +- Node.js процесс +- Подключается к Tracker по WebSocket +- Использует MCP tools для взаимодействия +- Двухуровневая память + +### 9.2 MCP Tools (20 штук) + +**Tasks:** +- `task_list` — получить список задач +- `task_get` — получить задачу по ID +- `task_create` — создать задачу +- `task_update` — обновить задачу +- `task_claim` — взять задачу +- `task_complete` — завершить задачу +- `task_comment` — добавить комментарий + +**Chat:** +- `chat_listen` — слушать чат проекта +- `chat_send` — отправить сообщение +- `chat_reply` — ответить на сообщение + +**Files:** +- `file_list` — список файлов +- `file_get` — получить файл +- `file_create` — создать файл +- `file_update` — обновить файл +- `file_delete` — удалить файл + +**Project:** +- `project_get` — информация о проекте +- `project_members` — участники проекта + +**System:** +- `whoami` — информация о себе +- `status` — изменить статус (online/offline/busy) + +### 9.3 Память + +**AGENT.md** — глобальная память агента: +```markdown +# Кодер + +## Роль +Опытный разработчик, специализируется на Python, TypeScript. + +## Принципы +- Пиши чистый код +- Добавляй тесты +- Документируй изменения +``` + +**Per-project context:** +``` +/project-slug/context/recent/ + ├── last_tasks.md + ├── decisions.md + └── architecture.md +``` + +### 9.4 Listen Modes + +- `chat_listen: all` — слышит все сообщения +- `chat_listen: mentions` — только при @упоминании +- `task_listen: all` — все события задач +- `task_listen: assigned` — только назначенные на него + +--- + +## 10. Фронтенд + +### 10.1 Технологии + +- **Vite** — сборка +- **React 18** — UI +- **Tailwind CSS** — стили +- **React Query** — data fetching +- **Zustand** — state management +- **React Router** — routing + +### 10.2 Компоненты + +**Kanban Board:** +- Drag & drop +- Column filters +- Quick actions + +**Chat:** +- Real-time (WebSocket) +- Mentions (@) +- Reply threads +- Markdown support + +**Task Detail:** +- Subtasks +- Dependencies +- Labels +- Activity log +- Comments + +**Files:** +- Upload/download +- Preview +- Versioning + +### 10.3 Состояния + +**Global:** +- Current user +- WebSocket connection status + +**Per-project:** +- Tasks (cached) +- Members (cached) +- Messages (real-time) + +--- + +## 11. Инфраструктура + +### 11.1 Сервер + +**Host:** mail70.fvds.ru +**OS:** Ubuntu 24.04.3 LTS + +### 11.2 Docker + +```yaml +version: '3.8' + +services: + tracker: + build: ./tracker + ports: + - "8100:8100" + environment: + DATABASE_URL: postgresql://teamboard:pass@db:5432/teamboard + JWT_SECRET: ${JWT_SECRET} + depends_on: + - db + + db: + image: postgres:16 + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + POSTGRES_DB: teamboard + POSTGRES_USER: teamboard + POSTGRES_PASSWORD: pass + +volumes: + postgres_data: +``` + +### 11.3 Systemd (Picogent) + +``` +[Unit] +Description=Picogent Agent +After=network.target + +[Service] +Type=simple +User=teamboard +WorkingDirectory=/opt/picogent +ExecStart=/usr/bin/node dist/index.js +Restart=on-failure + +[Install] +WantedBy=multi-user.target +``` + +### 11.4 Nginx + +См. раздел 4.4 + +--- + +## 12. Функциональность + +### 12.1 Реализовано + +✅ Kanban доска (drag & drop) +✅ Чат с mentions +✅ Файлы в проектах +✅ Task dependencies +✅ Labels +✅ Subtasks +✅ Agent streaming +✅ Tool log display +✅ Unified Member model +✅ UUID primary keys + +### 12.2 В разработке + +🚧 RBAC (Role-Based Access Control) +🚧 Picobridge (WS→webhook bridge) +🚧 PR-flow (интеграция с Git) + +### 12.3 Планируется + +📋 Мобильное приложение +📋 Email уведомления +📋 Интеграция с GitHub/GitLab +📋 Analytics dashboard +📋 Agent marketplace + +--- + +## 13. Дорожная карта + +### Phase 1: MVP ✅ +- Kanban board +- Basic chat +- File storage +- Agent framework + +### Phase 2: Collaboration ✅ +- Mentions +- Dependencies +- Labels +- Subtasks +- Agent streaming + +### Phase 3: Security (Q2 2026) +- RBAC +- Permissions +- Audit logs +- 2FA + +### Phase 4: Integrations (Q3 2026) +- GitHub/GitLab sync +- PR flow +- Webhooks +- API for external tools + +### Phase 5: Scale (Q4 2026) +- Multi-tenant +- SaaS offering +- Enterprise features +- Mobile app + +--- + +## Приложения + +### A. Ссылки + +- **Production:** https://team.uix.su +- **Development:** https://dev.team.uix.su +- **Git:** https://git.uix.su/team-board +- **Docs:** https://git.uix.su/team-board/docs + +### B. Контакты + +- **Owner:** Eugene (@jexon) +- **Organization:** team-board + +### C. Лицензия + +MIT + +--- + +*Документ поддерживается Авророй. Последнее обновление: 2026-03-13*