Orchestra stores the domain-to-tenant binding as a third-party setting on the domain module's own config entity. That is Orchestra data written into a module that knows nothing about Orchestra, and it is the reason this submodule needs two predelete sweeps instead of one. The binding belongs on the tenant.
Problem/Motivation
A tenant and a domain currently name each other, in two different config entities:
domain.record.*.third_party_settings.orchestra_domain.tenant, which says a request served on that domain acts in that tenant. Written by an Orchestra field this submodule alters onto the domain add/edit form, read byDomainTenantResolver.orchestra.orchestra_tenant.*.third_party_settings.orchestra_domain, which says where a tenant receives people and where its operators work. Written by the tenant's own Domains form, read byDomainNotificationContext.
The second is a submodule extending its own project's entity, which is what third-party settings are for. The first is not: it puts Orchestra's data in domain.record.*.yml, so a Domain Access site exports Orchestra configuration inside Domain's, and uninstalling Orchestra Domain leaves it behind.
It also costs a hook. Because the value lives on an entity Orchestra does not own, a deleted tenant has to be swept out of every domain record that named it (orchestraTenantPredelete()). Nothing would need sweeping if the value sat on the tenant, because a tenant's own settings go when the tenant does.
Proposed resolution
Move the binding to the tenant, beside the two settings the submodule already keeps there, so that everything Orchestra Domain knows about a tenant is in one place and all of it is on Orchestra's own entity.
- Add a list of the domains whose requests act in the tenant, with its config schema, edited on the tenant's existing Domains form. Many domains resolve to one tenant, so the list lives on the tenant.
DomainTenantResolverresolves through that list rather than reading the negotiated domain's setting, and declares the tenant list's cache tags rather than the domain's. This read is per-request, so the change is measured rather than assumed.- Remove the Orchestra field from the domain add/edit form and its entity builder, remove
orchestraTenantPredelete(), and remove thedomain.record.*entry from the config schema. A domain record goes back to holding only Domain's configuration. - Keep
domainPredelete(): a domain is never Orchestra's, so its deletion still has to clear the names a tenant holds, now including the new list.
Remaining tasks
None beyond the change itself.
User interface changes
The Orchestra tenant select disappears from the domain add/edit form. The tenant's Domains form gains the domains that resolve to it, so one form answers every question this submodule asks about a tenant.
API changes
None. TenantResolverInterface and the tagged-resolver contract are unchanged; only where this resolver reads from changes.
Data model changes
The binding moves from the domain record to the tenant. The project is pre-1.0, so the old setting is removed outright rather than migrated: a site already running an alpha re-states its bindings on the tenant's Domains form.
Release notes snippet
Orchestra Domain no longer writes to domain records. The domain-to-tenant binding is set on the tenant's Domains form, alongside its public and workspace domains.
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-3622940
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