From ccfd26c0cf8b5b806c8087071d58716a2f8af8b2 Mon Sep 17 00:00:00 2001 From: Meik Date: Wed, 11 Mar 2026 17:09:46 +0100 Subject: [PATCH] Add NTFS DFS path classification concept --- ...IAM_NTFS_DFS_Pfadklassifikation_Konzept.md | 431 ++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 Sonstiges/LIAM_NTFS_DFS_Pfadklassifikation_Konzept.md diff --git a/Sonstiges/LIAM_NTFS_DFS_Pfadklassifikation_Konzept.md b/Sonstiges/LIAM_NTFS_DFS_Pfadklassifikation_Konzept.md new file mode 100644 index 0000000..41f4a0b --- /dev/null +++ b/Sonstiges/LIAM_NTFS_DFS_Pfadklassifikation_Konzept.md @@ -0,0 +1,431 @@ +# LIAM NTFS / DFS Pfadklassifikation - Zielkonzept + +## Ziel + +Dieses Dokument beschreibt ein belastbares Zielkonzept fuer die Klassifikation von UNC-Pfaden im LIAM-NTFS-Provider. + +Der aktuelle Code behandelt die Unterscheidung zwischen Share und Folder im Wesentlichen ueber die Pfadtiefe. Das ist fuer einfache klassische UNC-Freigaben teilweise ausreichend, aber fachlich nicht robust genug. + +Insbesondere folgende Faelle sollen perspektivisch sauber unterstuetzt werden: + +- `\\server` +- `\\server\share` +- `\\server\share\folder` +- `\\server\namespace` +- `\\server\namespace\link` +- `\\server\namespace\link\folder` + +Das Konzept ist bewusst noch keine Implementierung. Es beschreibt, welche semantischen Informationen benoetigt werden und wie die Entscheidung logisch aufgebaut sein sollte. + +## Problem des aktuellen Ansatzes + +Der bestehende NTFS-Provider leitet den Objekttyp im Kern aus der Anzahl der UNC-Segmente ab. + +Beispiel: + +- `\\server\share` -> wird als Share behandelt +- `\\server\share\folder` -> wird als Folder behandelt + +Das hat mehrere fachliche Schwaechen: + +- Ein DFS-Link wie `\\server\namespace\link` ist semantisch oft ein Share-aehnlicher Einstiegspunkt, hat aber drei Segmente. +- Ein Root wie `\\server` ist mit der bisherigen Logik ueberhaupt nicht sinnvoll modellierbar. +- `LoadDataArea()` und `getDataAreasAsync()` arbeiten nicht zwingend mit derselben Semantik. +- Die Klassifikation basiert auf Syntax statt auf den tatsaechlichen Freigabe- und Namespace-Metadaten. + +Die Folge ist, dass bei DFS und bei kuenftigem Server-Root-Support keine verlaessliche Typbestimmung moeglich ist. + +## Grundprinzip der richtigen Loesung + +Die Klassifikation darf nicht von der Pfadtiefe abhaengen, sondern muss aus der tatsaechlichen Bedeutung des Pfads ermittelt werden. + +Das bedeutet: + +- Ein klassischer Windows-Share wird ueber Share-Metadaten erkannt. +- Ein DFS-Namespace oder DFS-Link wird ueber DFS-Metadaten erkannt. +- Ein Folder ist ein Pfad, der unterhalb eines Share- oder Link-Grenzpunkts liegt. + +Die zentrale Regel lautet daher: + +Nicht fragen "Wie tief liegt der Pfad?", sondern "Welches Namensobjekt repraesentiert dieser Pfad fachlich?". + +## Fachliche Objektarten + +Fuer eine robuste interne Modellierung sollten mehr Typen unterschieden werden als nur `Share` und `Folder`. + +Empfohlenes internes Zielmodell: + +- `ServerRoot` +- `ClassicShare` +- `DfsNamespaceRoot` +- `DfsLink` +- `Folder` +- `Unknown` + +Nach aussen kann das bei Bedarf weiter auf bestehende LIAM-Typen gemappt werden: + +- `ClassicShare` -> `NtfsShare` +- `DfsNamespaceRoot` -> je nach fachlicher Entscheidung `NtfsShare` oder Container-Typ +- `DfsLink` -> `NtfsShare` +- `Folder` -> `NtfsFolder` + +Der entscheidende Punkt ist, dass intern sauber unterschieden wird, auch wenn die externe API zunaechst kompatibel bleiben soll. + +## Semantische Datenquellen + +### 1. Klassische Windows-Freigaben + +Fuer klassische Shares ist die sichere Quelle die Share-Konfiguration des Zielservers. + +Fachlich wird geprueft: + +- Welche Shares existieren auf dem Server? +- Welcher UNC-Pfad repraesentiert exakt einen Share? +- Auf welchen lokalen Zielpfad zeigt der Share? + +Aus dieser Sicht gilt: + +- `\\server\share` ist ein Share, wenn auf dem Server genau dieser Share publiziert ist. +- Jeder Pfad unterhalb davon ist ein Folder. + +### 2. DFS + +Fuer DFS reicht die Share-Liste nicht aus. + +Hier muss zusaetzlich geprueft werden: + +- Ist `\\server\namespace` ein DFS-Namespace-Root? +- Ist `\\server\namespace\link` ein DFS-Link? +- Welche Link-Ziele sind hinterlegt? + +Aus dieser Sicht gilt: + +- `\\server\namespace` ist ein Namespace-Objekt, nicht einfach nur ein Folder. +- `\\server\namespace\link` ist fachlich ein Share-aehnlicher Einstiegspunkt. +- Jeder Pfad unterhalb eines DFS-Links ist ein Folder. + +## Zielbild fuer Roots + +### Fall 1: Root ist `\\server` + +Wenn `\\server` als Root erlaubt sein soll, muss die erste Ebene alle publizierten Einstiegspunkte des Servers liefern. + +Das bedeutet: + +- klassische Shares des Servers +- DFS-Namespaces, die ueber diesen Server angesprochen werden koennen +- administrative Shares wie `C$`, `ADMIN$`, `IPC$` sollten in der Regel herausgefiltert werden + +Unter `\\server` duerfen also nicht einfach Dateisystemordner enumeriert werden. Stattdessen werden Namensobjekte auf Server-Ebene enumeriert. + +Beispiele: + +- `\\server\shareA` -> `ClassicShare` +- `\\server\dfs` -> `DfsNamespaceRoot` +- `\\server\shareA\team1` -> `Folder` +- `\\server\dfs\link1` -> `DfsLink` + +### Fall 2: Root ist `\\server\share` + +Bei einem klassischen Share als Root ist die Bedeutung eindeutig: + +- Root selbst ist `ClassicShare` +- alle darunter liegenden Eintraege sind `Folder` + +Hier ist die fachliche Share-Grenze der Root-Pfad selbst. + +### Fall 3: Root ist `\\server\namespace` + +Bei einem DFS-Namespace als Root muss die erste Ebene nicht als Folderliste, sondern als Namespace-Inhaltsliste verstanden werden. + +Typischerweise bedeutet das: + +- Root selbst ist `DfsNamespaceRoot` +- direkte Kinder koennen `DfsLink`-Objekte sein +- alles unterhalb eines `DfsLink` ist `Folder` + +Ob der Namespace-Root selbst nach aussen als `NtfsShare` oder als eigener Container-Typ behandelt wird, ist eine fachliche API-Entscheidung. + +### Fall 4: Root ist `\\server\namespace\link` + +Wenn der Root-Pfad bereits ein DFS-Link ist, dann gilt: + +- Root selbst ist `DfsLink` +- alles darunter ist `Folder` + +Fuer die bestehende LIAM-Semantik waere das nach aussen typischerweise ein `NtfsShare`. + +## Empfohlene zentrale Klassifikationslogik + +Die Klassifikation sollte in einer einzigen zentralen Komponente gebuendelt werden. + +Wichtig ist: + +- `getDataAreasAsync()` muss dieselbe Logik verwenden wie `LoadDataArea()` +- die UI, Workflow-Aktivitaeten und Web-API duerfen nicht jeweils eigene Heuristiken haben + +Empfohlenes konzeptionelles Interface: + +```text +ClassifyPath(path) -> PathClassification +EnumerateChildren(path) -> List +``` + +Eine `PathClassification` sollte mindestens enthalten: + +- `NormalizedPath` +- `Kind` +- `DisplayName` +- `BoundaryPath` +- `ParentBoundaryPath` +- `BackingType` wie `SMB` oder `DFS` +- optionale Diagnoseinformationen zur Herleitung + +## Empfohlene Entscheidungsreihenfolge + +Die Aufloesung eines Pfads sollte in einer festen Reihenfolge passieren. + +### Schritt 1: Pfad normalisieren + +Vor jeder Klassifikation: + +- UNC-Pfad vereinheitlichen +- doppelte Separatoren bereinigen +- optional Gross-/Kleinschreibung fuer Vergleiche normalisieren +- Trailing Backslash konsistent behandeln + +Beispiele: + +- `\\server\share\` +- `\\SERVER\share` +- `\\server\\share` + +sollten intern auf einen stabilen Vergleichswert normalisiert werden. + +### Schritt 2: Root-Typ erkennen + +Zuerst wird geprueft, ob der Pfad einer dieser Grundtypen ist: + +- Server-Root +- klassischer Share +- DFS-Namespace-Root +- DFS-Link +- Folder unterhalb eines bekannten Grenzpunkts + +### Schritt 3: DFS zuerst pruefen + +Fuer UNC-Pfade mit mehreren Segmenten sollte zuerst geprueft werden, ob ein Pfad oder ein Pfadpraefix ein DFS-Namespace oder DFS-Link ist. + +Der Grund: + +- DFS kann Pfade erzeugen, die syntaktisch wie normale Ordner wirken +- semantisch sind sie aber eigenstaendige Einstiegspunkte + +Wenn ein Praefix als DFS-Link identifiziert wird, ist dieses Praefix die fachliche Share-Grenze. + +Beispiel: + +- Pfad: `\\server\namespace\link\teamA\finance` +- erkannter DFS-Link: `\\server\namespace\link` +- Klassifikation des Gesamtpfads: `Folder` +- fachlicher Parent-Share: `\\server\namespace\link` + +### Schritt 4: Klassische Shares pruefen + +Wenn kein DFS-Fall vorliegt, wird geprueft, ob der Pfad oder ein Praefix einem klassischen Share entspricht. + +Beispiel: + +- Pfad: `\\server\share\dept\project` +- erkannter Share: `\\server\share` +- Klassifikation des Gesamtpfads: `Folder` +- fachlicher Parent-Share: `\\server\share` + +### Schritt 5: Fallback nur kontrolliert verwenden + +Wenn weder DFS noch klassischer Share sicher ermittelt werden kann: + +- nicht blind ueber Segmentzahl entscheiden +- stattdessen `Unknown` liefern oder einen explizit konfigurierten Fallback nutzen + +Das ist wichtig, damit Unsicherheit nicht als scheinbar sichere Fachlogik maskiert wird. + +## Share-Grenze als zentrales Konzept + +Ein hilfreiches Kernmodell ist die sogenannte Share-Grenze. + +Die Share-Grenze ist der fachliche Einstiegspunkt, unterhalb dessen normale Folder-Hierarchie beginnt. + +Beispiele: + +- `\\server\share` -> Share-Grenze bei klassischem SMB-Share +- `\\server\namespace\link` -> Share-Grenze bei DFS-Link + +Ein Pfad wird damit nicht nur als `Share` oder `Folder` klassifiziert, sondern auch relativ zu seiner Share-Grenze verstanden. + +Das ist fuer mehrere Dinge wichtig: + +- korrektes Setzen von `ParentUID` +- konsistente Anzeige des Root-Objekts +- korrektes Nachladen von Kindern +- spaetere Berechtigungs- oder Traverselogik + +## Zielverhalten fuer typische Beispiele + +### Beispiel A: Klassische Freigabe + +- `\\filesrv\finance` -> `ClassicShare` +- `\\filesrv\finance\2026` -> `Folder` +- `\\filesrv\finance\2026\plan.xlsx` -> fuer LIAM ggf. ausserhalb des Scope, falls nur Ordner modelliert werden + +### Beispiel B: DFS-Namespace + +- `\\dfs01\file_shares` -> `DfsNamespaceRoot` +- `\\dfs01\file_shares\shareA` -> `DfsLink` +- `\\dfs01\file_shares\shareA\team1` -> `Folder` + +### Beispiel C: Server-Root + +- `\\dfs01` -> `ServerRoot` +- Kind `\\dfs01\file_shares` -> `DfsNamespaceRoot` +- Kind `\\dfs01\public` -> `ClassicShare` + +### Beispiel D: Gemischte Landschaft + +Ein Server kann gleichzeitig hosten: + +- klassische Shares +- DFS-Namespaces +- administrative Shares + +Die Enumeration unter `\\server` muss daher bewusst entscheiden, welche publizierten Namensobjekte sichtbar gemacht werden und welche nicht. + +## Konsequenzen fuer die LIAM-Architektur + +### 1. Eine gemeinsame Path-Classification-Schicht + +Die Logik darf nicht in mehreren Stellen verteilt bleiben. + +Stattdessen sollte es eine zentrale Schicht geben, die: + +- Pfade klassifiziert +- Kindobjekte enumeriert +- die Share-Grenze mitliefert +- Diagnoseinformationen fuer Logging bereitstellt + +### 2. `LoadDataArea()` und `getDataAreasAsync()` muessen dieselbe Semantik teilen + +Beide Methoden muessen dieselbe Klassifikation verwenden. + +Sonst entsteht wieder ein Fehlerbild wie heute: + +- Listenansicht liefert einen Typ +- Einzelaufladung liefert einen anderen Typ + +Das ist fachlich unzulaessig. + +### 3. Die Konstruktion von LIAM-Datenobjekten muss auf Klassifikation folgen + +Nicht: + +- Pfadtiefe bestimmen +- direkt `cLiamNtfsShare` oder `cLiamNtfsFolder` erzeugen + +Sondern: + +1. Pfad klassifizieren +2. daraus internes `Kind` bestimmen +3. danach passendes LIAM-Objekt erzeugen + +### 4. Nach aussen kann die API zunaechst kompatibel bleiben + +Wenn eine API-Aenderung vermieden werden soll, koennen intern mehrere Arten von Share-artigen Objekten existieren, die nach aussen zunaechst auf `NtfsShare` gemappt werden. + +Beispiel: + +- `ClassicShare` -> `NtfsShare` +- `DfsLink` -> `NtfsShare` +- `DfsNamespaceRoot` -> je nach Entscheidung ebenfalls `NtfsShare` oder eigener Typ spaeter + +So laesst sich die Semantik verbessern, ohne sofort alle Konsumenten anpassen zu muessen. + +## Technische Grenzen und Realitaet + +Die sichere Ermittlung ist programmatisch grundsaetzlich moeglich, aber an Infrastrukturbedingungen gebunden. + +Moegliche Einschraenkungen: + +- fehlende Rechte fuer Share- oder DFS-Abfragen +- Firewall- oder RPC-Beschraenkungen +- temporaer nicht verfuegbare Server +- unterschiedliche Betriebsweisen in der Kundenumgebung + +Deshalb ist ein kontrollierter Unsicherheitszustand wichtig. + +Empfohlene Regel: + +- wenn die Semantik sicher ermittelt werden kann, klaren Typ liefern +- wenn die Semantik nicht sicher ermittelt werden kann, `Unknown` oder einen expliziten diagnostischen Fehler liefern +- nicht stillschweigend auf reine Pfadtiefe zurueckfallen, wenn dadurch fachlich falsche Typen entstehen + +## Empfohlene Implementierungsstrategie in Etappen + +### Etappe 1: Fachmodell einziehen + +Intern neue Klassifikationsarten definieren: + +- `ServerRoot` +- `ClassicShare` +- `DfsNamespaceRoot` +- `DfsLink` +- `Folder` +- `Unknown` + +### Etappe 2: Zentrale Klassifikationskomponente bauen + +Eine zentrale Komponente einfuehren, die: + +- Pfade normalisiert +- Typen klassifiziert +- Share-Grenzen bestimmt +- Kinder kontextabhaengig enumeriert + +### Etappe 3: `LoadDataArea()` umstellen + +`LoadDataArea()` sollte zuerst die neue Klassifikation verwenden, weil dort der heutige Fehlpfad am deutlichsten sichtbar ist. + +### Etappe 4: `getDataAreasAsync()` umstellen + +Danach den Listenpfad auf dieselbe Klassifikation bringen. + +### Etappe 5: API-Mapping pruefen + +Danach bewerten: + +- reicht extern weiter `NtfsShare` / `NtfsFolder` +- oder wird spaeter ein eigener Typ fuer Namespace-Container benoetigt + +## Entscheidungspunkte, die fachlich geklaert werden muessen + +Vor einer spaeteren Implementierung sollten einige Punkte explizit entschieden werden: + +- Soll `\\server` als sichtbares DataArea-Objekt existieren oder nur als Enumerationsroot? +- Soll ein DFS-Namespace-Root nach aussen als `NtfsShare` gelten oder als eigener Container? +- Sollen nur DFS-Links als Share-aehnliche Objekte gelten? +- Sollen administrative Shares immer ausgeblendet werden? +- Wie soll sich das System bei fehlenden Rechten fuer DFS-/Share-Abfragen verhalten? + +Ohne diese Entscheidungen wird die technische Umsetzung sonst schnell inkonsistent. + +## Fazit + +Die bisherige Heuristik "Pfadtiefe bestimmt Share oder Folder" ist fuer eine Umgebung mit klassischen Shares, DFS und kuenftigem `\\server`-Root nicht ausreichend. + +Das richtige Zielbild ist: + +- zentrale semantische Pfadklassifikation +- Unterscheidung von Server, klassischem Share, DFS-Namespace, DFS-Link und Folder +- gemeinsame Logik fuer Listen- und Einzel-Ladepfad +- externe Rueckgabe weiterhin kompatibel, intern aber fachlich korrekt modelliert + +Nur mit diesem Ansatz koennen spaeter sowohl klassische Freigaben als auch DFS-Strukturen sauber und nachvollziehbar behandelt werden.