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.