feat: extend module platform with UI slots, runtime components, CLI tooling and {{userId}} search support
Completes the generic module platform that enables modules to contribute
UI elements, runtime JS components, and search resources without any
core hardcoding.
New generic UI slot types:
- topbar.right_item: module-contributed topbar buttons
- layout.body_end_template: module-contributed dialog/overlay templates
- layout.head_style: module-contributed global CSS
- runtime.component: declarative JS component registration with phase ordering
New infrastructure:
- ModuleAutoloader: PSR-4 autoloading for module-local PHP classes
- ModuleRuntimePageBuilder: symlinks module pages into runtime directory
- ModuleRuntimeAssetPublisher: publishes module CSS/JS to web/modules/
- ModulePermissionSynchronizer: syncs module permissions to DB
- CLI scripts: module-runtime-sync, module-build, module-migrate,
module-permissions-sync, module-assets-sync
- {{userId}} placeholder in SearchDataService for user-scoped search queries
- Component runtime with phased initialization (early/default/late)
- AppContainer.protectExistingBindings() to prevent module→core overwrites
- Architecture tests: ModuleStructureContractTest, CoreTemplateIsolationTest,
FrontendComponentRuntimeContractTest, AppContainerIsolationContractTest
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -267,6 +267,13 @@
|
||||
"title": "CSS reuse-first: prefer existing classes over new rules",
|
||||
"requirement": "MUST check existing CSS layers (base, components, layout, pages) for suitable classes before writing new rules. MUST use existing app-* component classes as the basis and only add additive overrides. MUST NOT duplicate declarations already defined in shared component or layout files.",
|
||||
"source": "tools/codex-skills/core-guardrails/references/boundaries-ui.md"
|
||||
},
|
||||
{
|
||||
"id": "GR-UI-017",
|
||||
"area": "ui",
|
||||
"title": "Component lifecycle contract for migrated UI modules",
|
||||
"requirement": "Components migrated to the lifecycle runtime MUST expose an init(root, config) entrypoint that returns an API with destroy(). Migrated component modules MUST NOT auto-initialize themselves via DOMContentLoaded/module side effects and MUST NOT retain legacy wrapper entrypoints or init alias exports. Event listeners, timers, and observers created during init MUST be cleaned up in destroy(). Runtime configuration MUST come from page-config payloads (readPageConfig) instead of scattered ad-hoc globals. Page-level initialization MUST be loaded via web/js/pages/* entry modules, not js/components/* script loads. Host-bound UI components (including tabs) MUST provide explicit data-app-component hosts in markup and remain root-strict (no document.querySelector fallback paths). Global utilities without a natural host MAY be runtime-registered with scope=global and MUST still satisfy the same lifecycle/destroy contract. Project-specific custom window.* globals are forbidden; cross-component communication MUST use core channel modules. Migrated UI storage MUST use the shared namespaced storage contract without legacy key fallback/sync paths.",
|
||||
"source": "tools/codex-skills/core-guardrails/references/boundaries-ui.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user