forked from fa/breadcrumb-the-shire
documentation update with module guidelines
This commit is contained in:
43
CLAUDE.md
43
CLAUDE.md
@@ -25,6 +25,9 @@ docker compose exec php vendor/bin/phpunit
|
||||
# Run PHPStan (level 5)
|
||||
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
|
||||
|
||||
# Sync module runtime (after module changes or APP_ENABLED_MODULES change)
|
||||
docker compose exec php php bin/module-runtime-sync.php
|
||||
|
||||
# Check unused Composer packages
|
||||
docker compose exec php vendor/bin/composer-unused
|
||||
```
|
||||
@@ -34,30 +37,40 @@ docker compose exec php vendor/bin/composer-unused
|
||||
```
|
||||
lib/ # All backend PHP (namespace MintyPHP\)
|
||||
App/ # DI container + bootstrap (AppContainer, Container/Registrars/)
|
||||
Module/ # Module platform (Registry, Manifest, Autoloader, Builder)
|
||||
Repository/ # SQL queries, prepared statements, filters/paging
|
||||
Service/ # Business logic, validation, orchestration
|
||||
Http/ # Auth guards, API auth, request helpers
|
||||
Input/ # Request input handling (RequestInput, FormErrors)
|
||||
Support/ # Crypto, flash, guard, search, helpers
|
||||
pages/ # Actions (controllers) — file-based routing
|
||||
modules/ # Self-contained feature modules (namespace MintyPHP\Module\<Name>\)
|
||||
<id>/module.php # Module manifest (routes, slots, providers, permissions)
|
||||
<id>/lib/ # Module PHP classes (Service, Repository, Providers)
|
||||
<id>/pages/ # Module actions + views (symlinked into runtime)
|
||||
<id>/templates/ # Module-specific templates
|
||||
<id>/web/ # Module CSS/JS (published to web/modules/<id>/)
|
||||
<id>/tests/ # Module PHPUnit tests
|
||||
pages/ # Core actions (controllers) — file-based routing
|
||||
pages/**/*.php # Action files (read input, check permissions, call services)
|
||||
pages/**/*.phtml # View files (rendering only, no DB calls)
|
||||
templates/ # Layouts and partials
|
||||
templates/ # Core layouts and partials
|
||||
partials/ # Reusable UI components
|
||||
emails/ # Email HTML templates
|
||||
pdfs/ # PDF templates (Dompdf)
|
||||
config/ # App config (routes, assets, settings cache, themes)
|
||||
config/ # App config (routes, assets, settings cache, themes, modules)
|
||||
web/ # Document root (entry point, CSS, JS, static assets)
|
||||
js/core/ # DOM utilities, Grid.js factory
|
||||
js/core/ # DOM utilities, Grid.js factory, component runtime
|
||||
js/components/ # Reusable UI components
|
||||
css/ # Layered CSS (base → components → layout → pages)
|
||||
storage/ # Uploaded files (branding/, imports/, tenants/, users/)
|
||||
modules/ # Published module assets (symlinks to modules/<id>/web/)
|
||||
storage/ # Uploaded files + runtime state
|
||||
runtime/pages/ # Symlinked page tree (core + modules, built by module-build)
|
||||
db/init/init.sql # Full schema + seed data (no migration framework)
|
||||
db/updates/ # Idempotent SQL update scripts for existing installs
|
||||
tests/ # PHPUnit tests (namespace MintyPHP\Tests\)
|
||||
docs/ # German-language documentation (Markdown)
|
||||
i18n/ # Translation files (de, en)
|
||||
bin/ # CLI scripts (scheduler, doctor.php health check)
|
||||
bin/ # CLI scripts (scheduler, module-runtime-sync, doctor.php)
|
||||
tools/ # Dev tooling scripts
|
||||
docker/ # Dockerfiles, Nginx configs, PHP configs
|
||||
```
|
||||
@@ -77,16 +90,30 @@ docker/ # Dockerfiles, Nginx configs, PHP configs
|
||||
5. **View** (`pages/**/*.phtml`): Pure rendering. **No DB calls.** HTML escaping via `e(...)`.
|
||||
6. **Template** (`templates/`): Layouts and partials.
|
||||
|
||||
### Modules
|
||||
|
||||
- Modules are self-contained feature packages under `modules/<id>/`
|
||||
- **Namespace:** `MintyPHP\Module\<Name>\*` — never use core namespaces (`MintyPHP\Service\*`, `MintyPHP\Repository\*`)
|
||||
- **Manifest:** `module.php` declares routes, UI slots, providers, permissions, scheduler jobs
|
||||
- **UI integration:** Only via platform slots (`aside.tab_panel`, `topbar.right_item`, `layout.head_style`, `runtime.component`, etc.) — no core template hardcoding
|
||||
- **Session keys:** Prefixed with `module.<id>.*`
|
||||
- **Activation:** `config/modules.php` or `APP_ENABLED_MODULES` env override
|
||||
- **Runtime sync:** `php bin/module-runtime-sync.php` after any module/manifest change (builds page symlinks, syncs permissions, publishes assets)
|
||||
- **Fingerprint guard:** `web/index.php` validates runtime state matches active modules; fails fast if stale
|
||||
- **API isolation:** API requests (`api/` prefix) skip session/auth/cookie flows entirely; modules using API endpoints rely on `ApiBootstrap.php`
|
||||
|
||||
### Routing
|
||||
|
||||
- File-based: `pages/admin/users/edit($id).php` → URL parameter `id`
|
||||
- Module pages: `modules/<id>/pages/` symlinked into `storage/runtime/pages/` at build time
|
||||
- `...(none).phtml` → no template layout
|
||||
- `data().php` suffix → data/AJAX endpoints
|
||||
- Named aliases in `config/routes.php` with `public` flag for auth guard
|
||||
- Module routes declared in manifest, merged at boot (fail-fast on collision)
|
||||
|
||||
### PHP Conventions
|
||||
|
||||
- PSR-4 autoload: `MintyPHP\` → `lib/`, `MintyPHP\Tests\` → `tests/`
|
||||
- PSR-4 autoload: `MintyPHP\` → `lib/`, `MintyPHP\Module\*` → `modules/*/lib/`, `MintyPHP\Tests\` → `tests/`
|
||||
- All user-facing text uses `t('key')` translation helper
|
||||
- Permissions + tenant scope enforced in actions/services, never just in UI
|
||||
- Security/integration settings stay in DB, not in `config/settings.php` file cache
|
||||
@@ -115,7 +142,7 @@ docker/ # Dockerfiles, Nginx configs, PHP configs
|
||||
|
||||
## Quality Gates
|
||||
|
||||
- **PHPStan level 5** — scans `config/`, `lib/`, `pages/`, `tests/`
|
||||
- **PHPStan level 5** — scans `config/`, `lib/`, `modules/`, `pages/`, `tests/`
|
||||
- **PHPUnit 11** — bootstrap: `tests/bootstrap.php`
|
||||
- **Frontend Smoke-Check** — browser console bleibt fehlerfrei in Kernflows
|
||||
- **composer-unused** — periodic check for unused dependencies
|
||||
|
||||
@@ -268,6 +268,34 @@
|
||||
"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-MOD-001",
|
||||
"area": "core",
|
||||
"title": "Module classes must use MintyPHP\\Module\\ namespace",
|
||||
"requirement": "All PHP classes under modules/<id>/lib/ MUST use the MintyPHP\\Module\\<Name>\\ namespace. MUST NOT use core namespaces (MintyPHP\\Service\\, MintyPHP\\Repository\\, MintyPHP\\Support\\, MintyPHP\\Http\\). Enforced by ModuleStructureContractTest::testModuleClassesUseModuleNamespace.",
|
||||
"source": "docs/reference-module-manifest-contract.md"
|
||||
},
|
||||
{
|
||||
"id": "GR-MOD-002",
|
||||
"area": "core",
|
||||
"title": "Module runtime fingerprint must be current",
|
||||
"requirement": "After any module/manifest/APP_ENABLED_MODULES change, MUST run php bin/module-runtime-sync.php before serving requests. web/index.php validates the runtime fingerprint and fails fast if stale. MUST NOT bypass or remove the fingerprint check.",
|
||||
"source": "docs/reference-module-manifest-contract.md"
|
||||
},
|
||||
{
|
||||
"id": "GR-MOD-003",
|
||||
"area": "ui",
|
||||
"title": "Module UI only via platform slots",
|
||||
"requirement": "Module UI contributions MUST use platform slots (aside.tab_panel, topbar.right_item, layout.head_style, layout.body_end_template, runtime.component, search.resource_item). MUST NOT add module-specific markup to core templates. Enforced by NoBookmarksHardcodingTest and NoAddressBookHardcodingTest.",
|
||||
"source": "docs/reference-module-manifest-contract.md"
|
||||
},
|
||||
{
|
||||
"id": "GR-SEC-007",
|
||||
"area": "security",
|
||||
"title": "API requests must not start PHP sessions",
|
||||
"requirement": "API requests (api/ prefix) MUST NOT trigger Session::start(), remember-me cookie handling, or session timeout redirects. API authentication is handled by ApiBootstrap.php with Bearer tokens. web/index.php enforces this via channel detection before session initialization.",
|
||||
"source": "docs/reference-module-manifest-contract.md"
|
||||
},
|
||||
{
|
||||
"id": "GR-UI-017",
|
||||
"area": "ui",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Lokale Entwicklung
|
||||
|
||||
Letzte Aktualisierung: 2026-03-09
|
||||
Letzte Aktualisierung: 2026-03-18
|
||||
|
||||
## Ziel
|
||||
|
||||
@@ -21,6 +21,18 @@ Bei inkonsistentem Laufzeitverhalten:
|
||||
docker compose restart php nginx
|
||||
```
|
||||
|
||||
## Module-Sync
|
||||
|
||||
Nach Aenderungen an Modulen, Manifesten oder `APP_ENABLED_MODULES`:
|
||||
|
||||
```bash
|
||||
docker compose exec php php bin/module-runtime-sync.php
|
||||
```
|
||||
|
||||
Dieser Befehl fuehrt automatisch aus: `migrate` → `permissions-sync` → `build` → `assets-sync`.
|
||||
|
||||
Falls `web/index.php` den Fehler "Module runtime is stale" wirft, ist der Sync noetig.
|
||||
|
||||
## Schema-Stand
|
||||
|
||||
- Basis-Schema + Seeds: `db/init/init.sql`
|
||||
@@ -42,6 +54,12 @@ docker compose exec php vendor/bin/phpunit
|
||||
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
|
||||
```
|
||||
|
||||
Bei Modul-/Manifest-Aenderungen zusaetzlich:
|
||||
|
||||
```bash
|
||||
docker compose exec php php bin/module-runtime-sync.php
|
||||
```
|
||||
|
||||
Bei JS-Änderungen zusätzlich Browser-Smoke mit DevTools-Console (keine JS-Errors).
|
||||
|
||||
## Struktur-Gates (empfohlen)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Konventionen (kurz und verbindlich)
|
||||
|
||||
Letzte Aktualisierung: 2026-03-17
|
||||
Letzte Aktualisierung: 2026-03-18
|
||||
|
||||
## 1) Code
|
||||
|
||||
@@ -48,8 +48,20 @@ Letzte Aktualisierung: 2026-03-17
|
||||
- Runtime-Komponenten nur über Lifecycle-Contract (`init(root, config)` + `destroy()`), ohne komponenteneigenen Auto-Init.
|
||||
- Host-gebundene Runtime-Komponenten über `data-app-component` markieren; nur echte Global-Utilities ohne Host als runtime-global registrieren.
|
||||
|
||||
## 6) Mindestchecks vor Merge
|
||||
## 7) Module
|
||||
|
||||
- Namespace: `MintyPHP\Module\<Name>\*` — nie Core-Namespaces (`MintyPHP\Service\*`, `MintyPHP\Repository\*`).
|
||||
- Verzeichnis: `modules/<id>/lib/Module/<Name>/` (Service, Repository, Providers, Support).
|
||||
- Session-Keys: Prefix `module.<id>.*`.
|
||||
- UI-Integration nur ueber Plattform-Slots (`aside.tab_panel`, `topbar.right_item`, `layout.head_style`, `runtime.component`, etc.).
|
||||
- Kein Modul-spezifisches Markup in Core-Templates.
|
||||
- Tests: `modules/<id>/tests/` (werden von `phpunit.xml` automatisch entdeckt via `modules/*/tests`).
|
||||
- Modul-Actions importieren nie `OperationsAuthorizationPolicy::ABILITY_*` — eigene Policy nutzen.
|
||||
- Manifest-Contract: `/docs/reference-module-manifest-contract.md`.
|
||||
|
||||
## 8) Mindestchecks vor Merge
|
||||
|
||||
- `docker compose exec php vendor/bin/phpunit`
|
||||
- `docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress`
|
||||
- bei Modul-/Manifest-Aenderungen: `docker compose exec php php bin/module-runtime-sync.php`
|
||||
- bei JS-Änderungen: Browser-Smoke mit DevTools-Console (keine JS-Errors)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Module Manifest Contract (V1.1)
|
||||
# Module Manifest Contract (V1.2)
|
||||
|
||||
Letzte Aktualisierung: 2026-03-18
|
||||
|
||||
@@ -11,6 +11,26 @@ Verbindlicher Contract fuer `modules/*/module.php`, damit Module zur Runtime det
|
||||
Dieses Dokument ist die kanonische (normative) Quelle fuer Manifest-, Runtime- und Guard-Regeln des Modul-Systems.
|
||||
`/docs/reference-extension-readiness.md` referenziert diesen Contract und dupliziert keine Felddefinitionen.
|
||||
|
||||
## Namespace-Konvention
|
||||
|
||||
Alle PHP-Klassen eines Moduls muessen den Namespace `MintyPHP\Module\<Name>\*` verwenden.
|
||||
Core-Namespaces (`MintyPHP\Service\*`, `MintyPHP\Repository\*`, `MintyPHP\Support\*`) sind fuer Modul-Code verboten.
|
||||
|
||||
Verzeichnis-Layout:
|
||||
|
||||
```
|
||||
modules/<id>/lib/Module/<Name>/
|
||||
Service/ # BookmarkService, Factory, etc.
|
||||
Repository/ # Repository + Interfaces
|
||||
Providers/ # SessionProvider, LayoutProvider, SearchProvider
|
||||
Support/ # Modul-spezifische Utilities
|
||||
<Name>ContainerRegistrar.php
|
||||
<Name>AuthorizationPolicy.php
|
||||
```
|
||||
|
||||
Der `ModuleAutoloader` mappt `MintyPHP\*` → `modules/<id>/lib/` per PSR-4.
|
||||
Enforcement: `ModuleStructureContractTest::testModuleClassesUseModuleNamespace`.
|
||||
|
||||
## Aktivierung (`APP_ENABLED_MODULES`)
|
||||
|
||||
- nicht gesetzt: `config/modules.php` gilt.
|
||||
@@ -86,6 +106,26 @@ Abgrenzung CSS:
|
||||
- Layout-Provider duerfen reservierte Core-Keys nicht ueberschreiben (`moduleSlots`, `csrfKey`, `currentTenant`, ...).
|
||||
- Layout-Provider-Top-Level-Keys muessen namespaced sein (`<module_id>.<key>`).
|
||||
|
||||
## Runtime-Fingerprint
|
||||
|
||||
`web/index.php` validiert bei jedem Request, dass der Runtime-Stand zur aktuellen Modul-Konfiguration passt.
|
||||
|
||||
- `bin/module-build.php` schreibt nach jedem Build `storage/runtime/.module-fingerprint` (sortierte Modul-IDs, kommasepariert).
|
||||
- `web/index.php` vergleicht den Fingerprint mit der erwarteten Modul-Liste.
|
||||
- Bei Mismatch: `RuntimeException` mit Hinweis auf `php bin/module-runtime-sync.php`.
|
||||
- Kein Auto-Build im Request-Pfad — Build ist ausschliesslich CLI-Aufgabe.
|
||||
|
||||
Methoden: `ModuleRuntimePageBuilder::expectedFingerprint()`, `readFingerprint()`, `writeFingerprint()`.
|
||||
|
||||
## API-Channel-Isolation
|
||||
|
||||
API-Requests (`api/`-Prefix) ueberspringen den gesamten Web-Session-Flow:
|
||||
|
||||
- Kein `Session::start()`, kein Cookie-Setting, kein CSRF-Token
|
||||
- Kein Remember-Me, kein Session-Timeout, kein Tenant-UI-Refresh
|
||||
- API-Auth erfolgt ueber `ApiBootstrap.php` (Bearer-Token)
|
||||
- `AccessControl` listet `api/` als always-public
|
||||
|
||||
## Standard-Runbook
|
||||
|
||||
`php bin/module-runtime-sync.php` fuehrt in fester Reihenfolge aus:
|
||||
|
||||
Reference in New Issue
Block a user