# Team Board — Полная Спецификация (Aurora Edition) Версия: 1.1 Дата: 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-дорожная-карта) 14. [Разработка и деплой](#14-разработка-и-деплой) 15. [Тестирование](#15-тестирование) 16. [Производительность](#16-производительность) 17. [Безопасность](#17-безопасность) 18. [Мониторинг и логирование](#18-мониторинг-и-логирование) 19. [Troubleshooting](#19-troubleshooting) 20. [Приложения](#20-приложения) --- ## 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 --- ## 14. Разработка и деплой ### 14.1 Локальная разработка **Backend (Tracker):** ```bash cd /root/projects/team-board/tracker python -m venv venv source venv/bin/activate pip install -r requirements.txt alembic upgrade head uvicorn app.main:app --reload --port 8100 ``` **Frontend:** ```bash cd /root/projects/team-board/web-client-vite npm install npm run dev ``` **Agent (Picogent):** ```bash cd /root/projects/team-board/picogent npm install npm run build npm run start --config agent.json ``` ### 14.2 Docker деплой **Сборка:** ```bash docker-compose build ``` **Запуск:** ```bash docker-compose up -d ``` **Логи:** ```bash docker-compose logs -f tracker ``` **Остановка:** ```bash docker-compose down ``` ### 14.3 Миграции БД **Создание миграции:** ```bash alembic revision --autogenerate -m "Add new table" alembic upgrade head ``` **Откат:** ```bash alembic downgrade -1 ``` **История:** ```bash alembic history ``` ### 14.4 Переменные окружения **Tracker (.env):** ```bash DATABASE_URL=postgresql://user:pass@localhost:5432/teamboard JWT_SECRET=your-secret-key CORS_ORIGINS=https://dev.team.uix.su,https://team.uix.su UPLOAD_DIR=/var/www/team-board/uploads ``` **Picogent (.env):** ```bash TRACKER_URL=http://localhost:8100 AGENT_TOKEN=tb-agent-xxx MODEL=claude-sonnet-4 ``` --- ## 15. Тестирование ### 15.1 Backend тесты **Стек:** pytest, pytest-asyncio **Структура:** ``` tests/ ├── conftest.py ├── test_auth.py ├── test_tasks.py ├── test_projects.py └── test_agents.py ``` **Пример:** ```python import pytest from httpx import AsyncClient @pytest.mark.asyncio async def test_create_task(client: AsyncClient, auth_headers): response = await client.post( "/api/projects/test-project/tasks", json={"title": "Test task"}, headers=auth_headers ) assert response.status_code == 201 data = response.json() assert data["title"] == "Test task" ``` **Запуск:** ```bash pytest tests/ -v pytest tests/ --cov=app ``` ### 15.2 Frontend тесты **Стек:** Vitest, React Testing Library **Пример:** ```typescript import { render, screen } from '@testing-library/react' import { KanbanBoard } from './KanbanBoard' test('renders kanban board', () => { render() expect(screen.getByText('To Do')).toBeInTheDocument() }) ``` **Запуск:** ```bash npm run test npm run test:coverage ``` ### 15.3 E2E тесты **Стек:** Playwright **Пример:** ```typescript test('user can create task', async ({ page }) => { await page.goto('/projects/test-project') await page.click('[data-testid="add-task"]') await page.fill('[data-testid="task-title"]', 'New task') await page.click('[data-testid="save-task"]') await expect(page.locator('.task-card')).toBeVisible() }) ``` ### 15.4 CI/CD **GitHub Actions:** ```yaml name: Tests on: [push, pull_request] jobs: backend: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.11' - run: pip install -r requirements.txt - run: pytest --cov=app frontend: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '20' - run: npm ci - run: npm run test ``` --- ## 16. Производительность ### 16.1 Оптимизации БД **Индексы:** ```sql CREATE INDEX idx_tasks_project_status ON tasks(project_id, status); CREATE INDEX idx_tasks_assignee ON tasks(assignee_id); CREATE INDEX idx_messages_project_created ON messages(project_id, created_at DESC); CREATE INDEX idx_members_slug ON members(slug); ``` **Connection pooling:** ```python from sqlalchemy.ext.asyncio import create_async_engine engine = create_async_engine( DATABASE_URL, pool_size=20, max_overflow=10, pool_pre_ping=True, pool_recycle=3600 ) ``` ### 16.2 Кэширование **Redis (будущее):** ```python import aioredis redis = await aioredis.create_redis_pool(REDIS_URL) # Cache project tasks async def get_cached_tasks(project_id: UUID): cached = await redis.get(f"tasks:{project_id}") if cached: return json.loads(cached) tasks = await fetch_tasks_from_db(project_id) await redis.setex(f"tasks:{project_id}", 300, json.dumps(tasks)) return tasks ``` ### 16.3 WebSocket масштабирование **Текущее:** In-memory connections dict **Будущее:** Redis Pub/Sub ```python # Horizontal scaling with Redis await redis.publish("ws:broadcast", json.dumps({ "project_id": str(project_id), "event": event_type, "data": data })) # Each worker subscribes async def redis_subscriber(): pubsub = redis.pubsub() await pubsub.subscribe("ws:broadcast") async for message in pubsub.listen(): event = json.loads(message["data"]) await broadcast_to_local_connections(event) ``` ### 16.4 Фронтенд оптимизации **Code splitting:** ```typescript const KanbanBoard = lazy(() => import('./KanbanBoard')) const Chat = lazy(() => import('./Chat')) ``` **Bundle analysis:** ```bash npm run build -- --mode analyze ``` **Asset optimization:** - Image compression (WebP) - Lazy loading images - Service Worker для offline --- ## 17. Безопасность ### 17.1 JWT Security **Token rotation:** ```python # Short-lived access token (15 min) access_token = create_access_token(user_id, expires_delta=timedelta(minutes=15)) # Long-lived refresh token (7 days) refresh_token = create_refresh_token(user_id, expires_delta=timedelta(days=7)) ``` **Token validation:** ```python async def get_current_user(token: str = Depends(oauth2_scheme)): try: payload = jwt.decode(token, JWT_SECRET, algorithms=["HS256"]) if payload["exp"] < time.time(): raise HTTPException(401, "Token expired") return await get_user(payload["sub"]) except jwt.InvalidTokenError: raise HTTPException(401, "Invalid token") ``` ### 17.2 Input Validation **Pydantic schemas:** ```python from pydantic import BaseModel, validator class TaskCreate(BaseModel): title: str description: str | None priority: Priority = Priority.medium @validator('title') def validate_title(cls, v): if len(v) < 3: raise ValueError('Title must be at least 3 characters') if len(v) > 200: raise ValueError('Title too long') return v ``` ### 17.3 SQL Injection Protection **SQLAlchemy параметризованные запросы:** ```python # ✅ Безопасно tasks = await session.execute( select(Task).where(Task.project_id == :project_id), {"project_id": project_id} ) # ❌ НЕБЕЗОПАСНО (никогда не использовать) query = f"SELECT * FROM tasks WHERE project_id = '{project_id}'" ``` ### 17.4 XSS Protection **Frontend sanitization:** ```typescript import DOMPurify from 'dompurify' const SafeHTML = ({ content }) => (
) ``` ### 17.5 Rate Limiting **Slowapi:** ```python from slowapi import Limiter from slowapi.util import get_remote_address limiter = Limiter(key_func=get_remote_address) @app.post("/api/tasks") @limiter.limit("10/minute") async def create_task(request: Request, task: TaskCreate): ... ``` ### 17.6 CORS **Настройка:** ```python from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins=[ "https://dev.team.uix.su", "https://team.uix.su" ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) ``` --- ## 18. Мониторинг и логирование ### 18.1 Структура логов **Уровни:** DEBUG, INFO, WARNING, ERROR, CRITICAL **Формат:** ```python import logging import json class JSONFormatter(logging.Formatter): def format(self, record): log_obj = { "timestamp": record.created, "level": record.levelname, "logger": record.name, "message": record.getMessage(), "module": record.module, "function": record.funcName, } if record.exc_info: log_obj["exception"] = self.formatException(record.exc_info) return json.dumps(log_obj) logging.setFormatter(JSONFormatter()) ``` ### 18.2 Prometheus метрики **Custom metrics:** ```python from prometheus_client import Counter, Histogram # Counters tasks_created = Counter('tasks_created_total', 'Tasks created') messages_sent = Counter('messages_sent_total', 'Messages sent') agents_active = Counter('agents_active', 'Active agents') # Histograms request_duration = Histogram( 'http_request_duration_seconds', 'HTTP request duration', ['method', 'endpoint'] ) @app.middleware("http") async def metrics_middleware(request: Request, call_next): start = time.time() response = await call_next(request) duration = time.time() - start request_duration.labels(request.method, request.url.path).observe(duration) return response ``` ### 18.3 Health Checks **Endpoint:** ```python @app.get("/api/health") async def health_check(): checks = { "database": await check_database(), "redis": await check_redis() if REDIS_URL else "disabled", "storage": check_storage(), } all_healthy = all(v == "ok" for v in checks.values()) status_code = 200 if all_healthy else 503 return JSONResponse( content={"status": "healthy" if all_healthy else "unhealthy", "checks": checks}, status_code=status_code ) ``` ### 18.4 Error Tracking **Sentry интеграция:** ```python import sentry_sdk from sentry_sdk.integrations.fastapi import FastApiIntegration sentry_sdk.init( dsn=SENTRY_DSN, integrations=[FastApiIntegration()], traces_sample_rate=0.1, environment=ENVIRONMENT, ) ``` ### 18.5 Log Aggregation **ELK Stack (будущее):** - Filebeat → Logstash → Elasticsearch → Kibana - Или: Loki + Grafana --- ## 19. Troubleshooting ### 19.1 Частые проблемы **Проблема:** WebSocket отключается ``` Решение: - Проверить nginx конфигурацию (proxy_read_timeout) - Проверить keepalive настройки - Клиент: reconnect logic ``` **Проблема:** Агент не видит задачи ``` Решение: - Проверить agent token - Проверить project membership - Проверить listen mode (all vs mentions) ``` **Проблема:** Медленные запросы к БД ``` Решение: - Проверить индексы - Проверить connection pool - Включить slow query log - EXPLAIN ANALYZE запроса ``` ### 19.2 Диагностика **Проверка здоровья системы:** ```bash # Backend curl http://localhost:8100/api/health # Database psql -c "SELECT 1" # Redis (если есть) redis-cli ping # Disk space df -h /var/www/team-board ``` **Логи:** ```bash # Tracker logs docker-compose logs tracker | grep ERROR # Nginx logs tail -f /var/log/nginx/error.log # System logs journalctl -u picogent -f ``` **Database queries:** ```sql -- Активные подключения SELECT count(*) FROM pg_stat_activity; -- Медленные запросы SELECT query, calls, total_time FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10; -- Размер таблиц SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size FROM pg_tables WHERE schemaname = 'public' ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC; ``` ### 19.3 Recovery процедуры **Восстановление БД:** ```bash # Backup pg_dump teamboard > backup_$(date +%Y%m%d).sql # Restore psql teamboard < backup_20260313.sql ``` **Откат миграции:** ```bash alembic downgrade -1 ``` **Перезапуск сервисов:** ```bash docker-compose restart tracker sudo systemctl restart picogent sudo systemctl reload nginx ``` --- ## 20. Приложения ### D. Глоссарий | Термин | Определение | |--------|------------| | **Tracker** | Единый backend-сервис | | **Picogent** | AI-агент фреймворк | | **Member** | Участник (человек или агент) | | **Project** | Проект с задачами и чатом | | **Task** | Задача на канбан-доске | | **MCP** | Model Context Protocol | | **BFF** | Backend for Frontend (не используется) | ### E. Changelog **2026-03-13 (v1.1):** - Добавлены разделы 14-19 (Deployment, Testing, Performance, Security, Monitoring, Troubleshooting) - Расширена документация - Aurora Edition **2026-03-13 (v1.0):** - Initial specification - Все основные разделы ### F. Roadmap Details **Q1 2026:** - RBAC implementation - Advanced permissions - Audit logging **Q2 2026:** - GitHub/GitLab integration - Webhooks - External API **Q3 2026:** - Multi-tenant architecture - SaaS preparation - Enterprise features **Q4 2026:** - Mobile application (React Native) - Offline support - Push notifications ### G. API Response Examples **GET /api/projects:** ```json { "projects": [ { "id": "uuid", "slug": "my-project", "name": "My Project", "description": "Description", "color": "#3B82F6", "archived": false, "created_at": "2026-03-13T10:00:00Z", "members_count": 5, "tasks_count": 23 } ], "total": 10, "page": 1, "per_page": 20 } ``` **POST /api/projects/my-project/tasks:** ```json { "id": "uuid", "slug": "TASK-123", "title": "Implement feature X", "description": "Detailed description", "status": "todo", "priority": "high", "assignee": null, "labels": [ {"id": "uuid", "name": "feature", "color": "#10B981"} ], "created_at": "2026-03-13T10:00:00Z", "actor": { "id": "uuid", "slug": "coder", "name": "Кодер" } } ``` ### H. Database Schema (ER Diagram) ``` ┌─────────────┐ │ Member │ ├─────────────┤ │ id (PK) │ │ slug │ │ name │ │ type │ └──────┬──────┘ │ │ 1:N │ ┌──────┴──────────┐ │ ProjectMember │ ├────────────────┤ │ project_id (FK)│ │ member_id (FK) │ │ role │ └──────┬──────────┘ │ │ N:1 │ ┌──────┴──────────┐ │ Project │ ├────────────────┤ │ id (PK) │ │ slug │ │ name │ └──────┬─────────┘ │ │ 1:N │ ┌──────┴──────────┐ │ Task │ ├────────────────┤ │ id (PK) │ │ project_id (FK)│ │ assignee_id(FK)│ │ parent_id (FK) │ └────────────────┘ ``` --- *Документ поддерживается Авророй. Последнее обновление: 2026-03-13* *Версия: Aurora Edition 1.1*