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

.
chore(mail): drop the unused smtp name option
A leftover of laminas-mail, where it was the HELO hostname. MailFactory builds the DSN from host, port, username, password, encryption and auth_mode and never reads this key, so it only misled whoever configured SMTP.
.
docs: update the documentation submodule
.
docs: update the documentation submodule
.
docs: describe the CSRF middleware and the validator replacement in the changelog
.
refactor: remove laminas-validator
The legacy validator, its rules and its message map are gone, and with the package go laminas-servicemanager, laminas-stdlib and laminas-escaper. No laminas package is left in the dependency tree.

Not one msgid was lost: the strings the rules need are registered by literal d__() calls in their constructors and factories, so twenty catalogs survive the migration untouched. What the .pot loses is the detailed laminas hostname diagnostics and the CSRF message, none of which the code produces any more.

.agents/validation.md documents the API, the null policy, how to add a rule and where its messages live.
.
refactor(install): move the installer to the new validator
The last caller of the legacy validator and the last reference to Laminas\Validator\Hostname. The email stays mandatory: it was only rejected as empty because the previous EmailAddress failed on an empty value, and the new rule requires a value outright.
.
chore: drop the orphaned legacy validator imports
Left behind when the CSRF-only calls were removed.
.
refactor(profile,registration): move the last forms to the new validator
The optional profile fields now say so: everything a visitor may leave blank carries allowEmpty, including the email, which the previous ruleset left optional only as a side effect of ModelNotExists finding nothing for an empty value.

The MX check of the address survives as the MxRecord rule, and the consent message again belongs to the rule that needs it rather than to every Identical of the form.
.
refactor(admin,consent): move the remaining admin forms to the new validator
The forum structure form uses ValidationResult::withError() for the cycle check, so a domain failure found outside the ruleset joins the result instead of unpacking it into an array.
.
refactor(forum): move the topic forms to the new validator
The meta fields become explicitly optional. They carried a StringLength with only a max, which the previous engine let an empty value through — under the new null policy a rule means the field is required unless it says otherwise, so allowEmpty keeps them optional instead of silently making them mandatory.