Files
breadcrumb-the-shire/docs/architektur.md
2026-03-04 15:56:58 +01:00

96 lines
4.2 KiB
Markdown

# 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
1. `web/index.php` bootstrappt Routing/Konfiguration und initialisiert den `AppContainer`.
2. Guard/Firewall/Session/Locale greifen.
3. Action in `pages/**` nimmt Input an.
4. Action delegiert an Service.
5. Service nutzt Repository für Datenzugriff.
6. 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/**` keine `Factory::class`-Referenzen.
- Request-Input in Actions nur über `requestInput()` lesen.
- Validierungsfehler über `FormErrors` führen und für APIs mit `ApiResponse::validationFromFormErrors(...)` ausgeben.
- `Flash` nur für Redirect-/Outcome-Meldungen verwenden, nicht als primäre Validation-Struktur.
- Listen-Endpoints in `pages/**/data().php` sind GET-only (`gridRequireGetRequest()`).
- Grid-Query-Parameter (`limit`, `offset`, `order`, `dir`) in `data().php` über `gridQueryLimitOffset()` und `gridQueryOrderDir()` 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.php` keine direkten `new ...Factory()`.
- In `lib/Service/**` außerhalb von `*Factory.php` keine direkten `new ...Service()`, `new ...Gateway()` oder `new ...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 `403` oder `404` modellieren.
- API-Fehlerformat konsistent halten (`error`, optional `errors`).
- 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::LAYOUT` bereitgestellt.
- Für einzelne Views setzen Actions explizit `$viewAuth['page']` (bevorzugt über `UiCapabilityMap` + `UiAccessService::pageCapabilities()`).
- In `templates/**` keine direkten `can('...')`- oder Permission-Key-Checks.
## Mindestchecks vor Merge
```bash
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:
```bash
(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:
```bash
docker compose exec php vendor/bin/phpunit tests/Architecture/CoreStarterkitContractTest.php
```
## Vertiefung
- `/docs/lib-standards.md`
- `/docs/sicherheitsmodell.md`
- `/docs/rbac-permissions-playbook.md`