4.2 KiB
4.2 KiB
Architektur-Kompass
Letzte Aktualisierung: 2026-02-25
Ziel
Verbindliche Kurzregeln für Architekturentscheidungen.
Systembild
- Server-gerenderte Admin-App + REST-API unter
/api/v1. - Multi-Tenant-Isolation ist Standard.
- Autorisierung läuft zentral über Policies.
- Externe API-Verträge sind UUID-first.
Request-Flow
web/index.phpbootstrappt Routing/Konfiguration und initialisiert denAppContainer.- Guard/Firewall/Session/Locale greifen.
- Action in
pages/**nimmt Input an. - Action delegiert an Service.
- Service nutzt Repository für Datenzugriff.
- Response wird als HTML/JSON/Datei ausgegeben.
Schichtregeln (MUSS)
pages/**: Input, Auth/AuthZ, Orchestrierung, Response.lib/Service/**: Fachlogik und Anwendungsfluss.lib/Repository/**: SQL, Filter, Paging, Mapping.templates/**: Rendering ohne Business-Logik.- Templates konsumieren nur vom Action-Layer vorbereitete View-Daten (
$viewAuth, Form/ViewModel), keine direkten Permission-Helper. - Service-Auflösung in Actions/Helpers nur über
app(Foo::class). - In Actions bevorzugt direkte Klassen-Bindings (
app(Service::class)) statt Factory-Ketten. - In
pages/admin/**keineFactory::class-Referenzen. - Request-Input in Actions nur über
requestInput()lesen. - Validierungsfehler über
FormErrorsführen und für APIs mitApiResponse::validationFromFormErrors(...)ausgeben. Flashnur für Redirect-/Outcome-Meldungen verwenden, nicht als primäre Validation-Struktur.- Listen-Endpoints in
pages/**/data().phpsind GET-only (gridRequireGetRequest()). - Grid-Query-Parameter (
limit,offset,order,dir) indata().phpübergridQueryLimitOffset()undgridQueryOrderDir()normalisieren.
Instanziierungsregeln (MUSS)
- Composition Root:
web/index.php+lib/App/registerContainer.php(→ Details:/docs/di-container.md). new ...Factory()nur im Composition Root und in*Factory.php.- In
lib/Service/**außerhalb von*Factory.phpkeine direktennew ...Factory(). - In
lib/Service/**außerhalb von*Factory.phpkeine direktennew ...Service(),new ...Gateway()odernew ...Repository(). - Legacy-Helper (
accessServicesFactory(),userServicesFactory()usw.) sind entfernt und werden nicht mehr genutzt.
API- und Security-Regeln (MUSS)
- Tenant-Scope und Permission nur serverseitig erzwingen.
- Denials je Endpunkt als
403oder404modellieren. - API-Fehlerformat konsistent halten (
error, optionalerrors). - OpenAPI bei API-Änderungen im selben Merge aktualisieren.
RBAC-UI-Standard (MUSS)
- Ability-Entscheidungen laufen serverseitig über
AuthorizationService. - Für Layout/Partials werden globale Capabilities zentral über
UiAccessService::layoutCapabilities()+UiCapabilityMap::LAYOUTbereitgestellt. - Für einzelne Views setzen Actions explizit
$viewAuth['page'](bevorzugt überUiCapabilityMap+UiAccessService::pageCapabilities()). - In
templates/**keine direktencan('...')- oder Permission-Key-Checks.
Mindestchecks vor Merge
docker compose exec php vendor/bin/phpunit
docker compose exec php vendor/bin/phpstan analyse -c phpstan.neon --no-progress
Bei JS-Änderungen zusätzlich Browser-Smoke mit DevTools-Console (keine JS-Errors).
Struktur-Gates zusätzlich:
(rg 'new\s+[^\s(]+Factory\(' lib/Service || true) | wc -l
(rg --glob '!**/*Factory.php' 'new\s+[^\s(]+(Service|Gateway|Repository)\(' lib/Service || true) | wc -l
(rg "\b(accessServicesFactory|directoryServicesFactory|userServicesFactory|authServicesFactory|tenantServicesFactory|settingServicesFactory|userRepositoryFactory|authRepositoryFactory|authGatewayFactory)\(" pages lib templates web || true) | wc -l
(rg -n 'new\s+[^\s(]+(Service|Gateway|Repository)\(' pages -g '*.php' || true) | wc -l
(rg -n '\bDB::' pages -g '*.php' || true) | wc -l
(rg -n 'app\([^\n]*Factory::class\)->create' pages/admin -g '*.php' || true) | wc -l
(rg -n 'Factory::class' pages/admin -g '*.php' || true) | wc -l
Architektur-Contract:
docker compose exec php vendor/bin/phpunit tests/Architecture/CoreStarterkitContractTest.php
Vertiefung
/docs/lib-standards.md/docs/sicherheitsmodell.md/docs/rbac-permissions-playbook.md