Initial commit: VoIdeaAI - voice-first AI idea assistant
This commit is contained in:
+840
@@ -0,0 +1,840 @@
|
||||
# VoIdeaAI — Финальная спецификация проекта
|
||||
|
||||
**Роль:** ты — старший архитектор ПО и продуктовый аналитик. Твоя задача — зафиксировать полное описание, промпты, архитектуру и все функциональные связи продукта VoIdeaAI.
|
||||
|
||||
**Цель:** голосовой AI-ассистент для генерации, проработки и сохранения идей с помощью группового ИИ-анализа. Пользователь говорит или печатает — система через оркестратора (Дирижёр) направляет запрос специализированному ролевому агенту, верифицирует ответ и возвращает результат с оценкой уверенности.
|
||||
|
||||
---
|
||||
|
||||
## 1. Общая архитектура
|
||||
|
||||
```
|
||||
Browser (PWA — React + TypeScript + Tailwind)
|
||||
│ Web Speech API (распознавание) / SpeechSynthesis (озвучивание)
|
||||
│ HTTPS
|
||||
▼
|
||||
Nginx (reverse proxy, SSL termination, Let's Encrypt)
|
||||
│
|
||||
▼
|
||||
FastAPI (Python 3.12+, async)
|
||||
├── StaticFiles — /assets, /icons, SPA fallback
|
||||
├── SecurityHeadersMiddleware — CSP, HSTS, X-Frame-Options и др.
|
||||
├── CORSMiddleware — whitelist origins
|
||||
├── Limiter (slowapi) — rate limiting на все endpoints
|
||||
│
|
||||
├── API v1 (/api/v1)
|
||||
│ ├── /auth — регистрация, логин, OAuth, сброс пароля
|
||||
│ ├── /voice — транскрибация, чат, сессии, рейтинг
|
||||
│ ├── /users — профиль, настройки
|
||||
│ ├── /ideas — CRUD идей
|
||||
│ ├── /agents — список и управление агентами
|
||||
│ ├── /admin — панель управления
|
||||
│ └── /sync — синхронизация
|
||||
│
|
||||
├── ConductorAgent (Дирижёр) — оркестратор, точка входа
|
||||
│ ├── → 13 Role Agents (ролевые)
|
||||
│ └── Верификация (confidence 0-100%)
|
||||
│
|
||||
├── AgentRegistry — 12 Dev/Ops агентов (автоматизация)
|
||||
│
|
||||
├── LLM Service — OpenAI-compatible (OpenAI / YandexGPT / GigaChat)
|
||||
├── Whisper Service — транскрибация аудио
|
||||
├── Email Service — SMTP (Jinja2), password reset
|
||||
├── Crypto Service — AES-256 Fernet (PBKDF2 600k итераций)
|
||||
│
|
||||
└── PostgreSQL — 8 таблиц (asyncpg)
|
||||
```
|
||||
|
||||
**Ключевые принципы:**
|
||||
- **PostgreSQL только** — единый `DATABASE_URL`, без SQLite
|
||||
- **No Docker** — systemd + venv напрямую на VPS (Ubuntu)
|
||||
- **Single-page app** — FastAPI StaticFiles раздаёт фронтенд
|
||||
- **Агенты имеют прямой доступ к БД** — через переданную async-сессию
|
||||
|
||||
---
|
||||
|
||||
## 2. Технологический стек
|
||||
|
||||
| Компонент | Технология |
|
||||
|-----------|-----------|
|
||||
| Бэкенд | Python 3.12+, FastAPI, Uvicorn |
|
||||
| Фронтенд | React 18, TypeScript, Tailwind CSS, Vite |
|
||||
| PWA | manifest.json, service worker, иконки всех размеров |
|
||||
| База данных | PostgreSQL 15+, asyncpg, SQLAlchemy 2.0 (async), Alembic |
|
||||
| Аутентификация | JWT (HS256), bcrypt (passlib), OAuth 2.0 |
|
||||
| ИИ-модели | OpenAI API (gpt-4o-mini), YandexGPT, GigaChat (fallback chain) |
|
||||
| Распознавание речи | Web Speech API (браузер) → Whisper API (OpenAI, fallback) |
|
||||
| Синтез речи | SpeechSynthesis API (браузер, русский голос) |
|
||||
| Шифрование | AES-256-CBC + HMAC-SHA256 (Fernet), PBKDF2 |
|
||||
| Rate limiting | slowapi (60/min default, 10/min auth, 3/min forgot-password) |
|
||||
| Защита заголовков | CSP, HSTS, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection |
|
||||
| Почта | aiosmtplib + Jinja2 (HTML-шаблоны) |
|
||||
| Мониторинг | Prometheus + Grafana (VPS) |
|
||||
| Развёртывание | systemd + venv, Nginx + certbot (Let's Encrypt) |
|
||||
|
||||
---
|
||||
|
||||
## 3. Аутентификация и OAuth
|
||||
|
||||
### 3.1 Email + пароль
|
||||
|
||||
- Регистрация: `POST /api/v1/auth/register` — email, пароль (8+ символов), имя
|
||||
- Логин: `POST /api/v1/auth/login` — email + пароль
|
||||
- JWT access token (60 мин) + refresh token (30 дней) с ротацией
|
||||
- bcrypt для хешей паролей
|
||||
- Brute-force защита: 5 неудачных попыток → блокировка на 15 минут (in-memory, в проде — Redis)
|
||||
- Rate limit: 10/min на login, 5/min на register, 3/min на forgot-password
|
||||
|
||||
### 3.2 Яндекс OAuth
|
||||
|
||||
- 7 scopes: `login:email`, `login:info`, `login:avatar`, `cloud_api:disk.write`, `cloud_api:disk.app_folder`, `cloud_api:disk.read`, `cloud_api:disk.info`
|
||||
- Папка на Диске: `/VoIdeaAI/`
|
||||
- Методы: `upload_file()`, `ensure_app_folder()`, `get_disk_info()`
|
||||
- Redirect URI настраивается через `OAUTH_YANDEX_REDIRECT_URI`
|
||||
|
||||
### 3.3 Google OAuth
|
||||
|
||||
- Scopes: `userinfo.email`, `userinfo.profile`, `drive.file`
|
||||
- Папка на Диске: `/VoIdeaAI/`
|
||||
- Активируется когда `OAUTH_GOOGLE_ID` не пуст
|
||||
- Redirect: `http://localhost:8020/auth/google/callback`
|
||||
|
||||
**Пример запроса:**
|
||||
```python
|
||||
from app.integrations.oauth.google import is_available, get_authorize_url, exchange_code, get_user_info, upload_file
|
||||
|
||||
if is_available():
|
||||
url = await get_authorize_url()
|
||||
token = await exchange_code(code)
|
||||
user = await get_user_info(token["access_token"])
|
||||
await upload_file(token["access_token"], "idea.txt", content)
|
||||
```
|
||||
|
||||
### 3.4 Apple OAuth
|
||||
|
||||
- Sign in with Apple через `appleid.apple.com`
|
||||
- Активируется когда `OAUTH_APPLE_ID` не пуст
|
||||
- Redirect: `http://localhost:8020/auth/apple/callback`
|
||||
- iCloud Drive через CloudKit API
|
||||
|
||||
### 3.5 Password Reset
|
||||
|
||||
- JWT reset token с отдельным секретом (`JWT_RESET_SECRET_KEY`), 1 час
|
||||
- HTML-письмо с кнопкой сброса (Jinja2-шаблон)
|
||||
- Если SMTP не настроен — лог в консоль
|
||||
- Rate limit: 3/min на forgot-password
|
||||
|
||||
### 3.6 2FA (TOTP)
|
||||
|
||||
- Включается через `ENABLE_2FA=true`
|
||||
- PyOTP + QR-код для настройки
|
||||
- Подтверждение кода при входе после пароля/OAuth
|
||||
|
||||
---
|
||||
|
||||
## 4. Голосовой ввод / вывод
|
||||
|
||||
### 4.1 Распознавание речи
|
||||
|
||||
**Цепочка приоритетов:**
|
||||
1. **Web Speech API** (браузер, `SpeechRecognition`) — основной, бесплатный, работает онлайн
|
||||
2. **MediaRecorder → Whisper API** (OpenAI `whisper-1`, `language=ru`) — fallback если Web Speech недоступен
|
||||
3. Если ключ OpenAI не задан — возвращается ошибка
|
||||
|
||||
**Компонент VoiceInput (`webui/src/components/VoiceInput.tsx`):**
|
||||
- Кнопка-микрофон с визуальной индикацией записи
|
||||
- `onMouseDown/onTouchStart` — начало записи
|
||||
- `onMouseUp/onTouchEnd` — остановка и отправка
|
||||
- Автоматическая остановка через 5 секунд (MediaRecorder)
|
||||
- Подавление шума через confidence ≥ 0.5
|
||||
|
||||
### 4.2 Текстовый ввод
|
||||
|
||||
- Поле ввода рядом с микрофоном, отправка по Enter
|
||||
- Пользователь может говорить ИЛИ печатать
|
||||
- Чекбокс «Озвучивать ответ» отключает TTS
|
||||
|
||||
### 4.3 Синтез речи (TTS)
|
||||
|
||||
- **SpeechSynthesis API** браузера (бесплатно, без серверной нагрузки)
|
||||
- Язык: `ru-RU`, скорость: 0.9
|
||||
- Автоматическое озвучивание ответов (кроме `needs_clarification`)
|
||||
- Кнопка «Стоп» для прерывания
|
||||
|
||||
### 4.4 Голосовые команды
|
||||
|
||||
Фоновый `SpeechRecognition` (continuous mode) слушает команды:
|
||||
|
||||
| Команда | Действие |
|
||||
|---------|----------|
|
||||
| «Стоп» | Остановить TTS |
|
||||
| «Повтори» | Повторить последний ответ |
|
||||
| «Уточнить» | Открыть диалог уточнения запроса |
|
||||
|
||||
- Отключается при отсутствии сообщений в чате
|
||||
- Confidence ≥ 0.5 для фильтрации шума
|
||||
|
||||
---
|
||||
|
||||
## 5. Оркестрация: Дирижёр
|
||||
|
||||
**Файл:** `app/agents/conductor_agent.py`
|
||||
|
||||
Дирижёр — единственная точка входа для пользовательских запросов. Полный pipeline:
|
||||
|
||||
```
|
||||
User Input (текст/голос)
|
||||
│
|
||||
▼
|
||||
┌─ 0. Авто-создание сессии ─────────────────┐
|
||||
│ Если session_id не передан → создаётся │
|
||||
│ новая сессия + LLM генерирует title │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 1. Сбор контекста ───────────────────────┐
|
||||
│ • Недавние обсуждения пользователя (5) │
|
||||
│ • Похожие успешные кейсы (word overlap) │
|
||||
│ • История текущей сессии │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 2. Маршрутизация (LLM) ──────────────────┐
|
||||
│ "Определи лучшего агента для ответа" │
|
||||
│ temperature=0.3, max_tokens=64 │
|
||||
│ Ответ ТОЛЬКО именем агента │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 3. Генерация ответа ─────────────────────┐
|
||||
│ Выбранный RoleAgent + system_prompt │
|
||||
│ temperature=0.7, max_tokens=1536 │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 4. Верификация ──────────────────────────┐
|
||||
│ Проверка: галлюцинации, противоречия, │
|
||||
│ логические ошибки, пропущенные детали │
|
||||
│ temperature=0.2, max_tokens=1024 │
|
||||
│ Ответ JSON: confidence, issues, corrected │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 5. Confidence scoring ───────────────────┐
|
||||
│ ≥ 80% → verified (зелёный) │
|
||||
│ 50-79% → warning (жёлтый) │
|
||||
│ < 50% → needs_clarification (красный) │
|
||||
│ issues_found → ответ скорректирован │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─ 6. Логирование + самообучение ───────────┐
|
||||
│ ConductorInteraction: input, output, │
|
||||
│ confidence, agent, время, session_id │
|
||||
└────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
Response { response, agent_name, confidence,
|
||||
verification_status, session_id,
|
||||
interaction_id }
|
||||
```
|
||||
|
||||
**Пример ответа:**
|
||||
```json
|
||||
{
|
||||
"response": "Идея стартапа по экологии имеет ROI 150%...",
|
||||
"agent_name": "Бизнес-аналитик",
|
||||
"agent_description": "Оценивает идею с точки зрения бизнес-показателей",
|
||||
"confidence": 85,
|
||||
"verification_status": "verified",
|
||||
"processing_time_ms": 2340.5,
|
||||
"interaction_id": "a1b2c3d4-...",
|
||||
"session_id": "e5f6g7h8-..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Ролевые агенты (13 шт)
|
||||
|
||||
Все агенты описаны в `app/agents/role_agents.py`. Каждый имеет `name`, `description` и `system_prompt`.
|
||||
|
||||
| # | Агент | Описание | System prompt |
|
||||
|---|-------|----------|--------------|
|
||||
| 1 | **Бизнес-аналитик** | Оценивает идею: ROI, окупаемость, ЦА, конкуренты | *«Ты — Бизнес-аналитик. Дай оценку по критериям: ROI (%), срок окупаемости (месяцы), целевая аудитория (тыс. чел.), конкурентные преимущества...»* |
|
||||
| 2 | **Организатор задач** | Разбивает на шаги, план реализации | *«Разбей идею на 5-7 шагов. Для каждого: название, срок, ответственный...»* |
|
||||
| 3 | **Юрист** | Проверяет на законы РФ (152-ФЗ, 44-ФЗ и др.) | *«Проанализируй на соответствие законодательству РФ. Правовые риски, способы минимизации...»* |
|
||||
| 4 | **Финансовый консультант** | Бюджет, прогноз доходов, точка безубыточности | *«Составь смету: разработка, маркетинг, поддержка. Прогноз дохода за год...»* |
|
||||
| 5 | **Архитектор решений** | 2 варианта архитектуры (монолит / микросервисы) | *«Предложи 2 варианта. Вариант A — монолит, B — микросервисы. Технологии, сложность...»* |
|
||||
| 6 | **Тестировщик** | Тест-кейсы (позитивные/негативные), инструменты | *«5-10 тест-кейсов. Шаги, ожидаемый результат, инструменты автоматизации...»* |
|
||||
| 7 | **UI-дизайнер** | 2 варианта дизайна, цвета, шрифты, UX | *«2 варианта главного экрана. Цветовая схема, шрифты, расположение элементов...»* |
|
||||
| 8 | **SMM-специалист** | Контент-план на месяц, платформы, хештеги | *«Контент-план: платформы (ВК, Telegram), форматы, частота, 3-4 примера постов...»* |
|
||||
| 9 | **Лайф-коуч** | SMART-цели, квартальные этапы, метрики | *«Помоги сформулировать цель по SMART. Q1-Q4, 3 метрики прогресса...»* |
|
||||
| 10 | **Эксперт по доступности** | Инклюзивность, WCAG 2.1 (AA) | *«Слабовидящие, глухие, моторные нарушения, когнитивные — доработки для WCAG 2.1...»* |
|
||||
| 11 | **Критик** | Конструктивный разбор: подводные камни, улучшения | *«Что НЕ учтено? Подводные камни, улучшения. Тон — доброжелательный коллега...»* |
|
||||
| 12 | **Копирайтер** | Продающий текст, сторителлинг | *«Упакуй идею в яркий текст: заголовки, метафоры, сторителлинг. Для инвесторов и команды...»* |
|
||||
| 13 | **Хранитель** | Сохраняет идею в БД (название, описание, теги) | *«Оформи для сохранения: Название, Описание, Теги. Строгий формат...»* |
|
||||
|
||||
**Агенты 11-13** (Критик, Копирайтер, Хранитель) добавлены дополнительно к базовым 10 из оригинальной спецификации.
|
||||
|
||||
---
|
||||
|
||||
## 7. Dev/Ops агенты (12 шт)
|
||||
|
||||
Зарегистрированы в `app/agents/registry.py`. Используются через `AgentRegistry.run_agent()` для автоматизации разработки и поддержки.
|
||||
|
||||
| # | Агент | Описание |
|
||||
|---|-------|----------|
|
||||
| 1 | **DocAgent** | Генерация документации по коду |
|
||||
| 2 | **BacklogAgent** | Управление бэклогом задач |
|
||||
| 3 | **SpecAgent** | Написание спецификаций |
|
||||
| 4 | **AuditAgent** | Аудит кода и безопасности |
|
||||
| 5 | **ObserverAgent** | Мониторинг и наблюдаемость |
|
||||
| 6 | **EvolutionAgent** | Предложения по эволюции кода |
|
||||
| 7 | **SecurityAgent** | Проверки безопасности |
|
||||
| 8 | **QATesterAgent** | Автоматическое тестирование |
|
||||
| 9 | **FixAgent** | Исправление типовых ошибок |
|
||||
| 10 | **UITestAgent** | UI-тестирование |
|
||||
| 11 | **RolloutAgent** | Развёртывание и релизы |
|
||||
| 12 | **ConductorAgent** | Дирижёр (в registry для Dev/Ops контекста) |
|
||||
|
||||
---
|
||||
|
||||
## 8. Связи агентов
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ Пользователь │
|
||||
│ (голос / текст) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Дирижёр │ ←── AgentRegistry
|
||||
│ (Conductor) │ (Dev/Ops)
|
||||
└────────┬─────────┘
|
||||
│ маршрутизация (LLM)
|
||||
▼
|
||||
┌──────────────────────────────┐
|
||||
│ 13 Role Agents │
|
||||
│ │
|
||||
│ Бизнес-аналитик │
|
||||
│ Организатор задач │
|
||||
│ Юрист │
|
||||
│ Финансовый консультант │
|
||||
│ Архитектор решений │
|
||||
│ Тестировщик │
|
||||
│ UI-дизайнер │
|
||||
│ SMM-специалист │
|
||||
│ Лайф-коуч │
|
||||
│ Эксперт по доступности │
|
||||
│ Критик │
|
||||
│ Копирайтер │
|
||||
│ Хранитель │
|
||||
└──────────────┬───────────────┘
|
||||
│ response
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Верификация │
|
||||
│ (внутри Дирижёра)│
|
||||
│ confidence 0-100 │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Пользователь │
|
||||
│ + лог в БД │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
**Ключевые правила:**
|
||||
- Дирижёр — **единственная точка входа** для пользователя
|
||||
- Верификация выполняется **внутри Дирижёра** (не отдельный агент) — быстрее, меньше загрузки LLM
|
||||
- Dev/Ops агенты вызываются через `/api/v1/agents/` (не через Дирижёр)
|
||||
- 26 агентов всего: 1 Дирижёр + 13 ролевых + 12 dev/ops
|
||||
- Все ролевые агенты имеют прямой доступ к БД через переданную `db: AsyncSession`
|
||||
|
||||
---
|
||||
|
||||
## 9. Самообучение
|
||||
|
||||
### 9.1 Рейтинг (1-5)
|
||||
|
||||
После каждого ответа пользователь может поставить оценку:
|
||||
- Звёзды 1-5 в интерфейсе
|
||||
- `POST /api/v1/voice/rate` — сохраняет `user_rating` в `ConductorInteraction`
|
||||
- Используется для фильтрации успешных кейсов
|
||||
|
||||
### 9.2 Похожие кейсы (word overlap)
|
||||
|
||||
При обработке запроса:
|
||||
1. Выборка успешных interaction (rating ≥ 4, confidence ≥ 70) за последние 7 дней
|
||||
2. Сравнение через `_text_similarity()` — пересечение множеств слов
|
||||
3. Если overlap > 30% — кейс подмешивается в контекст LLM
|
||||
|
||||
Пример:
|
||||
```
|
||||
Было: "придумай идею для стартапа в экологии"
|
||||
Ответ: "Идея: переработка пластика..." (rating: 5)
|
||||
```
|
||||
Подмешивается в контекст похожего запроса.
|
||||
|
||||
### 9.3 Динамические команды
|
||||
|
||||
- Хранятся в таблице `voice_commands` (привязка к `user_id`)
|
||||
- Если фраза сработала 3+ раза — система предлагает добавить как команду
|
||||
- Поля: `phrase`, `action`, `agent_name`, `count`, `is_active`
|
||||
|
||||
### 9.4 ConductorInteraction (таблица логов)
|
||||
|
||||
| Поле | Описание |
|
||||
|------|----------|
|
||||
| `user_id` | FK → users |
|
||||
| `session_id` | FK → sessions |
|
||||
| `input_text` | Запрос пользователя |
|
||||
| `detected_intent` | Распознанное намерение |
|
||||
| `selected_agent` | Какой агент отвечал |
|
||||
| `response_text` | Ответ агента |
|
||||
| `user_rating` | 1-5 (заполняется позже) |
|
||||
| `confidence_score` | 0-100 |
|
||||
| `verification_status` | verified / warning / needs_clarification / issues_found |
|
||||
| `processing_time_ms` | Время обработки |
|
||||
| `context` | JSON с деталями верификации |
|
||||
|
||||
---
|
||||
|
||||
## 10. Сессии
|
||||
|
||||
**Модель:** `app/models/session.py`, таблица `sessions`
|
||||
|
||||
- **1 сессия = 1 обсуждение идеи**
|
||||
- Авто-создание при первом сообщении без `session_id`
|
||||
- Дирижёр формирует заголовок через LLM (до 7 слов) на основе первого запроса
|
||||
- Статусы: `active`, `archived`
|
||||
- Привязка к `idea_id` (когда идея сохранена)
|
||||
|
||||
**API:**
|
||||
- `GET /api/v1/voice/sessions` — список сессий пользователя
|
||||
- `GET /api/v1/voice/sessions/{id}` — детали сессии
|
||||
- `GET /api/v1/voice/sessions/{id}/history` — история взаимодействий
|
||||
- `DELETE /api/v1/voice/sessions/{id}` — удалить сессию
|
||||
|
||||
**UI:**
|
||||
- Сайдбар слева со списком сессий
|
||||
- Кнопка «Новый чат» → сброс текущей сессии
|
||||
- Активная сессия подсвечена
|
||||
- Кнопка удаления с confirm-диалогом
|
||||
|
||||
---
|
||||
|
||||
## 11. Интеграции с дисками
|
||||
|
||||
Единый интерфейс для облачных хранилищ. Все провайдеры создают папку `/VoIdeaAI/` и загружают файлы туда.
|
||||
|
||||
### 11.1 Яндекс.Диск (реализован)
|
||||
|
||||
`app/integrations/oauth/yandex.py`:
|
||||
- `get_authorize_url()` → URL авторизации
|
||||
- `exchange_code(code)` → токен
|
||||
- `get_user_info(token)` → профиль
|
||||
- `ensure_app_folder(token)` → создаёт /VoIdeaAI/
|
||||
- `upload_file(token, local_path, remote_name)` → загружает файл
|
||||
- `get_disk_info(token)` → квота
|
||||
|
||||
### 11.2 Google Drive
|
||||
|
||||
`app/integrations/oauth/google.py`:
|
||||
- Активируется при непустом `OAUTH_GOOGLE_ID`
|
||||
- `is_available()` → bool
|
||||
- Те же методы: `get_authorize_url`, `exchange_code`, `get_user_info`, `ensure_app_folder`, `upload_file`, `get_disk_info`
|
||||
- Использует `https://www.googleapis.com/drive/v3`
|
||||
|
||||
### 11.3 Apple iCloud Drive
|
||||
|
||||
`app/integrations/oauth/apple.py`:
|
||||
- Активируется при непустом `OAUTH_APPLE_ID`
|
||||
- `is_available()` → bool
|
||||
- Те же методы (через CloudKit API)
|
||||
- Требует дополнительной настройки entitlements в Apple Developer Console
|
||||
|
||||
---
|
||||
|
||||
## 12. Безопасность
|
||||
|
||||
### 12.1 Криптография
|
||||
|
||||
| Компонент | Метод |
|
||||
|-----------|-------|
|
||||
| Пароли | bcrypt (passlib, 12 раундов) |
|
||||
| JWT Access Token | HS256, 60 мин, отдельный secret |
|
||||
| JWT Refresh Token | HS256, 30 дней, ротация при каждом использовании |
|
||||
| JWT Reset Token | HS256, 1 час, отдельный secret (`JWT_RESET_SECRET_KEY`) |
|
||||
| Шифрование данных | AES-256-CBC + HMAC-SHA256 (Fernet), PBKDF2 600k итераций |
|
||||
| Шифруются: идеи, ответы ConductorInteraction, логи |
|
||||
|
||||
### 12.2 Rate Limiting
|
||||
|
||||
| Endpoint | Лимит |
|
||||
|----------|-------|
|
||||
| `/login` | 10/min |
|
||||
| `/register` | 5/min |
|
||||
| `/refresh` | 10/min |
|
||||
| `/forgot-password` | 3/min |
|
||||
| `/reset-password` | 5/min |
|
||||
| `/oauth/*` | 10/min |
|
||||
| `/health` | 30/min |
|
||||
| Все остальные | 60/min |
|
||||
|
||||
### 12.3 Security Headers
|
||||
|
||||
Все ответы содержат:
|
||||
- `X-Content-Type-Options: nosniff`
|
||||
- `X-Frame-Options: DENY`
|
||||
- `X-XSS-Protection: 1; mode=block`
|
||||
- `Strict-Transport-Security: max-age=31536000; includeSubDomains`
|
||||
- `Content-Security-Policy: default-src 'self'; script-src 'self'; ...`
|
||||
|
||||
### 12.4 Brute Force
|
||||
|
||||
- 5 неудачных попыток логина за 15 минут → временная блокировка email
|
||||
- In-memory (TODO: Redis в production)
|
||||
- Не блокирует другие аккаунты с того же IP
|
||||
|
||||
### 12.5 Дополнительно
|
||||
|
||||
- CORS whitelist (настраивается)
|
||||
- Токены в `localStorage` (с предупреждением о XSS)
|
||||
- SQLAlchemy ORM (параметризованные запросы — защита от SQL injection)
|
||||
- Pydantic-валидация всех входящих данных
|
||||
- `is_active` check на каждом запросе
|
||||
- `require_admin` dependency для админ-роутов
|
||||
|
||||
---
|
||||
|
||||
## 13. База данных (PostgreSQL)
|
||||
|
||||
### 13.1 Схема
|
||||
|
||||
```sql
|
||||
-- 8 таблиц, все с UUID первичными ключами + created_at/updated_at
|
||||
|
||||
users
|
||||
id UUID PRIMARY KEY
|
||||
email VARCHAR(255) UNIQUE NOT NULL
|
||||
password_hash VARCHAR(255) NULLABLE
|
||||
display_name VARCHAR(255) NOT NULL
|
||||
avatar_url VARCHAR(512) NULLABLE
|
||||
is_active BOOLEAN DEFAULT true
|
||||
is_superuser BOOLEAN DEFAULT false
|
||||
oauth_provider VARCHAR(50) NULLABLE
|
||||
oauth_id VARCHAR(255) NULLABLE
|
||||
|
||||
ideas
|
||||
id UUID PRIMARY KEY
|
||||
user_id UUID FK → users(id) ON DELETE CASCADE
|
||||
title VARCHAR(255) NOT NULL
|
||||
description TEXT
|
||||
tags TEXT
|
||||
status VARCHAR(20) DEFAULT 'draft'
|
||||
|
||||
agent_configs
|
||||
id UUID PRIMARY KEY
|
||||
agent_name VARCHAR(100) NOT NULL
|
||||
user_id UUID FK → users(id) ON DELETE CASCADE
|
||||
model VARCHAR(100)
|
||||
enabled BOOLEAN DEFAULT true
|
||||
|
||||
backlog_tasks
|
||||
id UUID PRIMARY KEY
|
||||
title VARCHAR(255) NOT NULL
|
||||
description TEXT
|
||||
priority INTEGER DEFAULT 0
|
||||
status VARCHAR(20) DEFAULT 'pending'
|
||||
|
||||
log_entries
|
||||
id UUID PRIMARY KEY
|
||||
level VARCHAR(10) NOT NULL
|
||||
message TEXT NOT NULL
|
||||
agent VARCHAR(100)
|
||||
user_id UUID FK → users(id) ON DELETE SET NULL
|
||||
|
||||
conductor_interactions
|
||||
id UUID PRIMARY KEY
|
||||
user_id UUID FK → users(id) ON DELETE SET NULL
|
||||
session_id UUID FK → sessions(id) ON DELETE SET NULL
|
||||
input_text TEXT NOT NULL
|
||||
detected_intent VARCHAR(100)
|
||||
selected_agent VARCHAR(100)
|
||||
response_text TEXT
|
||||
user_rating INTEGER NULLABLE
|
||||
confidence_score INTEGER DEFAULT 80
|
||||
verification_status VARCHAR(20) DEFAULT 'verified'
|
||||
was_auto_routed BOOLEAN DEFAULT true
|
||||
processing_time_ms FLOAT
|
||||
context TEXT (JSON)
|
||||
|
||||
sessions
|
||||
id UUID PRIMARY KEY
|
||||
user_id UUID FK → users(id) ON DELETE CASCADE
|
||||
title VARCHAR(255) DEFAULT 'Новое обсуждение'
|
||||
status VARCHAR(20) DEFAULT 'active'
|
||||
idea_id UUID FK → ideas(id) ON DELETE SET NULL
|
||||
|
||||
voice_commands
|
||||
id UUID PRIMARY KEY
|
||||
user_id UUID FK → users(id) ON DELETE CASCADE
|
||||
phrase VARCHAR(255) NOT NULL
|
||||
action VARCHAR(50) NOT NULL
|
||||
agent_name VARCHAR(100) NULLABLE
|
||||
count INTEGER DEFAULT 0
|
||||
is_active BOOLEAN DEFAULT true
|
||||
```
|
||||
|
||||
### 13.2 Индексы
|
||||
|
||||
- `users.email` — UNIQUE
|
||||
- `users(oauth_provider, oauth_id)` — для OAuth lookup
|
||||
- `conductor_interactions(user_id)` — история пользователя
|
||||
- `conductor_interactions(session_id)` — история сессии
|
||||
- `sessions(user_id, status)` — список сессий
|
||||
- `voice_commands(user_id)` — команды пользователя
|
||||
|
||||
---
|
||||
|
||||
## 14. Фронтенд (PWA)
|
||||
|
||||
### 14.1 Страницы и маршруты
|
||||
|
||||
| Маршрут | Страница | Описание |
|
||||
|---------|----------|----------|
|
||||
| `/` | Главная | SPA entry point |
|
||||
| `/login` | LoginPage | Email + Яндекс OAuth + ссылка «Забыли пароль?» |
|
||||
| `/register` | RegisterPage | Регистрация email+password |
|
||||
| `/forgot-password` | ForgotPasswordPage | Форма ввода email |
|
||||
| `/reset-password?token=` | ResetPasswordPage | Новый пароль |
|
||||
| `/oauth/callback` | OAuthCallback | Обработка OAuth callback |
|
||||
| `/voice` | VoiceChat | Голосовой ассистент с сайдбаром |
|
||||
| `/ideas` | IdeaList | Список идей |
|
||||
| `/ideas/new` | IdeaCreate | Новая идея |
|
||||
| `/ideas/:id` | IdeaEdit | Редактирование идеи |
|
||||
|
||||
### 14.2 Ключевые компоненты
|
||||
|
||||
- **VoiceChat** — основной интерфейс: сайдбар сессий, список сообщений, confidence badge, звёзды рейтинга, кнопка «Уточнить», голосовые команды
|
||||
- **VoiceInput** — кнопка микрофона, Web Speech API → Whisper fallback
|
||||
- **VoiceCommands** — хук `useVoiceCommands` для фоновых команд «Стоп»/«Повтори»/«Уточнить»
|
||||
- **AuthContext** — контекст аутентификации: `login()`, `register()`, `logout()`, `refreshToken()`
|
||||
- **Layout** — навигация, пункт «Голос»
|
||||
- **OAuthCallback** — обработка кода авторизации
|
||||
- **ForgotPasswordPage / ResetPasswordPage** — сброс пароля
|
||||
|
||||
### 14.3 PWA
|
||||
|
||||
- manifest.json с иконками всех размеров (16, 32, 192, 512, apple-touch-icon)
|
||||
- favicon.ico + SVG fallback
|
||||
- service worker (Vite PWA plugin)
|
||||
- Тёмная тема (Tailwind `dark:` классы)
|
||||
- Адаптивный дизайн (mobile-first)
|
||||
|
||||
---
|
||||
|
||||
## 15. API Reference
|
||||
|
||||
### 15.1 Auth (`/api/v1/auth`)
|
||||
|
||||
| Метод | Endpoint | Тело | Ответ |
|
||||
|-------|----------|------|-------|
|
||||
| POST | `/register` | `{email, password, display_name}` | `TokenResponse` |
|
||||
| POST | `/login` | `{email, password}` | `TokenResponse` |
|
||||
| POST | `/refresh` | `{refresh_token}` | `TokenResponse` (ротация) |
|
||||
| GET | `/oauth/yandex` | — | `{url, provider}` |
|
||||
| POST | `/oauth/yandex/callback` | `{code}` | `TokenResponse` |
|
||||
| GET | `/oauth/google` | — | `{url, provider}` |
|
||||
| POST | `/oauth/google/callback` | `{code}` | `TokenResponse` |
|
||||
| GET | `/oauth/apple` | — | `{url, provider}` |
|
||||
| POST | `/oauth/apple/callback` | `{code}` | `TokenResponse` |
|
||||
| POST | `/forgot-password` | `{email}` | `{message}` |
|
||||
| POST | `/reset-password` | `{token, new_password}` | `{message}` |
|
||||
|
||||
### 15.2 Voice (`/api/v1/voice`)
|
||||
|
||||
| Метод | Endpoint | Тело / Параметры | Ответ |
|
||||
|-------|----------|-------------------|-------|
|
||||
| POST | `/transcribe` | `file: UploadFile` (audio) | `{text}` |
|
||||
| POST | `/chat` | `{text, session_id?}` | `ChatResponse` |
|
||||
| POST | `/rate` | `{interaction_id, rating}` | `{status}` |
|
||||
| GET | `/agents` | — | `[{name, description}]` |
|
||||
| GET | `/sessions` | `?status=` | `[SessionResponse]` |
|
||||
| GET | `/sessions/{id}` | — | `SessionResponse` |
|
||||
| GET | `/sessions/{id}/history` | — | `[{interactions}]` |
|
||||
| DELETE | `/sessions/{id}` | — | `{status}` |
|
||||
|
||||
### 15.3 Ideas (`/api/v1/ideas`)
|
||||
|
||||
| Метод | Endpoint | Описание |
|
||||
|-------|----------|----------|
|
||||
| GET | `/` | Список идей |
|
||||
| POST | `/` | Создать идею |
|
||||
| GET | `/{id}` | Детали идеи |
|
||||
| PUT | `/{id}` | Обновить идею |
|
||||
| DELETE | `/{id}` | Удалить идею |
|
||||
|
||||
### 15.4 Admin (`/api/v1/admin`)
|
||||
|
||||
Под защитой `require_admin`:
|
||||
- `GET /users` — список пользователей
|
||||
- `GET /logs` — просмотр логов
|
||||
- `GET /agents` — статус агентов
|
||||
|
||||
---
|
||||
|
||||
## 16. Фазы реализации
|
||||
|
||||
- **Фаза 0: База данных** — Модели (8 таблиц), миграция Alembic, SQLAlchemy async, UUID primary keys
|
||||
- **Фаза 1: Сессии** — Авто-создание сессии, авто-title (LLM), сайдбар, история, удаление
|
||||
- **Фаза 2: Сохранение идей** — Хранитель (Keeper Agent), кнопка «Сохранить», экспорт на Яндекс.Диск / Google Drive / iCloud
|
||||
- **Фаза 3: Команды + самообучение** — Встроенные и динамические голосовые команды, VoiceHelpPage, docs/voice-commands.md
|
||||
- **Фаза 4: UI/анимация** — Dark-стили VoiceChat, анимированная волна микрофона, микро-анимации переходов
|
||||
- **Фаза 5: Multi-сессия** — BroadcastChannel API, параллельные обсуждения, переключение между сессиями без потери контекста
|
||||
- **Фаза 6: Rate limit** — Применение slowapi ко всем auth endpoints, настройка лимитов
|
||||
- **Фаза 7: Security hardening** — Security headers middleware, brute force (5 попыток), refresh token rotation, отдельный reset secret
|
||||
- **Фаза 8: 2FA (TOTP)** — PyOTP + QR-код, подтверждение кода при входе, настройка через профиль
|
||||
- **Фаза 9: VPS deploy** — Nginx + certbot (Let's Encrypt) + systemd + Alembic upgrade + production .env + мониторинг
|
||||
- **Фаза 10: Google/Apple OAuth** — Активация роутов авторизации, Drive клиенты, полная интеграция с дисками
|
||||
|
||||
---
|
||||
|
||||
## 17. Ключевые архитектурные решения
|
||||
|
||||
| Решение | Обоснование |
|
||||
|---------|-------------|
|
||||
| **PostgreSQL-only** | Единый `DATABASE_URL`. Никакого SQLite. Дев и прод на одном PostgreSQL |
|
||||
| **systemd (no Docker)** | Прямое управление процессом, простота деплоя на Ubuntu VPS |
|
||||
| **FastAPI StaticFiles** | Фронтенд раздаётся бэкендом — не нужен отдельный сервер для SPA |
|
||||
| **Дирижёр = единственная точка входа** | Верификация внутри Дирижёра (не отдельный агент) — быстрее, меньше загрузки LLM |
|
||||
| **Confidence scoring** | ≥80% OK, 50-79% warning, <50% уточнение. Прозрачность для пользователя |
|
||||
| **Web Speech → Whisper** | Бесплатный браузерный API как primary, Whisper API как fallback |
|
||||
| **SpeechSynthesis (TTS)** | Браузерный API — бесплатно, без серверной нагрузки |
|
||||
| **Пустой OAuth ID = флаг** | `bool(oauth_google_id)` — естественный gate, не может быть рассинхрона |
|
||||
| **Отдельный JWT reset secret** | Reset token не может быть использован как access/refresh и наоборот |
|
||||
| **Refresh token rotation** | Каждый refresh выдаёт новую пару — старый токен становится недействительным |
|
||||
| **Brute force in-memory** | Достаточно для MVP. В проде — Redis с TTL |
|
||||
| **Агенты имеют прямой доступ к БД** | Все внутренние агенты работают через переданную async-сессию |
|
||||
|
||||
---
|
||||
|
||||
## 18. Примеры использования
|
||||
|
||||
### Пример 1: Пользователь придумывает стартап
|
||||
|
||||
**Запрос:** «Придумай идею для стартапа в сфере экологии»
|
||||
|
||||
**Pipeline:**
|
||||
1. Дирижёр создаёт сессию «Стартап в экологии»
|
||||
2. Маршрутизация → Бизнес-аналитик
|
||||
3. Бизнес-аналитик генерирует: ROI, окупаемость, ЦА, конкуренты
|
||||
4. Верификация: confidence 92%, verified
|
||||
5. Ответ + звёзды рейтинга
|
||||
|
||||
**UI:**
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ← Стартап в экологии [85%] │
|
||||
│ │
|
||||
│ Придумай идею для стартапа... │
|
||||
│ ─────────────────────────────────── │
|
||||
│ Бизнес-аналитик [92%] │
|
||||
│ Идея: переработка пластика... │
|
||||
│ ★ ★ ★ ★ ☆ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Пример 2: Пользователь уточняет
|
||||
|
||||
**Запрос:** «А какие юридические риски?»
|
||||
|
||||
1. Дирижёр определяет: нужен Юрист
|
||||
2. Юрист анализирует: 152-ФЗ, ответственность за экологию
|
||||
3. Confidence: 73% → warning
|
||||
4. Пользователь может уточнить или поставить оценку
|
||||
|
||||
### Пример 3: Сохранение идеи
|
||||
|
||||
**Команда:** «Сохрани идею»
|
||||
|
||||
1. Дирижёр → Хранитель
|
||||
2. Хранитель формулирует: название, описание, теги
|
||||
3. Идея сохраняется в БД + экспорт на Яндекс.Диск (если OAuth подключён)
|
||||
|
||||
---
|
||||
|
||||
## 19. Файловая структура (ключевые файлы)
|
||||
|
||||
```
|
||||
voidea/
|
||||
├── app/
|
||||
│ ├── api/v1/
|
||||
│ │ ├── auth.py — аутентификация + OAuth + password reset
|
||||
│ │ ├── voice.py — транскрибация, чат, сессии, рейтинг
|
||||
│ │ ├── ideas.py — CRUD идей
|
||||
│ │ ├── admin.py — админ-панель
|
||||
│ │ └── agents.py — управление агентами
|
||||
│ ├── agents/
|
||||
│ │ ├── conductor_agent.py — Дирижёр (оркестратор)
|
||||
│ │ ├── role_agents.py — 13 ролевых агентов + верификация
|
||||
│ │ ├── conductor_storage.py — логирование, рейтинг, похожие кейсы
|
||||
│ │ ├── registry.py — 12 dev/ops агентов
|
||||
│ │ └── base.py — базовый класс агента
|
||||
│ ├── core/
|
||||
│ │ ├── config.py — настройки (.env)
|
||||
│ │ ├── security.py — JWT, bcrypt, хеши
|
||||
│ │ ├── middleware.py — SecurityHeadersMiddleware
|
||||
│ │ ├── limiter.py — shared slowapi limiter
|
||||
│ │ ├── dependencies.py — get_db, get_current_user
|
||||
│ │ └── database.py — async SQLAlchemy engine
|
||||
│ ├── models/
|
||||
│ │ ├── user.py, idea.py, session.py, conductor.py
|
||||
│ │ ├── voice_command.py, agent.py, backlog.py, log.py
|
||||
│ ├── services/
|
||||
│ │ ├── auth_service.py — логин, регистрация, OAuth, brute force
|
||||
│ │ ├── session_service.py — CRUD сессий
|
||||
│ │ ├── whisper_service.py — OpenAI Whisper API
|
||||
│ │ ├── llm_service.py — единый LLM-клиент
|
||||
│ │ ├── email_service.py — SMTP + Jinja2
|
||||
│ │ ├── password_reset_service.py — JWT reset token
|
||||
│ │ └── crypto_service.py — AES-256 Fernet
|
||||
│ └── integrations/oauth/
|
||||
│ ├── yandex.py — Яндекс OAuth + Disk (работает)
|
||||
│ ├── google.py — Google OAuth + Drive (stub, ждёт OAuth)
|
||||
│ └── apple.py — Apple OAuth + iCloud (stub, ждёт OAuth)
|
||||
├── webui/
|
||||
│ ├── src/
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── VoiceChat.tsx — чат + сайдбар + text input
|
||||
│ │ │ ├── VoiceInput.tsx — микрофон (Speech → Whisper)
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── LoginPage.tsx, RegisterPage.tsx
|
||||
│ │ │ ├── ForgotPasswordPage.tsx, ResetPasswordPage.tsx
|
||||
│ │ │ ├── OAuthCallback.tsx
|
||||
│ │ └── hooks/
|
||||
│ │ └── useVoiceCommands.ts — голосовые команды
|
||||
│ ├── public/
|
||||
│ │ ├── favicon.ico / .svg / .png
|
||||
│ │ ├── apple-touch-icon.png
|
||||
│ │ ├── site.webmanifest
|
||||
│ │ └── icons/ (192, 512, android-chrome)
|
||||
│ └── index.html
|
||||
├── alembic/versions/
|
||||
│ └── 001_create_all_tables.py
|
||||
├── docs/
|
||||
│ ├── full.md ← данный файл (финальная спецификация)
|
||||
│ ├── architecture.md — архитектурная документация
|
||||
│ └── decision-log.md — лог ключевых решений
|
||||
├── .env.example
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*VoIdeaAI — идеи рождаются вслух, решения приходят мгновенно!*
|
||||
*Документ финальной спецификации. Версия 1.0.0.*
|
||||
Reference in New Issue
Block a user