Tenant Switcher
TenantSwitcherModule renders tenant choices supplied by TenantContextProviderInterface. It is a server-owned selection surface: the browser can submit only a tenant key, and Adminix validates that key against the configured provider before storing it in the session.
If provider() is omitted, Adminix uses adminix.tenant_context.provider. The provider receives TenantContextRequestDto with panel key, page name, module name, page params, selected key, and current user. It returns the current context and the available contexts through TenantContextDto and TenantContextResultDto.
Module API
name()is required and must be unique within the page.title()renders the card heading.description()renders helper text under the title.icon()accepts a Bootstrap icon class; the default isbi bi-building.placeholder()customizes the empty select option.selectedMessage()customizes the success notification after a valid selection.provider()overrides the global tenant context provider for this module.fullWidth()makes the card span the full page width; otherwise it uses the standard half-width desktop layout.stayOnPage()disables the default post-selection reload for custom pages that update their UI without a reload.
Selection flow
The rendered select includes only provider-returned records with non-empty keys. When the admin clicks Apply, Adminix posts to the panel-aware tenant_context_select endpoint with:
the selected
tenant_key;a signed switcher context containing the page name, module name, and route params;
the CSRF token from the rendered page.
The endpoint rejects missing or tampered switcher context and rejects keys that are not returned by the provider. On success, Adminix stores the selected key in the session for the current panel and module name. By default, the page reloads after the successful response so server-rendered modules can see the new selected key.
Signed endpoint context
After a tenant context is active, Adminix embeds a signed tenant payload inside module endpoint contexts such as export, bulk action, import, soft-delete and clone actions, reorder, progress polling, table views, relation contexts, and form contexts. The payload contains the provider-approved tenant key and a hash of the provider criteria for the current server-side context.
Endpoint verification recalculates the current tenant context from the panel, selected switcher/provider, page name, module name, route params, and current user. If the signed endpoint context is stale, missing its tenant payload, or no longer matches the provider result, Adminix treats the module context as invalid. The browser never supplies tenant criteria directly.
Criteria injection
Adminix automatically injects the active provider criteria into server-side list and resource scopes. The injected criteria are applied in addition to module criteria() for rendered lists, resource/detail fetches, CSV exports, bulk actions, reorder, soft-delete actions, clone actions, relation/modal resource fetches, and resource update not-found checks.
For create flows, Adminix derives default input values only from simple tenant equality criteria, for example ['tenant_id', '=', 9]. Those values are server-owned and override browser-submitted values before validation and persistence. Complex criteria such as ranges, like, or array values are query constraints only and are not written into create payloads.
Provider criteria should reference real datasource columns used by the scoped modules. Application policies, guards, handlers, and import/media routes still own domain authorization and persistence rules.
Security boundary
TenantSwitcherModule, signed endpoint contexts, and criteria injection cover Adminix-owned list/resource query scopes and simple create defaults. They do not authorize arbitrary application routes, import handlers, media routes, custom action handlers, queued jobs, external storage writes, or business-side tenancy. Keep required tenant/user restrictions in policies, guards, handlers, and application authorization.
Never treat a browser-submitted tenant key as write authority. The provider must derive membership and criteria from authenticated application state.
Doctor
php artisan adminix:doctor --strict validates that global adminix.tenant_context.provider and module-level provider() values implement TenantContextProviderInterface. Doctor also warns when one page defines multiple tenant switchers, because endpoint context binding is panel-level until an explicit per-module binding API exists.