6.8 KiB
6.8 KiB
lib-Standards
Letzte Aktualisierung: 2026-03-03
Praktische Regeln nur für lib/**. Ergänzt docs/architektur.md.
1) Repository-Regeln
- Verantwortlich für SQL, Filter, Paging und Mapping.
- Keine HTTP-, Session-, Redirect- oder Policy-Logik.
2) Service-Regeln
- Verantwortlich für Fachlogik und Orchestrierung.
- Keine Superglobals (
$_POST,$_GET,$_SESSION). - Keine Header- oder Redirect-Ausgabe.
- Keine direkten
DB::...-Aufrufe im Service. - Abhängigkeiten per Constructor Injection.
- DB-Locks und Transaktionen über Repository-Schicht (z. B.
DatabaseSessionRepository). - Audit-Hooks für fachliche Schreibaktionen laufen in Services (
SystemAuditService), nicht in Templates. - API-Request-System-Audit läuft zentral über
ApiSystemAuditReporter(Lifecycle inApiBootstrap+ApiResponse), nicht pro Endpoint. - Scheduler-Run-/Job-Ereignisse werden zentral im
SchedulerRunServiceinSystemAuditServicegeschrieben. - CLI-System-Audit für zentrale Commands wird am Entrypoint (
bin/**) geschrieben, mit minimaler Metadata (ohne Argumentwerte).
3) Instanziierung
- Composition Root ist
web/index.php+lib/App/registerContainer.php(→ Details:/docs/di-container.md). - Domain-Abhängigkeiten mit
newnur im Composition Root und in*Factory.php. - In
pages/**,templates/**,lib/Support/**und Gateway-/Service-Fallbacks nur überapp(Foo::class)auflösen. - In Actions bevorzugt direkte Service/Gateway-Bindings (
app(Service::class)) stattapp(...Factory::class)->create...(). - In
pages/admin/**keineFactory::class-Referenzen; nur direkteapp(Service::class)/app(Repository::class). - 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-Service-Helper (
accessServicesFactory(),userServicesFactory()usw.) werden nicht mehr verwendet. - Für neue Domain-Logik keine statischen Utility-Klassen.
3.1) Schnell-Gates (lokal)
(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
Erwartung jeweils: 0.
3.2) Architektur-Contract-Test
- Verbindlicher Guardrail:
tests/Architecture/CoreStarterkitContractTest.php - Deckt die Hard-Cut-Regeln ab:
- keine direkten
new ...Service|Gateway|Repositoryinpages/** - kein
DB::inpages/** - keine
app(...Factory::class)->create...-Ketten inpages/admin/** - keine Input-Superglobals in
pages/** - kein
ApiResponse::readJsonBody(...)inpages/api/v1/**
- keine direkten
4) Autorisierung und Scope
- Zentral über
AuthorizationServiceund Policy-Abilities. - Keine verteilten Einzelchecks als primäre Zugriffslogik.
- UI-Capabilities zentral über
UiAccessServiceauflösen. $viewAuth['layout']wird zentral im Front Controller aufgebaut (web/index.php), nicht in Templates.- Templates nutzen nur
$viewAuth['layout']bzw.$viewAuth['page'], keinecan('...')-Helper.
4.1) Erweiterung neuer Permissions (Starter-Kit)
- Permission-Key in
PermissionService+ Migration/Seed ergänzen. - Ability in passender Policy ergänzen (oder neue Operation-Ability).
- Bei UI-Bedarf Mapping zentral in
UiCapabilityMapergänzen. - Action setzt benötigte
$viewAuth['page']-Flags. - Template konsumiert nur
$viewAuth. - Architektur-/Service-Tests und Doku aktualisieren.
Details und Sonderfälle: /docs/rbac-permissions-playbook.md
5) data().php-Standard
pages/**/data().phpsind ausschließlich GET-Endpunkte (gridRequireGetRequest()).- Query-Normalisierung zentral über
gridParseFilters($query, gridSchemaQuery($filterSchema)). - Pro Liste gibt es ein
filter-schema.phpim selben Verzeichnis (Single Source of Truth). - Schema-Typen:
int,number,bool,string,enum,uuid,date,csv_ids,csv_uuid,csv_strings,order,dir. - Keine Alias-Parameter (
*_id) in Listen-Querys; IDs immer als CSV über*_ids. - Bei JSON-Listenantworten immer konsistent:
{'data': [...], 'total': <int>}. - Für MultiSelect-Filter in Listen:
- Toolbar-Rendering zentral über
renderGridFilterToolbar(...). - Select-/MultiSelect-/Text-/Date-/Hidden-Filter werden aus dem Schema gerendert (kein dupliziertes HTML in Templates).
- Grid-Filterbindung clientseitig zentral über
gridFiltersFromSchema(...). - Grid-Filter verwenden CSV-Parameter (z. B.
event_types,actor_user_ids), keine[]-Query-Arrays. - Repository-Filter über
IN (???)und serverseitige Limitierung/Validierung.
- Toolbar-Rendering zentral über
5.1) Status/Outcome-Taxonomien (Backed Enums)
- Persistierte Status-/Outcome-Domänen liegen zentral in
lib/Domain/Taxonomy/*. - Jede Taxonomie liefert einheitlich:
values(),tryNormalize(),normalizeOr(),labelToken(),badgeVariant(). - Filter-Schemas lesen Allowed-Listen aus
Enum::values()odergridEnumSanitizer(Enum::class). - Data-Endpunkte erzeugen Badge/Label über Enum-Cases, nicht über lokale
if/elseif-Mappings. - In Services/Repositories keine verstreuten Literal-Listen für diese Domänen (
success,failed, ...). - DB-seitig sind die gleichen Domänen per
CHECK-Constraints abgesichert (db/init/init.sql+db/updates/2026-03-03-status-taxonomy-hard-cut.sql).
6) API-Contract
- Extern UUID-first.
- Interne IDs nur intern auflösen und mappen.
7) Input + Validation in pages/**
- Request-Daten nur über
requestInput()lesen. - Kein direktes
$_POST,$_GET,$_FILES,$_SERVER['REQUEST_METHOD']inpages/**. - Validierungsfehler intern über
FormErrorsaufbauen (formErrors(),formErrorsFrom()). - API-Validation-Antworten einheitlich über
ApiResponse::validationFromFormErrors(...). - Web-Templates bekommen weiterhin kompakte Listen (
$errors) ausFormErrors::toFlatList(). Flashnicht als primäre Validation-Struktur verwenden; nur für Redirect-/Outcome-Meldungen.
Kurz-How-to: /docs/request-input-validation.md
8) Definition of Done für lib/**
- Schichtgrenzen eingehalten.
- AuthZ zentral.
- Instanziierungsregeln aus Abschnitt 3 eingehalten (inkl. Gate-Checks).
- Unit-Tests ergänzt, bei Strukturänderung zusätzlich Contract-Test.
phpunitundphpstangrün.