Files
nexarch/mail/docs/SRC-01-PRUEFPROTOKOLL.md
sysopsandClaude Sonnet 5 c3bf8100b1 SRC-01: manticore-suchindex-fuer-mails
Manticore-RT-Index für Mail-Suchdokumente (Betreff, Text, Anhangstext,
Metadaten), statisches versioniertes Schema.

- fields.go: statische Feld-/Index-Namen-Whitelist, einzige Quelle für
  Feldnamen im Paket (vermeidet known-issues-archivmail.md #11/#12:
  Sprintf/Join-basierte SQL-Klauselbildung).
- migrations/0001_mail_documents.sql: statisches Schema, per go:embed
  eingebettet, über /sql?mode=raw angelegt (kein String-Zusammenbau).
- client.go: Index/Search über die strukturierte Manticore-HTTP-JSON-API,
  Tenant-Filter über strukturiertes equals-Feld statt WHERE-Interpolation.

Prüfungen (alle real durchgeführt, siehe mail/docs/SRC-01-PRUEFPROTOKOLL.md):
1. TestNoDynamicSQLClauseBuilding: automatisierter Quelltext-Scan bestätigt
   keine Sprintf/Join-SQL-Klauselbildung.
2. TestSearch_MaliciousInputDoesNotAlterFieldNames: Injection-artige
   Eingaben verändern nachweislich keine Feldnamen im gesendeten Payload.
3. TestSearch_FindsExpectedDocument: Funktionstest gegen echtes Manticore
   auf 192.168.1.131 liefert erwartete Treffer.
Zusätzlich TestSearch_TenantIsolation für Akzeptanzkriterium 3.

Kein Umbau: storage/crypto/encstorage/dedup unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
2026-08-31 09:40:29 +02:00

3.6 KiB
Raw Permalink Blame History

SRC-01 Prüfprotokoll: Manticore-Suchindex für Mails

Voraussetzung ARC-01, ARC-03 (beide Fertig).

Umsetzung

  • mail/internal/search/fields.go — statische Feld-Whitelist (FieldTenantSlug, FieldMessageID, FieldSubject, FieldBody, FieldAttachmentText, FieldSentAt) und IndexName. Bekannten Fehler vermeiden (known-issues-archivmail.md #11/#12): archivmail baute WHERE-Klauseln und teils Spalten-/Tabellennamen dynamisch über fmt.Sprintf/strings.Join. Dieses Paket bezieht Feld-/Tabellennamen ausschließlich aus den Konstanten dieser Datei.
  • mail/internal/search/migrations/0001_mail_documents.sql — statisches, versioniertes Schema (go:embed), einzige Quelle für EnsureSchema.
  • mail/internal/search/client.goClient:
    • EnsureSchema legt den Index über den Manticore /sql?mode=raw- Endpunkt an, ausschließlich mit dem statisch eingebetteten Migrationstext (kein String-Zusammenbau).
    • Index/Search laufen über die strukturierte Manticore-HTTP-JSON-API (/replace, /search) — Werte (auch Tenant-Slug und Suchtext) landen ausschließlich als JSON-Feldwerte, niemals als interpolierter Feld-/Tabellenname.
    • Search filtert zwingend über FieldTenantSlug (Akzeptanzkriterium 3).
  • Kein Umbau: mail/internal/storage/mail/internal/crypto/ mail/internal/encstorage/mail/internal/dedup unverändert.

Prüfungen

# Prüfung Ergebnis
1 Codereview bestätigt: keine Sprintf/Join-basierte SQL-Klauselbildung im Index-Zugriff bestanden TestNoDynamicSQLClauseBuilding: automatisierter Quelltext-Scan von client.go bestätigt, dass kein fmt.Sprintf verwendet wird und in der Nähe des /sql?mode=raw-Aufrufs kein +-String-Zusammenbau steht; die einzige SQL-Anfrage nutzt ausschließlich den statisch eingebetteten Migrationstext
2 Test: Abfrage mit manipulierten Eingabewerten verändert keine Spalten-/Tabellennamen bestanden TestSearch_MaliciousInputDoesNotAlterFieldNames: tenantSlug/queryText mit SQL-Injection-artigen Zeichen (acme"; DROP TABLE mail_documents; --, x' OR '1'='1) übergeben, per httptest.Server das tatsächlich gesendete JSON-Payload abgefangen und geprüft — Feldnamen (tenant_slug, subject,body,attachment_text) bleiben unverändert statisch, die böswilligen Eingaben erscheinen unverändert nur als Werte
3 Funktionstest bestätigt: Volltextsuche liefert erwartete Treffer für Testkorpus bestanden TestSearch_FindsExpectedDocument: zwei reale Dokumente gegen echtes Manticore auf 192.168.1.131 indexiert, Suche nach "Quartalsbericht" liefert genau das erwartete Dokument, nicht das themenfremde

Zusätzlich (Akzeptanzkriterium 3, mandantengetrennt): TestSearch_TenantIsolation — identischer Suchbegriff bei Mandant A indexiert, Suche bei Mandant B liefert keinen Treffer aus Mandant A.

Build/Test-Ergebnis (192.168.1.131)

go build ./...  -> clean
go vet ./...    -> clean
golangci-lint run ./...  -> 0 issues
TEST_TENANT_DSN=postgresql://nexarch_test:***@localhost:5432/tenant_acme?sslmode=disable \
TEST_MANTICORE_URL=http://127.0.0.1:9308 \
  go test ./... -v -p 1  -> alle Pakete bestanden, inkl. internal/search (4 Tests)

Manticore lief bereits produktiv auf 192.168.1.131 (Port 9308, Version 7.4.1, Dienst manticore.service aktiv seit 2026-08-28). Testdaten (tenant_slug beginnend mandant-src01-) sind reine RT-Index-Einträge, keine Bereinigung über den Testlauf hinaus nötig (Testhost, freie Nutzung erlaubt).

Gesamtergebnis

Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Entsperrt SRC-02, SRC-03, SRC-09.