Ministra stops being a module — the whole Stalker portal (portal.php,
MinistraBootstrap, PortalHandler/PortalHelpers and the STB front-end) now
lives in src/Ministra/ under the XcVm\Ministra namespace, served at
/home/xc_vm/Ministra via the nginx alias.
- src/ministra/* and Modules/ministra_85a7d/{PortalHandler,PortalHelpers}
→ src/Ministra/; MinistraModule.php + module.json removed. Ministra was
the only committed module, so src/Modules/ keeps a .gitkeep.
- portal.php resolves PortalHandler as a sibling and derives MAIN_HOME from
its new location (glob crutch gone).
- nginx alias + AuthRepository $rAlias switched to /home/xc_vm/Ministra
(PascalCase); ministra entry dropped from bundled_modules.php.
- Makefile: Modules/ removed from LB_DIRS — all modules are MAIN-only, so
the ~50 MB of portal assets no longer ship to LB nodes.
- ArchitectureTest: zero committed modules is now a valid state.
- PHPStan: analyse src/Ministra, exclude the procedural portal.php entry,
repath the ministra baseline entries.
- Docs (architecture, ministra-browser-emulation, extraction plan) updated
to the new layout; the "extract to a separate repo" plan is cancelled.
Verified: php -l, make gates, make phpstan (No errors), full unit suite
(432 tests). On-server smoke: handshake + get_profile work end-to-end with
a registered MAC after deploy.
14 KiB
План выноса Ministra в полноценный модуль
Статус: черновик плана (июль 2026). Цель — довести ministra от «полумодуля»
(логика в Modules/ministra_85a7d/, но вход и 50 MB ассетов в src/ministra/)
до самодостаточного модуля в отдельном репозитории Module_Ministra,
устанавливаемого и обновляемого штатным модульным механизмом.
Обновление 2026-08-11 (ветка
refactor/ministra-to-core): направление изменено — ministra перенесена В ЯДРО, а не в отдельный модуль/репозиторий. Этот план (вынос вModule_Ministra) тем самым отменён. Сделано:PortalHandler/PortalHelpers+portal.php/MinistraBootstrap+ STB-фронтенд переехали вsrc/Ministra/(namespaceXcVm\Ministra),MinistraModule.phpиmodule.jsonудалены, запись убрана изbundled_modules.php, nginx-alias и#ALIAS#вAuthRepositoryпереведены на/home/xc_vm/Ministra,Modulesубран изLB_DIRS. Причина разворота: запутанность ministra — это учёт MAG-устройств, который и так живёт в ядре (см. раздел «Связи с ядром»), поэтому протокол портала логичнее держать рядом, в ядре, а не тащить в отдельный репозиторий.
0. Текущее состояние
Код и ассеты:
| Что | Где | Примечание |
|---|---|---|
Вход portal.php (~1130 строк, процедурный) |
src/ministra/ |
nginx исполняет его напрямую через fastcgi (не через front controller) |
MinistraBootstrap.php |
src/ministra/ |
обёртка над StreamingRequestBootstrap::init('portal') |
STB-фронтенд: ~84 JS, template/, external/, index.html |
src/ministra/ (~50 MB) |
nginx отдаёт как статику через alias /home/xc_vm/ministra/ |
MinistraModule, PortalHandler (вся серверная логика), PortalHelpers (мёртвый класс — нигде не вызывается) |
src/Modules/ministra_85a7d/ |
module.json: bundled, environment: main, миграций нет |
Связи с ядром:
- nginx:
template_ministra(кодовые локации → alias на/home/xc_vm/ministra/); legacy/c/и/portal.phpс toggle$ministra_legacy_redirect(генеритсяRootSignalsCronJobиз настройкиmag_legacy_redirect). - AuthRepository: типы access-кодов
ministraиministra/new(каталогаministra/newна диске нет — см. риски). Public/index.php: scopeMap содержитministra/ministra/new.- Paths:
MINISTRA_TMP_PATH(+ чистка вTmpCronJob/CacheCronJob). - БД (все таблицы в core
database.sql):mag_devices— ядро пишет (админка, реселлер,MagService,LineService,UserRepository) + портал;mag_events— админка (MagEventController, quick_tools, topbar),MagService, reseller API + портал;mag_claims—MagService,StreamRepository+ портал;mag_logs— толькоMagService/бэкап.
- Настройки (core settings + UI в
settings.php):disable_ministra,mag_legacy_redirect,enable_debug_stalker,stalker_theme,mag_default_type,mag_disable_ssl,allowed_stb_types,stalker_lock_images. - LB: nginx на LB отдаёт 404 для portal;
src/ministraне входит вLB_DIRS(не шипится на LB).bundled_modules.phpуже спроектирован под flipbundled → gitпо стабильномуhash_id.
1. Границы модуля (ключевые решения)
Принцип: модуль владеет протоколом портала (portal.php, PortalHandler, STB-фронтенд, темы), ядро владеет учётом MAG-устройств (это часть линий/биллинга, используется реселлером и Enigma независимо от портала).
- Таблицы
mag_devices,mag_events,mag_claims,mag_logsостаются в ядре: их пишет админка/реселлер/MagService, а правило архитектуры запрещает ядру трогать модульные таблицы (обратное — модуль читает core-таблицы — допустимо). Следствие: модулю не нужны миграции; он чистый потребитель схемы ядра. - Настройки остаются в core settings; UI — в
settings.php(опционально позжеhas_settings: trueи перенос секции в модуль). - Access-code типы
ministra/ministra/new— фича ядра (AuthRepository), остаются в ядре; при отсутствии модуля кодовая локация отдаёт 404 — приемлемо. environment: mainсохраняется — на LB портал не работает (как сейчас).
2. Фаза A — консолидация кода в модуле (модуль остаётся bundled)
Цель: весь код и ассеты в Modules/ministra_85a7d/, ядро ссылается только
на стабильный путь-симлинк.
- A1. Перенести
src/ministra/*→Modules/ministra_85a7d/www/(portal.php, MinistraBootstrap.php, index.html, JS, template/, external/). - A2. В portal.php подключать
PortalHandlerпо__DIR__(соседний файл) — класс проблем с хеш-каталогом исчезает навсегда (текущий glob-резолв в portal.php:20 — временный костыль, фаза A его вытесняет). - A3. Симлинк
/home/xc_vm/ministra → Modules/ministra_<hash>/www:- создаётся в
install()модуля, удаляется вuninstall()(черезBaseModule-hook или логику самого модуля); - nginx-конфиги (
template_ministra,/c/alias) не меняются; - проверить
disable_symlinksв бандловом nginx (по умолчанию off — ок).
- создаётся в
- A4.
index.phpscopeMap иAuthRepository— без изменений (путь сохранён симлинком). - A5.
MinistraModule::getEntryPoint()— привести к фактическому пути. - A6. Разобрать мёртвый
PortalHelpers: либо удалить, либо (рекомендуется) перенести в него глобальные функции из portal.php (getDevice,getItems,updateCache,getEPG,shutdown, …) статическими методами — portal.php становится тонкой обёрткой. Это же снимет конфликт имён при повторном require. - A7. Гейты:
check-procedural-useдля перенесённых файлов (use-импорты сверху),php -l,make gates.
3. Фаза B — развязка с ядром
- B1. Поведение при выключенном/удалённом модуле: симлинк снят → nginx 404
на статику и portal.php; проверить, что fallback
@fc_CODEне даёт 500. Настройкаdisable_ministraпродолжает работать как программный выключатель. - B2.
MINISTRA_TMP_PATHостаётся в corePaths(константа безвредна при отсутствии модуля, чистку в кронах сохраняем). Рефакторинг «модуль регистрирует свои tmp-пути» — не обязателен для v1, отметить как tech debt. - B3. События: пока модуль не владеет таблицами — событийная чистка не нужна.
Если появятся модульные таблицы — только через
#[ListensTo](см. правило ядра). - B4.
bundled_modules.php— на этой фазе остаётсяbundled.
4. Фаза C — вынос в отдельный репозиторий Module_Ministra
- C1. Репозиторий
Vateron-Media/Module_Ministraпо образцуModule_Watch:module.jsonс блокомupdate(git, stable) — с первого релиза;changelog.json;- CI-релиз: ассеты
module.tar.gz+hashes.md5; - бинарники/шрифты/видео из
external/,template/— Git LFS в репо модуля; - проверить размер
module.tar.gz(~50 MB несжатых ассетов).
- C2.
module.json: bump версии (1.1.0), update-блок. - C3. Панель: flip записи в
bundled_modules.php(hash_id85a7d…) наsource: git+ repository —syncBundledModules()начнёт ставить модуль с GitHub на fresh install /console.php status. - C4. Удалить из панели
src/Modules/ministra_85a7dиsrc/ministra(только после публикации релиза модуля). - C5. Обновление существующих инсталляций (порядок критичен):
- апдейт панели не должен ломать работающий портал до установки модуля;
- если
Modules/ministra_*уже есть локально — не трогать, иначеsyncBundledModules()тянет с GitHub; - legacy-каталог
/home/xc_vm/ministraудалять только после успешной установки модуля и создания симлинка (в каталоге нет данных — только код/ассеты; сессии устройств живут вMINISTRA_TMP_PATH).
- C6. GitHub rate-limit: установка/обновление без токена упирается в
60 req/h на IP (уже наблюдалось на боевом сервере). Завести настройку
github_tokenи пробрасывать её вGitHubReleases(конструктор уже принимает).
5. Фаза D — сборка и инфраструктура
- D1. Makefile: после C4
src/ministraисчезает из main-архива сам; аудитLB_DIRS— комментарий говорит «Modules/ intentionally excluded», но список фактически содержитModules(строка 26) — выяснить и починить расхождение отдельным фиксом. - D2.
grep -r ministraпоinstall/,update/,tools/— не должно остаться ссылок на старую раскладку. - D3. Гейты:
verify-lb-archive,check-procedural-use— зелёные.
6. Тест-план / приёмка
Матрица:
- fresh install (модуль приходит через
syncBundledModulesс GitHub); - update со старой версии: legacy
/home/xc_vm/ministra, legacy bareModules/ministra(без хеша), текущийministra_85a7d; - портал: handshake → get_profile → авторизация MAG → live/vod/series/EPG/ tv_archive/radio/watchdog/account_info;
- legacy
/c/и/portal.phpпри обоих значенияхmag_legacy_redirect; - оба типа кодов (
ministra,ministra/new); - uninstall/reinstall модуля (симлинк создаётся/удаляется);
- обновление модуля кнопкой Update (git-релиз) и кроном
cron:module_updates; - регрессия ядра при ВЫКЛЮЧЕННОМ модуле: страницы mags/mag_events админки, reseller MAG flows, Enigma — учёт устройств не зависит от портала;
- LB не затронут (portal 404, архив без модуля).
7. Риски
| Риск | Митигация |
|---|---|
Симлинк + nginx alias (права, disable_symlinks, open_basedir) |
проверить на стейдже; fallback — копирование www/ в /home/xc_vm/ministra при install (дороже на диск) |
| 50 MB релизный ассет тянется при каждом install/update | кэш архивов storeModuleArchive уже есть; LFS в репо модуля |
Тип кода ministra/new без каталога на диске — похоже, сломан уже сейчас |
отдельный аудит: починить или удалить тип |
| OPcache держит старый portal.php после переноса | reload PHP-FPM в шаге обновления (RootSignals) |
Кастомные темы пользователей внутри /home/xc_vm/ministra пропадут при удалении каталога |
предупреждение в release notes + бэкап каталога в update-скрипте |
| GitHub API 403 при установке | C6 (github_token) |
8. Порядок релизов
- Release N — фазы A+B: модуль самодостаточен, но всё ещё bundled; симлинк; раскладка новая, источник старый.
- Release N+1 — фазы C+D: вынос в репо, flip на git, удаление из панели.
Разнесение по двум релизам разделяет два рискованных изменения (смена раскладки и смена источника) и даёт точку отката: если git-дистрибуция забуксует, Release N полностью рабочий.