Files
archivmail/features/PROJ-9-ordner-und-labels.md
T
sysops d360c9a5ba feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg)
- Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist
- Feature-Status auf In Review gesetzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 11:43:19 +01:00

5.6 KiB
Raw Blame History

PROJ-9: Ordner- & Label-Verwaltung

Status: In Progress

Created: 2026-03-12 Last Updated: 2026-03-12

Dependencies

  • Requires: PROJ-1 (Authentifizierung)
  • Requires: PROJ-5 (Speicherung & Indexierung)

User Stories

  • Als Nutzer möchte ich E-Mails mit Labels versehen, damit ich sie thematisch organisieren kann.
  • Als Admin möchte ich globale Labels definieren, die automatisch beim Import vergeben werden (z.B. nach Absender-Domain oder Import-Quelle).
  • Als Nutzer möchte ich meine Suchergebnisse auf ein bestimmtes Label einschränken.
  • Als Nutzer möchte ich Labels erstellen, umbenennen und löschen.

Acceptance Criteria

  • Nutzer können Labels erstellen (Name, Farbe)
  • E-Mails können mit mehreren Labels versehen werden
  • Label-Filter in der Suche verfügbar
  • Keine IMAP-Ordnerstruktur das System ist ein Archiv, keine Ordnerhierarchie wird übernommen
  • Admin kann Regeln für automatische Label-Vergabe beim Import definieren (z.B. nach Absender-Domain)
  • Admin kann globale Labels definieren (für alle Nutzer sichtbar)
  • Löschen eines Labels entfernt es von allen E-Mails, löscht E-Mails nicht
  • Label-Übersicht in der Seitenleiste mit E-Mail-Anzahl pro Label

Edge Cases

  • Label-Name bereits vergeben → Fehlermeldung
  • E-Mail wird gelöscht aber Labels bleiben → Labels bleiben erhalten, E-Mail-Referenz entfernt
  • Sehr viele Labels (> 100) → Suchfeld in der Label-Auswahl

Technical Requirements

  • Labels: n:m-Beziehung zwischen E-Mails und Labels
  • Performance: Label-Filter darf Suchantwortzeit nicht verdoppeln

Tech Design (Solution Architect)

Komponentenstruktur

Next.js Frontend:

Seitenleiste (global, alle Seiten)
└── LabelList
    ├── Label-Eintrag (Name, Farbe, Anzahl)  ← klickbar → filtert Suche
    ├── [+ Label erstellen] Button
    └── Suchfeld (bei > 10 Labels)

Label-Verwaltung (Inline / Modal)
├── LabelForm
│   ├── Name (Textfeld)
│   └── Farbe (Color-Picker, 8 Vorschläge)
└── LabelItem-Aktionen
    ├── Umbenennen
    └── Löschen (mit Bestätigung)

E-Mail-Ansicht (PROJ-7, Erweiterung)
└── LabelPicker
    ├── Aktuelle Labels der Mail (als Badges)
    ├── Dropdown: Labels hinzufügen/entfernen
    └── [+ Neues Label] Shortcut

Admin-Bereich (/admin/labels)
├── Globale Labels verwalten
└── Auto-Label-Regeln
    ├── RegelListe
    └── RegelForm
        ├── Bedingung: from-Domain / Import-Quelle / Betreff enthält
        └── Aktion: Label zuweisen

Go Backend:

Label-API
├── GET    /api/labels              ← alle Labels des Nutzers + globale
├── POST   /api/labels              ← neues Label anlegen
├── PATCH  /api/labels/{id}         ← umbenennen / Farbe ändern
├── DELETE /api/labels/{id}         ← löschen (entfernt von allen Mails)
├── POST   /api/mails/{id}/labels   ← Label einer Mail zuweisen
└── DELETE /api/mails/{id}/labels/{label_id} ← Label entfernen

Admin Label-API
├── POST   /api/admin/labels        ← globales Label anlegen
├── GET    /api/admin/label-rules   ← Auto-Label-Regeln
├── POST   /api/admin/label-rules   ← Regel anlegen
└── DELETE /api/admin/label-rules/{id}

Label-Filter in Suche (Erweiterung PROJ-6)
└── Xapian-Term "label:<label_id>" pro Mail
    → Label-Filter läuft direkt in Xapian

Datenmodell

Tabelle labels:

Feld Beschreibung
id Interne ID
name Label-Name (eindeutig pro Nutzer)
color Hex-Farbe (z.B. #e74c3c)
owner_id Nutzer-ID (NULL = globales Admin-Label)
created_at Erstellungszeitpunkt

Tabelle email_labels n:m Verknüpfung:

Feld Beschreibung
email_id Referenz auf emails
label_id Referenz auf labels
assigned_at Zeitpunkt der Zuweisung
assigned_by user / auto-rule / import

Tabelle label_rules Auto-Label beim Import:

Feld Beschreibung
id Interne ID
condition_field from_domain / source / subject_contains
condition_value z.B. example.com oder imap-account-1
label_id Welches Label vergeben

Label-Filter in Xapian

Beim Indexieren einer Mail werden ihre Labels als Xapian-Terms gespeichert:

Label "Kunde"   → Term: "label:42"
Label "Projekt" → Term: "label:17"

Suche mit Label-Filter läuft vollständig in Xapian kein zusätzlicher DB-Join nötig. Labels werden beim Zuweisen/Entfernen sofort im Xapian-Dokument aktualisiert.

Technische Entscheidungen

Entscheidung Begründung
Labels statt Ordner Archiv hat keine Hierarchie eine Mail kann mehrere Labels haben, aber nicht in mehreren Ordnern gleichzeitig sein
Label-Terms in Xapian Filter läuft direkt bei der Suche kein nachträglicher DB-Join, keine Verdopplung der Antwortzeit
Globale Labels (owner_id NULL) Admin definiert unternehmensweite Labels Nutzer können sie nicht löschen, nur zuweisen
Auto-Label-Regeln Importierte Mails werden sofort kategorisiert kein manueller Aufwand für Bulk-Importe
assigned_by-Feld Nachvollziehbar ob Label manuell, per Regel oder beim Import vergeben wurde

Abhängigkeiten

Next.js Frontend:

Paket Zweck
shadcn/ui Badge, Popover, Color-Picker-Basis (bereits installiert)

Go Backend: Nur Stdlib + pgx (bereits vorhanden).

QA Test Results

To be added by /qa

Deployment

To be added by /deploy