Explorer
/tmp/fast-repeat-3.json
← Zurück ↓ Download
{"queue_id": 3, "relative_path": "Runbooks/EMAIL_INGESTION_ARCHITECTURE.md", "title": "Email Ingestion Architecture — Hermes Agent", "import_key": "34ca6fa41d80904a525d2786a134a94486a2b0b12a4cf5a28b77292c56cb0176", "chunk_count": 35, "created_nodes": 0, "created_relationships": 0, "body": null, "chunks": [{"chunk_key": "12af81705507df703aa1970b4310a97b72839cb6d71c6581a5383511bd3eb555", "chunk_index": 0, "heading": "Email Ingestion Architecture — Hermes Agent", "text": "# Email Ingestion Architecture — Hermes Agent\n\n**Version:** 1.0\n**Status:** Verbindlich\n**Erstellt:** 2026-05-21\n**Gilt für:** hermes-carlo\n**Abhängigkeiten:** Tool-Gateway (8645), Session-Memory, Review-Queue\n\n---", "text_hash": "ed848ba9c9afb707392023d4f8bd8f5b79817c888c3e5c6d700e4b2e77327987"}, {"chunk_key": "ff309b57dbfd04d4b99b8ded6a359e26b9033eba9fef9dd25b6ee5fdef4ee6c3", "chunk_index": 1, "heading": "Grundsatz", "text": "**Status:** Verbindlich\n**Erstellt:** 2026-05-21\n**Gilt für:** hermes-carlo\n**Abhängigkeiten:** Tool-Gateway (8645), Session-Memory, Review-Queue\n\n---\n## Grundsatz\n\nE-Mails sind Roh-Eingabe — keine Wahrheit.\nOriginal-E-Mails werden niemals verändert.\nKein direkter Obsidian- oder Graphiti-Write.\nJede extrahierte Information wird als `proposed_fact` behandelt.\n\n---", "text_hash": "840d8d1486bd7391fc9cc8f7d5070323aa8fb2865187d6cbb476817fe4da24fc"}, {"chunk_key": "d8fc18fcac1e343a925eadf456007f2bcbe51428dcb2987ba0995a389e2d9c38", "chunk_index": 2, "heading": "Pipeline-Übersicht", "text": "l-E-Mails werden niemals verändert.\nKein direkter Obsidian- oder Graphiti-Write.\nJede extrahierte Information wird als `proposed_fact` behandelt.\n\n---\n## Pipeline-Übersicht\n\n```\nEINGANG (E-Mail)\n      │\n      ▼\n[1]  RAW SPEICHERN          → /ingestion/email/raw/{sha256}.json\n      │  Original unverändert, SHA256 für Duplikatsprüfung\n      ▼\n[2]  DUPLIKAT-CHECK         → SHA256 gegen raw/ prüfen\n      │  Duplikat → /ingestion/email/rejected/{sha256}_duplicate.json\n      ▼\n[3]  TEXT EXTRAHIEREN       → /ingestion/email/extracted/{sha256}.txt\n      │  Subject + Body, HTML→Text, Attachments ignoriert (Phase 1)\n      ▼\n[4]  PII / SECRET MASKING   → /ingestion/email/masked/{sha256}.txt\n      │  E-Mail, Telefon, IBAN, API-Keys, Passwörter\n      ▼\n[5]  PROJEKT ERKENNEN       → /ingestion/email/classified/{sha256}.json\n      │  Keyword-Matching gegen PROJECT_MAP\n      ▼\n[6]  RETRIEVAL              → POST /retrieval/context\n      │  Kontext aus Obsidian + Graphiti laden\n      ▼\n[7]  PROPOSED_FACTS ERZEUGEN\n      │  Aus E-Mail-Inhalt + Retrieval-Kontext ableiten\n      │  Status immer: inferred (nicht user_stated, nicht verified)\n      ▼\n[8]  REVIEW-QUEUE           → /memory/review-queue/{review_id}.json\n      │  Ein Eintrag pro proposed_fact\n      ▼\n[9]  AUDIT LOG              → /ingestion/email/ingestion_audit.jsonl\n```\n\n---", "text_hash": "936918e55f0c4777fca2572dd53ea17e6594c020b3a8ed70c860ec48f04996ef"}, {"chunk_key": "54c0fee2130f2e650e6353157bda03892e50950d8ae323bb8805fe66c2e4de8b", "chunk_index": 3, "heading": "Verzeichnisstruktur", "text": "ew-queue/{review_id}.json\n      │  Ein Eintrag pro proposed_fact\n      ▼\n[9]  AUDIT LOG              → /ingestion/email/ingestion_audit.jsonl\n```\n\n---\n## Verzeichnisstruktur\n\n```\n/opt/struktur/ingestion/email/\n├── raw/           ← Original-E-Mails (niemals verändern)\n│   └── {sha256}.json\n├── extracted/     ← Reiner Text (Subject + Body)\n│   └── {sha256}.txt\n├── classified/    ← Projektzuordnung + Metadaten\n│   └── {sha256}.json\n├── masked/        ← PII-maskierter Text\n│   └── {sha256}.txt\n├── rejected/      ← Dubletten + fehlerhafte Eingaben\n│   └── {sha256}_{reason}.json\n├── approved/      ← Nach Human-Review approved (leer in Phase 1)\n└── ingestion_audit.jsonl  ← Jede Operation geloggt\n```\n\n---", "text_hash": "b308bc1a802571c76df1a02a4e4f6b3247380c9a21583b28add452141319b99a"}, {"chunk_key": "e9c79db0f350786564834c65b08f54c618681b977d2b95b8d8dd645b30e48f9c", "chunk_index": 4, "heading": "Schritt 1: Raw-Speicherung", "text": " {sha256}_{reason}.json\n├── approved/      ← Nach Human-Review approved (leer in Phase 1)\n└── ingestion_audit.jsonl  ← Jede Operation geloggt\n```\n\n---\n## Schritt 1: Raw-Speicherung", "text_hash": "48c66d7074daeff88910edd627ddd89557f9e5851d6e424984e7a7b5cbd2c704"}, {"chunk_key": "9da9d54ad92d09531818ec3c0b279b150123265582d8eee657b3be1b6b7513bf", "chunk_index": 5, "heading": "Format (`raw/{sha256}.json`):", "text": "## Schritt 1: Raw-Speicherung\n### Format (`raw/{sha256}.json`):\n```json\n{\n  \"sha256\": \"abc123...\",\n  \"ingested_at\": \"2026-05-21T14:00:00Z\",\n  \"source\": \"manual | gmail_api | imap\",\n  \"message_id\": \"<id@domain>\",\n  \"from_raw\": \"[EMAIL]\",\n  \"to_raw\": \"[EMAIL]\",\n  \"subject\": \"...\",\n  \"date\": \"2026-05-21T13:00:00Z\",\n  \"body_raw\": \"...\",\n  \"attachments\": [],\n  \"processing_status\": \"raw\"\n}\n```", "text_hash": "925ba283a5ce2946c693d4f92d17bdacdb7671e33954561dd9c90e2b3945e79c"}, {"chunk_key": "0d8bf1c91eaa77383c88e5b4441e81696ebb44b09e84b37dfea33425741cda41", "chunk_index": 6, "heading": "Regeln:", "text": "to_raw\": \"[EMAIL]\",\n  \"subject\": \"...\",\n  \"date\": \"2026-05-21T13:00:00Z\",\n  \"body_raw\": \"...\",\n  \"attachments\": [],\n  \"processing_status\": \"raw\"\n}\n```\n### Regeln:\n- SHA256 über `message_id + subject + date` (nicht über Body — zu volatil)\n- `from_raw` und `to_raw` sofort als `[EMAIL]` maskieren beim Speichern\n- Original-Body unverändert in `body_raw`\n- `processing_status` wird durch Pipeline-Schritte aktualisiert\n\n---", "text_hash": "130393271739f688a00ef4602dd2d702ebae17b1e28ee76b9efaa87834d61f4c"}, {"chunk_key": "2a958f605f6e3085c54c1a1e87b9c02f57ff9cb0f077ac5c721068c0163c63e0", "chunk_index": 7, "heading": "Schritt 2: Duplikat-Check", "text": " als `[EMAIL]` maskieren beim Speichern\n- Original-Body unverändert in `body_raw`\n- `processing_status` wird durch Pipeline-Schritte aktualisiert\n\n---\n## Schritt 2: Duplikat-Check", "text_hash": "34f2021e10525647248a499d14f5ff978f28622b13d956950d3563f112282f2b"}, {"chunk_key": "d8291bab6da4ea61233be3a10c8e9c01fb3c433b29b47d0593777bd810d405e0", "chunk_index": 8, "heading": "Methode:", "text": "## Schritt 2: Duplikat-Check\n### Methode:\nSHA256 des eingehenden Mails gegen alle Dateien in `raw/` prüfen.\n\n```python\nsha256 = hashlib.sha256(f\"{message_id}{subject}{date}\".encode()).hexdigest()\nif (RAW_DIR / f\"{sha256}.json\").exists():\n    → rejected/{sha256}_duplicate.json\n```", "text_hash": "d9bbcd63dbe9c428515e9505b526f0762bf9c8c52849308031f7e488ac64d569"}, {"chunk_key": "4a97af202d0b2e549d869e1ef1e10d51c3e4f79d26e8eb7729a711669ec3e101", "chunk_index": 9, "heading": "Rejected-Format:", "text": "shlib.sha256(f\"{message_id}{subject}{date}\".encode()).hexdigest()\nif (RAW_DIR / f\"{sha256}.json\").exists():\n    → rejected/{sha256}_duplicate.json\n```\n### Rejected-Format:\n```json\n{\n  \"sha256\": \"...\",\n  \"reason\": \"duplicate\",\n  \"rejected_at\": \"...\",\n  \"original_file\": \"raw/{sha256}.json\"\n}\n```\n\n---", "text_hash": "1f3d33bf967db9e4ec084bc730732925273e9188112f2d364f79652090c7a470"}, {"chunk_key": "823870687af0c06031f1dbcf7b26ee813984112acde7e32428463790be9b0128", "chunk_index": 10, "heading": "Schritt 3: Textextraktion", "text": "### Rejected-Format:\n```json\n{\n  \"sha256\": \"...\",\n  \"reason\": \"duplicate\",\n  \"rejected_at\": \"...\",\n  \"original_file\": \"raw/{sha256}.json\"\n}\n```\n\n---\n## Schritt 3: Textextraktion", "text_hash": "88ae7db584b7e7276681811d124644384612da3029323170b02853d90690dc7c"}, {"chunk_key": "8b24ef4479e789ef17d1d493766432ecd99430cbeafa056d07714a98b661f7d7", "chunk_index": 11, "heading": "Was extrahiert wird:", "text": "## Schritt 3: Textextraktion\n### Was extrahiert wird:\n- Subject (vollständig)\n- Body (plain text; HTML wird zu Text konvertiert)", "text_hash": "11d56f3de947987d2dc3d1efc50766c86db858ae1daa64f2402bd9355c05ea2e"}, {"chunk_key": "1bdef13bd0fc000ee72f5a9ea0aa0ba994b7426e5fd674994eae29080b7ee2a4", "chunk_index": 12, "heading": "Was ignoriert wird (Phase 1):", "text": "### Was extrahiert wird:\n- Subject (vollständig)\n- Body (plain text; HTML wird zu Text konvertiert)\n### Was ignoriert wird (Phase 1):\n- Anhänge (PDFs, Bilder, Excel)\n- Inline-Bilder\n- E-Mail-Header (außer Subject/Date/From/To)", "text_hash": "7322ca03c365d38c7c0db690d4afbfc29f1719b896fd7087a3310c48887aa03e"}, {"chunk_key": "9932903a5c0739a411ce731c0f8df545c565f2d3509fe4213b9ba0c198b62268", "chunk_index": 13, "heading": "Output (`extracted/{sha256}.txt`):", "text": "### Was ignoriert wird (Phase 1):\n- Anhänge (PDFs, Bilder, Excel)\n- Inline-Bilder\n- E-Mail-Header (außer Subject/Date/From/To)\n### Output (`extracted/{sha256}.txt`):\n```\nSUBJECT: [Betreff]\nDATE: [Datum]\n---\n[Body als plain text]\n```\n\n---", "text_hash": "5c559679e76b0686baaf0449ad29564ef3432d6bce9760883b80d862d32488fc"}, {"chunk_key": "daeeb4e229d852c572c6521b942d29c05b99ee4ee8d90b26870295926e6bc4e1", "chunk_index": 14, "heading": "Schritt 4: PII- und Secret-Masking", "text": "### Output (`extracted/{sha256}.txt`):\n```\nSUBJECT: [Betreff]\nDATE: [Datum]\n---\n[Body als plain text]\n```\n\n---\n## Schritt 4: PII- und Secret-Masking", "text_hash": "9f48969b61bcf51157e0c73a43bfc965326d4fe596146d49f9d70d0ec7e660a0"}, {"chunk_key": "37e3e5648cdcf70da5c8a560e554a4c6289c159645a556de17b5d68364fe90f5", "chunk_index": 15, "heading": "Maskiert werden:", "text": "## Schritt 4: PII- und Secret-Masking\n### Maskiert werden:\n| Typ | Muster | Ersatz |\n|-----|--------|--------|\n| API-Keys | `sk-...`, `ghp_...`, `sk-or-v1-...` | `[API_KEY]` |\n| Tokens | `Bearer ...`, `xoxb-...` | `[TOKEN]` |\n| Passwörter | `password=...`, `pwd:...` | `[PASSWORD]` |\n| E-Mail-Adressen | `x@y.z` | `[EMAIL]` |\n| Telefonnummern | `+34 ...`, `0049...` | `[PHONE]` |\n| IBAN | `DE12 ...` | `[IBAN]` |", "text_hash": "2704d74af1552267e0ad51be3177523bfd56822f72352b65b446d7aff12672a1"}, {"chunk_key": "6e39fe8c9a764542c53621bc07442fb74f459f583fc9c98c23796243d4f5bad7", "chunk_index": 16, "heading": "Wichtig:", "text": "...` | `[PASSWORD]` |\n| E-Mail-Adressen | `x@y.z` | `[EMAIL]` |\n| Telefonnummern | `+34 ...`, `0049...` | `[PHONE]` |\n| IBAN | `DE12 ...` | `[IBAN]` |\n### Wichtig:\n- Masking läuft auf dem maskierten Text — nicht auf dem Raw\n- Raw-Datei bleibt immer unverändert\n- Masking-Output nach `masked/{sha256}.txt`\n\n---", "text_hash": "0333f3ad016c2aa7612ab221cd7c71710347fbb88c29e3c53eac1685c0777ac3"}, {"chunk_key": "416be21b1bc24dfc1cbbaebc39d917609884ab4000ec27a9171a88a6ebc4124a", "chunk_index": 17, "heading": "Schritt 5: Projekterkennung", "text": "tig:\n- Masking läuft auf dem maskierten Text — nicht auf dem Raw\n- Raw-Datei bleibt immer unverändert\n- Masking-Output nach `masked/{sha256}.txt`\n\n---\n## Schritt 5: Projekterkennung", "text_hash": "c5717c82a45798bb6383ec0819ed4c65b60f359ab22e6147883dddd6e0b9a0c7"}, {"chunk_key": "5c3ca9482079b9dbfb828917283c71dbdfa11bc97da31fd69339802a9ccba55d", "chunk_index": 18, "heading": "Methode: Keyword-Matching", "text": "## Schritt 5: Projekterkennung\n### Methode: Keyword-Matching\n\n```python\nPROJECT_MAP = {\n    \"vento\":           [\"vento\", \"whatsapp\", \"dialog-engine\", \"twilio\"],\n    \"hermes\":          [\"hermes\", \"agent\", \"gateway\", \"retrieval\"],\n    \"graphiti\":        [\"graphiti\", \"knowledge graph\", \"neo4j\"],\n    \"mirofish\":        [\"mirofish\", \"multi-agent\", \"simulation\"],\n    \"n8n\":             [\"n8n\", \"workflow\", \"automation\"],\n    \"the donna\":       [\"the donna\", \"donna\", \"electron\"],\n    \"kiki\":            [\"kiki\", \"lernbegleiterin\"],\n    \"agent solutions\": [\"agent solutions\", \"agentsolutions\"],\n}\n```", "text_hash": "08cc69f4bdd980b6799ba6310b085fc4dabb92b3ae8c4caae491837993c59594"}, {"chunk_key": "248a3570d92a8dd1ded8f0b74c355f4b48fe7956dcb72e99425eb6b83ff7400c", "chunk_index": 19, "heading": "Scoring:", "text": " donna\", \"donna\", \"electron\"],\n    \"kiki\":            [\"kiki\", \"lernbegleiterin\"],\n    \"agent solutions\": [\"agent solutions\", \"agentsolutions\"],\n}\n```\n### Scoring:\n- Jeder Treffer im Subject: 3 Punkte\n- Jeder Treffer im Body: 1 Punkt\n- Projekt mit höchstem Score gewinnt\n- Kein klares Ergebnis (Score = 0): `project = \"unclassified\"`", "text_hash": "e2ce1d8c1105153ad7ef06abd9d61794e4a2af6708ee307fadda3d77953b7e50"}, {"chunk_key": "34785ba38292c27764bbc88a5609edea90caacb1bf325136e7867a1b3b6728e4", "chunk_index": 20, "heading": "Output (`classified/{sha256}.json`):", "text": "Subject: 3 Punkte\n- Jeder Treffer im Body: 1 Punkt\n- Projekt mit höchstem Score gewinnt\n- Kein klares Ergebnis (Score = 0): `project = \"unclassified\"`\n### Output (`classified/{sha256}.json`):\n```json\n{\n  \"sha256\": \"...\",\n  \"project\": \"vento\",\n  \"project_score\": 7,\n  \"matched_keywords\": [\"vento\", \"whatsapp\"],\n  \"classified_at\": \"...\"\n}\n```\n\n---", "text_hash": "323a4319c871fb4abacb292eab3d7f3ec6148a6040ec7733e2da56ab1e01c308"}, {"chunk_key": "2905719dd3db6cfea1a11e943a99bc6439d606869f4064b56c1c7c3aca5a02c2", "chunk_index": 21, "heading": "Schritt 6: Retrieval", "text": "json\n{\n  \"sha256\": \"...\",\n  \"project\": \"vento\",\n  \"project_score\": 7,\n  \"matched_keywords\": [\"vento\", \"whatsapp\"],\n  \"classified_at\": \"...\"\n}\n```\n\n---\n## Schritt 6: Retrieval", "text_hash": "1cf2e0d8227abdae261030419ad48eca71ada4f65db14437710f61e3f028f3d0"}, {"chunk_key": "ad4d7a6f2f88d744591e87bbdb0146819ea0fee3b403d08fed7f374a7a4643d3", "chunk_index": 22, "heading": "Aufruf:", "text": "## Schritt 6: Retrieval\n### Aufruf:\n```json\nPOST /retrieval/context\n{\n  \"query\": \"<Subject der E-Mail>\",\n  \"project\": \"<erkanntes Projekt>\"\n}\n```", "text_hash": "d5fc313146a8936bc1f23485536a3bd4462d27167955481327a84d5b4fea5593"}, {"chunk_key": "b3927587703a584df4d8fe3edbf41487a16a4316fa842d51ff6704b97d340f9c", "chunk_index": 23, "heading": "Zweck:", "text": "### Aufruf:\n```json\nPOST /retrieval/context\n{\n  \"query\": \"<Subject der E-Mail>\",\n  \"project\": \"<erkanntes Projekt>\"\n}\n```\n### Zweck:\n- Bestehenden Obsidian-Kontext laden\n- Graphiti-Facts laden\n- Abgleich: Widerspricht der E-Mail-Inhalt bestehendem Wissen?\n- Confidence bestimmt Fact-Status der proposed_facts", "text_hash": "2b6cbb19280f73770b4b6d738f985dc8e9a4680c969557794eb6b6c73305d6f4"}, {"chunk_key": "b2b64e38f6705f033cbbbf4d948d1e4489e11898dfe3e9af28d6b217068f61b8", "chunk_index": 24, "heading": "Confidence-Mapping:", "text": "ntext laden\n- Graphiti-Facts laden\n- Abgleich: Widerspricht der E-Mail-Inhalt bestehendem Wissen?\n- Confidence bestimmt Fact-Status der proposed_facts\n### Confidence-Mapping:\n| Retrieval-Confidence | proposed_fact Status |\n|---------------------|---------------------|\n| `high` | `inferred` (guter Kontext vorhanden) |\n| `medium` | `inferred` |\n| `low` | `inferred` + Risk-Flag \"Wenig Kontext\" |\n\n---", "text_hash": "22ac8a8ad630bf6cbd23eca8fd6ca21848c95e36e5403e386499479b5016f1a7"}, {"chunk_key": "afefe46de4a87dc990359e8485847cc97ab52038bbab3bab7934a61637af0172", "chunk_index": 25, "heading": "Schritt 7: Proposed Facts erzeugen", "text": "-----------------|\n| `high` | `inferred` (guter Kontext vorhanden) |\n| `medium` | `inferred` |\n| `low` | `inferred` + Risk-Flag \"Wenig Kontext\" |\n\n---\n## Schritt 7: Proposed Facts erzeugen", "text_hash": "29da4815c3bbe41cb872dbfbaabf33ce55d516fc6e231f43ff285e40385e8fe5"}, {"chunk_key": "412c4123bb89c6ba6bbd3c070a0ac94f070a11440b2bdde75ae7793e33f87d6c", "chunk_index": 26, "heading": "Regeln:", "text": "## Schritt 7: Proposed Facts erzeugen\n### Regeln:\n- Status immer `inferred` (nie `user_stated`, nie `verified`)\n- E-Mail ist Fremdquelle — nicht vertrauenswürdiger als Chat\n- Maximal 5 proposed_facts pro E-Mail\n- Nur faktische Aussagen, keine Vermutungen extrahieren\n- Kein PII in proposed_facts", "text_hash": "3b39beefa054464d4fa661510ad495c9dd501337281888295b3690f5f527ad32"}, {"chunk_key": "cb180c2a73a1428c21de017f4c2570311aeb4aa2b1db336f048a9e02ad173b6f", "chunk_index": 27, "heading": "Format:", "text": "vertrauenswürdiger als Chat\n- Maximal 5 proposed_facts pro E-Mail\n- Nur faktische Aussagen, keine Vermutungen extrahieren\n- Kein PII in proposed_facts\n### Format:\n```json\n{\n  \"fact\": \"Vento Telegram-Integration wurde implementiert\",\n  \"status\": \"inferred\",\n  \"confidence\": \"unverified\",\n  \"source_type\": \"email\",\n  \"source_sha256\": \"abc123...\",\n  \"proposed_obsidian_page\": \"03-Projekte/LP-VENTO.md\",\n  \"obsidian_write_allowed\": false,\n  \"graphiti_write_allowed\": false\n}\n```\n\n---", "text_hash": "9696a19fe0b0607b5faddf3bb771ac8c7a7038fcec2d951671b43469ed16f6d2"}, {"chunk_key": "3a779f8d5adef92c0d4227a7820dc6a91b3e01acd1af0a51b78318bcef5c1816", "chunk_index": 28, "heading": "Schritt 8: Review-Queue-Integration", "text": "\": \"abc123...\",\n  \"proposed_obsidian_page\": \"03-Projekte/LP-VENTO.md\",\n  \"obsidian_write_allowed\": false,\n  \"graphiti_write_allowed\": false\n}\n```\n\n---\n## Schritt 8: Review-Queue-Integration", "text_hash": "02b641b7ced221cbbff79f939213ab344ccb58d1d422e64a2a8b2ec0d4a53248"}, {"chunk_key": "7ff3042cec76995710086e8ac0bff9e122dcf2832fa110d5d9e291534f024f4d", "chunk_index": 29, "heading": "Pro proposed_fact eine Review-Datei:", "text": "## Schritt 8: Review-Queue-Integration\n### Pro proposed_fact eine Review-Datei:\n```json\n{\n  \"review_id\": \"REVIEW-{ts}-{uuid6}\",\n  \"created_at\": \"...\",\n  \"status\": \"pending\",\n  \"source_type\": \"email\",\n  \"source_sha256\": \"abc123...\",\n  \"source_subject\": \"[maskierter Betreff]\",\n  \"proposed_fact\": \"...\",\n  \"fact_status\": \"inferred\",\n  \"confidence\": \"unverified\",\n  \"requires_human_review\": true,\n  \"obsidian_write_allowed\": false,\n  \"graphiti_write_allowed\": false,\n  \"expires_at\": \"<created_at + 14 Tage>\"\n}\n```\n\n---", "text_hash": "edb3c98e08120602d0169f5a64ada8ab2c7b13eb78404c7501af966a6d9fdf9c"}, {"chunk_key": "67f97f73bcf8daf064dd0d98e1c2b1190cbb1fbe2452dd66f3123f3160c95104", "chunk_index": 30, "heading": "Schritt 9: Audit-Logging", "text": "equires_human_review\": true,\n  \"obsidian_write_allowed\": false,\n  \"graphiti_write_allowed\": false,\n  \"expires_at\": \"<created_at + 14 Tage>\"\n}\n```\n\n---\n## Schritt 9: Audit-Logging", "text_hash": "6b7a7dd96c8a152423bb5c9b3547ac8ec1771210c63bfbfe99b16938972ed181"}, {"chunk_key": "96331006191853c0797045d676c6ffd5da0aa6fc2ea5f33c001defcc9c0c3a68", "chunk_index": 31, "heading": "Jede Operation wird in `ingestion_audit.jsonl` geloggt:", "text": "## Schritt 9: Audit-Logging\n### Jede Operation wird in `ingestion_audit.jsonl` geloggt:\n```json\n{\"timestamp\": \"...\", \"sha256\": \"...\", \"step\": \"raw|extract|mask|classify|retrieval|facts|review\", \"status\": \"ok|error|duplicate\", \"detail\": \"...\"}\n```\n\n---", "text_hash": "fedd0c8a416cc0502a5dc4f498295cc6ba6571dcd1fe47420d07cecad9879ba1"}, {"chunk_key": "d0596e6dd3f6b640d340fc5ab457b8538320a540873f99f3edd2a7191663b7b2", "chunk_index": 32, "heading": "Fehlerbehandlung", "text": "estamp\": \"...\", \"sha256\": \"...\", \"step\": \"raw|extract|mask|classify|retrieval|facts|review\", \"status\": \"ok|error|duplicate\", \"detail\": \"...\"}\n```\n\n---\n## Fehlerbehandlung\n\n| Fehler | Verhalten |\n|--------|-----------|\n| Duplikat erkannt | → `rejected/`, Pipeline stoppt, Audit-Eintrag |\n| Textextraktion schlägt fehl | → Pipeline stoppt, Fehler in Audit |\n| PII-Masking schlägt fehl | → Pipeline stoppt, Raw-Datei bleibt unverändert |\n| Projekterkennung: kein Treffer | → `project: unclassified`, Pipeline läuft weiter |\n| Retrieval nicht erreichbar | → proposed_facts trotzdem erzeugen, Risk-Flag: \"Kein Retrieval-Kontext\" |\n| Review-Queue-Write schlägt fehl | → Fehler in Audit, proposed_facts gehen verloren (kein Silent Fail) |\n\n---", "text_hash": "c5abf0f6bdb1a54c007150d4a507800e940bcc969c04167e5f8738207c8df3f5"}, {"chunk_key": "95e6a5f93c1e479961b4b75e8c591fcb024336f1202f2761cd37e7e3a723b9a4", "chunk_index": 33, "heading": "Sicherheitsregeln", "text": ", Risk-Flag: \"Kein Retrieval-Kontext\" |\n| Review-Queue-Write schlägt fehl | → Fehler in Audit, proposed_facts gehen verloren (kein Silent Fail) |\n\n---\n## Sicherheitsregeln\n\n| Regel | Detail |\n|-------|--------|\n| Original niemals verändern | `raw/` ist write-once |\n| Secrets niemals persistieren | Masking vor jedem Write außer `raw/` |\n| Kein Obsidian-Write | Kein Endpunkt freigegeben |\n| Kein Graphiti-Write | Kein Endpunkt freigegeben |\n| Kein Silent Fail | Jeder Fehler wird auditiert |\n| Kein Batch-Auto-Approve | Jeder proposed_fact einzeln per Human-Review |\n\n---", "text_hash": "9bf9a260510e25e0c71a083a9231c52aced1e61a7d795d4d14985a4bec36abd6"}, {"chunk_key": "216ea52e431889ac9473da3ef2ebfa196c26aaa4993b74b7a8ce3e1a5ad5e7b1", "chunk_index": 34, "heading": "Erkannte Risiken", "text": "punkt freigegeben |\n| Kein Silent Fail | Jeder Fehler wird auditiert |\n| Kein Batch-Auto-Approve | Jeder proposed_fact einzeln per Human-Review |\n\n---\n## Erkannte Risiken\n\n| Risiko | Impact | Mitigation |\n|--------|--------|-----------|\n| E-Mail enthält API-Key im Body | Kritisch | Masking vor Extract; Raw nie geteilt |\n| Falsche Projektzuordnung | Mittel | Score-Threshold; unclassified als Fallback |\n| Viele proposed_facts aus Sammel-Mails | Mittel | Max. 5 Facts pro E-Mail |\n| Retrieval offline → Facts ohne Kontext | Mittel | Risk-Flag, Human entscheidet bei Review |\n| Gleiche Information aus mehreren Quellen | Niedrig | SHA256-Duplikatsprüfung + Dublettencheck in Review |\n| PII in proposed_fact | Hoch | Masking auf maskierten Text anwenden bevor Facts extrahiert werden |\n\n---\n\n*Architekturdatei: `/opt/struktur/hermes-carlo/ingestion/EMAIL_INGESTION_ARCHITECTURE.md`*\n*Pipeline-Script: `/opt/struktur/ingestion/ingest_email.py`*\n*Ingestion-Root: `/opt/struktur/ingestion/email/`*", "text_hash": "2634843fce84f5d30e5bc9e7936f7f43f7c1ca67248fc6b255b7e511924a8dfe"}], "elapsed_s": 0.053}