mitai-jinkendo/.claude/docs/jinkendo-foundation/design-principles/REGISTRY_PLUGIN_DESIGN_PRINCIPLES.md
Lars 532e17c4cd
All checks were successful
Deploy Development / deploy (push) Successful in 1m5s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 24s
feat: add Jinkendo Foundation design principles documentation
- Introduced a new section for the Jinkendo Foundation, detailing design principles for the product family.
- Updated README files to include references to the new design principles documentation.
- Enhanced the overall documentation structure to improve navigation and accessibility of design resources.
- Ensured consistency across documentation related to the Jinkendo Foundation and its principles.
2026-07-22 11:11:07 +02:00

16 KiB
Raw Blame History

Registry- & Plugin-Muster Designprinzipien (Extraktion)

Status: Analyse / Arbeitspapier
Stand: 2026-07-04
Geltungsbereich: Querschnittsmuster für erweiterbare Registries — drei Implementierungen in Mitai (Platzhalter, Dashboard-Widgets, CSV-Import)

Serie: Designprinzipien für Produktfamilie · Dokument 4 von n
Vorgänger: FEATURE_ENTITLEMENT_DESIGN_PRINCIPLES.md

Die drei Registries:

Registry Backend-Kanon Frontend-/Runtime-Registry Leitfaden
Platzhalter placeholder_registry.py + placeholder_registrations/ PLACEHOLDER_MAP in placeholder_resolver.py PLACEHOLDER_REGISTRY_FRAMEWORK.md
Dashboard-Widgets widget_catalog.py registerDashboardWidgets.jsdashboardWidgetRegistry.jsx DASHBOARD_WIDGETS_AGENT_GUIDE.md
CSV-Import-Module csv_parser/module_registry.py — (Executor + Admin-UI konsumieren API) UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md

Modul

Registry- & Plugin-Muster (Meta-Schicht)

Wiederkehrendes Architekturmuster: Zentral registrierte, ID-basierte Erweiterungspunkte mit Metadaten, Validierung und getrennten Konsumenten (GUI, API, Batch). Kein einzelnes Runtime-Modul — ein Familien-Designpattern, das in Mitai dreimal konkret umgesetzt ist.


Fachliche Verantwortung

Registries übernehmen:

  1. Autoritative ID-Liste — Was existiert, was ist erlaubt, in welcher Reihenfolge (optional).
  2. Metadaten für Mensch & Maschine — Titel, Beschreibung, Typen, Abhängigkeiten, semantische Verträge.
  3. Validierung — Unbekannte IDs werden abgelehnt; Konfigurationen gegen Kanon geprüft.
  4. Entkopplung — Implementierung (Resolver, React-Komponente, Import-Executor) registriert sich an den Kanon, nicht umgekehrt.
  5. Erweiterbarkeit ohne Schema-Explosion — Neue Einträge über Code-Registrierung (+ ggf. DB-Overrides), nicht über neue DB-Spalten pro Feature.

Registries übernehmen nicht:

  • Fachliche Berechnung (→ Data Layer)
  • Entitlement-Auflösung (→ Feature System; Widgets referenzieren Features)
  • Auth / Mandanten

Gemeinsames Strukturschema

┌─────────────────────────────────────────────────────────┐
│  REGISTRY (Kanon)                                        │
│  ID + Metadaten + optionale Policies/Abhängigkeiten    │
└────────────────────┬────────────────────────────────────┘
                     │
     ┌───────────────┼───────────────┐
     ▼               ▼               ▼
 Implementierung  Validierung    Konsumenten
 (Resolver/       (Schema/       (GUI-Picker,
  Component/       Tests)          API, Executor)
  Executor)

Vergleich der drei Implementierungen

Aspekt Platzhalter Dashboard-Widgets CSV-Import
Primär-ID key (snake_case) id (snake_case) Modul-Name (nutrition, activity, …)
Kanon-Speicher Python Singleton + Cluster-Module Python-Liste WIDGET_CATALOG Python-Dict MODULE_DEFINITIONS
Metadaten-Tiefe Sehr hoch (22+ Felder, Evidence) Mittel (title, description, requires_feature) Hoch (fields, types, duplicate_key, aggregates)
Runtime-Registry register_placeholder() beim Import registerDashboardWidget() idempotent Keine — Executor liest Dict
Frontend-Spiegel PlaceholderPicker, Admin-Prompt-Modal ensureDashboardWidgetsRegistered() Admin CSV Template Editor
Validierung metadata.validate(), Governance-Docs Pydantic Layout + validate_widget_entry_config validate_field_mappings, validate_csv_template
Tests test_placeholder_metadata.py, … test_widget_catalog.py test_template_validator.py, …
DB-Override Nein (nur Code) Ja (widget_feature_requirements, Layout pro Profil) Ja (Vorlagen, Nutzer-Mappings)
Entitlements Indirekt (Data/Features) requires_featurecheck_feature_access Feature-Limits beim Import

Designprinzipien (übergreifend)

1. Single Source of Truth für erlaubte IDs

Prinzip Jede erweiterbare Einheit hat eine autoritative ID-Liste; Router und UI duplizieren keine Feld-/Widget-/Platzhalter-Listen.
Begründung Verhindert „funktioniert in der UI, scheitert in der API“ und umgekehrt.
Quelle module_registry.py Kommentar; widget_catalog.py; PLACEHOLDER_REGISTRY_FRAMEWORK.md §2.3
Tragfähigkeit hoch
Einschränkung Platzhalter: paralleles PLACEHOLDER_MAP neben Registry.

2. ID-Stabilität als Vertrag

Prinzip IDs/Keys sind stabile API-Verträge; Umbenennung = neuer Key + Deprecation, nicht stilles Rename.
Begründung Prompts, Layouts und CSV-Vorlagen referenzieren IDs persistent.
Quelle docs/PLACEHOLDER_GOVERNANCE.md §4.24.3; Widget-Layout in profiles.dashboard_layout
Tragfähigkeit hoch
Einschränkung Nicht überall runtime-erzwungen (Platzhalter-Governance prozessual).

3. Metadaten getrennt von Implementierung

Prinzip Registry speichert Was (ID, Beschreibung, Typ, Policies); Implementierung lebt in separaten Modulen.
Begründung GUI, Export, Validierung und Docs können Metadaten nutzen ohne Resolver/Component zu laden.
Quelle PlaceholderMetadata Dataclass; WidgetCatalogEntry; MODULE_DEFINITIONS.fields
Tragfähigkeit hoch
Einschränkung Platzhalter bindet _resolver_func optional an Metadata-Objekt.

4. Zwei-Phasen-Registrierung (Backend-Kanon + Runtime-Binding)

Prinzip Phase A: Kanon definiert IDs und Metadaten. Phase B: Implementierung registriert sich (Platzhalter-Cluster-Import, registerDashboardWidget, Executor nutzt Modul-Def).
Begründung Backend bleibt autoritativ; Frontend/plugins können nachziehen, Tests können Lücken finden.
Quelle import placeholder_registrations in main.py; ensureDashboardWidgetsRegistered()
Tragfähigkeit hoch
Einschränkung Fehlende Frontend-Registrierung zeigt „Unbekanntes Widget“ — kein Build-Time-Fail.

5. Auto-Registration via Package-Import

Prinzip Side-Effect-Import eines Packages triggert vollständige Registrierung (placeholder_registrations/__init__.py).
Begründung Keine vergessene manuelle Registrierungsliste in main.py pro Eintrag.
Quelle placeholder_registrations/__init__.py; main.py
Tragfähigkeit hoch
Einschränkung Import-Reihenfolge und zirkuläre Imports beachten.

6. Validierung am Registry-Rand

Prinzip Unbekannte Keys/Widget-IDs/Feld-Mappings werden an Registry-Grenzen abgewiesen, nicht erst in der Business-Logik.
Begründung Frühes, klares Fehlerbild für Admins und Entwickler.
Quelle DashboardWidgetEntry + ALLOWED_WIDGET_IDS; validate_field_mappings(); get_unknown_placeholders()
Tragfähigkeit hoch
Einschränkung Prompt-Templates können unbekannte Platzhalter erst zur Laufzeit offenbaren.

7. Konsumenten-Agnostik

Prinzip Dieselbe Registry bedient mehrere Konsumenten (KI, Charts, Export, Admin-Browser) ohne duplizierte Metadaten.
Begründung DRY für Beschreibungen, Kategorien, Beispielwerte.
Quelle PLACEHOLDER_REGISTRY_FRAMEWORK.md §2.2; get_placeholder_catalog()
Tragfähigkeit hoch
Einschränkung Legacy-Export-Pfade mergen noch „Registry + Legacy“.

8. Erweiterungs-Checkliste statt Ad-hoc

Prinzip Jedes Registry hat dokumentierte Schritte A→G (Katalog-Eintrag, Validierung, Tests, Version-Bump).
Begründung Agenten und Menschen erweitern konsistent; Review an Checkliste.
Quelle DASHBOARD_WIDGETS_AGENT_GUIDE.md §2; UNIVERSAL_CSV_IMPORT_AGENT_GUIDE.md §2; PLACEHOLDER_DEVELOPMENT_GUIDE.md
Tragfähigkeit hoch
Einschränkung Drei separate Guides — kein unified „Registry Agent Guide“.

9. Tests auf Katalog-Konsistenz

Prinzip Automatisierte Tests prüfen Eindeutigkeit, Reihenfolge, Payload-Shape, ID-Abgleich Kanon ↔ abgeleitete Sets.
Begründung Regression wenn Katalog wächst but Registry/Layout nicht mitzieht.
Quelle test_widget_catalog.py; Placeholder-Metadata-Tests
Tragfähigkeit hoch
Einschränkung Kein Cross-Registry-Test „Frontend widget IDs == backend catalog“.

10. Optionale Entitlement-Referenz im Kanon

Prinzip Registry-Einträge referenzieren Feature-IDs (requires_feature), lösen Entitlements aber nicht selbst auf.
Begründung Tier-Logik bleibt in check_feature_access; Katalog bleibt deklarativ.
Quelle WidgetCatalogEntry.requires_feature; dashboard_widget_entitlements.py
Tragfähigkeit hoch
Einschränkung Platzhalter haben kein direktes requires_feature — Gating nur indirekt.

Designprinzipien (spezifisch pro Registry)

Platzhalter-Registry

# Prinzip Tragfähigkeit Schwäche
P1 Semantischer Vertrag (semantic_contract) pro Key — Platzhalter sind API, nicht Prompt-Hilfe hoch Viele Legacy-Keys mit schwachem Vertrag
P2 Evidence-Tagging — Herkunft jedes Metadatenfelds nachvollziehbar mittel Pflegeaufwand
P3 Cluster-Module — Registrierung nach Domäne (nutrition_part_a, body_metrics, …) hoch 114 Keys Sync mit PLACEHOLDER_MAP
P4 Data-Layer-Referenz in Metadata (data_layer_function) — Bindung an Layer 1 hoch Nicht alle Keys vollständig verknüpft
P5 Singleton get_registry() — globaler Kanon hoch Test-Isolation braucht Disziplin

Dashboard-Widget-Registry

# Prinzip Tragfähigkeit Schwäche
W1 Backend-Katalog = ALLOWED_WIDGET_IDS — Layout-Schema leitet ab hoch Frontend-Registry manuell parallel
W2 merge_missing_catalog_widgets — neue Katalog-IDs erscheinen im Layout ohne User-Reset hoch
W3 Strikte config-Validierung nur für whitelisted Widgets (WIDGETS_ALLOWING_CONFIG) hoch Config-Schemas pro Widget heterogen
W4 Graceful Degradation — unregistrierte ID → Fehler-Karte, nicht Crash mittel Maskiert Deploy-Fehler
W5 WidgetErrorBoundary pro Instanz hoch

CSV-Modul-Registry

# Prinzip Tragfähigkeit Schwäche
C1 MODULE_DEFINITIONS = einzige Feldliste — Router duplizieren nicht hoch Activity erweitert dynamisch um training_parameters
C2 Deklarative Duplikat-Strategie (duplicate_key, update/skip) hoch Modul-spezifische Executor-Sonderfälle
C3 import_row_processing — Aggregation in Registry, nicht im Router hoch Legacy-Defaults in Modul-Def
C4 validate_field_mappings vor Persistenz hoch Nutzer-Mappings teils ohne volle Validator-Parität (#71)
C5 Persistenz-Orchestrator liest Registry-Felder (activity_persistence_orchestrator) hoch Nur Activity voll ausgebaut

Anti-Pattern: Doppel-Registry

Mitai zeigt an Platzhaltern das Risiko explizit:

placeholder_registrations/  ──register──►  PlaceholderRegistry (Metadata)
       │                                          ▲
       └── resolver in code ──►  PLACEHOLDER_MAP (Runtime, 114 Keys)

Regel für Produktfamilie: Runtime-Auflösung soll Metadata-Registry lesen, nicht spiegeln.

Widgets sind näher am Ideal: Backend WIDGET_CATALOG ist Kanon; Frontend muss IDs manuell in registerDashboardWidgets.js binden — akzeptabel, aber testbar machen (Cross-Check).


Nicht übernehmen

  1. Parallele Runtime-MapsPLACEHOLDER_MAP + Registry; eine Quelle für Keys und Resolver-Pfad.

  2. Frontend-Registry ohne Build-/Test-Gate — fehlende registerDashboardWidget-Einträge erst zur Laufzeit sichtbar.

  3. Metadaten-Duplikation in Export-Code — hardcodierte Beschreibungen außerhalb der Registry.

  4. Registry-Einträge ohne Validierungs-Tests — besonders bei 100+ Platzhaltern.

  5. Import-Feldlisten in Routern — alles über module_registry (Mitai-Zielbild, noch nicht überall).

  6. Evidence-/Metadata-Pflicht für einfache Plugins — 22 Felder für Widgets wären Overkill; Metadaten-Tiefe an Risiko anpassen.

  7. Dynamische Registry aus DB ohne Versionierung — Widget-Feature-Overrides OK; kompletter Kanon nur in DB wäre schwer testbar.

  8. Registry ohne Deprecation-Pfad — Breaking Key-Changes still (Platzhalter-Governance existiert, durchsetzen).

  9. Entitlements in Registry auflösen — Widgets richtig: referenzieren; nicht Tier-Logik im Katalog.

  10. Schlaf-Modul leeres fields: {} — Sondermodus (import_mode) statt sauberem Registry-Eintrag; technische Schuld.


Entscheidungsmatrix: Welche Registry-Tiefe?

Wenn … dann Metadaten-Tiefe … Beispiel
Externe Verträge / KI / Compliance Hoch (Vertrag, Evidence, Missing-Policy) Platzhalter
UI-Plugin mit optionaler Config Mittel (ID, title, config schema, feature ref) Widgets
Daten-Ingest / Schema-Mapping Hoch (Typen, keys, constraints) CSV-Module
Internes Hilfsmodul Minimal (ID + Handler-Ref)

Modul-Inventar (Querschnitt)

backend/
├── placeholder_registry.py
├── placeholder_registrations/          # Auto-import Cluster
├── placeholder_resolver.py             # PLACEHOLDER_MAP (Legacy-Spiegel)
├── placeholder_registry_export.py
├── widget_catalog.py
├── dashboard_layout_schema.py
├── dashboard_widget_config.py
├── dashboard_widget_entitlements.py
├── widget_feature_requirements_db.py
└── csv_parser/
    └── module_registry.py

frontend/src/
├── widgetSystem/
│   ├── registerDashboardWidgets.js
│   └── dashboardWidgetRegistry.jsx
└── components/workflow/panels/PlaceholderPicker.jsx

Verwandte Dokumentation


Geplante Folgedokumente (Serie)

# Modul Status
1 Prompt Engine
2 Data Layer
3 Feature & Entitlement
4 Registry-/Plugin-Muster dieses Dokument
5 Auth & Session AUTH_SESSION_DESIGN_PRINCIPLES.md
6 Universal Import
7 Dashboard Widgets
8 Navigation / IA
9 Migration & Deploy

Hinweis: Dokumente 6 und 7 vertiefen Einzel-Registries; dieses Meta-Dokument ist die übergreifende Extraktion.