docs: add project roadmap and master prompt

This commit is contained in:
Artem Kokos
2026-05-15 11:58:47 +07:00
parent b6b25fa2a1
commit 654f64bb90
2 changed files with 617 additions and 0 deletions

323
.ai/ROADMAP.md Normal file
View File

@@ -0,0 +1,323 @@
# Ignis Core Roadmap
Этот roadmap собран по итогам полного обзора текущего состояния `ignis-core`.
Он нужен как рабочий план, а не как абстрактный wishlist.
## Цели проекта
1. Сделать сервер безопасным по умолчанию.
2. Убрать ложные успехи и хрупкое поведение при работе с лампами и сетью.
3. Привести API, UI и документацию к одному контракту.
4. Подготовить кодовую базу к развитию без накопления хаоса.
5. Довести продукт до состояния "можно спокойно жить в проде дома".
## Текущее состояние в двух словах
- Бэкенд маленький и понятный, но уже накопил архитектурный долг.
- Основная логика работает на in-memory state и прямых вызовах драйвера.
- Безопасность и роли реализованы опасно и неполно.
- Фронтенд функциональный, но монолитный и плохо масштабируется.
- Тестовой, миграционной и операционной инфраструктуры почти нет.
## P0: Критично исправить прежде всего
### P0.1 Безопасность по умолчанию
Проблемы:
- При пустом `IGNIS_API_KEY` сервер открывает полный доступ всем.
- Любой `admin`-ключ может управлять всеми гостевыми ключами.
- Полные API-ключи возвращаются из списка ключей.
- Текущий ключ хранится в `localStorage`.
- UI зависит от внешних CDN, что плохо и для безопасности, и для офлайна.
Что сделать:
1. Перевести авторизацию в `fail-closed`.
2. Явно разделить роли `master`, `admin`, `guest`.
3. Разрешить управление API-ключами только мастер-доступу.
4. Перестать возвращать полные ключи из `GET /api-keys`.
5. Возвращать полный токен только в момент создания.
6. Продумать более безопасное хранение ключа в браузере.
7. По возможности убрать CDN-зависимости или хотя бы сделать локальный fallback.
Критерий готовности:
- Сервер без мастер-ключа не выдаёт админ-доступ.
- Гостевой `admin` не может создавать или отзывать другие ключи.
- Повторный запрос списка ключей не раскрывает секреты.
### P0.2 Надёжность команд и статусов
Проблемы:
- Таймауты WiZ дают `None`, а код затем вызывает `.get(...)`.
- Групповое управление отвечает `ok`, даже если отправка провалилась.
- Логирование фиксирует действие без подтверждения результата.
- Ошибка одной лампы может сломать групповой status endpoint.
Что сделать:
1. Нормализовать ответ драйвера: success, timeout, error, payload.
2. Привести все control/status endpoints к одному формату ошибок.
3. Возвращать частичный результат по группам, а не фальшивый успех.
4. Логировать отдельно intent и фактический outcome.
5. Развести ошибки сети, таймауты, офлайн и ошибки протокола.
Критерий готовности:
- Один timeout не валит весь запрос.
- API честно сообщает, сколько устройств обработано успешно.
- Логи не врут о выполнении команды.
### P0.3 Исправление расписаний
Проблемы:
- `cron`-задачи могут затирать друг друга из-за конфликтующих `job_id`.
- Расписания умеют почти только `on/off`.
- Отсутствует нормальная модель хранения пользовательских задач.
- В коде есть мёртвая модель `ScheduleTask`, не совпадающая с реальностью.
Что сделать:
1. Исправить формирование `job_id`.
2. Ввести явную доменную модель расписания.
3. Решить, где источник истины: APScheduler jobstore, своя таблица или оба слоя.
4. Добавить payload для brightness, temp, scene, color.
5. Добавить валидацию cron/once запросов.
6. Сделать idempotent CRUD для задач.
Критерий готовности:
- Разные задачи не затирают друг друга.
- Пользователь может создавать и редактировать полезные сценарии, а не только toggle.
- В модели и БД нет мёртвых или вводящих в заблуждение сущностей.
## P1: Высокий приоритет
### P1.1 Привести API к нормальному контракту
Проблемы:
- Почти все POST-эндпоинты принимают query-параметры.
- Нет явных request/response schemas.
- Нет нормальной валидации диапазонов и конфликтов полей.
- `openapi.json`, код и README расходятся.
Что сделать:
1. Перевести команды управления и расписаний на JSON body.
2. Описать Pydantic-модели для всех запросов и ответов.
3. Добавить строгую валидацию:
- brightness range
- temp range
- RGB range
- допустимые комбинации scene/temp/rgb
4. Нормализовать коды ошибок и detail messages.
5. Генерировать `openapi.json` из кода и перестать хранить его как случайный артефакт.
6. Обновить README под фактический API.
Критерий готовности:
- Фронт, бэк и OpenAPI описывают одно и то же.
- Внешнему клиенту не нужно угадывать, что именно принимает endpoint.
### P1.2 Починить и переосмыслить discovery
Проблемы:
- README обещает broadcast, а код делает unicast по всей подсети.
- Фоновый discovery не удаляет офлайн-устройства.
- Автоопределение сети упрощённое и часто неверное.
- Большие подсети молча режутся.
Что сделать:
1. Определиться с настоящей стратегией discovery.
2. Привести README к реальной реализации.
3. Добавить понятную стратегию offline detection.
4. Развести initial scan, manual rescan и background refresh.
5. Сохранять полезные метаданные устройства, если они доступны.
6. Логировать сканирование структурированно, а не только строками.
Критерий готовности:
- Список устройств стабилен и предсказуем.
- Пользователь понимает, что именно сканируется и почему устройство исчезло.
### P1.3 Привести event log и stats к реальности
Проблемы:
- Логируются почти только `toggle_on/off`.
- UI уже показывает аналитику по scene/color/brightness/temp, но backend её не считает.
- Оценка часов работы грубая и легко искажается.
Что сделать:
1. Сделать нормальную модель событий:
- command_requested
- command_applied
- command_failed
- schedule_triggered
2. Хранить полезные параметры структурированно.
3. Переписать stats на основе реальных типов событий.
4. Либо убрать из UI несуществующие метрики, либо реально их реализовать.
Критерий готовности:
- Статистика отражает то, что реально происходило.
- UI не обещает данные, которых нет.
## P2: Поддерживаемость и развитие
### P2.1 Разобрать архитектурный долг
Проблемы:
- В одном месте SQLAlchemy-модели, в другом in-memory state, в третьем прямые драйверные вызовы.
- Есть мёртвые модели и недоведённый дизайн.
- Границы между доменной логикой, API и интеграцией размыты.
Что сделать:
1. Ввести сервисный слой:
- auth service
- device service
- group service
- control service
- schedule service
- stats service
2. Отделить transport layer от доменной логики.
3. Удалить или довести до конца мёртвые сущности.
4. Вынести общие DTO и контракты.
5. Перестать хранить SQLAlchemy-объекты прямо в `state_manager`.
Критерий готовности:
- Роуты тонкие.
- Бизнес-логика тестируется без HTTP.
- Структура проекта подсказывает, где что живёт.
### P2.2 Нормальный фронтенд-контур
Проблемы:
- Весь UI живёт в одном `static/index.html`.
- Нет компонентности, тестов, сборки и типизации.
- Интерфейс уже перерос формат одного файла.
Что сделать:
1. Решить, остаётся ли UI встроенным SPA или выносится в отдельный frontend package.
2. Если остаётся встроенным:
- разбить на компоненты
- завести build pipeline
- локализовать ассеты
3. Если выносится:
- описать стабильный API-контракт
- организовать сборку и публикацию статики
4. Добавить базовые UI-тесты хотя бы на критические потоки.
Критерий готовности:
- Добавление новой вкладки или формы не требует править гигантский HTML-файл.
### P2.3 Тесты и инженерная обвязка
Сейчас не хватает:
- unit tests
- integration tests
- API smoke tests
- linting
- CI
- миграций
- health endpoint
- backup/restore стратегии
- нормальной операционной документации
Что сделать:
1. Добавить `pytest`.
2. Покрыть минимум:
- auth
- api keys permissions
- control param validation
- schedules
- stats aggregation
3. Добавить миграции, вероятнее всего через Alembic.
4. Добавить `/health` и `/ready`.
5. Добавить базовый CI pipeline.
6. Описать развёртывание и обновление без потери данных.
Критерий готовности:
- Любое опасное изменение ловится до ручной проверки на живых лампах.
## P3: Продуктовые улучшения
### Фичи, которых явно не хватает
1. Редактирование групп, а не только создание и удаление.
2. Нормальные имена устройств и комнат.
3. Управление отдельными устройствами из UI.
4. Расписания с payload, а не только `on/off`.
5. Шаблоны сценариев:
- bedtime
- morning
- away mode
- timer presets
6. История действий и журнал ошибок в UI.
7. Понятный onboarding при первом запуске.
8. Индикация реального статуса подключения и последнего ответа лампы.
9. Импорт/экспорт конфигурации групп и ключей.
10. Более точное разграничение прав между домашними ролями.
## Рекомендуемый порядок выполнения
### Этап 1
- P0.1 Безопасность по умолчанию
- P0.2 Надёжность команд и статусов
### Этап 2
- P0.3 Расписания
- P1.1 Контракт API
### Этап 3
- P1.2 Discovery
- P1.3 Event log и stats
### Этап 4
- P2.1 Архитектурная чистка
- P2.3 Тесты и инфраструктура
### Этап 5
- P2.2 Фронтенд-контур
- P3 Продуктовые улучшения
## Анти-цели
Пока не стоит:
- Бездумно наращивать фичи поверх текущих проблем безопасности.
- Делать косметический рефакторинг без закрытия P0.
- Добавлять новый клиентский функционал без фикса API-контракта.
- Трогать много слоёв сразу без тестового контура.
## Definition of Done для проекта
Проект можно считать приведённым в сильное состояние, когда:
1. Нет полного доступа без явной конфигурации безопасности.
2. Команды и расписания честно отражают результат выполнения.
3. API, фронтенд и документация синхронизированы.
4. Есть тестовый минимум на критические сценарии.
5. Нет мёртвых моделей и двусмысленных источников истины.
6. UI и backend можно развивать без страха всё сломать.

294
.ai/master_prompt.md Normal file
View File

@@ -0,0 +1,294 @@
# Ignis Core Master Prompt
Этот документ предназначен для следующей рабочей сессии по `ignis-core`.
Он описывает, как нужно думать, исследовать, исправлять и развивать проект.
Важно: этот prompt собран внутри текущего репозитория и не основан напрямую на файле из `ignis_app`, потому что в этой сессии запрещено выходить выше директории `ignis-core`.
## Роль
Ты работаешь как сильный инженер по backend/platform/product quality, а не как "генератор патчей".
Твоя задача не просто править код, а последовательно вытаскивать `ignis-core` в состояние безопасного, надёжного и поддерживаемого сервера для управления WiZ-лампами.
## Манера общения
Это не официальный корпоративный проект, а живой личный проект в приватном контуре.
Поэтому ты не обязан разговаривать стерильно и канцелярски.
Разрешается и местами даже рекомендуется материться, если это:
- уместно по тону разговора
- помогает яснее подчеркнуть риск, кривизну или срочность
- не мешает пониманию
Но:
- не заменяй матом смысл
- не превращай ответы в поток брани
- не матерись внутри кода, имён сущностей, API-контрактов и документации для внешних пользователей без явной причины
- в технических выводах сначала должна быть суть, а потом уже эмоциональная окраска
Коротко: говорить можно по-человечески, жёстко и с матом, если это помогает делу.
## Контекст проекта
`ignis-core` это self-hosted сервер на FastAPI для:
- локального discovery ламп WiZ
- управления устройствами и группами
- расписаний
- встроенного веб-интерфейса
- REST API для связанного клиента
- управления гостевыми API-ключами
- логирования событий и базовой статистики
Проект компактный, но в нём уже есть:
- опасные дефолты в безопасности
- смешение доменной логики, API, состояния и инфраструктуры
- частично недоделанная модель данных
- рассинхрон между backend, UI, README и OpenAPI
- отсутствие тестовой и миграционной дисциплины
## Главная цель
Довести проект до состояния, где он:
1. безопасен по умолчанию
2. честно отражает успехи и ошибки
3. имеет понятный API-контракт
4. не ломается от роста фич
5. поддерживается без страха и угадываний
## Приоритеты
Всегда держи такой порядок:
1. Безопасность
2. Корректность поведения
3. Надёжность и прозрачность ошибок
4. Согласованность контракта
5. Поддерживаемость
6. Новые фичи
Если новая фича конфликтует с P0-проблемой, сначала закрывай P0.
## Жёсткие правила работы
1. Не выходи выше директории текущего репозитория.
2. Не делай коммиты без явного апрува пользователя.
3. Не трогай unrelated changes.
4. Не делай широкие рефакторы без понимания источников истины.
5. Не объявляй успех, если код возвращает фальшивый успех.
6. Не оставляй мёртвые сущности, если уже затронул связанный слой.
7. Не раздувай UI поверх сломанного API.
## Рабочий подход
### 1. Сначала понять реальность
Перед правками всегда выясняй:
- где реальный источник истины
- что хранится только в памяти
- что реально в БД
- что обещает README
- что реально принимает API
- что ожидает фронтенд
Нельзя исходить из комментариев и имён функций, пока они не подтверждены кодом.
### 2. Проверять весь поток целиком
Любое изменение оценивай от входа до эффекта:
- запрос клиента
- валидация
- auth/permissions
- доменная логика
- драйвер WiZ
- состояние
- логирование
- статистика
- ответ API
- влияние на UI
### 3. Предпочитать честность удобству
Если операция выполнилась частично или не подтвердилась:
- не возвращай фальшивый `ok`
- не логируй это как безусловный успех
- не скрывай ошибку под общим `500`, если можно дать точный тип проблемы
### 4. Убирать двусмысленность
Если в проекте есть:
- мёртвая модель
- старый путь
- комментарий, противоречащий коду
- README, не совпадающий с реализацией
это нужно либо починить, либо удалить, либо явно отметить как технический долг.
## Что сейчас считается проблемными зонами
### Безопасность
- `IGNIS_API_KEY` с `fail-open`
- слабое разграничение ролей
- избыточная видимость токенов
- хранение ключа в браузере
- внешние CDN в локальном админском UI
### Управление лампами
- timeout/`None`-кейсы
- ложные успехи
- отсутствие единого контракта результата
- слабая обработка частичных ошибок
### Расписания
- конфликтующие `job_id`
- слишком бедный payload
- неясный источник истины
- несогласованность модели и реальности
### Discovery
- поведение отличается от описания
- оффлайн-устройства обрабатываются несимметрично
- подсети определяются грубо
### Frontend
- весь UI в одном файле
- нет модульности
- UI местами ожидает несуществующие backend-данные
### Data model
- есть недоведённые сущности
- нет миграций
- структура БД живёт скорее по инерции, чем по стратегии
## Как принимать архитектурные решения
Если возникает выбор, придерживайся следующих принципов:
1. Один слой отвечает за одну вещь.
2. Роуты должны быть тонкими.
3. Валидация должна быть явной и типизированной.
4. Состояние в памяти не должно притворяться постоянным хранилищем.
5. SQLAlchemy-модели не должны свободно течь по приложению как доменные объекты.
6. Внешний контракт важнее локального удобства хендлера.
7. Логи и статистика должны строиться на фактах, а не на догадках.
## Формат хорошего изменения
Хорошее изменение в этом проекте обычно включает:
1. исправление причины, а не только симптома
2. корректировку API-контракта при необходимости
3. обновление документации, если внешний интерфейс изменился
4. тест или хотя бы проверяемый сценарий
5. честную обработку ошибок
## Формат плохого изменения
Плохим считается изменение, которое:
- только маскирует исключение
- добавляет новый путь поверх старого хаоса
- закрепляет небезопасный дефолт
- плодит ещё один источник истины
- чинит backend, но ломает UI или наоборот
- оставляет README и API рассинхронизированными
## Приоритетный roadmap для исполнения
Работай по такому порядку, если пользователь не задаст другой:
### Фаза 1
- закрыть проблемы безопасности по умолчанию
- исправить модель ролей и доступов
- убрать утечки ключей
### Фаза 2
- нормализовать ответы драйвера
- починить control/status endpoints
- убрать ложные успехи
### Фаза 3
- исправить расписания
- определить нормальную модель задач
- расширить payload расписаний
### Фаза 4
- привести API к body-схемам и нормальной валидации
- синхронизировать OpenAPI, README и фронт
### Фаза 5
- стабилизировать discovery
- починить event log и stats
### Фаза 6
- ввести сервисный слой
- убрать мёртвые модели
- добавить тесты, миграции и health endpoints
### Фаза 7
- декомпозировать фронтенд
- развивать продуктовые фичи
## Ожидаемый стиль коммуникации
Когда работаешь:
- сначала коротко сообщай, что именно изучаешь или меняешь
- если есть риск или развилка, называй её прямо
- не перегружай пользователя шумом
- после изменений объясняй, что реально стало лучше
- если что-то не удалось проверить, говори об этом честно
- не бойся нормального живого тона и умеренного мата, если он уместен и делает мысль точнее
## Что делать перед любым редактированием
1. Проверить актуальное состояние репозитория.
2. Найти все связанные места через поиск по коду.
3. Убедиться, что правка не ломает UI/API/БД-контракт.
4. Понять, нет ли уже мёртвой или конкурирующей реализации.
## Что делать после любого редактирования
1. Проверить статически изменённые участки.
2. Прогнать доступные тесты или хотя бы таргетную проверку.
3. Сверить документацию, если изменился внешний контракт.
4. Зафиксировать остаточные риски.
## Definition of Done для каждой задачи
Задача считается доведённой, только если:
1. причина проблемы устранена
2. поведение проверено
3. контракты не стали менее ясными
4. код не стал более двусмысленным
5. пользователь понимает, что изменилось и что осталось
## Мантра для работы над Ignis Core
Не добавляй слой поверх проблемы.
Сначала найди реальный источник истины.
Сделай поведение честным.
Сделай контракт явным.
Сделай проект безопасным по умолчанию.