- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks - Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists - Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services - Add Microsoft OIDC SSO, API token management, and user lifecycle features - Add swagger-ui vendor integration and OpenAPI spec - Add production Docker setup and bin/ scripts - Update composer dependencies, config, templates, and frontend assets throughout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
Architektur
Letzte Aktualisierung: 2026-02-21
1) Zielbild
Die Anwendung ist eine servergerenderte Multi-Tenant-Admin-Anwendung mit klarer Trennung von:
- HTTP/Request-Flow (
/web/index.php,lib/Http/*) - Action-Layer (
/pages/**) - Business-Logik (
/lib/Service/**) - Datenzugriff (
/lib/Repository/**) - Rendering (
/templates/**,*.phtml) - Frontend-Verhalten (
/web/js/**)
2) Request-Lebenszyklus
Zentraler Entry Point ist /web/index.php.
Ablauf pro Request:
- Bootstrap (
vendor/autoload.php,config/config.php,config/router.php, Helper) - Firewall + Session Start
- Locale-Ermittlung (URL/Session/Cookie/default)
- Remember-Me Auto-Login
- Optionales Tenant-Snapshot-Refresh in Session
- Redirect auf locale-prefixed URL (falls nötig)
- Access Guard (
AccessControl) für Public/Protected Paths - Action-Layer aus
pages/**laden - View + Template rendern
- Session beenden, DB schließen
3) Routing-Modell
- Route-Definitionen liegen in
/config/routes.php. - Registrierung erfolgt in
/config/router.php. public=trueinroutes.phpsteuert, welche Pfade ohne Login erlaubt sind.
MintyPHP-Konvention (Dateinamensrouting):
pages/admin/users/edit($id).phperwartet URL-Parameteridpages/admin/users/data().phpfür Datenendpunkte...(none).phtmlfür responses ohne Template-Layout- Binarausgaben (z. B. Onboarding-PDF/ZIP) setzen
MINTY_ALLOW_OUTPUTim Action-Endpoint.
4) Schichten und Verantwortungen
Action-Layer (/pages)
- Eingaben lesen/validieren
- Permissions und Tenant-Scope prüfen
- Services aufrufen
- View-Daten vorbereiten
Service-Layer (/lib/Service)
- Geschäftsregeln
- Cross-Cutting-Logik (z. B. Auth, Settings, Branding)
- Orchestrierung mehrerer Repositories
Repository-Layer (/lib/Repository)
- SQL und Mapping
- Filter-/Paging-Mechaniken
- Keine UI-/HTTP-Logik
Template/View-Layer (/templates, *.phtml)
- Nur Rendering
- Keine DB-Zugriffe
- Wiederkehrende UI-Teile als Partials
5) Datenmodell (fachlich)
Kernobjekte:
userstenantsdepartmentsrolespermissions
Verknüpfungen:
user_tenants,user_departments,user_rolesrole_permissionstenant_auth_microsoft,user_external_identitiestenant_custom_field_definitions,tenant_custom_field_optionsuser_custom_field_values,user_custom_field_value_options
Hinweis:
departmentsist 1:1 antenantsgebunden überdepartments.tenant_id(kein M:N-Mapping).- In der User-Organisation wird die Department-Auswahl tenantweise gerendert (ein Multi-Select je zugewiesenem Tenant), gespeichert wird weiterhin flach über
user_departments. - Tenant-spezifische User-Zusatzfelder werden separat modelliert:
- Definitionen/Optionen pro Tenant in
tenant_custom_field_* - Werte pro User in
user_custom_field_* - Filterung im Address Book über dynamische Query-Keys
cf_*,cfm_*,cfd_*.
- Definitionen/Optionen pro Tenant in
field_keybleibt intern (tenant-weit eindeutig), wird im Tenant-UI automatisch aus dem Label erzeugt und nicht manuell gepflegt.is_filterableist fachlich nur fürselect,multiselect,boolean,dateaktiv.- User-Zusatzfeldwerte sind in V1 optional (keine Pflichtvalidierung).
- Tenant-Theme-Overrides werden direkt auf
tenantsgespeichert:tenants.default_theme(NULL= globalesapp_theme)tenants.allow_user_theme(NULL= globalesapp_theme_user).- Auflösung immer über
$_SESSION['current_tenant']und damit tenant-spezifisch für Multi-Tenant-User.
- Tenant-SSO für Microsoft Entra ID:
- Konfiguration pro Tenant in
tenant_auth_microsoft. - Externe Identitäts-Verknüpfung stabil über
user_external_identities(provider + tid + oid). - Login-Endpunkte:
login(optional?tenant={slug}),auth/microsoft/start,auth/microsoft/callback. - Shared-App-Credentials liegen global in
settings; optionale Tenant-Overrides sind möglich. - Profil-Sync wird tenant-spezifisch über
tenant_auth_microsoft.sync_profile_on_loginundtenant_auth_microsoft.sync_profile_fieldsgesteuert. - Erlaubte Sync-Felder in V1:
first_name,last_name,phone,mobile,avatar. phone/mobile/avatarkommen über Microsoft Graph (/me,/me/photo/$value) und sind fail-open (Graph-Fehler blockieren den Login nicht).
- Konfiguration pro Tenant in
Sicherheits-/Audit-nahe Tabellen:
user_remember_tokenspassword_resetsemail_verificationsmail_log
6) Sicherheits- und Scope-Modell
- Auth Guard: protected by default
- Permission Checks: feature-spezifisch in Actions/Services
- Tenant Scope: datenabhängig über Tenant-Matches
- Strictness steuerbar über
TENANT_SCOPE_STRICT
Details siehe:
/docs/sicherheitsmodell.md
7) Frontend-Architektur
JS-Struktur:
/web/js/coreBasismodule (DOM/Grid Factory)/web/js/componentsUI-Komponenten/web/js/pagesseitenspezifische Helfer
Bootstrap:
app-boot.jsfrüh (no-js/js state, localStorage UI state)app-init.jsfür Default-Templateapp-login-init.jsfür Login-Template
CSS-Struktur:
- Layer-Entrypoint:
/web/css/app-layers.css - Basen/Variablen in
/web/css/base - Layout in
/web/css/layout - Komponenten in
/web/css/components - Seitenstile in
/web/css/pages - Vendor-Overrides in
/web/css/vendor-overrides
8) Asset-Steuerung
Konfiguration liegt in /config/assets.php.
- Template-Gruppen:
default,login - Seiten-Gruppen optional via
Buffer::set('style_groups', ...) - Rendering über Helper:
renderTemplateStyles()undrenderPageStyles()
9) Erweiterungsstrategie
Pragmatischer Weg für neue Features:
- Repository erweitern (SQL)
- Service-Regel bauen
- Action anbinden
- View/Partial integrieren
- JS nur falls interaktiv nötig
- Tests + Lint/Analyse laufen lassen
So bleibt die Trennung stabil und Refactoring kontrollierbar.
10) Settings-Architektur (DB + Datei-Cache)
settings(DB) ist die alleinige fachliche Quelle für globale Settings.config/settings.phpist ein technischer Teil-Cache für sehr häufig gelesene UI-Basiswerte.- Zugriffsmuster:
SettingService::get*/SettingService::set*-> DBappSetting(...)-> Datei-Cache (SettingCacheService)
- Konsequenz:
- Es ist korrekt, dass nicht alle DB-Settings im Datei-Cache stehen (z. B. SMTP/SSO/API-Details).
- Der Cache muss nur die Keys enthalten, die im Runtime-Helper
appSetting(...)verwendet werden.
Details:
/docs/einstellungen-speicherung.md