17 KiB
Team Board — Модели данных
Базовая модель (Base)
Таблица: все таблицы наследуются от Base
Файл: base.py
Общие поля:
id: UUID # Primary key, автогенерируемый UUID4
created_at: TIMESTAMP WITH TIMEZONE # Автоматически при создании
updated_at: TIMESTAMP WITH TIMEZONE # Автоматически при обновлении
Members — Участники системы
Таблица: members
Файл: member.py
Поля:
id: UUID # Primary key
name: str # Отображаемое имя
slug: str # Уникальный идентификатор (URL-safe)
type: str # human | agent | bridge
role: str # owner | member | observer | bridge
auth_method: str # password | oauth | token
password_hash: str? # Bcrypt hash (только для type=human)
token: str? # Bearer токен (только для type=agent/bridge)
status: str # online | offline | busy
avatar_url: str? # Ссылка на аватар
is_active: bool # Флаг активности (soft delete)
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
agent_config→ AgentConfig (1:1, optional)project_memberships→ ProjectMember[] (1:many)
Индексы:
UNIQUE (slug)UNIQUE (token)гдеtoken IS NOT NULL
AgentConfig — Конфигурация агентов
Таблица: agent_configs
Файл: member.py
Поля:
id: UUID # Primary key
member_id: UUID # FK → members.id (UNIQUE)
capabilities: str[] # Массив возможностей агента
labels: str[] # Лейблы для auto-assign (соответствие с задачами)
chat_listen: str # all | mentions | none
task_listen: str # all | mentions | none
prompt: text? # Системный промпт
model: str? # Модель ИИ (gpt-4, claude-3, etc)
provider: str? # Провайдер (openai, anthropic, etc)
max_concurrent_tasks: int # Лимит одновременных задач (по умолчанию 2)
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
member→ Member (1:1)
Projects — Проекты
Таблица: projects
Файл: project.py
Поля:
id: UUID # Primary key
name: str # Название проекта
slug: str # Уникальный идентификатор (для URL и префиксов задач)
description: text? # Описание проекта
repo_urls: str[] # Массив ссылок на репозитории
status: str # active | archived | paused
task_counter: int # Счётчик задач для генерации номеров (инкрементальный)
auto_assign: bool # Включена ли автоназначение задач по лейблам
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
tasks→ Task[] (1:many, CASCADE DELETE)chats→ Chat[] (1:many, CASCADE DELETE)members→ ProjectMember[] (1:many, CASCADE DELETE)
Индексы:
UNIQUE (slug)
ProjectMember — Участники проектов
Таблица: project_members
Файл: project.py
Поля:
id: UUID # Primary key
project_id: UUID # FK → projects.id (CASCADE DELETE)
member_id: UUID # FK → members.id (CASCADE DELETE)
role: str # owner | member
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
project→ Project (many:1)member→ Member (many:1)
Ограничения:
UNIQUE (project_id, member_id)— один участник не может быть дважды в проекте
Tasks — Задачи
Таблица: tasks
Файл: task.py
Поля:
id: UUID # Primary key
project_id: UUID # FK → projects.id
parent_id: UUID? # FK → tasks.id (для иерархии: эпик → история → задача)
number: int # Номер в рамках проекта (XX-1, XX-2, XX-3)
title: str # Заголовок задачи
description: text? # Детальное описание
type: str # task | bug | feature
status: str # backlog | todo | in_progress | in_review | done
priority: str # critical | high | medium | low
labels: str[] # Массив лейблов (для фильтрации и auto-assign)
assignee_id: UUID? # FK → members.id (исполнитель)
reviewer_id: UUID? # FK → members.id (ревьюер)
watcher_ids: UUID[] # Массив ID участников, подписанных на уведомления
depends_on: UUID[] # Массив ID задач-зависимостей
position: int # Позиция в колонке канбана
time_spent: int # Потраченное время в минутах
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
project→ Project (many:1)assignee→ Member (many:1, optional)reviewer→ Member (many:1, optional)parent→ Task (many:1, self-reference)subtasks→ Task[] (1:many, self-reference)steps→ Step[] (1:many, CASCADE DELETE, ordered by position)
Steps — Этапы задач (чеклист)
Таблица: steps
Файл: task.py
Поля:
id: UUID # Primary key
task_id: UUID # FK → tasks.id (CASCADE DELETE)
title: str # Название этапа
done: bool # Выполнен ли (по умолчанию false)
position: int # Порядок в списке
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
task→ Task (many:1)
Labels — Глобальные лейблы
Таблица: labels
Файл: task.py
Поля:
id: UUID # Primary key
name: str # Название лейбла
color: str # HEX цвет (по умолчанию "#6366f1")
created_at: TIMESTAMP
updated_at: TIMESTAMP
Индексы:
UNIQUE (name)
TaskLabel — Связи задач и лейблов
Таблица: task_labels
Файл: task.py
Поля:
id: UUID # Primary key
task_id: UUID # FK → tasks.id (CASCADE DELETE)
label_id: UUID # FK → labels.id (CASCADE DELETE)
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
- Связывает Task и Label (many:many)
TaskLink — Зависимости между задачами
Таблица: task_links
Файл: task.py
Поля:
id: UUID # Primary key
source_id: UUID # FK → tasks.id (CASCADE DELETE) - исходная задача
target_id: UUID # FK → tasks.id (CASCADE DELETE) - целевая задача
link_type: str # blocks | depends_on | relates_to
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
source→ Task (many:1)target→ Task (many:1)
Типы связей:
blocks— source блокирует target (target заблокирована source)depends_on— source зависит от target (source заблокирована target)relates_to— информационная связь (двусторонняя)
TaskAction — Аудит действий с задачами
Таблица: task_actions
Файл: task.py
Поля:
id: UUID # Primary key
task_id: UUID # FK → tasks.id (CASCADE DELETE)
actor_id: UUID # FK → members.id (кто совершил действие)
action: str # created | status_changed | assigned | etc.
field: str? # Какое поле изменилось
old_value: text? # Старое значение
new_value: text? # Новое значение
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
task→ Task (many:1)actor→ Member (many:1)
Chats — Чаты
Таблица: chats
Файл: chat.py
Поля:
id: UUID # Primary key
project_id: UUID? # FK → projects.id (null для lobby чата)
kind: str # lobby | project
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
project→ Project (many:1, optional)messages→ Message[] (1:many, CASCADE DELETE)
Messages — Сообщения
Таблица: messages
Файл: chat.py
Универсальная модель: работает и для чатов, и для комментариев к задачам.
Поля:
id: UUID # Primary key
chat_id: UUID? # FK → chats.id (для сообщений в чате)
task_id: UUID? # FK → tasks.id (для комментариев к задаче, CASCADE DELETE)
parent_id: UUID? # FK → messages.id (для тредов - ответов на сообщения)
author_type: str # human | agent | system
author_id: UUID? # FK → members.id (автор сообщения)
actor_id: UUID? # FK → members.id (инициатор действия для системных сообщений)
tool_log: JSON? # JSON массив вызовов инструментов [{name, args, result, error}]
content: text # Текст сообщения
thinking: text? # Внутренние размышления ИИ (для агентов)
mentions: str[] # Массив ID упомянутых участников
voice_url: str? # Ссылка на голосовое сообщение
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
chat→ Chat (many:1, optional)author→ Member (many:1, optional)actor→ Member (many:1, optional)attachments→ Attachment[] (1:many, CASCADE DELETE)replies→ Message[] (1:many, self-reference для тредов)parent→ Message (many:1, self-reference)
Ограничения:
- Должно быть заполнено либо
chat_id, либоtask_id(не оба)
Attachments — Файловые вложения
Таблица: attachments
Файл: chat.py
Поля:
id: UUID # Primary key
message_id: UUID # FK → messages.id
filename: str # Исходное имя файла
mime_type: str? # MIME тип файла
size: int # Размер в байтах (по умолчанию 0)
storage_path: str # Путь к файлу в файловой системе
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
message→ Message (many:1)
Хранение:
- Файлы сохраняются в
/data/uploads/ storage_pathсодержит имя файла на диске (UUID + расширение)
ProjectFile — Файлы проектов
Таблица: project_files
Файл: project_file.py
Поля:
id: UUID # Primary key
project_id: UUID # FK → projects.id (CASCADE DELETE)
filename: str # Имя файла
description: text? # Описание файла
mime_type: str? # MIME тип файла
size: int # Размер в байтах
uploaded_by: UUID # FK → members.id (кто загрузил, CASCADE DELETE)
storage_path: str # Относительный путь внутри папки проекта
created_at: TIMESTAMP
updated_at: TIMESTAMP
Связи:
project→ Project (many:1)uploader→ Member (many:1)
Хранение:
- Файлы сохраняются в
/data/projects/{project_slug}/ storage_pathсодержит относительный путь (обычно совпадает сfilename)
Enums — Перечисления
Файл: enums.py
MemberType
HUMAN = "human" # Обычный пользователь
AGENT = "agent" # ИИ агент
BRIDGE = "bridge" # Мост (например, Telegram)
MemberRole
OWNER = "owner" # Владелец (все права)
MEMBER = "member" # Обычный участник
BRIDGE = "bridge" # Мост (ограниченные права)
MemberStatus
ONLINE = "online" # В сети
OFFLINE = "offline" # Не в сети
AuthMethod
PASSWORD = "password" # Аутентификация по паролю
TOKEN = "token" # Аутентификация по Bearer токену
ChatKind
LOBBY = "lobby" # Общий чат
PROJECT = "project" # Чат проекта
ListenMode
ALL = "all" # Получать все уведомления
MENTIONS = "mentions" # Только при упоминаниях
ASSIGNED = "assigned" # Назначенные задачи + упоминания
NONE = "none" # Не получать уведомления
ProjectStatus
ACTIVE = "active" # Активный проект
ARCHIVED = "archived" # Архивный проект
PAUSED = "paused" # Приостановленный проект
TaskStatus
BACKLOG = "backlog" # В беклоге
TODO = "todo" # Готово к работе
IN_PROGRESS = "in_progress" # В работе
IN_REVIEW = "in_review" # На ревью
DONE = "done" # Завершено
TaskType
TASK = "task" # Обычная задача
BUG = "bug" # Баг
FEATURE = "feature" # Новая функциональность
TaskPriority
LOW = "low" # Низкий приоритет
MEDIUM = "medium" # Средний приоритет
HIGH = "high" # Высокий приоритет
CRITICAL = "critical" # Критический приоритет
AuthorType
HUMAN = "human" # Сообщение от человека
AGENT = "agent" # Сообщение от агента
SYSTEM = "system" # Системное сообщение
TaskActionType
CREATED = "created"
STATUS_CHANGED = "status_changed"
ASSIGNED = "assigned"
UNASSIGNED = "unassigned"
PRIORITY_CHANGED = "priority_changed"
TITLE_CHANGED = "title_changed"
DESCRIPTION_CHANGED = "description_changed"
REVIEWER_CHANGED = "reviewer_changed"
WATCHER_ADDED = "watcher_added"
WATCHER_REMOVED = "watcher_removed"
DELETED = "deleted"
TaskLinkType
BLOCKS = "blocks" # source блокирует target
DEPENDS_ON = "depends_on" # source зависит от target
RELATES_TO = "relates_to" # информационная связь
WSEventType
# Auth события
AUTH = "auth"
AUTH_OK = "auth.ok"
AUTH_ERROR = "auth.error"
# Системные
HEARTBEAT = "heartbeat"
ACK = "ack"
ERROR = "error"
# Чат и подписки
CHAT_SEND = "chat.send"
PROJECT_SUBSCRIBE = "project.subscribe"
PROJECT_UNSUBSCRIBE = "project.unsubscribe"
MESSAGE_NEW = "message.new"
# Задачи
TASK_CREATED = "task.created"
TASK_UPDATED = "task.updated"
TASK_ASSIGNED = "task.assigned"
TASK_DELETED = "task.deleted"
# Агенты
AGENT_STATUS = "agent.status"
AGENT_STREAM_START = "agent.stream.start"
AGENT_STREAM_DELTA = "agent.stream.delta"
AGENT_STREAM_TOOL = "agent.stream.tool"
AGENT_STREAM_END = "agent.stream.end"
CONFIG_UPDATED = "config.updated"
Схема связей
Member 1:1 AgentConfig
Member 1:N ProjectMember N:1 Project
Project 1:N Task
Task 1:N Step
Task N:M Label (через TaskLabel)
Task 1:N TaskLink N:1 Task
Task 1:N TaskAction N:1 Member
Project 1:N Chat
Chat 1:N Message
Message 1:N Attachment
Message 1:N Message (parent/replies)
Project 1:N ProjectFile N:1 Member
Этот документ описывает структуру базы данных на основе моделей SQLAlchemy в /root/projects/team-board/tracker/src/tracker/models/ на дату создания спецификации.