docs/spec/SPECIFICATION-aurora.md
Markov cad887daf4 Expand specification (Aurora Edition v1.1)
- Move to spec/ folder
- Add Aurora to filename
- New sections:
  - 14. Development & Deployment
  - 15. Testing (backend, frontend, E2E, CI/CD)
  - 16. Performance (DB, caching, WebSocket, frontend)
  - 17. Security (JWT, validation, SQL injection, XSS, rate limiting)
  - 18. Monitoring & Logging (logs, Prometheus, health checks, Sentry)
  - 19. Troubleshooting (common issues, diagnostics, recovery)
- Expanded appendices (Glossary, Changelog, Roadmap, API examples, ER diagram)
- Total: 1200+ lines of comprehensive documentation
2026-03-13 15:54:07 +01:00

1537 lines
35 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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(<KanbanBoard projectId="test-project" />)
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 }) => (
<div dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(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*