Skip to content

DMS — Konzept "Beste DMS in Wirtschaft & Schulwelt"

Status: Konzept v1 (2026-05-03). Vorbereitet als Grundlage für die Reparatur + den großen Umbau am 03.05.

Ziel: Aus dem heutigen DMS (Tag-System mit 4 Ansichten) ein State-of-the-Art-DMS machen, das in beiden Märkten — Schulen und mittelständischer Wirtschaft — den Standard setzt. Inspiriert von M-Files (Metadata-First), DocuWare (Workflow + IDP), ELO (Compliance), Paperless-ngx (UX), Folderit/Box (Smart Folders).


0. Sofort-Reparatur (vor jedem Feature-Bau)

BugFix
🔴 Upload kaputt auf jeder Tenant-Box (SignatureDoesNotMatch)Agent-Update + nginx-Rewrite, Code committed (siehe project_dms_morgen.md)
🔴 DMS-Hub öffnet Mein FachDMS-Welt-Icon (Hub) navigiert auf neue Route /dms (institutionelles DMS), Mein Fach bleibt auf /mein-fach (Top-Bar Inbox-Icon)
🟡 "Mein Fach (DMS)"-Naming verwirrendIm Apps-Settings rename "DMS & Mein Fach" → "Mein Fach" (rein persönlich); neuer App-Eintrag "Dokumenten-Management" für die institutionelle Sicht

Routing-Klärung:

  • /dms → Institutionelles DMS (Cross-Space, Tenant-weit, alle Dokumente die ich sehen darf)
  • /mein-fach → Persönliches Fach (PERSONAL + INBOX scope)
  • /spaces/:id/files → Space-DMS (innerhalb eines Spaces)
  • Alle drei Sichten teilen sich das Document-Modell, unterscheiden sich nur im Filter.

1. Was die Besten haben — Feature-Recherche

M-Files — Metadata-First

  • "Find by what it is, not where it's filed" — kein Folder-Zwang
  • Vault-Konzept mit Klassen (Invoice, Contract, Report, ...)
  • AI-gestützte Metadaten-Vorschläge (Intelligent Metadata Layer)
  • Federated: zeigt Inhalte aus SharePoint/GDrive ohne Migration
  • Beziehungen zwischen Docs ("dieses Dokument gehört zu diesem Projekt + diesem Kunden")

DocuWare — Workflow + IDP

  • Drag-and-Drop Workflow-Designer für mehrstufige Freigaben
  • Intelligent Document Processing: AI liest gescannte Dokumente, extrahiert Felder
  • Rechnung kommt rein → AI weiß: Lieferant + Betrag + Fälligkeitsdatum → Workflow startet
  • Native E-Signatur
  • E-Mail-Integration (Outlook plugin)

ELO Digital Office

  • Auto-Indexierung beim Import
  • Records Management mit Aufbewahrungsfristen + Legal Hold
  • Vollständige Audit-Trail-Kette

Paperless-ngx (Open Source)

  • Nested Tags (Hierarchie max. 5 tief, Auto-Inheritance)
  • Custom Fields pro Dokument-Typ
  • Correspondents + Document Types als zweite Ordnungsachse neben Tags
  • Auto-Lernen: System merkt sich Tag-Vorschläge basierend auf bisherigen Zuordnungen
  • OCR + Volltextsuche (Tika + ngx)
  • Flach-strukturiert, keine klassischen Ordner

Folderit / Box / SharePoint

  • Smart Folders: dasselbe Dokument erscheint in mehreren Sichten (Projekt-Ordner UND Kunden-Ordner UND Jahres-Ordner)
  • Saved Searches als virtuelle Ordner
  • Public-Share-Links mit Expiry, Passwort, Watermark

Schul-Spezifika (DSGVO, DSchVO NRW)

  • Aufbewahrungsfristen: 5 Jahre für die meisten Schülerdaten, 50 Jahre für Abschlusszeugnis-Duplikate
  • Pflicht zur Löschung nach Ablauf (Storing beyond retention = unrechtmäßig)
  • Pflicht zur Übergabe ans Archiv vor Vernichtung
  • Schulrechtliche Akten-Klassen (BASS NRW): Schülerakte, Klassenakte, Personalakte, Verwaltungsakte
  • §8a SGB VIII Kinderschutz: 10 Jahre, Vier-Augen-Prinzip

Wirtschaft-Spezifika

  • Vertragsmanagement mit Kündigungsfristen-Reminder
  • Rechnungseingangs-Workflow mit AI-OCR
  • HR-Akten mit Personal-Datenschutz
  • Projekte mit Cross-Referenzen
  • §147 AO (Steuer): 6/8/10 Jahre für Geschäftsunterlagen

2. Unsere Architektur — Konsolidiert

Existierende Bausteine (live):

  • ✅ Document-Modell mit DocumentScope (PERSONAL / SPACE / GLOBAL / INBOX)
  • ✅ Per-Tenant S3 (AES-256-GCM verschlüsselte Credentials)
  • ✅ Volltextsuche (Postgres tsvector, deutsch)
  • ✅ Tag-System (DocumentTag join table)
  • ✅ Versionierung (parentId + version)
  • ✅ Soft-Delete + Restore + Star + Lock
  • ✅ Audit-Log
  • ✅ ClamAV
  • ✅ Postfach (INBOX) + Verteiler-Drop
  • ✅ Chat-Anhänge wandern direkt ins DMS
  • prilog://file/<id> Internen-Link-Schema mit Resolver
  • ✅ Vier Ansichten: Liste / Kacheln / Ordner / Zeitstrom

Was fehlt für State-of-the-Art:

  1. Mehrere Ordner-Hierarchien ("Multiple folder systems")
  2. Smart Folders / Saved Searches als virtuelle Ordner
  3. Custom Fields pro Document Type (z.B. Rechnung: Lieferant, Betrag, Fälligkeit)
  4. Document Types als Klassifikation (Vertrag, Rechnung, Schülerakte, ...)
  5. Verschachtelte Tags (Hierarchie wie Paperless-ngx)
  6. OCR für gescannte PDFs + Bilder
  7. Auto-Klassifikation (AI-gestützte Tag/Type-Vorschläge)
  8. Aufbewahrungsfristen (Retention Policies) mit Auto-Aktion
  9. Legal Hold (sperrt Doc auch gegen Retention-Löschung)
  10. Workflow-Engine über Dokumente (Freigabe-Ketten) — wir haben Flow-Designer, müssen ihn ans DMS andocken
  11. E-Signatur (digital signing)
  12. Public-Share-Links mit Expiry + Watermark
  13. WebDAV-Mount (oder Desktop-Sync — Konzept existiert)
  14. Office-Integration (Word/Excel direct edit) — Tiptap haben wir, MS-Office wäre Bonus
  15. E-Mail-zu-DMS (Mail an spezielle Adresse → wandert ins DMS)
  16. Vorlagen-Bibliothek (Templates)
  17. Annotationen auf PDFs (Kommentare in/an Dokumenten)
  18. Beziehungen zwischen Dokumenten ("gehört zu Projekt X" + "gehört zu Kunde Y")

3. Architektur-Entscheidungen

3.1 Klassifikation — die drei Achsen

                     ┌──────────────────────────┐
                     │   Ein Dokument            │
                     └──────────────────────────┘

        ┌───────────────────────┼───────────────────────┐
        │                       │                       │
   1. Document-Type         2. Tags (n)            3. Folder-Refs (n)
   (was es IST)             (Schlagwörter)         (wo es HÄNGT)
   z.B. "Vertrag"           "wichtig", "2026"      verschiedene Ordner-
                                                    hierarchien

Ergebnis: Ein Dokument kann gleichzeitig

  • ein Document-Type sein (Vertrag, Rechnung, Schülerakte, ...) — exklusiv
  • mehrere Tags haben (verschachtelt, wie Paperless-ngx)
  • in mehreren Ordnern in mehreren parallelen Ordner-Bäumen sein

3.2 Mehrere Ordner-Hierarchien — der Kern-Twist

Problem: Schule will Akten nach Klasse sortiert und nach Akten-Typ und nach Schuljahr sehen. Wirtschaft will nach Projekt und nach Kunde und nach Dokument-Typ sehen.

Lösung: Multiple Folder Systems — der Tenant-Admin definiert pro Tenant beliebig viele Ordner-Hierarchien (Folder-Trees). Jede Hierarchie ist ein eigener Baum mit eigener Bedeutung.

Beispiel Schule:

  • Hierarchie "Schuljahr": 2025-26 → Klasse 7b → Lukas Meier
  • Hierarchie "Akten-Art": Schülerakten → Anmeldungen / Zeugnisse / Bescheinigungen
  • Hierarchie "Verwaltung": Personal / Finanzen / Verträge / Beschwerden

Beispiel Wirtschaft:

  • Hierarchie "Kunde": Acme GmbH → Verträge / Rechnungen
  • Hierarchie "Projekt": Projekt-X → Phase 1 / Phase 2
  • Hierarchie "Jahr": 2026 → Q1 / Q2 / ...

Ein Dokument hängt gleichzeitig in mehreren Ordnern aus unterschiedlichen Hierarchien. Verschieben in einer Hierarchie ändert nichts an den anderen.

3.3 Smart Folders / Saved Searches

Eine "Saved Search" ist ein gespeicherter Filter, der wie ein Ordner aussieht. Beispiele:

  • "Alle ungelesenen Rechnungen über 10.000 €"
  • "Verträge mit Kündigungsfrist in den nächsten 30 Tagen"
  • "Schülerakten Klasse 7b — Schuljahr 2025-26"

Smart Folders erscheinen in der Sidebar wie normale Ordner, sind aber dynamisch. User kann sie personal oder shared anlegen.

3.4 Document Types + Custom Fields

Tenant-Admin definiert Document Types mit zugehörigen Custom Fields:

yaml
DocumentType: "Schülerakte"
  fields:
    - schuelerName: text, required
    - klasse: text, required
    - schuljahr: select [2025-26, 2024-25, ...]
    - akteArt: select [Anmeldung, Zeugnis, Bescheinigung]
    - aufbewahrungBis: date  # auto-berechnet aus akteArt
  retentionPolicy: "schule-schuelerakte"  # verweist auf Retention-Regel
yaml
DocumentType: "Rechnung"
  fields:
    - lieferant: text
    - rechnungsnummer: text, unique
    - betrag: money
    - faelligAm: date
    - bezahltAm: date, optional
  retentionPolicy: "ao-§147-10jahre"

Beim Upload kann der User einen Type wählen, OCR/AI macht Vorschläge.

yaml
RetentionPolicy "ao-§147-10jahre"
  duration: 10 years
  trigger: "rechnungsdatum"  # Custom-Field
  action_after: archive  # oder delete | shred | offer_to_archive
  legalHoldOverride: true

RetentionPolicy "schule-schuelerakte"
  duration: 5 years
  trigger: "schulaustritt"
  action_after: offer_to_archive  # wird dem Operator angeboten

RetentionPolicy "schule-zeugnis-duplikat"
  duration: 50 years  # BASS NRW

Legal Hold: Admin markiert ein Doc als "rechtlich gesperrt" → Retention-Aktion wird ignoriert. Audit-Log dokumentiert wer + warum.

3.6 Tags — verschachtelt mit Auto-Inheritance

Wie Paperless-ngx: Tag-Hierarchie max. 5 tief.

  • Verwaltung > Formulare > Anmeldung
  • Beim Setzen werden Eltern-Tags automatisch mitgesetzt
  • Beim Entfernen werden Kinder mit-entfernt

3.7 Beziehungen zwischen Dokumenten

yaml
Document A: Vertrag mit Acme GmbH
  relations:
    - { type: "BELONGS_TO", target: "Acme GmbH" (Contact) }
    - { type: "BELONGS_TO", target: "Projekt-X" (Document) }
    - { type: "RELATED_TO", target: Rechnung-2026-042 (Document) }
    - { type: "SUPERSEDES", target: Vertrag-2024-Acme }

Backend-Modell: neue Tabelle document_relations. Web-Client zeigt sie im Detail-Panel als verlinkte Karten.


4. UX — die "DMS-Hub"-Sicht

4.1 Navigation (linke Sidebar)

┌────────────────────────────┐
│  📁 DOKUMENTE              │
│  ├ ⭐ Favoriten             │
│  ├ 🕐 Zuletzt              │
│  ├ ⚡ Smart Folders         │
│  │  ├ Eingang heute        │
│  │  ├ Verträge < 30 Tage   │
│  │  └ + Neu anlegen        │
│  ├ 🗂 Ordnersysteme         │
│  │  ├ 📂 Schuljahr           │
│  │  │  ├ 2025-26           │
│  │  │  └ 2024-25           │
│  │  ├ 📂 Verwaltung         │
│  │  │  ├ Personal          │
│  │  │  └ Finanzen          │
│  │  └ + Hierarchie anlegen │
│  ├ 🏷 Tags                  │
│  │  ├ Wichtig (47)         │
│  │  ├ Klausur (12)         │
│  │  └ ...                  │
│  ├ 📋 Dokument-Typen        │
│  │  ├ Vertrag (8)          │
│  │  ├ Rechnung (24)        │
│  │  └ Schülerakte (143)    │
│  └ 🗑 Papierkorb            │
└────────────────────────────┘

4.2 Hauptbereich

┌──────────────────────────────────────────────────────────┐
│  [Toolbar: Hochladen] [Neu]  [⚙ Ansicht: Kacheln ▼]      │
│  [Suche                                              🔍] │
│  Filter: [Typ ▼] [Tag ▼] [Datum ▼] [Custom-Field ▼]      │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  Ergebnisse (47)                                         │
│  ┌──────┐ ┌──────┐ ┌──────┐                              │
│  │ Doc1 │ │ Doc2 │ │ Doc3 │  ...                         │
│  └──────┘ └──────┘ └──────┘                              │
│                                                          │
└──────────────────────────────────────────────────────────┘

4.3 Ansichten (4 bestehende + 1 neu)

  1. Liste (klassisch) — bleibt
  2. Kacheln mit Vorschau-Thumbnails (PDF-Page-1, Bilder, Office-Preview) — erweitern um echte Thumbnails
  3. Ordner — wird zur aktiv gewählten Ordner-Hierarchie ("Brille auf eine Hierarchie")
  4. Zeitstrom — bleibt
  5. NEU: Tabelle — wie Excel, mit Custom-Field-Spalten je Document-Type. Sortierbar, filterbar.

4.4 Detail-Panel (rechte Seite)

┌────────────────────────────────────────┐
│  Titel der Datei                       │
│  Typ: Schülerakte · v3 · 2.3 MB        │
├────────────────────────────────────────┤
│  Vorschau (PDF/Image/Text)             │
├────────────────────────────────────────┤
│  Aktionen:                             │
│  [Download] [🔗 Internen Link]          │
│  [✍ Bearbeiten] [📤 Teilen] [🗑]        │
├────────────────────────────────────────┤
│  Metadata:                             │
│  Schüler: Lukas Meier                  │
│  Klasse: 7b                            │
│  Aufbewahrung: bis 2031-08             │
├────────────────────────────────────────┤
│  Tags:                                 │
│  [Anmeldung] [2025-26] [+]             │
├────────────────────────────────────────┤
│  In Ordnern:                           │
│  📂 Schuljahr/2025-26/7b               │
│  📂 Akten-Art/Schülerakten/Anmeldung   │
│  [+ In weiteren Ordner ablegen]        │
├────────────────────────────────────────┤
│  Beziehungen:                          │
│  → gehört zu: Lukas Meier (Person)     │
│  → folgt auf: Anmeldung-2024.pdf       │
│  → verwandt: Zeugnis-7b-2025.pdf       │
├────────────────────────────────────────┤
│  Versionen (3) · Audit-Log (12)        │
│  Sicherheit · Aufbewahrung             │
└────────────────────────────────────────┘

5. Daten-Modell

5.1 Bestehend (bleibt)

  • Document — Kern-Modell
  • DocumentTag — Tags
  • Tag — Tag-Definition
  • InboxDropMeta — Postfach-Meta
  • Distribution — Verteiler

5.2 Neue Tabellen

prisma
// Mehrfache Ordnerhierarchien pro Tenant
model FolderTree {
  id           String  @id @default(cuid())
  tenantId     String
  name         String  // "Schuljahr", "Verwaltung", "Kunde"
  description  String?
  iconEmoji    String? // optional Visual
  sortOrder    Int     @default(0)
  createdBy    String
  createdAt    DateTime @default(now())

  folders      Folder[]

  @@index([tenantId])
}

// Ein Knoten in einer Hierarchie
model Folder {
  id           String  @id @default(cuid())
  tenantId     String
  treeId       String
  parentId     String?  // null = top-level
  name         String
  iconEmoji    String?
  sortOrder    Int     @default(0)
  createdBy    String
  createdAt    DateTime @default(now())

  tree         FolderTree @relation(fields: [treeId], references: [id], onDelete: Cascade)
  parent       Folder?    @relation("FolderHierarchy", fields: [parentId], references: [id], onDelete: Cascade)
  children     Folder[]   @relation("FolderHierarchy")
  placements   DocumentFolderPlacement[]

  @@index([tenantId, treeId])
  @@index([parentId])
}

// Many-to-many: ein Dokument in beliebig vielen Ordnern (auch ueber Trees hinweg)
model DocumentFolderPlacement {
  id           String  @id @default(cuid())
  documentId   String
  folderId     String
  placedBy     String
  placedAt     DateTime @default(now())

  document     Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
  folder       Folder   @relation(fields: [folderId], references: [id], onDelete: Cascade)

  @@unique([documentId, folderId])
  @@index([folderId])
}

// Verschachtelte Tags
model Tag {
  // bestehend, neu:
  parentId     String?  // null = top-level
  parent       Tag?     @relation("TagHierarchy", fields: [parentId], references: [id], onDelete: SetNull)
  children     Tag[]    @relation("TagHierarchy")
}

// Document Types
model DocumentType {
  id           String  @id @default(cuid())
  tenantId     String
  key          String  // "schuelerakte", "rechnung"
  label        String  // "Schülerakte"
  iconEmoji    String?
  description  String?
  retentionPolicyId String?
  fields       Json    // [{ key, label, type, required, options }]
  createdAt    DateTime @default(now())

  documents    Document[]

  @@unique([tenantId, key])
  @@index([tenantId])
}

// Document → Type
model Document {
  // bestehend, neu:
  documentTypeId  String?
  documentType    DocumentType? @relation(fields: [documentTypeId], references: [id])
  customFields    Json?  // { schuelerName: "Lukas", klasse: "7b", ... }
  retentionUntil  DateTime?  // berechnet aus DocumentType + customFields
  legalHold       Boolean  @default(false)
  legalHoldReason String?
  legalHoldBy     String?
  legalHoldAt     DateTime?
}

// Saved Searches / Smart Folders
model SavedSearch {
  id           String  @id @default(cuid())
  tenantId     String
  ownerUserId  String?  // null = shared
  name         String
  iconEmoji    String?
  query        Json     // { tags: [...], type: "...", customFields: {...}, dateRange: ..., scope: ... }
  sortOrder    Int     @default(0)
  createdAt    DateTime @default(now())

  @@index([tenantId])
}

// Beziehungen zwischen Dokumenten
model DocumentRelation {
  id           String  @id @default(cuid())
  fromId       String
  toId         String
  relationType String  // "BELONGS_TO" | "RELATED_TO" | "SUPERSEDES" | "PART_OF"
  createdBy    String
  createdAt    DateTime @default(now())

  from         Document @relation("RelationFrom", fields: [fromId], references: [id], onDelete: Cascade)
  to           Document @relation("RelationTo", fields: [toId], references: [id], onDelete: Cascade)

  @@unique([fromId, toId, relationType])
  @@index([fromId])
  @@index([toId])
}

// Retention Policies
model RetentionPolicy {
  id           String  @id @default(cuid())
  tenantId     String
  key          String
  label        String
  durationDays Int
  triggerField String?  // "rechnungsdatum", "schulaustritt", "createdAt"
  actionAfter  String   // "archive" | "delete" | "offer_to_archive"
  legalHoldOverride Boolean @default(true)
  createdAt    DateTime @default(now())

  documentTypes DocumentType[]

  @@unique([tenantId, key])
}

// Public Share Links
model PublicShareLink {
  id           String  @id @default(cuid())
  documentId   String
  slug         String   @unique  // 32-char random
  passwordHash String?
  expiresAt    DateTime?
  watermark    Boolean  @default(false)
  maxViews     Int?
  views        Int      @default(0)
  createdBy    String
  createdAt    DateTime @default(now())

  document     Document @relation(fields: [documentId], references: [id], onDelete: Cascade)

  @@index([slug])
  @@index([documentId])
}

// E-Signaturen (geplant Phase 4)
model DocumentSignature {
  id           String  @id @default(cuid())
  documentId   String
  signerUserId String
  signedAt     DateTime
  signatureHash String
  ipAddress    String?
  // ...
}

6. Phasenplan

Phase 0 — Reparatur (DAG 1, 2-3h)

  • ✅ Code committed (siehe project_dms_morgen.md)
  • 🟢 Agent-Update auf shared-Hosts → nginx-Rewrite → DB-Endpoint-Fix → Backend-Restart
  • 🟢 Routing: /dms neue Route, DMS-Hub-Welt zeigt institutionelles DMS, nicht Mein Fach

Acceptance: Upload funktioniert auf allen Tenants, DMS-Hub zeigt nicht Mein Fach.

Phase 1 — Mehrfache Ordnerhierarchien (Tag 1-2)

  • DB-Migration: folder_trees, folders, document_folder_placements
  • Backend-Endpoints: CRUD Trees + Folders, Drop-into-Folder, Read-by-Tree
  • Web-Client: Sidebar-Sektion "Ordnersysteme" mit dynamisch ladbaren Trees, Tree-Anlegen-Modal, Drag-and-Drop in Ordner
  • Settings → DMS → "Ordnersysteme" zum Anlegen / Verwalten

Acceptance: Admin legt Tree "Schuljahr" + "Akten-Art" an, Doc kann in beiden gleichzeitig liegen, Sidebar zeigt beides parallel.

Phase 2 — Verschachtelte Tags + Smart Folders (Tag 2-3)

  • DB-Migration: tags.parentId
  • Tag-Auto-Inheritance (Save Tag → Eltern-Tags rein, Remove → Kinder raus)
  • DB-Migration: saved_searches
  • Backend: CRUD Saved-Search + GET-Resolver (führt Query gegen Document aus)
  • Web-Client: "Smart Folders"-Sektion in Sidebar, "Aus aktueller Suche speichern"-Button

Acceptance: Tag-Tree mit 3 Ebenen, Save Search "Verträge < 30 Tage" speichert + erscheint in Sidebar.

Phase 3 — Document Types + Custom Fields (Tag 3-5)

  • DB-Migration: document_types, documents.documentTypeId, documents.customFields
  • Backend: CRUD Document-Types, Validation, Custom-Field-Filter im Search
  • Web-Client:
    • Settings → DMS → Document-Types (CRUD-UI mit Field-Designer)
    • Beim Upload: Type-Picker, danach Custom-Field-Form
    • Tabellen-Ansicht: Spalten = Custom-Fields des aktuellen Types
  • 2-3 Default-Types vorbereitet (Vertrag, Rechnung, Schülerakte) — als Vorlage importierbar

Acceptance: Admin legt Type "Schülerakte" mit 5 Feldern an, Upload zeigt Form, Tabellenansicht zeigt Spalten.

Phase 4 — Beziehungen + erweiterte Detail-Sicht (Tag 5-6)

  • DB-Migration: document_relations
  • Backend: CRUD Relations
  • Web-Client: Detail-Panel um "Beziehungen"-Sektion erweitern, Relation-Picker
  • Bidirektionale Anzeige (X gehört zu Y → Y wird auch in X gezeigt)

Acceptance: Vertrag verlinkt mit Kunden-Kontakt + Folge-Vertrag, Detail zeigt beide Richtungen.

  • DB-Migration: retention_policies, documents.retentionUntil + legalHold + legalHoldReason
  • Backend: Retention-Cron läuft täglich, prüft Docs deren retentionUntil < heute, führt actionAfter aus
  • Web-Client:
    • Settings → DMS → Retention-Policies
    • Doc-Detail zeigt "Aufbewahrung bis" + Legal-Hold-Toggle
    • Banner "Wird in 7 Tagen archiviert" für ablaufende Docs
  • Admin-UI: Liste auslaufender Docs mit Quick-Actions

Acceptance: Schul-Akte mit Schulaustritt → wird nach 5 Jahren automatisch archiviert. Legal Hold blockt Aktion.

  • DB-Migration: public_share_links
  • Backend:
    • POST /documents/:id/share — Slug + Passwort + Expiry generieren
    • GET /share/:slug — public route, ggf. Passwort-Form, dann Download/Preview
    • Watermark-Renderer (PDF mit Logo + Empfaenger-Email + Zeitstempel als Overlay)
  • Web-Client: "Teilen"-Modal im Detail-Panel
  • Audit: jeder Aufruf eines Public-Links wird geloggt

Acceptance: Doc geteilt mit 7-Tage-Expiry + Passwort, Externer öffnet ohne Login + Auto-Watermark mit IP.

Phase 7 — OCR + Auto-Klassifikation (Tag 8-10)

  • Tesseract-Integration auf Backend (Per-Tenant-Worker oder zentral)
  • Beim Upload: PDF/Image → OCR-Job in Queue → extrahierter Text in documents.content → tsvector aktualisiert
  • Auto-Type-Vorschlag: Klassifikator lernt aus bestehenden Zuordnungen (einfacher Naive-Bayes über Wort-Häufigkeit)
  • Custom-Field-Extraktion: Regex-Library pro DocumentType (z.B. Rechnung → IBAN, Betrag, Datum)

Acceptance: Gescannte PDF hochgeladen → 30s später durchsuchbar. Zweite Rechnung des gleichen Lieferanten → System schlägt Type "Rechnung" + Lieferant vor.

Phase 8 — Workflows ans DMS andocken (Tag 10-11)

  • Process-Engine bekommt neue Component-Kinds:
    • dms.upload — Wartet auf Upload eines Dokuments mit bestimmtem Type
    • dms.approve — Dokument zur Freigabe vorlegen, Stakeholder bestätigt/lehnt ab
    • dms.sign — E-Signatur einholen
    • dms.archive — Dokument archivieren
  • Beispiel-Flow "Rechnungseingang": Upload → OCR → Approval (Buchhaltung) → Bezahlt-Markierung → Archiv

Acceptance: Drag-and-Drop einer Rechnung startet Flow, Buchhalter bekommt Aufgabe, Approve → Status auf "bezahlt" gesetzt.

Phase 9 — E-Signatur (Tag 11-13)

  • DB-Migration: document_signatures
  • Backend:
    • Sign-Request endpoint: erstellt Anfrage, sendet Mail/Push an Empfänger
    • Empfänger öffnet, bestätigt → SHA256-Hash über (Doc-Hash + Timestamp + UserId + IP) wird gespeichert
    • eIDAS-konform "fortgeschritten" (kein qualifizierter Schlüssel, das wäre Phase X)
  • Web-Client: Sign-Dialog mit Vorschau + Bestätigung
  • PDF-Export mit Signatur-Block am Ende

Acceptance: Vertrag wird zur Signatur an 3 Personen gesendet, alle bestätigen, signiertes PDF mit allen 3 Signaturen + Audit-Trail.

Phase 10 — Annotationen + Vorlagen + Sonstiges (Tag 13-15) — LIVE 2026-05-03

  • ✅ Thread-Kommentare am Document (DocumentAnnotation, Resolve/Reopen, optionale Page/Pos-Anker fuer kuenftiges Inline-Highlighting)
  • ✅ Template-Library: jedes Doc als Vorlage markierbar mit Kategorie, "Neu aus Vorlage"-Picker im DMS-Hub mit Scope-Wahl PERSONAL/SPACE
  • ✅ Mail-zu-DMS: dms-<slug>@mail.prilog.chat (User-Alias, ein/aus/rotieren), eingehende Mails via Stalwart-Webhook landen in Mein Fach (Body als .txt + Anhaenge als einzelne Documents)
  • WebDAV-Mount: spaeter (Desktop-Sync-Client deckt das Use-Case bereits ab)
  • PDF-Annotation-Highlighting im PDF.js-Viewer: spaeter (Daten-Modell steht bereits, UI nachzuziehen)

Acceptance: Kommentar-Thread am Doc → Resolve, "Neu aus Vorlage" → kopiertes Doc im DMS, Mail an dms-Alias → Anhaenge in Mein Fach.


7. Quick-Wins für Tag 1 (DAG 1 sofortige Sichtbarkeit)

  1. Routing-Fix — DMS-Welt-Icon → /dms (institutionell), Mein Fach bleibt eigene Welt
  2. Phase 1 (Ordnerhierarchien) — der größte UX-Sprung. Macht aus dem heutigen Ein-Tag-System ein "echtes" DMS-Gefühl
  3. Tabellen-Ansicht (vorbereitend für Phase 3) — auch ohne Custom Fields schon mal da haben

Ergebnis nach Tag 1: User landet im DMS-Hub, sieht seine Spaces als parallele Ordner-Hierarchie + neue eigene Hierarchien, kann Docs in mehrere Ordner gleichzeitig hängen.


8. Was wir NICHT bauen (bewusst)

  • Keine eigene Office-Suite — Tiptap reicht für Notizen, MS Office Online wäre zu teuer
  • Keine eigene OCR-Engine — Tesseract ist gut genug, kein eigener Trainings-Aufwand
  • Keine qualifizierte E-Signatur (eIDAS) — viel zu komplex (HSM, Trust-Service-Provider). Stattdessen "fortgeschritten" — reicht für 95% der Anwendungsfälle
  • Kein Compliance-Auditor-Tool — wir liefern Audit-Logs, das Reporting darauf ist Nische
  • Kein WORM-Storage — S3-Object-Lock ist möglich aber teuer, Phase X
  • Keine Migrations-Toolchain für SharePoint/etc. — Nice-to-have, später

9. Marktpositionierung

Tagline: "Das DMS, das beides versteht — den Schul-Alltag und die Buchhaltung."

USPs gegenüber:

  • DocuWare/M-Files: viel günstiger, integrierter ins ganze Schul-/Workspace-Erlebnis, deutsche Sprache nativ
  • Paperless-ngx: keine Self-Hosting-Pflicht, Multi-User, Schul-Compliance bereits drin
  • NextCloud Files: spezialisiert statt generisch, mit Workflow + Retention out-of-the-box
  • ELO: günstiger, einfacher, Cloud-First, ohne Verkaufsgespräch buchbar

Preis-Modell (Vorschlag): in das bestehende Per-Active-User Pro (3 EUR/User) inkludiert, Pro-Modul-Preis für AI-Klassifikation (Phase 7) optional.


10. Risiken + Mitigations

RisikoMitigation
Schul-Datenschutz-Anforderungen unterschätztPhase 5 Retention von Anfang an mitdenken, Schul-Use-Cases mit Lehrer testen
OCR-Performance auf großen PDFsQueue-System (Bull/Redis), Tenant-übergreifender Worker-Pool
Custom-Field-Schema-Drift bei Type-UpdatesMigrations-Konzept: Type-Update versioniert, alte Docs behalten alte Schema
Datenmenge wächst schneller als S3-QuotaPer-Tenant-Quota-Monitoring + Auto-Mahnungen + Hetzner-Object-Storage als günstige Alternative für kalte Daten
Folder-Hierarchien werden zu tiefUX-Limit (max 5 Ebenen pro Tree, klar kommuniziert)
Migration der alten "Tags-as-Folders"-Brille auf echte FoldersEin-Klick-Migration: für jeden Top-Level-Tag mit "/"-Hierarchie ein Folder-Tree erzeugen

11. Nächste Schritte (Reihenfolge für 03.05.)

  1. Morgen früh — Phase 0 (Reparatur Upload + Routing-Fix) — 2h
  2. Mittag — Diskussion: dieses Konzept durchgehen, Prioritäten festlegen, ggf. Zuschnitt auf MVP
  3. Mittag-Abend — Phase 1 starten (Mehrfache Ordnerhierarchien)
  4. Tage 2-15 — Phasen 2-10 nach festgelegter Priorität

Default-Zuschnitt für MVP-1 (1 Woche): Phase 0 + 1 + 2 + 3 (Folders + Tags + Document-Types). Damit hat das DMS schon den "großen Sprung" gegenüber heute. Phase 4-10 als Roadmap-Story für Verkauf.


Anhang — Feature-Vergleichs-Matrix

FeatureHeutePhase 1Phase 5Phase 10M-FilesDocuWarePaperless-ngx
Volltextsuche
Tags✅ flach✅ verschachtelt
Mehrere Ordnerhierarchien
Smart Folders
Document Types + Custom Fields
OCR
Auto-Klassifikation
Retention Policies
Legal Hold
Versionierung
Public-Share-Links
E-Signatur
Workflow-Engine❌ ext.
Beziehungen
Schul-Compliance
Pro-Active-User-Pricing
Open-Source-Kern
Deutsche UI nativ

⚠ = nur teilweise / nur über Plugins