Verify every dev-doc claim against src/ and fix factual drift: wrong method signatures/return types, wrong enum casing (BootContext cases are PascalCase), stale paths (M3u parsers are Composer deps under vendor/, MobileDetect is mobiledetect/mobiledetectlib v4.9.0 \Detection\MobileDetect, NotFoundException lives in XcVm\Core\Container\Psr), a fictional `stream:check` command/class, reversed migration-failure semantics ([FAIL] = not recorded, retried), inverted isStreamRunning/isStreamAlive descriptions, findProcessPIDs ANY-not-ALL, acquireCronLock has no shutdown callback, and nonexistent make targets. Split oversized pages and fix nav + cross-links: - modules.md -> module-authoring / module-lifecycle / module-extension-points - cli-tools.md -> cli-tools + database-migrations - streaming-subsystem.md -> + streaming-diagnostics - geoip-and-device-detection.md -> geoip-isp-and-geo-routing + device-detection-and-stb-locking Add development/core-wiring.md: how the core assembles itself at boot (container population, ServiceContainer reference, bootAll orchestration, CLI command auto-discovery, end-to-end Admin/CLI boot walkthroughs). Only docs/en + mkdocs.yml touched; docs/ru is regenerated before release.
4.3 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/ |
Framework primitives: DI container, events, HTTP/router, config, auth, logging |
src/Domain/ |
Business contexts: Stream, VOD, Line, User, Server, Security, etc. |
src/Infrastructure/ |
External adapters: DatabaseFactory, cache readers, Redis, TMDb |
src/Streaming/ |
Streaming subsystem: bootstrap, auth, delivery, balancer, protection |
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 and module classes do not take $db in their constructor. They
use \XcVm\Infrastructure\Database\DatabaseAware and call self::db(), which lazily
resolves the shared connection. bootstrap.php::wireDomainDatabase() sets that connection
once per boot (via DatabaseAware::setDb()) — there is no per-class wiring and 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 Authoring for the full reference (and the linked Lifecycle / Extension Points pages).
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 the ServerEnvironment enum and each module.json's environment field
(main / lb / any). At boot, ModuleLoader::getCurrentEnvironment() resolves the node's
environment from the SERVER_TYPE constant ('lb' → ServerEnvironment::LoadBalancer, else
ServerEnvironment::Main); a module whose environment doesn't match the node is skipped, so
the LB gets a subset of modules.
Key extension points
| Mechanism | How to use |
|---|---|
| PSR-14 events | EventDispatcher::listen() / #[ListensTo] — see Event System |
| Service decoration | $container->decorate('id', callable, priority) — see Module Extension Points |
| Stream middleware | Implement StreamMiddlewareProviderInterface — see Module Extension Points |
| Cron entries | getCronEntries() in the module class — see Module Extension Points |
| DB migrations | MigratableInterface::getMigrations() — see Module Extension Points |
Contributor rules
- Modules must not modify core files.
- No
eval, monkey patching, or runtime file replacement. - Any module can be disabled via
config/modules.phpwithout touching core. - Protected services (
db,settings,config,auth) cannot be decorated. - Keep EN and RU docs in sync in the same commit.