Problem/Motivation
The engine states its own rule in OrchestraUiHooks::entityTypeAlter(): an entity stays UI-agnostic and orchestra_ui attaches the screens, so a headless site installs the engine and gets no administration it did not ask for. The status entity follows it, and the workflow declares nothing either.
The tenant does not. It declares a list builder, add, edit and delete form classes and four link templates on its own #[ConfigEntityType], and the engine ships the four routes, the Tenants menu link and the Add tenant action link with them. It is the only entity in the project whose administration comes from the engine rather than from the module whose job that is.
Proposed resolution
Move the tenant's administration to orchestra_ui, exactly as the status already does:
TenantForm,TenantDeleteFormandTenantListBuildermove, and the entity stops naming them: the handlers and the link templates are attached byOrchestraUiHooks::entityTypeAlter()instead.- The four routes, the menu link, the action link and the edit-form local task move with them, verbatim, so no path, title or permission changes.
TenantAccessControlHandlerstays in the engine. It is access, not interface, and it is what refuses to delete the default tenant.TenantRetentionFormandTenantReadAccessFormstay in the engine with their routes, exactly as the four per-workflow setting forms do. They are settings the engine owns, not the entity's own screens, and they stay reachable by URL and permission on a site with no interface module, which is the same split the workflow tabs already make.- The strings in the moved files move to
orchestra_ui's catalog, since a catalog is only read for the project that ships the string.
What changes for a site
This is not a pure refactor, and it should not be described as one. A site running the engine with orchestra_ui sees nothing move: same paths, same titles, same permissions. A site running the engine without it loses the tenant administration pages, which is the point of the change rather than a side effect: that site administers a tenant through configuration, as it already does for a status.
What a move like this breaks quietly
Two things, both found by auditing rather than by the diff:
- Namespace siblings.
TenantListBuilderread five classes with nousestatement because they sat in the same namespace. - A route another module names.
orchestra_domaindepends on the engine alone and redirected to the tenant collection after saving. That route becomes optional here, andUrl::fromRoute()resolves nothing when it is built, so nothing threw until a response was built: saving the domains form answered with aRouteNotFoundExceptionon a site with no interface module. It now redirects to its own route, the way the engine's per-tenant forms do.
Remaining tasks
None beyond the move, the redirect fix and their tests.
AI-Generated: Yes (Claude Code was used to survey where each entity declares its administration, to draft this issue summary, and to write the change and its tests. The redirect defect and the broken tests were found by auditing the change against a running site, and each fix was proven by making the test fail against the unfixed code first.)
Issue fork orchestra-3625074
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 #4
mably commentedComment #6
mably commented