Requirements
What Scriptlog requires to run, and which of those requirements are enforced by
the code rather than merely hoped for.
PHP 7.4 – 8.5. The `develop` branch CI runs the unit suite on PHP 8.1, and a pre-commit hook runs a PHP 7.4-compatibility ruleset on staged files. The hook explicitly refuses to be bypassed.
No framework, no ORM, no template engine. Dependencies are hand-wired in `lib/core/Bootstrap.php`. The only runtime package is a PSR-0/PSR-4 autoloader plus Dotenv, both under `lib/vendor/`.
A writable `data/` tree for cache, media and state. Path constants come from `lib/options.php`.
2. Configuration is mandatory
`lib/main.php` checks for `config.php` before it will boot. If the file is
absent and `install/` exists, the request is handed to the installer; if the
installer is also gone, the request is terminated.
Two consequences worth knowing:
The site cannot boot read-only for inspection. Reading a configuration file is a precondition for the framework existing at all.
`config.php` is a `config.sample.php` derivative, so every deployment has to produce one before anything else works.
3. Quality requirements, as actually met
The table gives, per layer, the percentage of methods that are documented, that
declare a return type, and whose parameters are fully typed. “Fully typed” is
the strictest of the three: a single untyped parameter makes the method count
against it.
| Layer | Methods | Documented | Return-typed | Params typed |
| — | — | — | — | — |
| controller | 291 | 66% | 14% | 14% |
| service | 453 | 82% | 14% | 24% |
| dao | 289 | 85% | 30% | 29% |
| dto | 17 | 53% | 35% | 100% |
| model | 61 | 100% | 0% | 28% |
| handler | 59 | 100% | 85% | 100% |
| validator | 13 | 100% | 0% | 63% |
| core | 782 | 75% | 27% | 24% |
| utility | 475 | 97% | 6% | 9% |
| admin | 19 | 68% | 0% | 0% |
| tests | 2649 | 22% | 73% | 45% |
These counts cover concrete classes and global functions only; interfaces and
traits are excluded, so a layer's total is slightly below the method count on
its module index. `dto` and `handler` reach 100% parameter typing on very few
parameters (15 and 63 respectively), so treat those two as low-sample rather
than as a trend.
Reading the table:
Parameter typing is the weak column almost everywhere. Controllers sit at 14% and the admin UI at 0%, so request values reach most entry points untyped. That is what makes validator classes load-bearing rather than decorative.
`utility` is the inversion of every other layer: 97% documented and only 9% of parameters typed, with 6% of functions declaring a return type. These are loosely-typed global helpers with strong docblocks, which is self-consistent but means the docblock is the only contract.
Return types are absent in `model`, `validator` and `admin` (0% in all three). Callers cannot rely on a declared shape.
`handler` is the most disciplined layer: 100% documented, 85% return-typed, 100% of parameters typed.
`dao` is well documented (85%) and reasonably typed (30% returns, 29% parameters), which is the expected shape for the layer whose job is to be predictable.
`tests` documents only 22% while typing 73% of returns and 45% of parameters. The suite is well-typed and largely undocumented, so a failing assertion often has to be read before it can be understood.
`core` is the largest real-code layer at 782 methods and sits mid-table on every measure.
4. Deprecated surface that is still required
There are 14 first-party `@deprecated` annotations, and 13 of them are in a
single file: `Scriptlog\Core\FrontHelper`. It is a facade kept alive on purpose,
forwarding to `Scriptlog\Service\FrontService`. Themes written against the old
helper name keep working because the facade still exists.
Its own docblock records why it exists, and it is worth quoting because it
doubles as a boundary rule:
Every data-access method delegates to the `FrontService` instance that `Bootstrap` registers through `FrontHelper::setFrontService()`.
When no service is registered the methods return `null` or an empty array instead of falling back to raw SQL. The inline queries that used to be there were removed because they drifted from `FrontService`, used string interpolation, and one path was mysqli-only and broke on PDO.
So the facade is a genuine operational requirement — removing it, or rebuilding
the autoload-alias map without it, breaks every un-updated theme — but it
converts a hard failure into a silent empty result. That is documented on
Limits and Non-behaviour.
The 14th annotation is on a member of `Scriptlog\Controller\DownloadController`.
5. Testing requirement
The full verification command is `composer build`, which chains
`phpstan:strict` (level 5 on `lib/`), `phpcs` against the `BlogwarePSR12`
ruleset, the PHPUnit suite and `composer-audit`.
Static analysis is therefore part of the definition of done, not an optional
extra. The level-5 ruleset is the strictest of the configured levels; code that
passes it still must pass the PHP 7.4 compatibility ruleset at commit time.