Resolve the booking tenant from the domain being served
Adds the optional yoyaku_domain submodule: a booking.tenant_resolver that maps the domain being served to the yoyaku tenant naming it.
The binding lives on the tenant
Each tenant names the domains it is served on, as the yoyaku_domain.domains third-party setting, edited on a Domains tab on the tenant. Domain records are left alone and keep meaning what Domain says they mean; several domains may point at one tenant, and validation keeps one domain to a single tenant, so two tenants claiming one domain is unreachable through the UI. Deleting a domain drops it from every tenant naming it.
Nothing changes until a tenant names a domain: an unclaimed domain, and a binding left behind by a deleted domain, defer, so the tenant with id default applies exactly as it does today.
Which domain is being served is Domain's answer
A hostname Domain cannot match, as on the CLI and in cron, falls back to the default domain record, so such a run acts in the tenant naming that domain. Documented rather than worked around: give the default domain to the tenant background work belongs to, or to no tenant to keep it in default.
One layering fix outside the submodule
The tenant edit page's own Edit local task lived in yoyaku_manager, which put it there so its Managers tab had a sibling. Moved to yoyaku_ui, which owns the tenant admin routes, so any module adding a tenant tab (Domains here) renders a complete tab set rather than a lone tab, which core does not render at all.
Coverage
DomainTenantResolverTest(kernel, 5 cases): a claimed domain resolves to its tenant, an unclaimed one defers todefault, several domains may name one tenant, an unmatched hostname acts in the default domain's tenant, a site with no domain records resolves nothing, and a binding left by a deleted domain neither resolves nor survives the deletion.TenantDomainsFormTest(kernel, 3 cases): checked domains are stored sorted, clearing them removes the setting rather than storing an empty list, an id outside the options never reaches storage, and a domain another tenant is served on is refused with the claiming tenant named.TenantDomainsTabTest(functional): the tab is access-controlled, lists the domains, saves the binding, and the tenant tab set is complete with no other tenant tab installed.
drupal/domain is added to require-dev (so CI has it) and to suggest. Documentation (docs/multi-tenancy.md, module README.md, the module maps) and the French translations are updated.