fix(modules): protect the names the core holds
The alias of a module was checked against other modules and against nothing else, but an
alias is a key in several registries at once and not every holder is a module. The CMS
answers to "system" as a source of migrations and as the domain its strings are written
in; the theme engine answers to "theme" as a namespace of templates. Both were free to
take.
Taking "system" was the dangerous one. MigrationLocator collected sources without looking
for duplicates, so the module and the core ended up behind one name, locate() returned
both directories, and uninstalling that module with --purge would have rolled back the
schema of the site. Nothing stopped it but an accident: none of the three core migrations
has a down(), so the purge was refused before it began — and would stop being refused the
day one gets one.
The names are declared by whoever holds them — a constant of the migration source, of the
template registry, of the translator — and assembled by ModuleRegistryFactory, which is
where the registry is put together. So the list shrinks by itself as the core moves into
modules, instead of being a hand-kept blacklist that rots on the first move.
"admin" is deliberately not on it: @admin is the templates of the theme and of the admin
module merged on purpose, the name is held by that module, and the check between modules
already covers it.
The registry marks such a module broken and keeps the site running, the way it does for
an alias another module holds; installing refuses with the same sentence. And the reason
it mattered is closed on its own terms: two sources of migrations may no longer answer to
one name, whoever declared them.
alias is a key in several registries at once and not every holder is a module. The CMS
answers to "system" as a source of migrations and as the domain its strings are written
in; the theme engine answers to "theme" as a namespace of templates. Both were free to
take.
Taking "system" was the dangerous one. MigrationLocator collected sources without looking
for duplicates, so the module and the core ended up behind one name, locate() returned
both directories, and uninstalling that module with --purge would have rolled back the
schema of the site. Nothing stopped it but an accident: none of the three core migrations
has a down(), so the purge was refused before it began — and would stop being refused the
day one gets one.
The names are declared by whoever holds them — a constant of the migration source, of the
template registry, of the translator — and assembled by ModuleRegistryFactory, which is
where the registry is put together. So the list shrinks by itself as the core moves into
modules, instead of being a hand-kept blacklist that rots on the first move.
"admin" is deliberately not on it: @admin is the templates of the theme and of the admin
module merged on purpose, the name is held by that module, and the check between modules
already covers it.
The registry marks such a module broken and keeps the site running, the way it does for
an alias another module holds; installing refuses with the same sentence. And the reason
it mattered is closed on its own terms: two sources of migrations may no longer answer to
one name, whoever declared them.