- ontology/know.yaml: 49 Klassen, 66 Beziehungen, 12 Vokabulare (72 Konzepte); erzeugt: know.ttl (OWL + SKOS), Ansicht aus viewer.html.tmpl - knaster.ontology: Modell + Prüfung, Export, Momentaufnahme der n8n-Workflows (nur GET; KNOW-Spezifikation aus dem Workflow-Code, Aufrufe inkl. Laufzeit- Operationen, direktes SQL), Abgleich, Übernahme von Entscheidungen - Service-Routine Schritt 8: Verstöße als Befunde, Ontologie-Änderungen als Vorschläge ontology_change (immer Freigabe); „ordne P-x <konzept> zu“; Entscheidungen in ontology_decisions, `knaster ontology apply` schreibt sie in die YAML (Version +1) - CLI: knaster ontology validate|export|snapshot|check|apply; knaster validate prüft Modell und Aktualität der Turtle-Datei - Gegen echten n8n-Export geprüft: neue Befunde B31–B33 (verified/confirmed, KAN ruft unbekannte Operation, MPA ordnet Projektereignisse nie ein) - SPEC-ontology, BETRIEB §6, Router-Image enthält die Ontologie Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
28 KiB
KNOW: Befunde zur Datenhaltung (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. B11–B30 stammen aus der Vollanalyse in vier Ebenen:
- Schema: Schlüssel, Indizes, Typen, nachträgliche Spalten.
- SQL der 80 Operationen: Was wird geschrieben, was bei Konflikten nicht aktualisiert, was nie befüllt.
- Abgleich mit den Payloads der Aufrufer.
- Datenablagen außerhalb von KNOW: staticData, direkte Verbindungen, LLM-Aufrufe.
Jeder Befund wurde am Code nachgeprüft, Artefakte der automatischen Auswertung sind aussortiert. 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
- Interaktive Ansichten (privat):
- Datenfluss: https://claude.ai/artifact/GP8FfU8M6Wk9hPRmJuk96h
- Ontologie: https://claude.ai/artifact/R7zxBJsCKkkCWdCcztLFUT (Quelle: ontology/know.yaml)
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 |
| B11 | Kein einziger Fremdschlüssel; alle Verweise sind freier Text | hoch |
| B12 | Zwei Schlüsselschemata für Kontakte → Dubletten, Join findet nichts | hoch |
| B13 | Zwei Projekt-Kennungen, projects leer, Projekte kommen live aus KanBau |
hoch |
| B14 | Zu enge Eindeutigkeit: Ereignisse und Prüfungen werden überschrieben bzw. verworfen | hoch |
| B15 | Fehlende Eindeutigkeit: jede Extraktion erzeugt eine neue Zeile | mittel |
| B16 | Drei Tabellen ohne Primärschlüssel, doppelte Indizes | niedrig |
| B17 | Upserts frieren Fachdaten ein (Kontakte, Ankaufsfälle, Falldokumente) | hoch |
| B18 | Gespeicherte abgeleitete Werte veralten (deadline_is_overdue u. a.) |
mittel |
| B19 | Felder, die nie geschrieben werden (confidence, confirmed_by, verified_at) |
mittel |
| B20 | Kategorien in mehreren Vokabularen; Safety-Floor-Kategorien über CAT unerreichbar | hoch |
| B21 | Postfach und Absender uneinheitlich normalisiert | mittel |
| B22 | Zwei Listen für Dokumenttypen | niedrig |
| B23 | Sechs Statusfelder rund um den Ankaufsfall | mittel |
| B24 | Schema-Drift: 45 nachgezogene Spalten, Laufzeit-DDL, keine Versionierung | mittel |
| B25 | Uneinheitliche Typen und Benennung (Geld als Text, Cent vs. Euro, deutsch/englisch) | niedrig |
| B26 | Fehlende Indizes auf Such- und Join-Spalten | niedrig |
| B27 | Ein Datenbankzugang für alles, geteilt mit dem Chat-Gedächtnis | mittel |
| B28 | Zustand in staticData von 9 Workflows, außerhalb von KNOW | mittel |
| B29 | Browser-Sessions (Cookies, Header) unverschlüsselt gespeichert | hoch (Sicherheit) |
| B30 | LLM-Aufrufe am PSE-LiteLLM vorbei, u. a. Kaufvertragstexte | hoch (Datenschutz) |
| B31 | Zwei Wörter für „bestätigt“: verified vs. confirmed |
niedrig |
| B32 | KAN-Gateway ruft get_kanbau_project_patterns auf, die es nicht gibt |
hoch |
| B33 | MPA speichert jedes Projektereignis als info/normal |
hoch |
B1 – CANCEL protokolliert ins Leere
- Beleg:
CANCEL - Unsubscribe Link(aktiv) ruft in 4 Knoten (KNOW: Log Erfolg,… Fehler,… Duplikat-Erfolg,… Dry Run)log_workflow_decisionauf. Diese Operation steht nicht in der Liste von KNOW, KNOW wirftNicht 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_decisionumstellen. Sie schreibt inworkflow_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 KnotenKNOW: Save Patternsupsert_kanbau_project_patternsauf. 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 Gatewayaufgerufen. - 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) ruftupsert_input_validation_ruleundupsert_input_validation_source_snapshotauf. 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 PipelineführtUPDATE 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_keybricht 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_casemitquality_status: confirmedauf, 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_ataus. - Er setzt
confirmed_byohne Angabe aufr.rapp@mygodel.de.
- Er führt bei jedem Aufruf
- 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).
- Die beiden Spalten fehlen in
- Vorschlag: die Spalten in
setup_schemaaufnehmen, dasALTER TABLEentfernen undconfirmed_byzur Pflichtangabe machen.
B7 – document_extractions nur von außen
- Beleg:
store_document_extractionruft kein n8n-Workflow auf, auchDOC - Dokumenten-Analysenicht. 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, einDELETEaufproject_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.promptund.resultdocument_extractions.extracted_textproperty_development_cases.meeting_transcriptsagent_context_documents.contentmail_events(Absender, Betreff)
purge_*gibt es nur für Absender-Beobachtungen und Aliase.browser_sessions.session_dataist unverschlüsselt, siehe B29. -
Vorschlag: Aufbewahrungsfristen festlegen, z. B.
llm_jobsnach Abschluss nach 30 Tagen leeren. Zubrowser_sessionssiehe B29.
B10 – Absender-Report zeigt eingefrorene Statistik
- Beleg:
ASP - Absender-Profil Backfillschreibt die Statistik eines Absenders (mail_count,dominant_category,avg_confidence…) perupsert_contactincontacts.raw_evidence_json.upsert_contactaktualisiert bei einem vorhandenen Kontakt nurdisplay_name,normalized_name,last_seen_atundupdated_at, nichtraw_evidence_json.ASP - Absender-Reportliest 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 perupsert_sender_observationmit. - 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_observationsumstellen und den Kontakt nur noch überemaildazuholen. Die Statistik ausupsert_contactherausnehmen.
Vollanalyse: B11–B30
A. Integrität und Schlüssel
B11 – Keine Fremdschlüssel
- Beleg:
setup_schemaenthält kein einzigesREFERENCES.- Alle Verweise (
project_key,contact_key,case_key,message_id,kuerzel,mac…) sind freier Text ohne Prüfung. - Auch Löschungen (
purge_*,reject_project_alias) räumen abhängige Zeilen nicht auf.
- Alle Verweise (
- Folge: Verwaiste und ungültige Verweise sind jederzeit möglich, und es fällt nicht auf. Besonders betroffen ist
project_key: Es wird in 7 Tabellen benutzt, aberprojectswird nie befüllt (B13). Kein einziger Projektverweis lässt sich gegen eine Projekttabelle prüfen. - Vorschlag:
- Für die Kernbezüge Fremdschlüssel einführen, zuerst
NOT VALID, dann nach einer Bereinigung validieren: Falldokument → Ankaufsfall, Alias → Kontakt, Beteiligung → Kontakt und Projekt. - Für
project_keyerst B13 lösen.
- Für die Kernbezüge Fremdschlüssel einführen, zuerst
B12 – Zwei Schlüsselschemata für Kontakte
- Beleg:
upsert_contactbildet den Schlüssel standardmäßig alsnormalisierter Name|E-Mail. Kein Aufrufer übergibt einen eigenen Schlüssel.update_sender_relevancelegt Kontakte mit dem SchlüsselE-Mailan, mit der E-Mail-Adresse als Anzeigename.find_workflow_hintsverknüpftworkflow_hints.pattern_key(Absenderadresse) mitcontacts.contact_key.
- Folge:
- Ein Absender kann zweimal als Kontakt existieren.
- Der Relevanz-Score landet auf dem Schattenkontakt mit dem E-Mail-Schlüssel.
- Die vom Backfill angelegten Kontakte („Name|E-Mail“) findet der Join in
find_workflow_hintsnie. - Ändert sich der Anzeigename, entsteht ein neuer Kontakt.
- Vorschlag: einen Schlüssel festlegen, z. B. die kleingeschriebene E-Mail für Personen und Absender, Namen nur noch als Attribut bzw. Alias. Bestehende Dubletten über
emailzusammenführen.
B13 – Zwei Projekt-Kennungen, projects leer
- Beleg:
- Verweise nutzen
project_key. - Der Ankaufsfall speichert dagegen
selected_project_id, eineproject_idaus der KAF-Bestätigung. projectsundproject_aliasesführen zusätzlichkanbau_project_id.- Keine KNOW-Operation schreibt
projects(B5a). PRO - Project Assignmentfragt Projekte live beimygodel.kanbau.comab.
- Verweise nutzen
- Folge: Es gibt keine Stelle, an der
project_keyund die KanBau-ID verlässlich zusammengehören. Lesende Abfragen aufprojects(NEX-Teams-Agent,find_project_candidates) finden vermutlich nur Treffer über Aliase. - Vorschlag: einen Abgleich KanBau →
projectsanlegen (z. B. nachts, über das vorhandene KAN-Gateway) mitkanbau_project_idals festem Schlüssel.project_keydaraus ableiten oder ersetzen.
B14 – Zu enge Eindeutigkeit
project_events:UNIQUE(message_id)mitON CONFLICT (message_id) DO UPDATE SET project_key, category, summary ….- Meldet eine Mail zwei Ereignisse oder betrifft sie zwei Projekte, überschreibt das zweite das erste.
- Vorschlag: Schlüssel
(message_id, project_key, category).
kaf_review_snapshots:UNIQUE(case_key)mit Aktualisierung nur beireview_status='pending'.- Nach einer Freigabe kann für denselben Fall kein neuer Vertragsstand gespeichert werden. Der Insert läuft ohne Fehler ins Leere.
- Vorschlag: eine Version pro Prüfung (
case_key, version).
mail_events:UNIQUE(message_id)ohne Postfach.- Das ist unkritisch, solange die Graph-IDs pro Postfach verschieden sind. Bei Internet-Message-IDs würde eine Mail an zwei Postfächer zu einer Zeile.
- Prüfen, welche ID CAT und MPA übergeben.
B15 – Fehlende Eindeutigkeit bei Extraktionen
- Beleg:
document_extractionshat keinen eindeutigen Schlüssel,store_document_extractionmacht ein reinesINSERT. - Folge: Jede erneute Verarbeitung desselben Anhangs erzeugt eine weitere Zeile, und es ist nicht festgelegt, welche gilt.
- Vorschlag:
UNIQUE(message_id, attachment_id)mit Upsert.
B16 – Tabellen ohne Primärschlüssel
- Beleg:
workflow_hints,workflow_hint_configundkanbau_method_exampleshaben nurUNIQUE, keinenPRIMARY KEY. Aufhint_keyundmethod_keyliegt zusätzlich ein zweiter, überflüssiger Index. - Vorschlag: den eindeutigen Schlüssel zum Primärschlüssel machen und die doppelten Indizes entfernen.
B. Aktualität
B17 – Upserts frieren Fachdaten ein
Bei einem vorhandenen Datensatz aktualisieren mehrere Upserts nur wenige Spalten. Alles andere behält den Wert vom ersten Insert:
upsert_contact: aktualisiert nur Name,last_seen_atundupdated_at. E-Mail, Telefon, Website, Steuer-Nr., USt-IdNr., IBAN-Hash, Adresse, Kontakttyp, Qualitätsstatus und Belege werden nie korrigiert. B10 ist ein Spezialfall davon.upsert_property_development_case: aktualisiert nur Name, die drei Statusfelder,sharepoint_jsonundraw_evidence_json. Rund 50 Fachfelder bleiben eingefroren, darunter Angebotsfrist, Kaufpreis, Fläche,next_action,next_action_due_at, Risiko, Unterlagen-Flags und Mitschriften.upsert_property_development_document:is_current_versionundsupersedes_document_keywerden nie aktualisiert. Ein altes Dokument bleibt „aktuell“, die Versionierung funktioniert nicht. Ebenso bleiben Zusammenfassung, Absender und Dokumentdatum stehen.- Vorschlag: In den Upserts alle fachlichen Felder mit
COALESCE(EXCLUDED.x, tabelle.x)aktualisieren. Felder, die bewusst nur einmal gesetzt werden, im Code kennzeichnen.
B18 – Gespeicherte abgeleitete Werte veralten
- Beleg:
deadline_is_overdueist eine gespeicherte Spalte.find_cases_by_deadlineliest sie, sie lässt sich aber ausoffer_deadlineund dem heutigen Datum berechnen.document_count,missing_documentsunddetected_documentswerden nur vonsync_property_development_folder_snapshotgepflegt, und das ruft niemand auf (B5b).
- Folge: „Überfällig“ und „fehlende Unterlagen“ zeigen den Stand vom Einfügen.
- Vorschlag:
deadline_is_overduezur Laufzeit berechnen (View oder Ausdruck in der Abfrage). Die Zähler ausproperty_development_documentsableiten.
B19 – Felder, die nie geschrieben werden
workflow_hints.confidence: Keine Operation schreibt das Feld.- CAT sendet die Konfidenz, aber innerhalb von
suggested_action. find_workflow_hintssortiert nach der Spalte, die immer 0 ist. Die Reihenfolge der Hinweise ist damit zufällig.
- CAT sendet die Konfidenz, aber innerhalb von
workflow_hints.confirmed_by:promote_workflow_hintsetzt Status und Zeit, aber nicht die Person. Wer einen Hinweis über den Bestätigungslink freigegeben hat, wird nicht gespeichert.contacts.verified_at,project_aliases.verified_at: Keine Operation setzt sie. Das Bestätigungsmodell (quality_status+verified_at) ist nur halb umgesetzt.- Vorschlag:
confidenceaussuggested_actionin die Spalte übernehmen (auch rückwirkend).confirmed_byaus dem Bestätigungs-Webhook mitgeben.
C. Vokabular und Normalisierung
B20 – Kategorien in mehreren Vokabularen
- Beleg: Dieselbe Idee „Kategorie einer Mail“ existiert in mindestens sechs Listen:
- CAT-Zuordnung: 8 Werte, darunter
bauvorhabenundprojekt. workflow_hint_config.config_key: 9 Werte, daruntermahnung,zahlungsaufforderungunddefault.outlook_category: Anzeigenamen in Outlook.sender_observations.dominant_category: vom Absender-Backfill vergeben.project_events.category: 5 feste Werte.mail_events.category: frei. MPA schreibt hier den Workflow-Namen"MPA".
- CAT-Zuordnung: 8 Werte, darunter
- Folge:
- CAT erzeugt
bauvorhabenundprojekt, die Konfiguration kennt sie nicht, also greiftdefault. - Umgekehrt erzeugt CAT nie
mahnungoderzahlungsaufforderung. Die Regeln mit Safety-Floor („immer manuell prüfen“) greifen bei Hinweisen aus CAT nie. - Auswertungen nach Kategorie mischen fachliche Kategorien mit dem Workflow-Namen „MPA“.
- CAT erzeugt
- Vorschlag:
- Ein Vokabular als Tabelle bzw. SKOS-Konzeptschema in der Ontologie, mit Abbildung der Outlook-Namen.
- CAT um Mahnung und Zahlungsaufforderung erweitern.
- MPA schreibt seinen Status in
workflow_status, nicht incategory.
B21 – Postfach und Absender uneinheitlich normalisiert
- Postfach: CAT setzt in
store_mail_eventfestinfo@mygodel.de, im CAT-Code kommt aber auchr.rapp@mygodel.devor. MPA übergibt dengrant_key. Der Absender-Backfill schreibt das Postfach kleingeschrieben. - Absender: CAT schreibt ihn klein, MPA übergibt ihn unverändert.
sender_observations.emailist immer klein. - Folge: Die weichen Bezüge Mail ↔ Absender ↔ Kontakt (Ontologie) treffen nur teilweise. Steht ein falsches Postfach fest im Code, werden Mails dem falschen Postfach zugeordnet.
- Vorschlag: E-Mail-Adressen und Postfächer in KNOW normalisieren (kleinschreiben, Anzeigename abtrennen), nicht in jedem Aufrufer. In CAT das Postfach aus dem Trigger übernehmen.
B22 – Zwei Listen für Dokumenttypen
- Beleg:
property_development_documents.document_typehat 19 feste Werte.document_extractions.document_typeist frei, mit Standardwertunknown. - Vorschlag: eine gemeinsame Liste (Ontologie-Klasse Dokumenttyp).
B23 – Sechs Statusfelder rund um den Ankaufsfall
- Beleg:
status(alt),pipeline_status,outcome_status,review_status,confirmation_statusundquality_status. Dazu kommt die zweite Bestätigungslogik aus B6, diequality_status='confirmed'setzt, während der Token-Ablaufconfirmation_statusnutzt. - Folge: Es ist nicht festgelegt, welches Feld „bestätigt“ bzw. „abgeschlossen“ bedeutet.
- Vorschlag:
status(alt) auspipeline_statusundoutcome_statusableiten oder entfernen. Eine Bestätigungslogik festlegen.
D. Schema-Pflege
B24 – Schema-Drift
- Beleg:
- 45 Spalten werden per
ALTER TABLE … ADD COLUMN IF NOT EXISTSnachgezogen, davon 41 inproperty_development_cases. Beikanzlei_field_patternsdoppelt mit unterschiedlichem Standardwert ('[]'bzw.'[]'::jsonb). - Dazu kommt Laufzeit-DDL in einer Anfrage (B6).
- Es gibt keine Schema-Version und keine Migrationshistorie.
- 45 Spalten werden per
- Folge: Welche Spalten eine Instanz hat, hängt davon ab, wann
setup_schemazuletzt lief und ob der KAF-Sonderweg je ausgeführt wurde. - Vorschlag: versionierte Migrationen (Tabelle
schema_migrations),setup_schemanur noch als Migrationslauf.
B25 – Uneinheitliche Typen und Benennung
- Geld: als Text (
commission_including_vat,godel_offer), Beträge mal in Cent (amount_cents BIGINT), mal in Euro (*_eur NUMERIC). - Konfidenz: mal
NUMERIC, malDOUBLE PRECISION. - Spaltennamen: deutsch und englisch gemischt (
kuerzel,gesellschaft,quelle,bestaetigt,baustelle,absender_typ,mail_art). - Zeitstempel:
updated_atfehlt u. a. inproject_aliases,contact_aliases,document_extractionsundmail_events. - Vorschlag: bei der nächsten Migration vereinheitlichen. Niedrige Priorität, aber Voraussetzung für generierte Schemas (Ontologie → JSON-Schema).
B26 – Fehlende Indizes
- Beleg: Ohne Index sind u. a.:
contacts.email(Abgleich mit Absendern)mail_events.sender,received_at,category,assigned_project_key(find_mail_eventsfiltert und sortiert danach)document_extractions.message_idundproject_keysender_observations.email(get_sender_profile)contact_project_relations
- Vorschlag: Indizes auf diese Spalten. Unkritisch, solange die Tabellen klein sind.
E. Ablage und Datenfluss außerhalb von KNOW
B27 – Ein Datenbankzugang für alles
- Beleg: KNOW, die direkten SQL-Knoten in CAT und ASP, der Postgres-Healthcheck und der Credentials-Watchdog nutzen dasselbe Credential „n8n Postgres memory account“. Darüber läuft auch das Chat-Gedächtnis.
- Folge: Jeder Workflow mit diesem Credential kann jede Tabelle lesen, ändern und löschen. Die Freigabeliste in KNOW und KGW lässt sich so umgehen (B4 ist ein Beispiel).
- Vorschlag: eigene DB-Rolle für KNOW mit Rechten nur auf
knowledge, getrennt vom Chat-Gedächtnis. Direkte SQL-Knoten auf eine Rolle nur mit Leserechten umstellen oder durch KNOW-Operationen ersetzen.
B28 – Zustand in staticData
- Beleg: 9 Workflows speichern Zustand in n8n-staticData:
- CANCEL (
successful_unsubscribes, wegen B1 die einzige Aufzeichnung der Abmeldungen) - BEL (
bel_alerts,bel_setup_sent) - KJW (
nextLink) - TDO (
manual_enrichment,etag) - MCR (
last_reported_sha) - MPA (Token-Cache, verschlüsselt, in Ordnung)
- ASP-Scheduler, KBT und KBJ (inaktiv)
- CANCEL (
- Folge: Dieser Zustand ist in KNOW unsichtbar, hat keine Historie und geht bei einem Neuimport des Workflows verloren.
- Vorschlag: Fachlich relevante Zustände (CANCEL, BEL) nach KNOW verlagern. Technische Cursor (KJW, MCR) dürfen bleiben.
B29 – Browser-Sessions unverschlüsselt
- Beleg:
BSB - Execute Loginspeichertsession_data: { cookies, headers }überupsert_browser_sessionals JSON im Klartext. - Folge: Gültige Sitzungs-Cookies (u. a. für KanBau) liegen lesbar in der Datenbank. Jeder mit dem gemeinsamen Credential (B27) kann sie übernehmen. Zum Vergleich: Die Postfach-Tokens sind mit AES-256-GCM verschlüsselt, auch im Cache.
- Vorschlag:
session_datagenauso verschlüsseln wiemailbox_grants. Die Lebensdauer kurz halten (Standard 60 Min. ist gut).
B30 – LLM-Aufrufe am PSE-LiteLLM vorbei
- Beleg (direkte HTTP-Aufrufe, sicher am LiteLLM vorbei):
KAF - Kaufvertrag Erkennung und Extraktion(aktiv) schickt den Kaufvertragstext (pdf_text) direkt anopenrouter.ai, ohne PSE-Aufruf.- Ebenso direkt gehen
KAN - Kanbau API Gateway(Intent-Erkennung),BSB - Discover Session(Login-Seiten anapi.anthropic.com),CDW(Prüfaufruf) undKSUM(inaktiv).
- Nicht entscheidbar: Die OpenAI-Knoten in ASP, DOC, MAIL, CAT und OR nutzen das Credential
openAiApi. Ob es auf den LiteLLM mit PSE zeigt, ist ohne Einsicht in das Credential nicht erkennbar. ASP ruft dabei kein PSE auf. - Folge: Widerspricht der Vorgabe im Aufbauplan („Starke Modelle nur über den LiteLLM mit PSE“). Kaufverträge enthalten Namen, Anschriften und Preise.
- Vorschlag: KAF, KAN und BSB auf den LiteLLM mit PSE umstellen. Das Ziel des Credentials
openAiApiprüfen.
Geprüft, ohne Befund
- Postfach-Tokens (
mailbox_grants) und der Token-Cache in MPA sind mit AES-256-GCM verschlüsselt. - KNOW maskiert alle Werte über
sqlString/sqlJson. Bei den Operationen gibt es keine offene String-Verkettung. Die Ausnahme ist der direkte SQL-Knoten in CAT (B4). - KGW prüft HMAC und Zeitfenster und lässt nur eine feste Liste von Operationen zu.
- Die vermeintlich fehlende Spalte
workflow_decisions.decided_byexistiert (perALTERergänzt).
Gefunden mit knaster ontology check (13.10.)
Diese Befunde hat der automatische Abgleich gefunden, nachdem die Ontologie im Repo als Quelle angelegt war (SPEC-ontology).
B31 – Zwei Wörter für „bestätigt“
- Beleg:
record_workflow_decisionsetztquality_statusaufverified. Alle anderen Tabellen und Operationen nutzenconfirmed. - Folge: Auswertungen über
quality_status = 'confirmed'übersehen bestätigte Entscheidungen. - Stand in der Ontologie:
verifiedist als alternative Schreibweise vonconfirmedim Vokabular Qualitätsstatus eingetragen. Vorschlag: in KNOW aufconfirmedvereinheitlichen.
B32 – KAN-Gateway ruft eine Operation auf, die es nicht gibt
- Beleg:
KAN - Kanbau API Gateway(aktiv) ruftget_kanbau_project_patternsauf. Die Operation steht nicht in der Liste von KNOW. Das Gegenstückupsert_kanbau_project_patternsin KAN-Learn fehlt ebenso (B2). - Folge: Gelernte Projektmuster für KanBau werden weder gespeichert noch gelesen. Je nach Fehlerbehandlung des Knotens bricht das Gateway an dieser Stelle ab.
- Vorschlag: die beiden Operationen samt Zieltabelle in KNOW anlegen (und dann in der Ontologie aufnehmen) oder die Aufrufe entfernen.
B33 – Projektereignisse ohne Einordnung
- Beleg:
MPA - Projekt-Ablageruftupsert_project_eventmit den festen Wertencategory: "info"undurgency: "normal"auf. - Folge: Die Ereignisarten
verzoegerung,mangel,terminundkosten(CHECK-Constraint der Tabelle) kommen nie vor, ebenso keine Dringlichkeithigh. Eine Auswertung „Mängel pro Projekt“ ist mit diesen Daten nicht möglich. - Vorschlag: Kategorie und Dringlichkeit aus der Mail-Analyse übernehmen (MAIL bzw. CAT kennen „Mangel“) oder ein kleines Modell bzw. einen knaster-Skill einordnen lassen.