The Paths/AppConfig/Binaries shims were byte-identical (each just called
ConstantsInitializer::init()), and ErrorCodes.php only bridged a $rErrorCodes
global that nothing reads any more. Every boot path required all five by name.
Replace those requires with a single ConstantsInitializer::init() at each of the
four call sites (ConstantsStage, WebApiBootstrap, StreamingRequestBootstrap, the
progress endpoint) and delete the four dead shim files. The generateError()/
generate404() functions are already provided globally via composer autoload.files,
so their require was redundant too — ErrorHandler.php stays (it is the
autoload.files target) but is no longer required by name.
Verified: init() defines the full constant set and the error functions autoload;
762 tests, PHPStan, phpcs and make gates green; all four boot smokes (cli/admin/
webapi/streaming) still PASS against a real MariaDB in the dev container.
OPENSSL_EXTRA was a hardcoded literal shared by every install, i.e. public in the
source tree. Give fresh installs their own secret while leaving existing installs
untouched.
- Installer: after writing config.ini, generate a 40-char secret into
config/openssl_extra (chmod 600), but ONLY when the file is absent. It is key
material for Encryption (hmac_keys rows, cached image filenames, proxy URL keys,
stream tokens), so it must be generated once and never rotated — re-running the
installer must not overwrite it or all existing encrypted data would orphan.
- ConstantsInitializer now sources OPENSSL_EXTRA from that file directly rather
than through the config extension. A standalone file is deliberate: it is
independent of the config.ini -> config.enc migration and never rewritten, so
the value is read back identically for the life of the install regardless of
how the proprietary extension surfaces config keys. Missing/empty file falls
back to the historical literal, so existing installs keep decrypting unchanged.
Verified: no file -> literal, file -> its value, empty file -> literal; installer
generation is idempotent (40 chars, 0600, not overwritten on re-run).
Introduce the source-of-truth classes for the bootstrap testability refactor.
Purely additive — nothing is wired to them yet.
- ConstantsInitializer: pure value maps (paths/appConfig/binaries/statuses)
plus the single define() site (init/initStatus). The maps evaluate with
different MAIN_HOME/BIN_PATH in one process, which the one-shot define()
constants they feed cannot — this is what makes them testable.
- ErrorResponder: the generateError()/generate404() logic extracted into pure
codes()/renderDebug()/render404()/respond*() plus a single side-effecting
emit(). A test-mode toggle throws ErrorResponseException instead of exit().
- ErrorResponseException: value carrier for a resolved error response.
OPENSSL_EXTRA is now sourced per-install via ConfigReader with a mandatory
fallback to the historical literal, so existing installs (whose persisted data
derives from it) keep decrypting; generation-at-install is left to the installer.
Verified byte-for-byte against the legacy prelude before wiring: 53/53 constants,
debug/404 HTML frozen as sha256 goldens, 65 error codes.