App lifecycle
The five stages between a package existing and an App serving requests, and what each one does and does not grant.
Runtime and installation lifecycle
When an App does not appear, identify the missing stage below before changing its code. A source checkout, Composer installation, tenant operational state, and actor access are separate facts. Follow Create an App Package for the first setup; use this page to diagnose activation, initialization, and grants.
What it is
An App present in Composer is not an App a user can use. Five stages sit between them, and each is a separate operation with a separate failure mode:
Check each stage independently; a source or installation problem can look like a navigation problem.
| Stage | Command | Scope | Grants access |
|---|---|---|---|
| Package source | — | Filesystem | No |
| Host activation | nexia-apps:activate-package-app | Whole host | No |
| Tenant installation | nexia-apps:install-tenant-app | One tenant | No |
| Initialization | part of installation | One tenant | No |
| Access Grant | an administrator, in the UI | One actor | Yes |
The last stage is often called "assigning a role", which is the UI shorthand. The
record that carries authority is an Access Grant: it binds an actor, one or
more Roles, a Data scope, a Subject population, and a validity period.
AccessGrant documents itself as the sole durable source of standing action
authority — Role membership alone grants nothing.
How it fits: Stage by stage
Host activation
task artisan -- nexia-apps:activate-package-app workshopValidates every package definition's prerequisite graph, installs the package into the host's Composer requirements, then synchronizes Permission definitions and Core Role definitions.
| Property | Behavior |
|---|---|
| Prerequisite problems | Missing prerequisites, duplicate keys, or cycles stop activation before any host change |
| Database | Manifest sync is strict — an unreachable database fails the command |
| Frontend | Without --build-assets, a running Vite process needs a restart |
| Grants | Permission definitions only. No authority |
Tenant installation
For local development (APP_ENV=local), set nexia_tenant to one ID from tenants:list. This command leaves publication and readiness unchanged. Production uses nexia-apps:install-tenant-app after catalog publication and any private tenant entitlement; follow Release an App.
task artisan -- nexia-apps:install-dev-app workshop --tenant="$nexia_tenant" --dry-run
task artisan -- nexia-apps:install-dev-app workshop --tenant="$nexia_tenant" --with-prerequisitesWrites a row per App into tenant_app_installations with an operational status
and an initialization state:
| State | Meaning |
|---|---|
pending | Row written, initializers not complete |
initialized | Initializers completed |
failed | An initializer failed; the error is recorded on the row |
The order is fixed: validate the prerequisite closure → apply its pending migrations in prerequisite order → write pending rows →
synchronize the tenant's permissions and baseline Roles → run each App's
initializers in separate transactions → mark the plan initialized.
Separate transactions mean an initializer that already committed is not rolled
back. The sequence still stops at the failure, and every item left pending in that
plan is marked failed alongside it. nexia-apps:repair-tenant-app replays the normal installation plan, including pending migrations. For unpublished local Apps, rerun nexia-apps:install-dev-app instead.
Operational
An App is exposed only when its installation is active, its initialization is complete, and every prerequisite is also operational.
The app.installed:{app_key} middleware refuses requests while an App is pending or failed. Its PHP routes may remain registered, but tenant consumers cannot use its protected routes, navigation, descriptors, or widgets.
Code-owned versus persisted
Product declarations remain code-owned, but contribution discovery has its own persisted build artifact:
| Persisted product state | Generated or code-owned runtime surface |
|---|---|
| Permission definitions | Contribution interface-to-class manifest |
| Core Role definitions | Navigation items and descriptors read through that manifest |
tenant_app_installations rows | Page elements and routes derived from indexed classes |
| Rows created by initializers | Locale catalogs |
| Copies created by templates | Installed App map and public Resource descriptor map |
Rebuild both generated maps after changing contribution source:
task artisan -- nexia-runtime:generate-app-map
task artisan -- nexia-runtime:refresh-runtime-caches
task artisan -- nexia-apps:activate-package-app workshop --build-assetsThen restart long-running processes — queue workers, Octane, Horizon, and Vite. A process holding an autoloader from before your class existed cannot see it.
Boundaries
No availability stage grants authority. Activation, installation, and initialization make declarations available. Protected destinations and operations still require the actor's applicable permissions.
Deactivation is ordered. nexia-apps:deactivate-tenant-app is refused while
dependent Apps remain active.
Prerequisites constrain lifecycle only. prerequisite_apps affects install and
activation order. It grants no access to the prerequisite App's data.
Repair, do not hand-edit. A failed installation is recovered with
nexia-apps:repair-tenant-app, which replays the plan. Editing installation rows
directly leaves the state inconsistent with what initializers actually did.
Use in your App
A folder under packages/ proves only that source exists. Confirm Composer resolves the package and the generated App map contains it before diagnosing tenant installation. After installation, inspect initialization and prerequisite state. Finally check the exact permission required by the destination; a permission-free overview and a protected Resource route need not have the same visibility.
Related
- Installation content — the install lifecycle in reference form
- Artisan commands — every command above with its operational scope
- Test an App — checking each stage completed
- Fix installation errors — diagnosing a stalled stage
New tenants receive Core schema only. Later tenants:migrate runs include Apps with installation history, including disabled Apps; deactivation retains their tables and data. For an unpublished local App, use nexia-apps:install-dev-app <app-key> --tenant=<tenant ID> --with-prerequisites for installation or recovery. Normal installation and repair continue to enforce distribution policy.