# Team Board — Модели данных ## Базовая модель (Base) **Таблица:** все таблицы наследуются от Base **Файл:** `base.py` ### Общие поля: ```python id: UUID # Primary key, автогенерируемый UUID4 created_at: TIMESTAMP WITH TIMEZONE # Автоматически при создании updated_at: TIMESTAMP WITH TIMEZONE # Автоматически при обновлении ``` --- ## Members — Участники системы **Таблица:** `members` **Файл:** `member.py` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python id: UUID # Primary key name: str # Название лейбла color: str # HEX цвет (по умолчанию "#6366f1") created_at: TIMESTAMP updated_at: TIMESTAMP ``` ### Индексы: - `UNIQUE (name)` --- ## TaskLabel — Связи задач и лейблов **Таблица:** `task_labels` **Файл:** `task.py` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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` **Универсальная модель:** работает и для чатов, и для комментариев к задачам. ### Поля: ```python 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` ### Поля: ```python 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` ### Поля: ```python 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 ```python HUMAN = "human" # Обычный пользователь AGENT = "agent" # ИИ агент BRIDGE = "bridge" # Мост (например, Telegram) ``` ### MemberRole ```python OWNER = "owner" # Владелец (все права) MEMBER = "member" # Обычный участник BRIDGE = "bridge" # Мост (ограниченные права) ``` ### MemberStatus ```python ONLINE = "online" # В сети OFFLINE = "offline" # Не в сети ``` ### AuthMethod ```python PASSWORD = "password" # Аутентификация по паролю TOKEN = "token" # Аутентификация по Bearer токену ``` ### ChatKind ```python LOBBY = "lobby" # Общий чат PROJECT = "project" # Чат проекта ``` ### ListenMode ```python ALL = "all" # Получать все уведомления MENTIONS = "mentions" # Только при упоминаниях ASSIGNED = "assigned" # Назначенные задачи + упоминания NONE = "none" # Не получать уведомления ``` ### ProjectStatus ```python ACTIVE = "active" # Активный проект ARCHIVED = "archived" # Архивный проект PAUSED = "paused" # Приостановленный проект ``` ### TaskStatus ```python BACKLOG = "backlog" # В беклоге TODO = "todo" # Готово к работе IN_PROGRESS = "in_progress" # В работе IN_REVIEW = "in_review" # На ревью DONE = "done" # Завершено ``` ### TaskType ```python TASK = "task" # Обычная задача BUG = "bug" # Баг FEATURE = "feature" # Новая функциональность ``` ### TaskPriority ```python LOW = "low" # Низкий приоритет MEDIUM = "medium" # Средний приоритет HIGH = "high" # Высокий приоритет CRITICAL = "critical" # Критический приоритет ``` ### AuthorType ```python HUMAN = "human" # Сообщение от человека AGENT = "agent" # Сообщение от агента SYSTEM = "system" # Системное сообщение ``` ### TaskActionType ```python 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 ```python BLOCKS = "blocks" # source блокирует target DEPENDS_ON = "depends_on" # source зависит от target RELATES_TO = "relates_to" # информационная связь ``` ### WSEventType ```python # 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/` на дату создания спецификации.