# 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<PathClassification>
```

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.
