A tenant goes on naming a domain that has been deleted, and a new, unrelated domain created later under the same machine name inherits the tenant public site: its links, its site name and its theme, with nothing in the tenant own configuration having said so.
Problem/Motivation
A tenant and a domain name each other by machine name, in both directions. The domain says which tenant its requests act in, and the tenant says which domains it lives on, its public site and its workspace, set on the Domains form and read by DomainNotificationContext to decide where a notification is rendered.
OrchestraDomainTenantHooks::orchestraTenantPredelete() already clears one direction when a tenant is deleted, and gives the reason in its own words: a tenant machine name is reusable, so a tenant later created under the same name would silently inherit the domain. The mirror has no hook. Deleting a domain leaves every tenant that named it pointing at a machine name nothing answers to.
Until somebody reuses that name the effect is inert rather than wrong: the render context logs the domain it cannot find and carries on, which is what has kept this quiet. The moment a new domain is created under the freed name, every tenant left naming it starts rendering its notifications there.
Observed against 1.x: after setting a tenant public domain and then deleting that domain, the tenant still names it; the tenant dependencies list only the module, as intended; and creating a new domain under the same id makes it the tenant public site.
Steps to reproduce
- Install
orchestra_domainwith more than one domain. - On a tenant, set its public domain to one of them, on the tenant Domains form.
- Delete that domain record.
- Create a new domain, for an unrelated site, and give it the machine name that is now free.
- Every notification for that tenant renders on the new site.
Proposed resolution
Add the hook that mirrors the one already there: a domain_predelete that clears the public and workspace settings on every tenant naming the domain being deleted, saving only the tenants that changed. The tenant Domains form already refuses to store a name no domain answers to, so this is the same rule applied at the other end: a name that stops answering stops being stored.
A config dependency is deliberately not the answer here, and the change does not add one. A dependency would delete the tenant along with the domain, and a tenant is not collateral of retiring a domain, any more than a domain is of retiring a tenant. That is why the existing direction is a predelete hook too.
Why no test caught it
The tenant direction was covered and the domain direction was not, although both fail the same way. The merge request asserts the two together, in one class, so neither can be changed without the other being read.
User interface changes
None.
API changes
None.
Data model changes
None. The stored shape is unchanged; a setting naming a deleted domain is removed rather than rewritten.
Release notes snippet
Deleting a domain now clears it from the tenants that named it as their public or workspace site, so a later domain reusing the machine name is not silently inherited.
AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code and tests on the merge request. I reviewed and ran the work myself before posting it.)
Issue fork orchestra-3622875
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mably commentedComment #5
mably commented