docs/SPECIFICATION.md
Markov 223be901aa Add comprehensive project specification
- Complete system architecture
- All repositories and components
- Data models with UUID
- API endpoints
- WebSocket events
- Agent system (Picogent)
- Frontend architecture
- Infrastructure setup
- Current features and roadmap
2026-03-13 15:08:27 +01:00

19 KiB
Raw Blame History

Team Board — Полная Спецификация

Версия: 1.0 Дата: 2026-03-13 Статус: В разработке


Оглавление

  1. Общее описание
  2. Архитектура
  3. Репозитории
  4. Компоненты
  5. Модели данных
  6. API
  7. WebSocket
  8. Аутентификация
  9. AI-агенты
  10. Фронтенд
  11. Инфраструктура
  12. Функциональность
  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:

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

Конфигурация:

{
  "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

Конфигурация:

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.

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

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

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

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:

{
  "mentions": [
    {"id": "uuid", "slug": "coder", "name": "Кодер"}
  ]
}

Actor (MemberBrief):

{
  "actor": {
    "id": "uuid",
    "slug": "coder",
    "name": "Кодер"
  }
}

7. WebSocket

7.1 Подключение

wss://dev.team.uix.su/ws?token=JWT_TOKEN

7.2 События

От сервера:

{
  "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.

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:

{
  "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}

Хранение: Хешированные в БД (как пароли)

Использование:

# 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 — глобальная память агента:

# Кодер

## Роль
Опытный разработчик, специализируется на 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

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. Ссылки

B. Контакты

  • Owner: Eugene (@jexon)
  • Organization: team-board

C. Лицензия

MIT


Документ поддерживается Авророй. Последнее обновление: 2026-03-13