docs: rewrite documentation and README from current codebase, add flaw analysis
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
Remove outdated claims (CRDT, DocRooms, presence, .md files on disk) and document the actual architecture, API, permissions and known flaws. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e9c4ffa8c
commit
bc13235da6
14 files changed
+733
-1618
No files matched your search
@@ -1,96 +1,55 @@
|
||||
# 👥 Synchrones Teilen & Berechtigungskonzept
|
||||
# Teilen & Berechtigungen
|
||||
|
||||
MindSift bietet ein mehrstufiges Kollaborations- und Freigabesystem. Es gewährleistet strikte Datensouveränität und Privatsphäre, ermöglicht aber gleichzeitig reibungslose Zusammenarbeit in Teams, Familien oder Unternehmen.
|
||||
## Rollen
|
||||
|
||||
---
|
||||
| Ebene | Werte | Bedeutung |
|
||||
|---|---|---|
|
||||
| Server | `admin`, `member` | Admins verwalten Benutzer, Einladungen und Einstellungen (`/admin/*`). |
|
||||
| Gruppe | `admin`, `member` | Gruppen-Admins ändern/löschen die Gruppe und verwalten Mitglieder. Wer eine Gruppe anlegt, wird Admin. |
|
||||
| Ressource | siehe unten | Eigentümer, Bearbeiter, Leser. |
|
||||
|
||||
## 🛡️ 1. Globale Rollen & System-Isolation
|
||||
## Berechtigungen je Ressource
|
||||
|
||||
### Globale Rollen
|
||||
- **Server-Admin (`role = 'admin'`):** Vollzugriff auf System-Einstellungen, E-Mail-Konfiguration (SMTP), Benutzerverwaltung, Einladungscodes und System-Statistiken.
|
||||
- **Mitglied (`role = 'member'`):** Regulärer Benutzer; arbeitet in seinen eigenen Notizen, Aufgaben und freigegebenen Teams.
|
||||
| Ressource | Eigentümer | Bearbeiter | Leser | Freigabe an |
|
||||
|---|---|---|---|---|
|
||||
| **Aufgabenliste** (`task_list_shares.permission`) | alles, löschen, (un)teilen | Aufgaben anlegen/ändern/abhaken/verschieben/löschen, Liste umbenennen, Spalten ändern | nur ansehen | Benutzer, Gruppen |
|
||||
| **Geteilte Liste** (`list_shares.role`) | alles, löschen, (un)teilen | Einträge anlegen/ändern/abhaken/löschen | nur ansehen | Benutzer, Gruppen |
|
||||
| **Notiz** (`doc_shares`, `doc_team_shares`) | schreiben | – | nur lesen | Benutzer, Gruppen |
|
||||
| **Geteilter Ordner** (`workspace_folder_shares`) | schreiben | – | nur lesen | Benutzer, Gruppen |
|
||||
|
||||
### System-Isolations-Modi (`sharing_mode`)
|
||||
Der Server-Admin legt global fest, wie Benutzer miteinander interagieren dürfen:
|
||||
- **Notizen und Ordner sind absichtlich schreibgeschützt für Empfänger.** Das erzwingt eine Migration beim Start (`permission = 'read'`); Schreibpfade im Code sind tot ([FLAW-17](flaws.md)).
|
||||
- Bei Aufgabenlisten und Listen gilt: Hat jemand mehrere Zugriffswege (direkt und über Gruppen), zählt die **höchste** Stufe.
|
||||
- Für Gruppen gilt die Freigabe für alle aktuellen und künftigen Mitglieder.
|
||||
- Aufgabenlisten besitzen zusätzlich das Altfeld `team_id`: Mitglieder dieser Gruppe haben ohne Freigabezeile Bearbeiterrechte. Eine Gruppenfreigabe über den Dialog setzt `team_id`, falls es noch leer ist.
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────────────┐
|
||||
│ System-Isolations-Modi │
|
||||
├──────────────────────┬─────────────────────────┬───────────────────────┤
|
||||
│ strict_private │ teams_only │ open │
|
||||
│ (Strikt Isoliert) │ (Teams & Gruppen) │ (Offene Instanz) │
|
||||
│ │ [EMPFOHLENER STANDARD]│ │
|
||||
├──────────────────────┼─────────────────────────┼───────────────────────┤
|
||||
│ Kein Adressbuch │ Adressbuch zeigt nur │ Alle Benutzer sehen │
|
||||
│ Keine Freigaben │ gemeinsame Teammit- │ alle anderen Konten │
|
||||
│ Autarke Einzel-Instanz│ glieder │ im System │
|
||||
└──────────────────────┴─────────────────────────┴───────────────────────┘
|
||||
```
|
||||
## Aufgabenlisten teilen (Details)
|
||||
|
||||
1. **`strict_private`:** Vollständige Abschottung. Benutzer wissen nicht voneinander. Keine Freigaben möglich.
|
||||
2. **`teams_only` (Standard):** Kollaboration ist strikt an Gruppen gebunden. Ein Benutzer kann Objekte nur mit Personen teilen, die mindestens in einer gemeinsamen Gruppe/Team mit ihm sind.
|
||||
3. **`open`:** Geeignet für Familien oder kleine Firmen. Jeder Benutzer kann für jeden anderen Benutzer Objekte freigeben.
|
||||
1. Eigentümer öffnet „Teilen“ an der Liste, wählt Gruppe oder Benutzer und die Stufe **Bearbeiten** oder **Nur Lesen**.
|
||||
2. `POST /task-lists/{id}/shares` speichert `permission`; erneutes Hinzufügen desselben Ziels ändert die Stufe.
|
||||
3. `GET /task-lists` liefert je Liste `permission` (`owner`/`editor`/`viewer`). Das Frontend blendet für `viewer` alle Eingabemöglichkeiten aus und zeigt „Nur Lesen“.
|
||||
4. Der Server prüft unabhängig davon jeden Schreibzugriff (`403`, `storage.ErrTaskListReadOnly`).
|
||||
|
||||
---
|
||||
Bestehende Freigaben aus der Zeit vor dieser Stufe wurden mit `editor` migriert, behalten also ihr Verhalten.
|
||||
|
||||
## 🏢 2. Gruppen & Teams (`teams` & `team_members`)
|
||||
## Isolations-Modi (`system_settings.sharing_mode`)
|
||||
|
||||
Gruppen strukturieren Benutzer (z.B. „Familie", „Entwicklung", „Marketing"):
|
||||
- **Gruppen-Admin:** Darf Mitglieder einladen, Rollen ändern oder die Gruppe löschen.
|
||||
- **Gruppen-Mitglied:** Hat Zugriff auf alle mit der Gruppe geteilten Ressourcen (Ordner, Aufgabenlisten, Einkaufslisten, Notizen).
|
||||
Werte: `strict_private`, `teams_only` (Standard), `open`. Gedacht ist:
|
||||
|
||||
Wird eine Ressource für eine Gruppe freigegeben, erhalten **alle aktuellen und zukünftigen Mitglieder** der Gruppe automatisch Zugriff, ohne dass Einzelberechtigungen gepflegt werden müssen.
|
||||
| Modus | Zweck |
|
||||
|---|---|
|
||||
| `strict_private` | Keine Sichtbarkeit zwischen Benutzern |
|
||||
| `teams_only` | Freigaben nur zwischen Mitgliedern gemeinsamer Gruppen |
|
||||
| `open` | Jeder kann für jeden freigeben |
|
||||
|
||||
---
|
||||
**Tatsächlich** wird der Modus nur in `GetDiscoverableUsers` ausgewertet, und dort liefert `teams_only` bereits alle Benutzer. `GET /collaborators` ignoriert den Modus, und keine Freigabe-Funktion prüft ihn. Die Einstellung hat derzeit also kaum Wirkung ([FLAW-10](flaws.md)).
|
||||
|
||||
## 📁 3. Entkoppelte Ordner-Freigabe (Decoupled Folder Mounts)
|
||||
## Entkoppelte Ablage geteilter Notizen und Ordner
|
||||
|
||||
### Das traditionelle Problem
|
||||
In herkömmlichen Cloud-Systemen (wie Google Drive oder Nextcloud) führt das Verschieben eines geteilten Ordners oft dazu, dass er auch bei allen anderen Teilnehmern den Platz wechselt. Verschiebt ein Kollege den Ordner in sein Unterverzeichnis „Archiv", verschwindet er beim Ersteller aus dem Sichtfeld.
|
||||
- **Geteilte Ordner:** Der Ordner existiert einmal (`workspace_shared_folders`); jeder Empfänger hat seinen eigenen Einhängepfad (`workspace_folder_mounts.mount_path`). Verschiebt ein Empfänger den Ordner, ändert sich nur sein Pfad. Der Unterpfad innerhalb des Ordners (`documents.sub_folder_path`) gilt für alle.
|
||||
- **Einzelne Notizen:** Jeder Empfänger kann eine geteilte Notiz in einen eigenen Ordner legen (`doc_user_folders`); die Notiz des Eigentümers bleibt unberührt.
|
||||
|
||||
### Die MindSift-Lösung: Unabhängige Einhängepunkte (Mounts)
|
||||
MindSift entkoppelt die physische Ordner-Identität von der persönlichen Ordner-Hierarchie des Benutzers:
|
||||
## Sitzungen und Zugriff
|
||||
|
||||
```
|
||||
Eigentümer (Alice):
|
||||
Ordner: "Kundenprojekte"
|
||||
└── Geteilter Ordner: "Projekt Phoenix" (wsf_123)
|
||||
├── spec.md
|
||||
└── roadmap.md
|
||||
|
||||
Empfänger (Bob):
|
||||
Ordner: "Meine Aufgaben"
|
||||
└── "Wichtiges"
|
||||
└── Einhängepunkt: "Projekt Phoenix" (wsf_123 eingehängt via mount_path)
|
||||
├── spec.md
|
||||
└── roadmap.md
|
||||
```
|
||||
|
||||
#### Wie es technisch funktioniert:
|
||||
1. Der geteilte Ordner existiert als Entität in `workspace_shared_folders`.
|
||||
2. Beim Eigentümer liegt der Ordner unter seinem Pfad.
|
||||
3. Jeder Empfänger erhält in `workspace_folder_mounts` seinen **eigenen lokalen `mount_path`**.
|
||||
4. **Unabhängiges Verschieben:** Schiebt Bob den Ordner an eine andere Stelle in seinem Dateibaum, wird **ausschließlich sein persönlicher `mount_path`** aktualisiert. Alice und andere Teammitglieder bemerken davon nichts.
|
||||
5. **Inhaltliche Synchronisation:** Verschiebt, erstellt oder bearbeitet jemand eine Notiz *innerhalb* des geteilten Ordners, wird der relative Unterpfad (`sub_folder_path`) synchronisiert, sodass alle dieselbe interne Dokumentstruktur sehen.
|
||||
|
||||
---
|
||||
|
||||
## 📄 4. Entkoppelte Notizen-Freigabe (`doc_user_folders`)
|
||||
|
||||
Dasselbe Prinzip gilt für einzeln geteilte Dokumente:
|
||||
- Erhält Benutzer Bob eine einzelne Notiz von Alice freigegeben, kann Bob diese Notiz in jeden beliebigen seiner eigenen Ordner einsortieren.
|
||||
- Seine persönliche Zuordnung wird in der Tabelle `doc_user_folders` (`user_id`, `doc_id`, `folder_path`) gespeichert.
|
||||
- Die Original-Notiz von Alice verbleibt an ihrem ursprünglichen Platz.
|
||||
|
||||
---
|
||||
|
||||
## 📋 5. Geteilte Aufgaben- & Einkaufslisten
|
||||
|
||||
- **Aufgabenlisten (`task_list_shares`):** Freigabe für Teams oder Einzelbenutzer, Spalte `permission`:
|
||||
- `editor`: Aufgaben anlegen, bearbeiten, abhaken, verschieben und löschen; Liste umbenennen und Spalten anpassen.
|
||||
- `viewer`: Nur Lesezugriff. Der Server lehnt Schreibzugriffe mit `403` ab (`storage.ErrTaskListReadOnly`).
|
||||
- Hat ein Benutzer über mehrere Wege Zugriff (direkt und über Gruppen), gilt die höchste Berechtigung.
|
||||
- **Geteilte Listen (`list_shares`):**
|
||||
- Rolle `editor`: Einträge hinzufügen, ändern, abhaken und löschen.
|
||||
- Rolle `viewer`: Nur Lesezugriff (Echtzeit-Ansicht).
|
||||
- **Einheitlicher Freigabe-Dialog:** [`UnifiedShareModal.tsx`](../../frontend/src/components/UnifiedShareModal.tsx) bündelt alle Freigabeoptionen (Teams, Benutzer, Berechtigungsstufen) in einer konsistenten Benutzeroberfläche.
|
||||
- Tokens werden bei Passwortänderung, Rollenwechsel, Deaktivierung und „Alle Sitzungen beenden“ ungültig (`token_version`); ausgeloggte Tokens landen in `revoked_tokens`.
|
||||
- Registrierung nur per Einladungscode oder, wenn vom Admin freigeschaltet, offen. Das erste Konto wird immer Administrator.
|
||||
- Bekannte Lücken in der Zugriffskontrolle: [FLAW-01](flaws.md), [FLAW-02](flaws.md), [FLAW-03](flaws.md), [FLAW-06](flaws.md), [FLAW-07](flaws.md), [FLAW-08](flaws.md), [FLAW-24](flaws.md).
|
||||
Reference in new issue
Block a user