Files
XC_VM/docs/en/development/architecture.md
T
Divarion_D fda7f41258 refactor(ministra): move Stalker portal from module into core (src/Ministra)
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.
2026-08-11 21:41:11 +03:00

3.6 KiB

Architecture Overview

Project type

Structured PHP monolith with a modular extension layer.

  • No DDD, no Hexagonal, no Clean Architecture — intentional.
  • Split by context with minimal abstractions: Controller → Service → Repository.
  • Two build artifacts from one codebase: MAIN (full panel) and LB (load balancer subset).

Source tree

Path Role
src/Core/ Infrastructure primitives: DI container, events, HTTP, config, auth, logging
src/Domain/ Business contexts: Stream, VOD, Line, User, Server, Security, etc.
src/Modules/ Optional extension layer — loaded by ModuleLoader
src/Public/ Front controller, router, controllers, views, assets
src/Cli/ Console commands and cron entry points
src/Ministra/ Stalker Portal — in core; served at /home/xc_vm/Ministra

Runtime model

Dependencies flow inward — modules may use core and domain, never the reverse.

Public/index.php
    └── XC_Bootstrap::boot(BootContext::ADMIN)
            └── ServiceContainer (DI)
                    ├── EventDispatcher (PSR-14)
                    ├── ModuleLoader → loadAll() → bootAll()
                    └── Router → dispatch()

Domain classes receive the database via setDb() injection (called from bootstrap.php::wireDomainDatabase()). No global $db in the web request path.


Module system

Modules are isolated directories under src/Modules/ with a module.json manifest and a class extending BaseModule. See Module System for the full reference.

src/Modules/my-module/
├── module.json          # metadata
├── MyModuleModule.php   # extends BaseModule, namespace XcVm\Module\MyModule
└── ...

Bootstrap contexts

Four contexts control which subsystems initialize. See Bootstrap Contexts.

Context Used for
BootContext::MINIMAL Scripts needing only paths/config
BootContext::CLI Cron jobs and CLI commands
BootContext::STREAM Streaming endpoints
BootContext::ADMIN Admin/reseller panel

Build variants (MAIN vs LB)

MAIN LB
Admin panel ✅ ❌
Streaming ✅ ✅
Module system ✅ subset

Controlled by ServerEnvironment enum and module.json environment field (main / lb / any).


Key extension points

Mechanism How to use
PSR-14 events EventDispatcher::listen() or #[ListensTo] attribute
Service decoration $container->decorate('id', callable, priority)
Stream middleware Implement StreamMiddlewareProviderInterface
Cron entries Override getCronEntries() in module class
DB migrations Implement MigratableInterface::getMigrations()

Contributor rules

  1. Modules must not modify core files.
  2. No eval, monkey patching, or runtime file replacement.
  3. Any module can be disabled via config/modules.php without touching core.
  4. Protected services (db, settings, config, auth) cannot be decorated.
  5. Keep EN and RU docs in sync in the same commit.
File Role
src/Core/ Framework primitives (DI, events, HTTP, config, auth, logging)
src/Domain/ Business contexts (Stream, VOD, Line, User, Server, Security)
src/Infrastructure/ External adapters (DatabaseFactory, CacheReader, Redis)
src/Streaming/ Streaming subsystem
src/Modules/ Optional modules (loaded by ModuleLoader)
src/Public/ Front controller, controllers, views
src/Cli/ Console commands and cron jobs