domovoy/PLAN.md

394 lines
16 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.

# План реализации проекта "Домовой"
Документ представляет собой пошаговый план разработки.
Каждая итерация — самостоятельный кусок функционала, который
можно реализовать, протестировать и запустить независимо.
После каждой итерации запускается scripts/check.sh.
Без успешного smoke test итерация не считается завершённой.
---
## Итерация 1. Каркас приложения
Цель: приложение открывается, есть логин, база, миграции, layout.
Что делаем:
- Slim 4 приложение с маршрутами
- Docker Compose: app (PHP 8.3) + MariaDB
- .env.example со всеми переменными
- Phinx: конфигурация, миграция users
- Регистрация первого пользователя (CLI setup)
- Логин/Logout с сессиями
- Bootstrap layout с левым меню и верхней панелью
- Dashboard с заглушками счётчиков
- scripts/check.sh с базовыми проверками
Файлы:
composer.json
phinx.php
docker-compose.yml
docker/Dockerfile
.env.example
public/index.php
public/assets/css/app.css
app/Controllers/AuthController.php
app/Controllers/DashboardController.php
app/Controllers/SetupController.php
app/Middleware/AuthMiddleware.php
app/Repositories/UserRepository.php
app/Services/AuthService.php
templates/layout.php
templates/auth/login.php
templates/dashboard/index.php
migrations/20250526000001CreateUsers.php
bin/console
scripts/check.sh
README.md
Проверка:
docker compose up -d --build
docker compose exec app php vendor/bin/phinx migrate
docker compose exec app php bin/console setup:user
curl -I http://localhost:8080/login
# Открыть в браузере, залогиниться, увидеть dashboard
---
## Итерация 2. Сканирование сети
Цель: добавить диапазон, запустить scan, увидеть найденные хосты.
Что делаем:
- Миграции: network_ranges, scan_jobs, discovered_hosts
- NetworkRanges CRUD (вкладка Discovery)
- NetworkScanner: ping sweep + TCP connect + ARP + reverse DNS
- CLI worker bin/run-scan-worker.php
- Страница Discovery: таблица discovered_hosts
- htmx для запуска scan и обновления статуса scan_jobs
- Audit log для действий сканрования
Файлы (новые/изменённые):
migrations/20250526000002CreateNetworkRanges.php
migrations/20250526000003CreateScanJobs.php
migrations/20250526000004CreateDiscoveredHosts.php
migrations/20250526000005CreateAuditLog.php
app/Controllers/DiscoveryController.php
app/Controllers/NetworkRangeController.php
app/Services/Discovery/NetworkScanner.php
app/Services/Discovery/PingScanner.php
app/Services/Discovery/TcpPortScanner.php
app/Services/Discovery/ArpTableReader.php
app/Services/Discovery/HostFingerprintService.php
app/Services/Jobs/ScanJobRunner.php
app/Services/Jobs/JobQueue.php
app/Repositories/ScanJobRepository.php
app/Repositories/DiscoveredHostRepository.php
app/Repositories/NetworkRangeRepository.php
app/Repositories/AuditLogRepository.php
templates/discovery/index.php
templates/discovery/ranges.php
templates/discovery/hosts.php
bin/run-scan-worker.php
Проверка:
# Добавить диапазон 192.168.1.0/24
# Запустить scan через UI
# В другом терминале:
docker compose exec app php bin/run-scan-worker.php
# Увидеть найденные хосты в таблице Discovery
---
## Итерация 3. Инвентарь устройств
Цель: создавать карточки устройств руками и из найденных хостов.
Что делаем:
- Миграция devices
- Devices CRUD (список, создание, редактирование, карточка)
- Создание device из discovered_host (кнопка "Создать устройство")
- Игнорирование discovered_host (кнопка "Игнорировать")
- Карточка устройства со всеми полями
- Merge suggestions (по MAC → высокая, hostname → средняя, IP → низкая)
- Обновление Dashboard: реальные счётчики устройств
Файлы (новые/изменённые):
migrations/...CreateDevices.php
app/Controllers/DeviceController.php
app/Services/Inventory/DeviceService.php
app/Services/Inventory/MergeSuggestionService.php
app/Repositories/DeviceRepository.php
templates/devices/index.php
templates/devices/create.php
templates/devices/edit.php
templates/devices/show.php
templates/dashboard/index.php (обновить счётчики)
Проверка:
# Создать устройство вручную
# Создать устройство из discovered_host
# Открыть карточку, проверить все поля
# Проверить merge suggestions
---
## Итерация 4. SSH-доступы
Цель: добавить SSH-доступ к устройству, проверить подключение.
Что делаем:
- Миграция credentials
- Credentials CRUD (только SSH для MVP)
- Шифрование секретов (defuse/php-encryption)
- Тест подключения через phpseclib
- Блок доступов на карточке устройства
- CredentialVault для шифрования/дешифрования
- Сохранение результата теста (last_test_status, last_test_at)
Файлы (новые/изменённые):
migrations/...CreateCredentials.php
app/Controllers/CredentialController.php
app/Services/Security/CredentialVault.php
app/Services/HostScan/SshClientFactory.php
app/Repositories/CredentialRepository.php
templates/credentials/_form.php
templates/credentials/_test_result.php
templates/devices/show.php (добавить блок доступов)
.env.example (добавить ENCRYPTION_KEY)
Проверка:
# Добавить SSH-доступ к устройству
# Нажать "Тест" — увидеть результат подключения
# Секрет не отображается в UI открытым текстом
# В базе хранится зашифрованное значение
---
## Итерация 5. Deep scan Linux-хоста
Цель: по SSH собрать read-only информацию с Linux-хоста.
Что делаем:
- Миграции: host_scans
- LinuxHostScanner: hostname, os, ip, ports, disk, systemd, cron
- CommandWhitelist с массивами аргументов
- SshClientFactory с таймаутами (connect=5s, auth=10s, cmd=8s)
- Сохранение raw JSON в storage/scans/
- Summary в host_scans.summary_json
- Кнопка "Глубокий скан" на карточке устройства
- Страница результата скана
- Worker поддерживает тип host_deep_scan
Файлы (новые/изменённые):
migrations/...CreateHostScans.php
app/Controllers/HostScanController.php
app/Services/HostScan/LinuxHostScanner.php
app/Services/HostScan/CommandWhitelist.php
app/Repositories/HostScanRepository.php
templates/host_scans/show.php
templates/devices/show.php (кнопка deep scan)
bin/run-scan-worker.php (поддержка host_deep_scan)
config/scan_commands.php (CommandWhitelist mapping)
.env.example (добавить SSH_* таймауты)
Проверка:
# Добавить SSH-доступ к устройству
# Нажать "Глубокий скан"
# В другом терминале:
docker compose exec app php bin/run-scan-worker.php
# Увидеть результат: hostname, os, порты, диски, systemd, cron
# raw JSON сохранён в storage/scans/
---
## Итерация 6. Docker scan + detected_services
Цель: найти контейнеры и создать предложения сервисов.
Что делаем:
- Миграция detected_services
- DockerScanner: docker ps, inspect, volumes, networks
- SecretMasker для env-переменных (PASSWORD, TOKEN, KEY...)
- Создание detected_services kind=docker_container
- Страница "Найденные сервисы" (detected services)
- Действия: Создать сервис, Объединить, Игнорировать, Детали
- Host scan обогащается docker-сканом
Файлы (новые/изменённые):
migrations/...CreateDetectedServices.php
app/Controllers/DetectedServiceController.php
app/Services/HostScan/DockerScanner.php
app/Services/Security/SecretMasker.php
app/Repositories/DetectedServiceRepository.php
templates/services/detected.php
templates/services/_detected_row.php
app/Services/HostScan/LinuxHostScanner.php (добавить docker)
Проверка:
# Запустить deep scan на хосте с Docker
# Увидеть detected_services с kind=docker_container
# Секретные env-переменные замаскированы
# Страница найденных сервисов показывает таблицу
---
## Итерация 7. Создание сервисов + связи
Цель: превратить найденный сервис в карточку с отношениями.
Что делаем:
- Миграции: services, service_endpoints, relations
- Service CRUD
- Создание service из detected_service (с выбором типа)
- Автоматическое создание service_endpoints (port, url)
- Создание связей (Device runs_on Service, Service exposes Endpoint)
- Карточка сервиса
- Обновление detected_service.status = accepted
Файлы (новые/изменённые):
migrations/...CreateServices.php
migrations/...CreateServiceEndpoints.php
migrations/...CreateRelations.php
app/Controllers/ServiceController.php
app/Services/Inventory/ServiceInventoryService.php
app/Services/Inventory/RelationService.php
app/Repositories/ServiceRepository.php
app/Repositories/ServiceEndpointRepository.php
app/Repositories/RelationRepository.php
templates/services/index.php
templates/services/create.php
templates/services/show.php
templates/services/detected.php (кнопка "Создать сервис")
Проверка:
# Нажать "Создать сервис" на detected_service
# Выбрать тип (web_app, database...)
# Сервис создан, endpoint-ы созданы, связи созданы
# detected_service.status = accepted
# Карточка сервиса показывает связи
---
## Итерация 8. Nginx/Cron/Backup сканеры
Цель: находить nginx vhost-ы, cron-задачи, backup-подсказки.
Что делаем:
- NginxScanner: парсинг server_name, listen, proxy_pass, root
- CronScanner: crontab -l, /etc/crontab, /etc/cron.d/*
- BackupHintScanner: поиск rsync, borg, restic, tar, mysqldump...
- detected_services kind=nginx_vhost, cron_job, backup_hint
- Миграция domains
- Создание domain suggestions из nginx server_name
- Host scan обогащается nginx/cron/backup сканами
Файлы (новые/изменённые):
migrations/...CreateDomains.php
app/Services/HostScan/NginxScanner.php
app/Services/HostScan/CronScanner.php
app/Services/HostScan/BackupHintScanner.php
app/Repositories/DomainRepository.php
templates/host_scans/show.php (добавить nginx/cron/backup)
templates/devices/show.php (найденные сервисы)
Проверка:
# Deep scan на хосте с nginx + cron + backup scripts
# Увидеть detected_services: nginx_vhost, cron_job, backup_hint
# Формулировка backup_hint: "Похоже на backup job"
# Domains созданы из nginx server_name
# Приватные ключи сертификатов НЕ прочитаны
---
## Итерация 9. Риски + Dashboard + История
Цель: предупреждения на dashboard, история сканов, diff.
Что делаем:
- RiskAnalyzer: сервис без backup, публичный endpoint, SSH открыт,
нет свежего scan, TLS истекает
- Dashboard: реальные предупреждения
- История scan jobs
- DiffAnalyzer: новые/пропавшие хосты, порты, контейнеры между сканами
- DiffAnalyzer: новые/пропавшие хосты, порты, контейнеры между сканами
- Documents CRUD (заметки/runbooks)
Файлы (новые/изменённые):
migrations/...CreateDocuments.php
app/Controllers/DocumentController.php
app/Controllers/ScanHistoryController.php
app/Controllers/DiffController.php
app/Services/Analysis/RiskAnalyzer.php
app/Services/Analysis/DiffAnalyzer.php
app/Repositories/DocumentRepository.php
templates/dashboard/index.php (real warnings)
templates/scans/history.php
templates/scans/diff.php
templates/documents/index.php
templates/documents/create.php
Проверка:
# Dashboard показывает предупреждения ( service без backup и т.д. )
# История scan jobs с статусами
# Diff между двумя сканами: новые/пропавшие хосты
# Документы: создать runbook, привязать к устройству
---
## Итерация 10. Полировка + документация
Цель: финальная доводка проекта.
Что делаем:
- Полный audit log для всех действий
- Документация в README полностью
- Скриншоты в README (опционально)
- Проверка всех security-правил
- scripts/check.sh обновлён под все итерации
- Финальный smoke test: весь цикл scan → device → service
---
## Сводная таблица
Итерация | Что делаем | Зависимости
1 | Каркас: Slim, Docker, auth, layout | —
2 | Network scan | 1
3 | Devices CRUD | 1
4 | SSH credentials | 1, 3
5 | Deep scan Linux | 1, 3, 4
6 | Docker scan + detected_services | 1, 5
7 | Services + relations | 1, 6
8 | Nginx/Cron/Backup scanners | 1, 5, 7
9 | Risks + Dashboard + History + Docs | 1-8
10 | Полировка + README | 1-9
---
## Правила для каждой итерации
1. Не переходить к следующей, пока check.sh не прошёл.
2. Показывать реальный вывод smoke test, а не "готово".
3. Маленькие атомарные коммиты.
4. Контроллеры — только роутинг, бизнес-логика в Services.
5. SQL только в Repository-классах.
6. Shell-команды только через CommandWhitelist (массивы аргументов).
7. Никакого произвольного shell executor из UI.
8. Никакого "чистый JS потом допишем" — весь JS заявлен заранее.
---
## Порядок выдачи задания owl-alpha
Рекомендуется выдавать по одной итерации:
Шаг 1: "Прочитай ТЗ и PLAN.md. Сделай Итерацию 1."
Шаг 2: "Прочитай текущий код. Сделай Итерацию 2 по PLAN.md."
...
После каждой итерации — ревью, smoke test, фикс замечаний,
и только потом следующая итерация.
Никогда не давай больше одной итерации за раз.