1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-06-21 19:04:05 +00:00
tenancy/resources/boost/skills/laravel-tenancy/references/package.md

363 lines
13 KiB
Markdown

# Tenancy Package Reference
This reference is for package-specific details that do not need to live in `SKILL.md`.
## Focused References
Load these smaller references for topic-specific work:
- `installation.md` for install, publishing, and setup checks
- `configuration.md` for `config/tenancy.php` sections
- `identification.md` for middleware and resolvers
- `routing-assets.md` for tenant routes, route modes, cloned routes, and asset routes
- `context-api.md` for `tenancy()`, `tenant()`, `run()`, and `central()` behavior
- `bootstrappers.md` for tenant-aware Laravel service scoping
- `database-tenancy.md` for database isolation and tenant database managers
- `migrations-commands.md` for tenant Artisan commands
- `models-domains.md` for tenant/domain models and single-database traits
- `filesystem-cache-queue.md` for storage, cache, sessions, Redis, and queues
- `lifecycle-jobs.md` for events, provisioning, and cleanup pipelines
- `resource-syncing.md` for synced central and tenant resources
- `impersonation.md` for tenant user impersonation
- `pending-tenants.md` for pending tenant pools
- `rls.md` for PostgreSQL row-level security
- `features.md` for optional package features
- `integrations.md` for URL, mail, broadcasting, Fortify, Scout, Livewire, Telescope, and Vite
- `testing.md` for test coverage guidance
## Main Entry Points
- `src/TenancyServiceProvider.php`
- `src/Tenancy.php`
- `assets/config.php`
- `assets/routes.php`
- `src/helpers.php`
## Published Files
The package publishes:
- `config/tenancy.php`
- `routes/tenant.php`
- `app/Providers/TenancyServiceProvider.php`
- `database/migrations/2019_09_15_000010_create_tenants_table.php`
- `database/migrations/2019_09_15_000020_create_domains_table.php`
- impersonation migrations
- resource syncing migrations
`tenancy:install` also creates `database/migrations/tenant`.
## Service Provider Behavior
`TenancyServiceProvider`:
- merges `assets/config.php` into `tenancy`
- binds `Stancl\Tenancy\Database\DatabaseManager` as a singleton
- binds `Stancl\Tenancy\Tenancy` as a singleton
- binds the current tenant to the `Stancl\Tenancy\Contracts\Tenant` contract
- binds the current domain to the `Stancl\Tenancy\Contracts\Domain` contract
- registers configured bootstrappers as singletons
- binds the configured unique ID generator to `UniqueIdentifierGenerator`
- registers package commands
- publishes config, routes, provider, and migrations
- loads package asset routes when `tenancy.routes` is enabled
- boots configured features through `tenancy()->bootstrapFeatures()`
- registers middleware groups: `clone`, `universal`, `tenant`, `central`
## Core Runtime API
`Stancl\Tenancy\Tenancy` exposes:
- `initialize(Tenant|int|string $tenant): void`
- `run(Tenant $tenant, Closure $callback): mixed`
- `central(Closure $callback): mixed`
- `end(): void`
- `reinitialize(): void`
- `bootstrapFeatures(): void`
- `getBootstrappers(): array`
- `find(int|string $id, ?string $column = null, bool $withRelations = false)`
Use these runtime methods instead of rolling your own context switch logic.
## Default Models
From `assets/config.php`:
- `tenancy.models.tenant` => `Stancl\Tenancy\Database\Models\Tenant`
- `tenancy.models.domain` => `Stancl\Tenancy\Database\Models\Domain`
- `tenancy.models.impersonation_token` => `Stancl\Tenancy\Database\Models\ImpersonationToken`
The default tenant key relation column is `tenant_id`.
## Tenant ID Generators
Supported generators exposed in config:
- `UUIDGenerator`
- `ULIDGenerator`
- `UUIDv7Generator`
- `RandomHexGenerator`
- `RandomIntGenerator`
- `RandomStringGenerator`
Set `tenancy.models.id_generator` to `null` only when the app intentionally uses auto-incrementing tenant IDs.
## Identification Middleware
Available middleware:
- `InitializeTenancyByDomain`
- `InitializeTenancyBySubdomain`
- `InitializeTenancyByDomainOrSubdomain`
- `InitializeTenancyByPath`
- `InitializeTenancyByRequestData`
- `InitializeTenancyByOriginHeader`
- `PreventAccessFromUnwantedDomains`
- `CheckTenantForMaintenanceMode`
- `ScopeSessions`
All package identification middleware inherit package failure handling through `IdentificationMiddleware::initializeTenancy()`. Failed identification throws a package exception unless an `onFail` callback is registered.
## Resolvers
Resolvers configured in `tenancy.identification.resolvers`:
- `DomainTenantResolver`
- `PathTenantResolver`
- `RequestDataTenantResolver`
Resolver config includes:
- cache enablement
- cache TTL
- cache store
- path tenant parameter name
- route name prefix
- request header, cookie, and query parameter names
- custom tenant model lookup column
## Default Bootstrappers
Enabled by default:
- `DatabaseTenancyBootstrapper`
- `CacheTenancyBootstrapper`
- `FilesystemTenancyBootstrapper`
- `QueueTenancyBootstrapper`
- `DatabaseSessionBootstrapper`
Optional bootstrappers:
- `CacheTagsBootstrapper`
- `DatabaseCacheBootstrapper`
- `RedisTenancyBootstrapper`
- `TenantConfigBootstrapper`
- `RootUrlBootstrapper`
- `UrlGeneratorBootstrapper`
- `MailConfigBootstrapper`
- `BroadcastingConfigBootstrapper`
- `BroadcastChannelPrefixBootstrapper`
- `Bootstrappers\Integrations\FortifyRouteBootstrapper`
- `Bootstrappers\Integrations\ScoutPrefixBootstrapper`
- `PostgresRLSBootstrapper`
- `PersistentQueueTenancyBootstrapper`
## Bootstrapper Semantics
- `DatabaseTenancyBootstrapper`
switches the active database connection into tenant context and reverts back to the central connection.
- `CacheTenancyBootstrapper`
scopes supported cache stores by prefix and can also scope cache-backed sessions.
- `CacheTagsBootstrapper`
is the older tag-based cache isolation approach and is less complete than prefix-based cache scoping.
- `DatabaseCacheBootstrapper`
scopes cache by moving database-backed cache stores onto the tenant connection instead of using prefixes.
- `FilesystemTenancyBootstrapper`
suffixes `storage_path()`, rewrites configured local disk roots, can scope file cache and file sessions, and can enable tenant-aware asset URLs.
- `QueueTenancyBootstrapper`
injects `tenant_id` into queued job payloads and re-initializes tenancy around queue job execution.
- `PersistentQueueTenancyBootstrapper`
is the queue bootstrapper variant for cases where worker processes should stay tenant-aware across jobs.
- `DatabaseSessionBootstrapper`
makes the database session driver use the tenant connection.
- `RedisTenancyBootstrapper`
sets Redis connection prefixes for configured direct Redis connections.
- `TenantConfigBootstrapper`
maps tenant attributes into arbitrary config keys during tenancy.
- `RootUrlBootstrapper`
overrides `app.url` and the URL generator root URL, primarily for CLI URL generation in tenant context.
- `UrlGeneratorBootstrapper`
swaps in `TenancyUrlGenerator` so route names and tenant parameters are generated correctly for path or query-string identification.
- `MailConfigBootstrapper`
maps tenant attributes into mail configuration at runtime.
- `BroadcastingConfigBootstrapper`
maps tenant-specific broadcaster credentials into broadcasting config and swaps in a tenancy-aware broadcast manager.
- `BroadcastChannelPrefixBootstrapper`
prefixes actual broadcast channel names with the tenant key for supported broadcasters.
- `Bootstrappers\Integrations\FortifyRouteBootstrapper`
rewrites Fortify redirect targets so tenant auth flows can land on tenant routes.
- `Bootstrappers\Integrations\ScoutPrefixBootstrapper`
sets `scout.prefix` to the tenant key.
- `PostgresRLSBootstrapper`
swaps the tenant connection to the configured PostgreSQL RLS user and session variable model.
## Database Isolation Options
The config supports:
- separate tenant databases
- PostgreSQL schema isolation
- optional permission-controlled database managers
- PostgreSQL RLS
Database manager mappings exist for:
- `sqlite`
- `mysql`
- `mariadb`
- `pgsql`
- `sqlsrv`
`tenancy.database.drop_tenant_databases_on_migrate_fresh` controls whether `migrate:fresh` also drops tenant databases through the package override.
## Cache, Filesystem, Queue, And Session Scoping
Important config sections:
- `tenancy.cache`
- `tenancy.filesystem`
- `tenancy.redis`
- `tenancy.migration_parameters`
- `tenancy.seeder_parameters`
Notable filesystem behavior:
- local disks can have tenant-specific root overrides
- `Storage::disk()->url()` can be overridden with tenant-aware public names
- `storage_path()` can be suffixed per tenant
- file cache and file sessions can be scoped
- `asset()` tenancy can be enabled, but may affect packages that assume global assets
## Routes
`assets/routes.php` registers:
- `/tenancy/assets/{path?}` named `stancl.tenancy.asset`
- `/{tenant}/tenancy/assets/{path?}` named `tenant.stancl.tenancy.asset` for path identification, behind the `tenant` middleware
The package route mode enum is `Stancl\Tenancy\Enums\RouteMode`, with central as the default route mode in config.
The service provider also registers empty middleware groups named:
- `clone`
- `universal`
- `tenant`
- `central`
These route modes and middleware groups are part of the package routing model and should be preferred over ad hoc tenant-versus-central route branching.
## Optional Features
Feature classes shipped in `src/Features`:
- `CrossDomainRedirect`
- `DisallowSqliteAttach`
- `TelescopeTags`
- `TenantConfig`
- `UserImpersonation`
- `ViteBundler`
Features bootstrap independently from tenant initialization and are intended to be enabled through `tenancy.features`.
Feature behavior:
- `CrossDomainRedirect`
adds a `RedirectResponse::domain(string $domain)` macro that swaps the redirect host without rebuilding the whole URL.
- `DisallowSqliteAttach`
blocks SQLite `ATTACH` usage by registering an authorizer on SQLite PDO connections, using a native authorizer on PHP 8.5+ and a loadable extension fallback on older runtimes.
- `TelescopeTags`
adds a `tenant:{tenantKey}` Telescope tag when tenancy is initialized.
- `TenantConfig`
maps tenant attributes into config values using event listeners. This feature is deprecated in favor of `TenantConfigBootstrapper`.
- `UserImpersonation`
adds a `tenancy()->impersonate()` macro, stores impersonation tokens in the configured impersonation token model, validates token TTL and tenant match, logs the user in with the configured guard, and exposes `isImpersonating()` plus `stopImpersonating()`.
- `ViteBundler`
configures Vite asset path generation to use `global_asset()` so asset URLs stay central rather than tenant-scoped.
## Pending Tenants
Pending tenant support is configured under `tenancy.pending`.
Important behavior:
- `include_in_queries` controls whether pending tenants are included in normal tenant queries.
- `count` controls the maintained size of the pending-tenant pool.
- the package ships dedicated commands for creating and clearing pending tenants.
If a task touches pre-provisioned tenant pools, inspect the pending-tenant commands and model scopes before implementing custom provisioning logic.
## Commands
Commands registered by `TenancyServiceProvider`:
- `tenancy:install`
- `tenants:up`
- `tenants:run`
- `tenants:down`
- `tenants:link`
- `tenants:seed`
- `tenant:tinker`
- `tenants:migrate`
- `tenants:rollback`
- `tenants:list`
- `tenants:dump`
- `tenants:migrate-fresh`
- `tenants:pending-clear`
- `tenants:pending-create`
- `tenants:purge-impersonation-tokens`
- `tenants:rls`
Prefer these commands over hand-written loops for tenant maintenance tasks.
Command notes:
- `tenancy:install`
publishes config, routes, service provider, and core migrations, then creates `database/migrations/tenant`.
- `tenants:migrate`
applies `tenancy.migration_parameters`, supports concurrent execution, and can continue with `--skip-failing`.
- `tenants:rollback`
rolls back tenant migrations.
- `tenants:migrate-fresh`
rebuilds tenant schema from scratch.
- `tenants:dump`
dumps a tenant schema and defaults the dump path from `tenancy.migration_parameters.--schema-path`.
- `tenants:seed`
uses `tenancy.seeder_parameters`.
- `tenants:run`
runs arbitrary artisan commands against tenant context.
- `tenant:tinker`
opens Tinker in a selected tenant context and supports searching by tenant key or domain.
- `tenants:link`
manages tenant storage symlinks used by tenant-aware public disk URLs.
- `tenants:down` / `tenants:up`
toggle tenant maintenance mode.
- `tenants:pending-create` / `tenants:pending-clear`
manage the pending-tenant pool.
- `tenants:purge-impersonation-tokens`
removes expired impersonation tokens.
- `tenants:rls`
creates the shared RLS user and row-level-security policies for tenant-related tables.
## Related Subsystems
The package also includes:
- `src/Events/*` for tenancy lifecycle, tenant, domain, database, storage, and pending-tenant events
- `src/Listeners/*` for bootstrapping and reverting context
- `src/Jobs/*` for database and storage lifecycle jobs
- `src/ResourceSyncing/*` for central-to-tenant resource syncing
- `src/RLS/*` for PostgreSQL row-level security support
- `src/Actions/*` for route cloning and storage symlink helpers
When a task touches one of these areas, inspect the relevant namespace before inventing a parallel abstraction in app code.