Phase A — Gate Reliability:
- Fix typography token violations in app-breadcrumb.css
- Switch QG-006 from composer cs:check to direct php-cs-fixer
- Align all docs/skills with new gate command
Phase B — Production Profile:
- Multi-stage Dockerfile: dev (xdebug) / prod (no xdebug)
- Compose files target explicit build stages
Phase C — Module Runtime Hardening:
- Atomic staging+swap build in ModuleRuntimePageBuilder
- SHA-256 fingerprint from manifest content + page entries
- 11 new regression tests for build safety and fingerprint drift
Task: STARTERKIT-HARDENING-ONPREM-001
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
deactivateOrphaned() treated ALL is_system=1 permissions as module-owned.
Core seed permissions (users.view, tenants.view, etc.) are also is_system=1,
so they were incorrectly deactivated — breaking admin panel access.
Fix: scan all module manifests on disk (enabled or not) to build the set of
module-owned permission keys. Only deactivate permissions whose key appears
in that set. Core seed permissions are never touched.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a module kernel (ModuleManifest, ModuleRegistry) that allows modules to
contribute routes, UI slots, search providers, layout context, session
lifecycle, and permissions. Modules are activated via config/modules.php or
APP_ENABLED_MODULES env variable. Conflicts (duplicate routes, permissions,
slot keys) cause a fail-fast with a clear error message.
Extract the address book from hardcoded Core integration points into the
first module (modules/addressbook/). The module provides:
- Aside icon-bar tab + People panel via UI slot system
- Global search resource via AddressBookSearchProvider
- Layout context data via AddressBookLayoutProvider
- Session lifecycle via AddressBookSessionProvider
Core cleanup removes address-book hardcodings from SearchSqlResourceProvider,
SearchUiMetaProvider, SearchItemMapperProvider, appBuildLayoutNavContext(),
and the aside templates. Permissions (ADDRESS_BOOK_VIEW) and business logic
(AddressBookService) remain in Core as they gate general user visibility.
Includes 38 new tests (894 total), PHPStan level 5 clean, and architecture
tests verifying zero hardcoded address-book references in search/templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>