История коммитов

.
feat(i18n): load the dictionary of a module wherever its messages are asked for
The domain of a module was registered only on its own routes. A module that
showed something of another — online naming a topic of the forum — registered
that domain by hand, and anything that forgot showed the untranslated message.

The translator now takes a locator, and the one of the site answers with the
locale directory of the switched-on module holding that alias. A domain nobody
registered is loaded the first time a message of it is asked for, kept for the
change of locale like any other, and a domain the locator does not know is not
asked about again. This is what lets a module show its messages through an
extension point on pages of another.
.
chore(deps): update the JS dependencies within their constraints
Vite 8.3, Vue 3.5.44, axios 1.20, sass 1.106, swiper 14.3 and the rest of the tree move to the newest release their ranges allow. npm audit is clean, the assets build, and the functional suite renders every page with them. jQuery 4 is a major release and stays out.
.
chore(deps): update the PHP dependencies within their constraints
Every package moves to the newest release its constraint allows. Two of them
carried advisories composer audit reported: symfony/http-foundation, a ReDoS
in the parsing of Cache-Control (7.4.16 -> 7.4.21), and league/flysystem, a
bypass of the check for control characters in a path (3.35.2 -> 3.36.0).
The audit is clean now.

roave/security-advisories now refuses PHP below 8.4.27, which carries
advisories of its own; the php-fpm image of the stack has to be rebuilt to
get it (docker compose build php-fpm).

PHPStan 2.3 remembers what a method returned unless it is told the method is
impure, and read two tests asserting a value twice as asserting it against
itself. remember() and rememberForever() of the cache, and the helper of the
mail queue test that reads a row anew, say so now. The baseline follows the
new wording of three findings it already held.
.
test: check the dependency rules of the architecture with phpat
The rules of .agents/architecture.md about which class may depend on which were
checked by a reviewer, and only when somebody asked for a review. phpat turns
them into PHPStan rules, so composer phpstan — and with it the gate and CI —
fails on a new breach:

- the core depends on no module;
- a module depends only on the core, on system modules and on the modules its
manifest requires;
- the Domain and the Application stay out of HTTP, controllers and middleware
aside;
- the Domain and the Application depend on no Infrastructure;
- a module reads no request off the RequestStack;
- a repository contract is declared in the Domain and implemented in the
Infrastructure.

The modules, the system ones and what each requires are read from composer.json
and the manifests, so a module added later is held to the same rules.

What the code already broke is in the baseline: Counters in the core, 33
dependencies on Infrastructure, 9 on HTTP types, and four modules depending
on others they do not require — online on forum, notifications on
downloads and library, homepage on news.
.
test(install): install a site from scratch and open it as its administrator
Nothing tested the installer, and three fixes of it landed this summer. It
writes the configuration of the site into config/autoload and ends its steps
with exit, so InstallerTest drives it from outside: the built-in server of PHP
serves public/ through a router that does what nginx of the stack does, and the
test goes through the steps as a browser would. A wrong password and a missing
database are refused, an empty form is refused, a filled one installs the site
with its demo data, and the installer closes behind itself. Then the home page
and the panel have to open for the administrator it signed in — the first run
found the panel refusing that account.

It needs a fresh checkout and MySQL, and skips itself elsewhere, the checkout
of the stack included. composer test:install runs it; the default run of
PHPUnit leaves the suite out. CI runs it after the functional suite on every
server of the matrix.
.
fix(install): make the administrator of a new site a supervisor
The installer created the administrator with rights = 9, the access level of
9.x. Neither the column nor the attribute exists in 10.x: the model dropped the
value without a word, no role was granted, and the account that installed the
site was refused its own panel with a 403.

The administrator is now granted the supervisor role, right after the seeder
has created it, through the repository the move from 9.9 grants roles with.
The access levels written for the administrator and the demo accounts are gone,
since nothing ever read them.
.
ci: show the line coverage of every area in the summary of a run
Nothing measured coverage, and the source list of PHPUnit named eight modules out of twenty. The list now takes system/src and the src of every module of every vendor, so a module added later is measured as well.

The check job runs the tests once more under pcov and turns the Clover report into a table by area — the core by its top directory, every module on its own, the least covered first — in the summary of the run. There is no threshold: it is a map of where tests are missing.
.
test(http): clear the request state before each factory test too
RequestFactoryTest cleared the trusted proxies, the trusted hosts and the configuration after each test, and assumed them clear before. A functional test run earlier in the same process leaves the configuration of the site and its trusted proxies behind, so in that order the test of an empty configuration found the proxies of the stand. The state is now cleared on both sides.
.
test: run the tests in random order
A test that relies on process state it does not set passes in one order and fails in another, and a fixed order hides it for as long as the order holds. PHPUnit now shuffles the tests on every run, failed ones still first, and prints the seed to repeat a run with. The first runs found one such test.
.
test(functional): add the CSRF token to a form through the harness
Three tests fetched the token from the container on their own, one of them through a private helper. withCsrfToken() of the harness puts it into the parameters of a form the way the page does.