# SRC-08 – Prüfprotokoll: Gespeicherte Suchanfragen Voraussetzung SRC-03 (Fertig). ## Umsetzung - `mail/internal/savedsearch/store.go` — `Store` (Postgres, `mail_saved_searches`): `Save` (Upsert über `UNIQUE(tenant_slug, user_id, name)`, Akzeptanzkriterium 1), `List`/`Get` streng auf Mandant UND Benutzer beschränkt (Akzeptanzkriterium 3), `Delete` löscht genau eine Zeile über `tenant_slug + user_id + id`. „Benutzer" ist bis zu einer zentralen Session-/IAM-Anbindung (Core-Board-Scope) ein vom Aufrufer mitgegebener opaker `userID`-String — dieselbe Konvention wie der Tenant-Kontext in `web/mail-search` (SRC-04). - `Execute(ctx, client, saved)` führt die gespeicherte Suche LIVE gegen `search.Client` aus — speichert selbst keine Treffer, jeder Aufruf fragt Manticore neu ab (Akzeptanzkriterium 2). - `mail/internal/search/facets.go` — kleinste nötige Erweiterung: neue Methode `Client.SearchWithFilters` (gemeinsame `buildFilteredMust`- Hilfsfunktion mit `Facets` extrahiert) liefert TATSÄCHLICH gefilterte Treffer statt nur Facettenzählungen — ohne dies gäbe es keinen echten Weg, gespeicherte Filter beim Wiederausführen anzuwenden. - Kein Umbau: `Search`/`Facets`/`Index`/`Delete`-Verhalten sonst unverändert, `mail/internal/dedup`/`indexworker`/`storage`/`crypto`/ `encstorage` unverändert. ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Test: gespeicherte Suche mit mehreren Filtern wird korrekt reproduziert | **bestanden** – `TestExecute_SavedSearchWithMultipleFiltersReproducesCorrectly`: 3 Dokumente, 2 Filter (Sender+Postfach) gespeichert, `Execute` liefert real genau das eine Dokument, das beide Filter erfüllt | | 2 | Test: Benutzer sieht keine gespeicherten Suchen anderer Mandanten | **bestanden** – `TestList_UserSeesNoOtherTenantsSavedSearches`: zwei Mandanten mit je einer gespeicherten Suche, `List` bei Mandant B liefert real nur die eigene, nicht die von Mandant A | | 3 | Test: Löschen einer gespeicherten Suche entfernt nur diese | **bestanden** – `TestDelete_RemovesOnlyThatSavedSearch`: zwei gespeicherte Suchen, eine gelöscht, `Get` liefert für die gelöschte real `ErrNotFound`, die andere bleibt real unverändert abrufbar | Zusätzlich (Akzeptanzkriterium 2, kein eingefrorener Snapshot): `TestExecute_ReturnsCurrentResultsNotFrozenSnapshot` — Ausführung vor einer neuen Indexierung liefert real 0 Treffer, danach real 1 Treffer, ohne dass die gespeicherte Suche selbst verändert wurde. ## 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 ./... -p 1 -> alle Pakete bestanden, inkl. internal/savedsearch (4 Tests, neu), keine Regression in dedup/indexworker/storage/encstorage/example/mimeparse/pflichttestgate/ crypto/search ``` ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Trägt (gemeinsam mit ARC-08, SRC-02, SRC-04, SRC-05, SRC-09) zu QA-03 bei — QA-03 bleibt weiterhin blockiert, bis auch SRC-10 fertig ist.