Install Contract
`bootstrap/install_contract.php` is the executable lifecycle handoff contract. The manifest says where the contract is; this file says what Installer can apply and which provider files/functions Installer should call.
File Location
Put the file here:
addons/{addon_key}/bootstrap/install_contract.phpThe file must return a PHP array and must keep the `HC_ACCESS` guard when shipped inside the app.
One Job
The install contract points Installer at executable install/update pieces. It should not repeat the full permission catalog or route catalog.
Use the install contract for:
- readiness flags
- owned table names
- schema provider path and function names
- permissions provider path and registration function
- route provider path and contract/register functions
- public target provider path and function names
- lifecycle boundary notes
Do not use the install contract for:
- a copied list of every permission
- a copied list of every route
- route/admin navigation truth
- duplicated public target records
Minimum Shape
<?php
declare(strict_types=1);
if (!defined('HC_ACCESS')) {
exit;
}
return [
'placeholder' => false,
'addon_key' => 'example_notes',
'display_name' => 'Example Notes',
'install_ready' => true,
'mount_ready' => true,
'schema_contract_present' => true,
'permissions_contract_present' => true,
'route_contract_present' => true,
'owned_tables' => [
'amv_example_notes',
],
'schema_contract' => [
'provider' => 'addons/example_notes/src/schema_contract.php',
'table_names_function' => 'amv_example_notes_schema_table_names',
'schema_tables_function' => 'amv_example_notes_schema_tables',
'schema_apply_function' => 'amv_example_notes_schema_apply',
],
'permissions_contract' => [
'provider' => 'addons/example_notes/src/permissions_contract.php',
'registration_function' => 'amv_example_notes_permissions_contract',
],
'route_contract' => [
'provider' => 'addons/example_notes/routes/routes.php',
'register_function' => 'amv_example_notes_register_routes',
'contract_function' => 'amv_example_notes_routes_contract',
],
'public_target_contract' => [
'provider' => 'addons/example_notes/src/public_targets.php',
'provider_function' => 'amv_example_notes_public_target_provider',
'targets_function' => 'amv_example_notes_public_targets',
'access_function' => 'amv_example_notes_public_target_access',
],
'lifecycle_contract' => [
'installer_owns' => ['schema_apply', 'permission_registration', 'route_registration'],
'aem_owns' => ['identity_validation', 'classification_validation', 'lifecycle_state'],
'addon_owns' => ['domain_records', 'admin_workflow', 'public_workflow'],
],
];Permissions Contract Fields
The clean install contract references the permission contract; it does not copy the permission list.
'permissions_contract' => [
'provider' => 'addons/example_notes/src/permissions_contract.php',
'registration_function' => 'amv_example_notes_permissions_contract',
],The full permission catalog belongs in `src/permissions_contract.php`.
Route Contract Fields
The clean install contract references the route contract; it does not copy route rows.
'route_contract' => [
'provider' => 'addons/example_notes/routes/routes.php',
'register_function' => 'amv_example_notes_register_routes',
'contract_function' => 'amv_example_notes_routes_contract',
],The full route table, admin target list, and public target provider references belong in `routes/routes.php`.
Drift Check
If you see permission rows in manifest, install contract, and `src/permissions_contract.php`, clean it up.
If you see route rows in manifest, install contract, and `routes/routes.php`, clean it up.
One detailed owner, many pointers. That is the whole trick.
Related pages: Addon Development/Manifest Contract, Addon Development/Permissions Contract Basics, Reference Samples/Current Addon Contract Shape.
Updated: 2026-05-07 20:06:59