- mail/internal/dedup/hash.go: HashAndBuffer, SHA-256 auf Klartext VOR Verschluesselung (ARC-02), liefert erneut lesbaren Reader zurueck. - mail/internal/dedup/store.go: Store (Postgres, tenant_slug fest im Primaerschluessel gebunden), Register: Duplikat referenziert Original statt redundant zu speichern. - Alle 3 Pflichtpruefungen real bestanden (siehe mail/docs/ARC-03-PRUEFPROTOKOLL.md): Duplikat aus zwei Quellen erkannt, zwei Mandanten mit identischem Inhalt nicht verknuepft, knapp unterschiedliche Nachricht korrekt nicht erkannt. - Kein Umbau: internal/storage, internal/crypto, internal/encstorage unveraendert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.0 KiB
3.0 KiB
ARC-03 – Prüfprotokoll: Dublettenerkennung E-Mail
Voraussetzung ARC-01 (Mail, Fertig).
Umsetzung
mail/internal/dedup/hash.go—HashAndBuffer(plaintext io.Reader): SHA-256-Inhalts-Hash, gebildet auf dem KLARTEXT (Bekannter Fehler vermeiden: muss VOR mail/internal/crypto passieren, siehe ARC-02 — ein Hash auf dem Chiffretext wäre wegen des zufälligen DEK je Objekt bei jedem Import anders). Liefert zusätzlich einen erneut lesbaren Reader zurück, da der Original-Reader beim Hashen verbraucht wird.mail/internal/dedup/store.go—Store.Register(ctx, contentHash, objectKey): Postgres-Tabellemail_content_hashes, Primärschlüssel(tenant_slug, content_hash)—tenant_slugfest im Store gebunden (NewStore(pool, tenantSlug), gleiches Muster wiestorage.Service/encstorage.Service), nicht nur Konvention.ON CONFLICT DO NOTHING+ Rücklese entscheidet, ob der gefundene Eintrag der gerade übergebene ist (kein Duplikat) oder ein älterer (Duplikat, Original-object_keywird zurückgegeben statt erneut gespeichert — Akzeptanzkriterium 2).- Kein Umbau:
mail/internal/storage/mail/internal/crypto/mail/internal/encstorageunverändert (git diff --statbleibt für alle drei leer).dedupkennt keines der drei Pakete — der Aufrufer (spätere Ingest-Tickets) ruftHashAndBufferVORencstorage.Putauf.
Prüfungen
| # | Prüfung | Ergebnis |
|---|---|---|
| 1 | Test: dieselbe Nachricht aus zwei Quellen wird als Duplikat erkannt | bestanden – TestRegister_SameMessageFromTwoSourcesIsDuplicate: gleicher Hash, zwei verschiedene object_key ("quelle-1/objekt", "quelle-2/objekt") — zweite Registrierung liefert real isDuplicate=true und referenziert das Original quelle-1/objekt |
| 2 | Test: zwei Mandanten mit identischem Mailinhalt werden nicht fälschlich verknüpft | bestanden – TestRegister_SameContentTwoTenantsNotLinked: zwei Store-Instanzen mit unterschiedlichem tenantSlug, IDENTISCHER Hash — beide Registrierungen liefern real isDuplicate=false, keine Verknüpfung über die Mandantengrenze |
| 3 | Test mit knapp unterschiedlichen Nachrichten bestätigt korrekte Nicht-Erkennung | bestanden – TestHashAndBuffer_SlightlyDifferentContentDifferentHash: zwei Nachrichten, die sich nur im letzten Zeichen unterscheiden (. vs ,) — real unterschiedlicher SHA-256-Hash |
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 \
go test ./... -v -p 1 -> alle Pakete bestanden, inkl. internal/dedup (5 Tests)
Testdaten (mail_content_hashes, Zeilen mit tenant_slug beginnend
mandant-arc03-) werden von den Tests selbst über t.Cleanup
entfernt.
Gesamtergebnis
Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Entsperrt SRC-01, SRC-02, SRC-07.