324 lines
15 KiB
Markdown
324 lines
15 KiB
Markdown
# 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 можно развивать без страха всё сломать.
|