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

.
docs(changelog): describe the editor image limits
.
feat(images): limit and scale down the pictures uploaded into the editor
The four editors of the site stored an upload as it came: no size limit, no
bounds, and the type checked by the extension of the name. A ten-megabyte photo
landed on the disk at its full resolution.

- new settings screen /admin/settings/images writes johncms.editor_images: the
size limit, the bounds a picture is scaled down to, the quality and the format
it is stored in (original / jpeg / webp)
- StoreEditorImageUseCase reads the type off the contents, refuses what is too
heavy and scales down what exceeds the bounds; a picture already within them is
stored untouched, and an animated GIF is never re-encoded
- forum, guestbook, news comments and the news admin form upload through one
responder, which also names the failure when a body over post_max_size was
discarded before PHP ran
- FunctionalTestCase::handleRequest() accepts uploaded files
.
docs(agents): fix the middleware example in the module scaffold
The example implemented MiddlewareInterface::handle() with a return type of
mixed, which is not compatible with the Response the interface declares, and
injected the User model where the modules take CurrentUser. It also credited
index.php with normalising the URI, which RequestPathNormalizer does.
.
docs: bump the documentation submodule
Points at docs(modules): correct the module guides against the code.
.
fix(view): resolve module templates by alias and manifest path
The Twig namespace of a module was basename() of its key, and its templates
were looked for under MODULES_PATH . <key>. The alias therefore did nothing
for templates — it only looked as if it worked, because every module of the
release is called what its directory is called — and a module Composer left in
vendor/ got no namespace at all: its manifest, services, routes, translations
and migrations were read from vendor/, while its templates were expected in a
modules/ directory that does not exist. Nothing moves a Composer package into
modules/; only an archive is unpacked there.

Both now come from the manifest: the namespace is the alias, the directory is
the one the manifest was read from. A theme keeps overriding such a template
under themes/<theme>/templates/<alias>/, and a page the theme does not carry
still falls back to the package.
.
docs: bump the documentation submodule
Points at docs(upgrade): login and registration are one module in 10.0.
.
refactor(auth): merge login and registration into one module
Both were thin screens over system/src/Auth with no tables of their own, and
signing in and signing up are one journey for one visitor. They now live in
modules/johncms/auth, together with the guest screens that sat in the profile
module although whoever opens them has no session.

- Login and registration keep their URLs. The recovery and address-confirmation
screens move to /password-recovery, /password-recovery/{id}/{code} and
/confirm-email/{id}/{code}; the old /profile/* addresses answer with a
permanent redirect, because links already sent by e-mail point there.
- RegistrationSettings moves to the core. The admin panel no longer depends on
the registration module for it, and the external sign-in flow stops reading
the raw config key, which missed the mod_reg fallback and let a site that
never saved its settings register unmoderated accounts through a provider.
- The module carries its own AuthUserRepositoryInterface rather than the
profile's, so the screens work on a site with profiles switched off;
findByNameLat() and confirmNewEmail() leave ProfileUserRepositoryInterface
with nobody to call them.
- Translation domain registration -> auth. The strings of the login screens
leave the system domain and the recovery ones the profile domain, carrying
their existing translations for every language that had them.
.
fix(admin): a section of a module is a page of the panel too
The news section rendered the whole admin menu in the source English. The
panel domain was entered by the access guards of the admin module, and a
section guarded by a permission of its own — news, collections — never went
through them. The same awaited any third-party module with a section: not a
bug of the news module but a hole in the contract.

Routes now say it: ->adminArea(), on a route or on a group, the way
->permission() already works. The pipeline enters the context from that
attribute, right after the module context and before any middleware, so a
page gets the translations of the panel and the first link of its
navigation chain whichever module it belongs to.

The guards stop entering it themselves — with the pipeline doing it, the
"Админ панель" link would be added twice.

Two things this turned up. A nested group inherits nothing from the group
around it, middleware included, so the super-admin group needed the mark of
its own: without that, 51 routes of /admin/settings and /admin/ip-bans lost
the context the guards used to give them. And consent and contacts relied
on AdminAccessMiddleware for it, so removing it from there would have fixed
the news section while breaking those two — both are marked as well.

Verified by walking every route under /admin: none is left unmarked.
.
i18n(ru): translate the modules section
The 32 strings the modules section brought, plus five in the system domain
that had been sitting untranslated: the permission to install modules, the
names of the captcha services and the hint under the image code.

Wording follows what the screens actually do rather than the English
literally — "Switched on/off" for a module is "Включён/Выключен", and the
warning before a purge says outright that it cannot be undone.

Also fixes something the suite was quietly depending on. The functional
tests drive real requests through the real registry, which reads the state
file of the site — so a developer who had switched a module off on their
own installation would see unrelated tests fail with a 404. The test
bootstrap now points the registry at a state file that does not exist,
which falls back to the modules of the release: what a fresh site has, and
what CI already ran against.
.
docs(migrations): the source of a module is its alias
Three things the module work changed about migrations, none of them written
down until now: the source is the alias rather than the directory, a
switched-off module keeps its source because its tables are still there,
and one that was never installed has none at all. Plus the rollback that
undoes a whole source, which uninstalling a module with --purge is built
on.

Also bumps the documentation submodule: the two module pages.