From 654f64bb902615c7cb16eed8de4fa46aed3a3526 Mon Sep 17 00:00:00 2001 From: Artem Kokos Date: Fri, 15 May 2026 11:58:47 +0700 Subject: [PATCH] docs: add project roadmap and master prompt --- .ai/ROADMAP.md | 323 +++++++++++++++++++++++++++++++++++++++++++ .ai/master_prompt.md | 294 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 617 insertions(+) create mode 100644 .ai/ROADMAP.md create mode 100644 .ai/master_prompt.md diff --git a/.ai/ROADMAP.md b/.ai/ROADMAP.md new file mode 100644 index 0000000..ed147dd --- /dev/null +++ b/.ai/ROADMAP.md @@ -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 можно развивать без страха всё сломать. diff --git a/.ai/master_prompt.md b/.ai/master_prompt.md new file mode 100644 index 0000000..52bf3ae --- /dev/null +++ b/.ai/master_prompt.md @@ -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 + +Не добавляй слой поверх проблемы. +Сначала найди реальный источник истины. +Сделай поведение честным. +Сделай контракт явным. +Сделай проект безопасным по умолчанию.