diff --git a/docs/matrix42-26-1-extension-migration.md b/docs/matrix42-26-1-extension-migration.md
index a0a037e..0e771ea 100644
--- a/docs/matrix42-26-1-extension-migration.md
+++ b/docs/matrix42-26-1-extension-migration.md
@@ -1,20 +1,28 @@
-# Matrix42 26.1 Extension/Webservice Migration
+# Matrix42 26.1 Legacy Extension Migration
-Diese Notizen dokumentieren die Learnings aus der Migration der alten F4SD Matrix42 Extension inklusive Custom Web Service auf die Matrix42 26.1 Sandboxed Extension Struktur.
+Diese Notizen dokumentieren die bisherigen Learnings aus der Migration einer alten Matrix42 Extension inklusive Custom Web Service auf eine Matrix42 26.1 Sandboxed Extension.
-Ausgangspunkt der eigentlichen 26.1-Migration war Commit `6c6ac272cd43` (`feat: support Matrix42 26.1 sandboxed web api`, 2026-06-26 11:44 +0200). Die Punkte hier sind bewusst als Checkliste fuer weitere Extensions formuliert.
+Die Anleitung ist bewusst als wiederverwendbare Checkliste fuer weitere Legacy-Pakete formuliert. Sie trennt zwischen belastbaren Ergebnissen, verworfenen Zwischenansaetzen und Punkten, die bei jeder Extension erneut geprueft werden muessen.
## Zielbild
- Extension als .NET 8 Library mit `Matrix42.WebApi.Contracts`.
- Webservice-Controller von `Matrix42.WebApi.Contracts.ApiController` ableiten.
- Controller ueber `Matrix42.Hosting.Contracts.IDependencyResolver` konstruieren.
-- Matrix42-Fachservices nicht direkt im Controller-Konstruktor injizieren.
-- Host-Konfig so klein wie moeglich halten.
-- Paketbau in den Visual-Studio-/MSBuild-Prozess integrieren.
-- Runtime zuerst mit minimalen Endpoints pruefen (`isAlive`, einfache Datenabfrage), dann erst komplexere Services aktivieren.
+- Matrix42-Fachservices nur dort lazy aufloesen, wo sie wirklich gebraucht werden.
+- Host-Konfig mit minimalen Modulen starten und gezielt erweitern.
+- Paketbau in MSBuild/Visual Studio integrieren.
+- Paketversion aus `AssemblyVersion` ableiten.
+- Signing nur fuer eine eigene signed Build-Konfiguration aktivieren.
+- Postman-Collection als Regressionstest fuer alte Client-URLs pflegen.
-## Projektstruktur und Paketbau
+## Ausgangspunkt
+
+Bei einer Portierung eines alten Produktstands muss der Zielstand klar sein. Fuer diesen Branch war der relevante alte Stand `26eac54f94`, nicht der spaetere neue Codezweig.
+
+Wichtiges Learning: Bei einem 26.1-Kompatibilitaetsport keine neuen fachlichen Methoden, Obsolete-Markierungen oder Verhaltensaenderungen aus einem anderen Codezweig uebernehmen. Erst die alte Funktionalitaet lauffaehig machen, dann separate fachliche Aenderungen behandeln.
+
+## Basisprojekt
Bewaehrte Projekt-Eigenschaften:
@@ -23,24 +31,53 @@ Bewaehrte Projekt-Eigenschaften:
Librarywin-x64;linux-x64true
+disable
+disable
+falsefalse...
-C4ITF4SD*.*
+...true
```
-Das Package wird ueber `M42SandboxedExtension.targets` gebaut. Die Paketversion wird automatisch aus der `AssemblyVersion` der gebauten WebApi-Assembly gelesen. In diesem Repo wird diese zentral in `SharedAssemblyInfo.cs` gepflegt.
+Referenzen auf Matrix42-DLLs sollen gegen die 26.1 Libraries zeigen und normalerweise `Private=false` haben, damit keine unnoetigen Matrix42-Plattform-DLLs ins Paket kopiert werden.
-Ein erfolgreicher Release-Build erzeugt:
+Die Host-Konfig muss exakt zum Assembly-Namen passen:
```text
-artifacts// v/
-artifacts// v.zip
+.dll.host.config
```
-Builds signieren die DLLs nicht automatisch. Signieren ist optional und muss explizit aktiviert werden. Wenn `M42SignAssemblies=true` gesetzt ist, werden die DLLs im Package vor dem Package-Build per Authenticode signiert.
+## Paketbau
-Konfigurierbare MSBuild-Properties:
+Das Paket wird ueber `M42SandboxedExtension.targets` gebaut.
+
+Aktuelle Regeln in diesem Repo:
+
+- `Debug` baut Debug-DLLs und ein Debug-Paket.
+- `Release` baut ein unsigniertes Release-Paket.
+- `Release_signed` baut ein Release-Paket und aktiviert `M42SignAssemblies=true`.
+- Artefakte liegen getrennt nach Konfiguration unter `artifacts//`.
+- Die Package-Version wird aus der `AssemblyVersion` der gebauten WebApi-Assembly gelesen.
+- `M42PackageVersion` wurde entfernt und soll nicht wieder eingefuehrt werden.
+
+Die zentrale Version liegt in `SharedAssemblyInfo.cs`.
+
+Beispiele:
+
+```powershell
+dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Debug
+dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release
+dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release_signed
+```
+
+Visual Studio:
+
+- `Debug`: Debugging und Testpakete.
+- `Release`: Release ohne Signierung.
+- `Release_signed`: Release mit Signierung.
+
+Signierbare MSBuild-Properties:
```powershell
/p:M42SignAssemblies=true
@@ -52,29 +89,32 @@ Konfigurierbare MSBuild-Properties:
/p:M42SignOptions="/a"
```
-Build-Befehl:
+## Package-Struktur
-```powershell
-dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release
-```
+Das neue Paket basiert auf einem `PackageTemplate` mit:
-Signierter Release-Build:
+- `package.json`
+- `install.xml`
+- `install/...`
+- `BasePackage/Assemblies` als Build-Ziel fuer Assemblies
-```powershell
-dotnet build "C:\Workspace\C4IT FASD\F4SD_M42WebApi\C4IT - F4SD - M42WebApi.sln" -c Release_signed
-```
+Beim Portieren eines Legacy-Pakets:
-In Visual Studio kann oben in der Konfiguration `Release` fuer einen unsignierten Build oder `Release_signed` fuer einen signierten Build gewaehlt werden.
+1. Altes Paket entpacken.
+2. WebAPI-Service (`PLSLServiceTypeWebAPI`) und Operationen (`PLSLWebServiceOperation`) identifizieren.
+3. Extension-/Assembly-ID beibehalten, wenn ein Update statt einer Neuinstallation gewollt ist.
+4. Operation-IDs nur dann aendern, wenn bewusst neue Operationen entstehen sollen.
+5. Obsolete oder entfernte Schema-Attribute aus 26.1 entfernen.
-## Host-Konfig
+Konkretes 26.1-Learning:
-Die Host-Konfig muss exakt zum Assembly-Namen passen:
+- `UsedInTypeSPSActivityTypeAlert` gibt es in 26.1 nicht mehr und muss aus dem Paket entfernt werden.
-```text
-C4ITF4SDM42WebApi.dll.host.config
-```
+## Host-Konfig und Module
-Final bewaehrte Minimal-Konfig:
+Mit so wenig Modulen wie moeglich starten. Jedes zusaetzliche Modul kann transitive Unity-Registrierungen erzwingen, die bereits beim Controller- oder Service-Aufbau scheitern.
+
+Minimaler Startpunkt fuer einfache Endpoints:
```xml
@@ -86,31 +126,35 @@ Final bewaehrte Minimal-Konfig:
```
-Wichtig: Module nicht auf Vorrat laden. Jedes zusaetzliche Modul kann transitive Unity-Registrierungen erzwingen, die fuer den konkreten Webservice gar nicht benoetigt werden.
+Der aktuelle Stand dieser Extension benoetigt fuer alle Funktionen mehr Module, insbesondere wegen Journal, Storage, Pandora, Teams Notification, ServiceConnection, Auth und Aurora Search. Aktuelle Host-Konfig:
-Module duerfen nicht auf Vorrat geladen werden. Fuer Endpunkte, die Matrix42-Services nutzen, muessen die transitiven Abhaengigkeiten aber vollstaendig als Host-Module registriert werden. Fuer den finalen `IJournalService`-Pfad wurden unter anderem folgende Module benoetigt:
-
-- `Matrix42.Pandora.Persistence`
-- `Matrix42.Pandora.ServiceStore`
-- `Matrix42.Pandora.BizLogic`
-- `Matrix42.Pandora.Services`
-- `Matrix42.MsTeamsNotification.BizLogic`
-- `Matrix42.Integration.Aurora.General`
-- `Matrix42.Integration.Aurora.Search.BizLogic`
-- `Matrix42.ServiceManager.BizLogic`
-- eigenes Webservice-Assembly als Host-Modul
-
-Waehrend der Migration zeigten fehlende Module oder fehlende Sandbox-Host-Registrierungen unter anderem folgende Fehler:
-
-```text
-IEntityDataService is an interface and cannot be constructed
-IUserProfileRepository is an interface and cannot be constructed
-IApiExplorer is an interface and cannot be constructed
-IComplianceRuleManager is an interface and cannot be constructed
-IRequestPropertiesProvider is an interface and cannot be constructed
-IExternalSearchService is an interface and cannot be constructed
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
```
+Regel: Wenn ein weiteres Interface nicht aufgeloest werden kann, nicht raten. In den Matrix42-DLLs nach dem Registrator/der Implementierung fuer genau dieses Interface suchen und nur das passende Modul laden.
+
## Controller-Konstruktion
Nicht so:
@@ -119,16 +163,17 @@ Nicht so:
public MyController(IEntityDataService entityDataService, IJournalService journalService, IPandoraUserProfile userProfile)
```
-Diese direkte Konstruktor-Injection zwingt Matrix42/Unity, alle Services schon beim Erzeugen des Controllers aufzuloesen. Dadurch kann bereits `isAlive` scheitern, obwohl der Endpoint selbst keinen dieser Services nutzt.
+Das zwingt Unity, alle Services schon beim Erzeugen des Controllers aufzuloesen. Dadurch kann bereits `isAlive` scheitern, obwohl der Endpoint selbst keinen dieser Services braucht.
-Besser:
+Bewaehrt:
```csharp
private readonly IDependencyResolver _resolver;
-public MyController(IDependencyResolver resolver)
+public MyController(IDependencyResolver resolver, IEnumerationProvider enumerationProvider)
{
_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
+ _enumerationProvider = enumerationProvider ?? throw new ArgumentNullException(nameof(enumerationProvider));
}
private T GetRequiredService() where T : class
@@ -141,16 +186,23 @@ private T GetRequiredService() where T : class
}
```
-Fachservices dann nur im jeweiligen Endpoint oder Helper lazy aufloesen.
+Fachservices im jeweiligen Endpoint oder Helper lazy aufloesen.
+
+## Dependency-Registrator
+
+Die Extension kann eigene Sandbox-Registrierungen bereitstellen, wenn der Matrix42-Sandbox-Host eine Plattform-Instanz nicht selbst registriert.
+
+Konkretes Learning:
+
+- Fuer den Journal-Pfad fehlte `System.Web.Http.Description.IApiExplorer`.
+- Die Extension registriert eine konkrete `ApiExplorer`-Instanz ueber `IDependencyRegistrator`.
+- Das eigene Assembly muss dafuer als Host-Modul geladen werden.
+
+Das ist kein Workaround im fachlichen Code, sondern eine Host-Registrierung fuer eine fehlende Infrastruktur-Dependency.
## WebAPI-Rueckgaben
-Matrix42 serialisiert manche Rueckgabetypen anders als klassische ASP.NET Web API.
-
-Bewaehrt:
-
-- Datenendpoints geben direkt Nutzdaten zurueck, z. B. `Task` oder `Task