{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://hejstack.com/export-specs/chats.schema.json",
  "title": "hejstack Export: chats.json",
  "description": "Alle Unterhaltungen aller Nutzer einer Organisation inklusive Ordnerstruktur, Fragen, Antworten, Quellenverweisen, Anhängen und Nutzer-Feedback. Anhänge liegen unter chats/<konversation-id>/<datei>, Transkripte von Sprachmemos daneben als <datei>.transcript.txt. Inhalte sind im Export entschlüsselt. Exportformat 1.0, Stand 15.09.2026.",
  "type": "object",
  "required": ["format_version", "folders", "conversations"],
  "properties": {
    "format_version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+$" },
    "folders": { "type": "array", "items": { "$ref": "#/$defs/folder" } },
    "conversations": { "type": "array", "items": { "$ref": "#/$defs/conversation" } },
    "feedback": { "type": "array", "items": { "$ref": "#/$defs/feedback" }, "description": "Bewertungen (👍/👎) der Nutzer zu Antworten." }
  },
  "$defs": {
    "uuid": { "type": "string", "format": "uuid" },
    "folder": {
      "type": "object",
      "required": ["id", "user_id", "name"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "user_id": { "$ref": "#/$defs/uuid", "description": "Eigentümer des Ordners (siehe nutzer.json)." },
        "name": { "type": "string", "maxLength": 120 },
        "parent_id": { "type": ["string", "null"], "format": "uuid", "description": "Übergeordneter Ordner, null auf oberster Ebene." },
        "position": { "type": "integer" },
        "created_at": { "type": "string", "format": "date-time" }
      }
    },
    "conversation": {
      "type": "object",
      "required": ["id", "user_id", "title", "created_at", "messages"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "user_id": { "$ref": "#/$defs/uuid", "description": "Nutzer, dem die Unterhaltung gehört." },
        "title": { "type": "string" },
        "folder_id": { "type": ["string", "null"], "format": "uuid" },
        "assistant_id": { "type": ["string", "null"], "format": "uuid", "description": "Verwendeter Assistent, siehe konfiguration.json → assistants." },
        "knowledge_group_ids": { "type": "array", "items": { "$ref": "#/$defs/uuid" }, "description": "Für diese Unterhaltung gewählte Wissensgruppen." },
        "marketplace_listing_ids": { "type": "array", "items": { "$ref": "#/$defs/uuid" }, "description": "Gewählte Marktplatz-Angebote (Fremdwissen)." },
        "created_at": { "type": "string", "format": "date-time" },
        "updated_at": { "type": ["string", "null"], "format": "date-time" },
        "messages": { "type": "array", "items": { "$ref": "#/$defs/message" }, "description": "In zeitlicher Reihenfolge." },
        "files": { "type": "array", "items": { "$ref": "#/$defs/file" }, "description": "Im Chat hochgeladene Anhänge." }
      }
    },
    "message": {
      "type": "object",
      "required": ["id", "role", "content", "created_at"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "role": { "type": "string", "enum": ["user", "assistant", "system", "tool"] },
        "content": { "type": "string", "description": "Nachrichtentext (Markdown), entschlüsselt." },
        "created_at": { "type": "string", "format": "date-time" },
        "model": { "type": ["string", "null"], "description": "Sprachmodell, das die Antwort erzeugt hat (nur role = assistant)." },
        "sources": { "type": "array", "items": { "$ref": "#/$defs/source" }, "description": "Quellenverweise der Antwort (nur role = assistant)." }
      }
    },
    "source": {
      "type": "object",
      "required": ["source"],
      "description": "Ein Quellenverweis. Eigene Quellen (Dokumente, Postfach-Wissen) enthalten Datei und Fundstelle; Marktplatz-Quellen nur Anbieter und Angebotstitel (Inhalt gehört dem Anbieter).",
      "properties": {
        "source": { "type": "string", "description": "Herkunft wie dokumente.json → source (upload, m365mail, imapmail, nextcloud, onedrive) oder marketplace." },
        "document_id": { "type": ["string", "null"], "format": "uuid", "description": "Verweis auf dokumente.json → documents." },
        "filename": { "type": ["string", "null"] },
        "knowledge_group_id": { "type": ["string", "null"], "format": "uuid" },
        "folder": { "type": ["string", "null"], "description": "Name der Wissensgruppe." },
        "page": { "type": ["integer", "null"], "description": "Seite im Dokument, falls bekannt." },
        "chunk_index": { "type": ["integer", "null"], "description": "Laufende Nummer des Textabschnitts im Dokument." },
        "text": { "type": ["string", "null"], "description": "Zitierter Textabschnitt." },
        "score": { "type": ["number", "null"], "description": "Relevanzwert der Suche (0–1)." },
        "remote_url": { "type": ["string", "null"], "format": "uri" },
        "provider_name": { "type": ["string", "null"], "description": "Nur marketplace: Name des Anbieters." },
        "listing_title": { "type": ["string", "null"], "description": "Nur marketplace: Titel des Angebots." }
      }
    },
    "file": {
      "type": "object",
      "required": ["id", "filename", "mimetype", "size_bytes", "created_at"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "filename": { "type": "string", "maxLength": 255 },
        "mimetype": { "type": "string" },
        "size_bytes": { "type": "integer", "minimum": 0 },
        "path": { "type": ["string", "null"], "description": "Pfad im Paket (chats/<konversation-id>/<datei>); null, wenn die Datei nicht mehr vorhanden ist." },
        "sha256": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" },
        "transcript_path": { "type": ["string", "null"], "description": "Nur Audio: Pfad des Transkripts (<datei>.transcript.txt)." },
        "uploaded_by": { "type": ["string", "null"], "format": "uuid" },
        "status": { "type": "string", "enum": ["pending", "indexed", "failed"] },
        "full_context": { "type": "boolean", "description": "true, wenn die Datei vollständig (statt per Suche) in den Kontext gegeben wurde." },
        "created_at": { "type": "string", "format": "date-time" }
      }
    },
    "feedback": {
      "type": "object",
      "required": ["id", "user_id", "rating", "created_at"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "user_id": { "$ref": "#/$defs/uuid" },
        "conversation_id": { "type": ["string", "null"], "format": "uuid" },
        "message_id": { "type": ["string", "null"], "format": "uuid" },
        "rating": { "type": "string", "enum": ["up", "down"] },
        "question": { "type": "string" },
        "answer": { "type": "string" },
        "expected_answer": { "type": ["string", "null"] },
        "comment": { "type": ["string", "null"] },
        "model": { "type": ["string", "null"] },
        "created_at": { "type": "string", "format": "date-time" }
      }
    }
  }
}
