Skip to content

Import/Export-Standard — Konzept

Ein einheitlicher Standard für den Import und Export von Prilog-Daten. Beginnt mit Aufgaben (WorkItem), wächst Schritt für Schritt zu Kontakten, Dokumenten, Briefen, Kalender-Einträgen.

Ziele

  • Schul-IT-tauglich: Sekretariat soll mit Excel oder einem Texteditor einen Import vorbereiten können.
  • Versionssicher: alte Exports lassen sich auch in 5 Jahren noch importieren — Schema-Version steht im Datei-Header.
  • Wachstumsfähig: neue Entitäten kommen einfach dazu, ohne den Standard zu ändern.
  • DSGVO-tauglich: jeder Import/Export wird im Activity-Log dokumentiert (wer, wann, wieviele Items).
  • Kein Vendor-Lock: Daten gehören dem Kunden — Export liefert lesbares JSON, niemand braucht Prilog um die Daten zu verstehen.

Format-Familie

Zwei Formate werden unterstützt, beide bauen auf demselben Datenmodell:

JSON (Hauptformat)

Strukturiert, hierarchisch, mit Sub-Entitäten (Checklisten, Kommentare). Default für Export. Eingabeformat für API-zu-API-Migration.

CSV (Sekundärformat)

Tabellarisch, ohne Sub-Entitäten. Excel-kompatibel. Default für manuellen Import durch Sekretariat. Nur Top-Level-Felder, Sub-Entitäten werden weggelassen oder per Spalten-Konvention serialisiert (z.B. assignee_emails: "anna@…|lee@…").


JSON-Schema v1 — Container

Jede JSON-Datei beginnt mit einem festen Container:

json
{
  "$schema": "https://docs.prilog.chat/schema/import-v1.json",
  "schema_version": 1,
  "entity_type": "tasks",
  "exported_at": "2026-05-10T08:00:00Z",
  "exported_by": "@lee:weser.prilog.team",
  "tenant_slug": "weser",
  "items": [ /* Entity-spezifische Objekte */ ]
}

Pflichtfelder:

FeldBedeutung
schema_versionInteger. Aktuell 1. Beim Import abgelehnt wenn unbekannt.
entity_typeString. Welche Art Daten? tasks, contacts, documents, …
itemsArray. Die eigentlichen Daten-Objekte.

Optional:

FeldBedeutung
exported_atISO-8601 — wann wurde exportiert.
exported_byMatrix-User-ID des Exporteurs (Audit).
tenant_slugQuell-Tenant — Hinweis bei Cross-Tenant-Import (z.B. zwischen Prilog-Instanzen).
default_space_idWenn ein Item space_id weglässt, wird dieser Wert verwendet. Praktisch beim Bulk-Import in einen einzelnen Space.
notesFreitext-Beschreibung des Exports.

Entity-Schema v1 — tasks

json
{
  "_import_id": "extern-1234",
  "title": "Klassenrats-Beschluss umsetzen",
  "description": "Beschluss vom 12.4. — Theaterprojekt für 2026/27",
  "status": "in_progress",
  "priority": "high",
  "due_date": "2026-05-15T00:00:00Z",
  "start_date": null,
  "space_id": "space-xyz",
  "board_name": "Aufgaben",
  "assignee_emails": ["anna@weser-schule.de", "lee@weser-schule.de"],
  "responsible_email": "lee@weser-schule.de",
  "checklists": [
    {
      "title": "Vorbereitung",
      "items": [
        { "title": "Klassenrat informieren", "checked": true },
        { "title": "Eltern anschreiben", "checked": false }
      ]
    }
  ],
  "comments": [
    {
      "content": "Schulleitung hat zugestimmt.",
      "created_by_email": "anna@weser-schule.de",
      "created_at": "2026-04-15T10:00:00Z"
    }
  ],
  "completion": {
    "type": "decision",
    "note": "Klassenrat einstimmig — Aufführung am 17.6.",
    "completed_at": "2026-05-09T14:30:00Z",
    "completed_by_email": "anna@weser-schule.de"
  }
}

Feld-Referenz

FeldTypPflichtBeschreibung
_import_idStringneinExterne ID aus dem Quell-System (Excel-Zeilennummer, Trello-ID …). Wird im Activity-Log mitgeführt; nicht in der Prilog-DB als Primärschlüssel verwendet.
titleStringjaAufgaben-Titel, max 500 Zeichen.
descriptionString oder nullneinLängere Beschreibung.
statusEnumneintodo (Default), in_progress, review, done.
priorityEnumneinlow, medium (Default), high, critical.
due_dateISO-8601 oder nullneinFälligkeit.
start_dateISO-8601 oder nullneinStartdatum.
space_idString oder nullneinZiel-Space. Wenn null, wird default_space_id aus dem Container verwendet.
board_nameString oder nullneinWenn das Board mit dem Namen nicht existiert, wird das Default-Board des Spaces verwendet.
assignee_emailsArray<String>neinBearbeiter — werden über Email zur Matrix-User-ID aufgelöst (UserDirectoryEntry-Lookup im Tenant). Unbekannte Emails werden weggelassen + im Result-Report aufgelistet.
responsible_emailString oder nullneinVerantwortliche Person.
checklistsArray<Checklist>neinSub-Entität (siehe unten).
commentsArray<Comment>neinSub-Entität (siehe unten).
completionObject oder nullneinBeim Status done: Resultat-Doku (Phase F).

Sub-Schema Checklist

json
{ "title": "...", "items": [{ "title": "...", "checked": true }] }

Sub-Schema Comment

json
{ "content": "...", "created_by_email": "...", "created_at": "ISO-8601" }

Sub-Schema Completion

json
{
  "type": "decision" | "letter" | "note" | "snoozed" | "other",
  "note": "...",
  "completed_at": "ISO-8601",
  "completed_by_email": "..."
}

Beim Import wird beim Setzen von status: 'done' die Resultat-Validierung wie im normalen Done-Flow angewandt — fehlt completion.type, schlägt der Import für dieses Item fehl (mit klarer Fehlermeldung im Result-Report).


CSV-Schema v1 — tasks

Eine Zeile pro Aufgabe. Sub-Entitäten werden weggelassen (Excel kann Hierarchie nicht darstellen). Kommentare/Checklisten können nachträglich im UI ergänzt werden.

Header:

title,description,status,priority,due_date,start_date,space_id,board_name,assignee_emails,responsible_email,completion_type,completion_note

Beispiel-Zeile:

"Klassenrats-Beschluss umsetzen","Theater 2026/27","in_progress","high","2026-05-15","","space-xyz","Aufgaben","anna@weser-schule.de|lee@weser-schule.de","lee@weser-schule.de","",""
  • Multi-Wert-Felder (assignee_emails): pipe-getrennt email1|email2|email3.
  • Datum: YYYY-MM-DD reicht; Zeit-Komponente optional.
  • Leere Felder: einfach leer, nicht null.
  • Anführungszeichen doppeln (Excel-Konvention) wenn der Wert ein Komma enthält.

CSV-Import liefert dieselben Result-Reports wie JSON-Import (siehe unten).


Result-Report

Jeder Import-Endpoint liefert ein strukturiertes Ergebnis:

json
{
  "schema_version": 1,
  "entity_type": "tasks",
  "imported": 23,
  "failed": 2,
  "warnings": [
    { "_import_id": "extern-1234", "field": "assignee_emails", "message": "Email anna@weser-schule.de nicht im Verzeichnis gefunden — Bearbeiter wurde weggelassen" }
  ],
  "errors": [
    { "_import_id": "extern-1240", "message": "title fehlt — Pflichtfeld" }
  ],
  "items": [
    { "_import_id": "extern-1234", "id": "cuid-...", "status": "imported" }
  ]
}
  • Imported: Anzahl erfolgreich angelegter Items.
  • Failed: Anzahl Items mit harten Fehlern (Pflichtfeld fehlt, ungültige Enum-Werte, …).
  • Warnings: Items wurden angelegt, aber nicht alles war perfekt (z.B. unbekannte Email).
  • Items: Mapping _import_id → erzeugte Prilog-ID für nachgelagerte Verknüpfungen.

Backwards-Compatibility-Strategie

Wenn schema_version erhöht wird (z.B. auf 2), gelten folgende Regeln:

  1. Alte Exports bleiben importierbar — der Import-Endpoint kennt v1 + v2.
  2. Neue Felder in v2 sind optional bei v1-Daten (undefined ist OK).
  3. Umbenennungen / Entfernungen brauchen einen expliziten Migration-Pfad — der wird im Konzept-Doc-Update dokumentiert, bevor v2 ausgerollt wird.
  4. Drei Versionen rückwärts werden mindestens unterstützt (v1, v2, v3 wenn v4 kommt).

Activity-Log-Integration

Pro Import wird ein Activity-Eintrag mit contentType: 'import.batch' geschrieben:

json
{
  "title": "23 Aufgaben importiert (2 Warnungen)",
  "metadata": {
    "entity_type": "tasks",
    "imported": 23,
    "failed": 2,
    "source": "json|csv|api",
    "actor": "..."
  }
}

Pro fehlgeschlagenem Import-Item wird kein einzelner Eintrag geschrieben (sonst Spam) — die Fehler stehen im Result-Report, der im Frontend angezeigt wird und im Backend für 7 Tage zur Nachschau gecached werden kann (Phase 2).


Permission-Model

AktionWer darf?
Export aller Tasks aus einem SpaceMitglied des Spaces (task:read)
Export tenant-weit aller TasksSchul-Admin
Import in einen SpaceMitglied mit file:upload (kann auch Tasks erzeugen)
Import tenant-weit (Bulk-Provisioning)Schul-Admin

Beim Import gilt die normale Schreibberechtigung für jedes erzeugte WorkItem. Email-Lookups sind tenant-isoliert: anna@weser-schule.de wird nur unter weser-Tenant aufgelöst.


Roadmap

PhaseInhaltAufwand
1Backend: Tasks-Export (JSON+CSV) + Tasks-Import (JSON+CSV)~6h
2Frontend: Hub-Page mit Tasks Export/Import + File-Upload + Vorschau~4h
3Result-Report-Cache + Activity-Log-Integration~2h
4Kontakte-Export/Import (Phase 2 der App)später
5Dokumente-Export (DMS-Bulk-Download als ZIP)später
6Briefe / Kalender / Checklisten-Templatesspäter

Phasen 1+2+3 werden in der ersten Implementations-Welle gebaut. Phase 4 startet, sobald Phase 1–3 produktiv getestet sind.


Konvention für JSON-Schema-Dateien

Die formalen JSON-Schema-Definitionen liegen unter prilog_docs/public/schema/import-v1.json und werden über https://docs.prilog.chat/schema/import-v1.json ausgeliefert. Damit kann jeder externe Tool (z.B. Excel-Validator, JSON-Editor) gegen das Schema prüfen.


Was wir nicht tun

  • Kein binäres Format (Excel .xlsx direkt) — wir nehmen CSV. Wer xlsx will, exportiert aus Excel als CSV.
  • Kein Round-Trip-ID-Garant — beim Import werden frische Prilog-IDs vergeben. Externe IDs landen in _import_id zur späteren Verknüpfung, nicht als Primärschlüssel.
  • Keine selektiven Feld-Updates beim Import — Import erzeugt neue WorkItems. Updates auf bestehende WorkItems gehen über die normale PATCH-API. (Phase 2 könnte Update-by-_import_id ergänzen.)
  • Keine automatische Konflikt-Auflösung — wenn _import_id bereits importiert wurde, wird das Item beim Re-Import als Duplikat angelegt. Frontend zeigt eine Vorschau mit Duplikat-Warnung.