docs/specs/MODELS.md

17 KiB
Raw Blame History

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_configAgentConfig (1:1, optional)
  • project_membershipsProjectMember[] (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

Связи:

  • memberMember (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

Связи:

  • tasksTask[] (1:many, CASCADE DELETE)
  • chatsChat[] (1:many, CASCADE DELETE)
  • membersProjectMember[] (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

Связи:

  • projectProject (many:1)
  • memberMember (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

Связи:

  • projectProject (many:1)
  • assigneeMember (many:1, optional)
  • reviewerMember (many:1, optional)
  • parentTask (many:1, self-reference)
  • subtasksTask[] (1:many, self-reference)
  • stepsStep[] (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

Связи:

  • taskTask (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)

Таблица: 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

Связи:

  • sourceTask (many:1)
  • targetTask (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

Связи:

  • taskTask (many:1)
  • actorMember (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

Связи:

  • projectProject (many:1, optional)
  • messagesMessage[] (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

Связи:

  • chatChat (many:1, optional)
  • authorMember (many:1, optional)
  • actorMember (many:1, optional)
  • attachmentsAttachment[] (1:many, CASCADE DELETE)
  • repliesMessage[] (1:many, self-reference для тредов)
  • parentMessage (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

Связи:

  • messageMessage (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

Связи:

  • projectProject (many:1)
  • uploaderMember (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/ на дату создания спецификации.