# KNOW: Befunde aus der Analyse vom 13.10.2026 Grundlage sind die Workflow-Definitionen auf n8n.mindboost.app, nur lesend über die n8n-API abgerufen. Ausgewertet wurde der Code von KNOW, KGW und allen aufrufenden Workflows. Inhalte der Datenbank wurden nicht gelesen. Für `CANCEL - Unsubscribe Link` und `KAN-Learn - Kanbau Pattern Learning` liefert die API keine gespeicherten Ausführungen, ein Nachweis aus der Laufzeit fehlt deshalb. - Übersicht der Tabellen: [KNOW-schema.md](KNOW-schema.md) - Interaktive Ansichten (privat): - Datenfluss: https://claude.ai/artifact/GP8FfU8M6Wk9hPRmJuk96h - Ontologie: https://claude.ai/artifact/R7zxBJsCKkkCWdCcztLFUT (OWL/Turtle: [know-ontology.ttl](know-ontology.ttl)) Status aller Befunde: **offen**. In n8n wurde nichts geändert. | # | Befund | Schwere | |---|---|---| | B1 | CANCEL protokolliert über eine Operation, die es nicht gibt | mittel | | B2 | KAN-Learn speichert über eine Operation, die es nicht gibt | mittel | | B3 | IN-Sync ruft zwei nicht vorhandene Operationen auf (inaktiv) | niedrig | | B4 | CAT schreibt per eigenem SQL an KNOW vorbei | niedrig | | B5 | 12 Tabellen ohne aktiven Schreibweg, mit drei Ursachen | hoch (Datenbasis unklar) | | B6 | KAF-Bestätigung führt bei jedem Aufruf DDL aus und setzt einen festen Bestätiger | mittel | | B7 | Anhang-Extraktionen kommen nur von außen | niedrig | | B8 | KGW erlaubt externen Aufrufern eine Lösch-Operation | niedrig | | B9 | Keine Löschfristen für Klartext-Felder | mittel (Datenschutz) | | B10 | Absender-Report zeigt eingefrorene Statistik | mittel | ## B1 – CANCEL protokolliert ins Leere - **Beleg:** `CANCEL - Unsubscribe Link` (aktiv) ruft in 4 Knoten (`KNOW: Log Erfolg`, `… Fehler`, `… Duplikat-Erfolg`, `… Dry Run`) `log_workflow_decision` auf. Diese Operation steht nicht in der Liste von KNOW, KNOW wirft `Nicht erlaubte KNOW operation`. Alle 4 Knoten haben „Continue on Fail“. - **Folge:** Der Workflow läuft durch, aber kein Abmeldevorgang wird protokolliert, und niemand merkt es. - **Vorschlag:** auf die vorhandene Operation `record_workflow_decision` umstellen. Sie schreibt in `workflow_decisions`, das heute leer bleibt (B5b). Vorher die Felder des Payloads abgleichen. ## B2 – KAN-Learn speichert nicht - **Beleg:** `KAN-Learn - Kanbau Pattern Learning` (aktiv) ruft im Knoten `KNOW: Save Patterns` `upsert_kanbau_project_patterns` auf. Die Operation gibt es in KNOW nicht, der Knoten hat keine Fehlerbehandlung. - **Folge:** Jede Ausführung bricht an dieser Stelle ab. KAN-Learn wird von `KAN - Kanbau API Gateway` aufgerufen. - **Vorschlag:** In der Ausführungsliste von n8n prüfen, ob und wie oft der Workflow läuft. Dann entweder die Operation in KNOW ergänzen (Zieltabelle festlegen) oder den Aufruf entfernen. ## B3 – IN-Sync ruft Operationen auf, die fehlen - **Beleg:** `IN - Sicherheitsregeln Source Sync` (inaktiv) ruft `upsert_input_validation_rule` und `upsert_input_validation_source_snapshot` auf. Beide fehlen in KNOW, ebenso eine passende Tabelle. - **Vorschlag:** vor einer Aktivierung in KNOW ergänzen. ## B4 – CAT schreibt direkt in `workflow_hints` - **Beleg:** Ein Postgres-Knoten in `CAT - Postfach Pipeline` führt `UPDATE knowledge.workflow_hints SET notified_at = now(), pending_notification = false WHERE hint_key = '{{ $json.hint_key }}'` aus. - **Folge:** - KNOW ist nicht mehr der einzige Schreibweg. - Der Wert wird ohne Escaping direkt in das SQL eingesetzt. Ein Hochkomma in `hint_key` bricht die Abfrage. - **Vorschlag:** eine KNOW-Operation dafür anlegen, z. B. `mark_hint_notified`. ## B5 – Tabellen ohne aktiven Schreibweg Kein aktiver Workflow schreibt diese 12 Tabellen über KNOW. Die Ursachen sind verschieden: **a) KNOW hat gar keine Schreib-Operation.** Gefüllt werden können diese Tabellen nur mit direktem Zugang zur Datenbank: | Tabelle | Wer liest | Bemerkung | |---|---|---| | `projects` | `NEX - Teams Chat Agent`, extern über KGW (`find_project_candidates`, `get_sender_profile`) | Ist die Tabelle leer, findet die Projektsuche nur Treffer über `project_aliases`. **Zuerst prüfen**: `SELECT count(*), max(last_synced_at) FROM knowledge.projects;` | | `contact_aliases` | extern über KGW (`find_contact_candidates`) | | | `contact_project_relations` | niemand | | | `agent_capabilities`, `agent_context_documents`, `agent_execution_log` | niemand | vermutlich Altlast oder außerhalb von n8n genutzt | **b) Die Operation gibt es, aber kein Workflow ruft sie auf:** | Tabelle | vorhandene Operationen | Wer liest | |---|---|---| | `property_development_cases` | `upsert_property_development_case`, `sync_property_development_folder_snapshot`, `store_kaf_confirmation_snapshot`, `claim_/complete_kaf_confirmation_create` | extern über KGW (6 Abfragen für Fristen, Angebote, fehlende Unterlagen) | | `property_development_documents` | `upsert_property_development_document` | extern über KGW (`summarize_property_development_case`) | | `project_folders` | `upsert_project_folder` | niemand | | `place_enrichments` | `upsert_place_enrichment` | niemand (`MAP - Maps/Geo Gateway` nutzt KNOW nicht) | | `workflow_decisions` | `record_workflow_decision` | niemand (siehe B1) | Die Abfragen zu Ankaufsfällen über KGW (Hermes) liefern also nur Daten, die einmal anders hineingekommen sind. Über KGW selbst dürfen diese Tabellen nicht beschrieben werden. **c) Gewollt:** `workflow_hint_config` wird von `setup_schema` mit 9 Kategorien befüllt (u. a. `mahnung`, `zahlungsaufforderung`, `newsletter_werbung`) und danach nur noch gelesen. **Nächster Schritt:** einmal die Zeilenzahlen aller Tabellen und das jüngste `updated_at` abfragen. Erst dann ist klar, ob die Tabellen leer sind oder von außerhalb von n8n befüllt werden. ## B6 – KAF-Bestätigung: DDL im Anfragepfad, fester Bestätiger - **Beleg:** Ruft jemand `upsert_property_development_case` mit `quality_status: confirmed` auf, führt KNOW einen Sonderweg aus (`Build KAF Case Confirmation SQL`). Dieser Sonderweg macht Folgendes: - Er führt bei **jedem** Aufruf `ALTER TABLE … ADD COLUMN IF NOT EXISTS confirmed_by / confirmed_at` aus. - Er setzt `confirmed_by` ohne Angabe auf `r.rapp@mygodel.de`. - **Folge:** - Die beiden Spalten fehlen in `setup_schema`. - DDL im Anfragepfad braucht eine exklusive Tabellensperre. - Bestätigungen ohne Absender werden einer bestimmten Person zugeschrieben. - Heute ruft kein Workflow diesen Weg auf (B5b). - **Vorschlag:** die Spalten in `setup_schema` aufnehmen, das `ALTER TABLE` entfernen und `confirmed_by` zur Pflichtangabe machen. ## B7 – `document_extractions` nur von außen - **Beleg:** `store_document_extraction` ruft kein n8n-Workflow auf, auch `DOC - Dokumenten-Analyse` nicht. Geschrieben wird nur extern über KGW. - **Vorschlag:** klären, ob DOC die Extraktionen speichern soll. Sie wären eine gute Quelle für Fälle bzw. Trainingsdaten in knaster. ## B8 – Lösch-Operation über KGW - **Beleg:** Die Freigabeliste von KGW enthält `purge_spf_aliases`, ein `DELETE` auf `project_aliases`. - **Vorschlag:** Prüfen, ob externe Aufrufer (Hermes, Skripte) das wirklich brauchen. Sonst streichen. ## B9 – Löschfristen - **Beleg:** Folgende Felder speichern Klartext, eine Bereinigung ist nicht erkennbar: - `llm_jobs.prompt` und `.result` - `document_extractions.extracted_text` - `property_development_cases.meeting_transcripts` - `agent_context_documents.content` - `mail_events` (Absender, Betreff) `purge_*` gibt es nur für Absender-Beobachtungen und Aliase. Bei `browser_sessions.session_data` ist am Schema nicht erkennbar, ob verschlüsselt wird. - **Vorschlag:** Aufbewahrungsfristen festlegen, z. B. `llm_jobs` nach Abschluss nach 30 Tagen leeren. `browser_sessions` im Code von BSB prüfen. ## B10 – Absender-Report zeigt eingefrorene Statistik - **Beleg:** - `ASP - Absender-Profil Backfill` schreibt die Statistik eines Absenders (`mail_count`, `dominant_category`, `avg_confidence` …) per `upsert_contact` in `contacts.raw_evidence_json`. - `upsert_contact` aktualisiert bei einem vorhandenen Kontakt nur `display_name`, `normalized_name`, `last_seen_at` und `updated_at`, **nicht** `raw_evidence_json`. - `ASP - Absender-Report` liest Kategorie und Mail-Anzahl per eigenem SQL aus genau diesem Feld. - **Folge:** Der Report zeigt für jeden Absender die Werte vom ersten Backfill, auch wenn sich die Lage seitdem geändert hat. Die aktuellen Werte stehen in `sender_observations`, dort schreibt derselbe Backfill per `upsert_sender_observation` mit. - **Ursache (ontologisch):** Das Absender-Profil gehört zur Klasse *Absender*, der Kontakt ist das fachliche Gegenüber. Beide sind über die E-Mail-Adresse verbunden. Liegt die Statistik zusätzlich im Kontakt, entsteht eine zweite Quelle, und die veraltet. - **Vorschlag:** Den Report auf `sender_observations` umstellen und den Kontakt nur noch über `email` dazuholen. Die Statistik aus `upsert_contact` herausnehmen.