// IMP-09: Tenant-Scoping-Nachweis für die Regelanwendung // (Akzeptanzkriterium 2). Bekannten Fehler vermeiden (known-issues- // archivmail.md #4): dieser Test schließt eine reale Lücke, die vor // IMP-09 bestand — kein bestehender Test bewies bislang explizit, dass // die Regeln eines Mandanten nicht auf die Nachrichten eines anderen // angewendet werden. package mailrules import ( "context" "testing" ) func TestStore_TenantScopingIsolatesRuleApplication(t *testing.T) { store := setupStore(t) ctx := context.Background() tenantA := "mandant-imp09-regeln-a" tenantB := "mandant-imp09-regeln-b" if _, err := store.Create(ctx, tenantA, Rule{Name: "a-regel", SenderPattern: "^ziel@", Category: "Kategorie-A", Priority: 10}); err != nil { t.Fatalf("regel mandant a anlegen: %v", err) } // Mandant B legt bewusst KEINE eigene Regel an — sein Regelset muss // leer bleiben, unabhängig davon, was Mandant A definiert hat. rulesA, err := store.List(ctx, tenantA) if err != nil { t.Fatalf("list mandant a: %v", err) } if len(rulesA) != 1 { t.Fatalf("mandant a: erwartete 1 eigene regel, habe %d", len(rulesA)) } rulesB, err := store.List(ctx, tenantB) if err != nil { t.Fatalf("list mandant b: %v", err) } if len(rulesB) != 0 { t.Fatalf("mandant b sieht regeln von mandant a — mandantentrennung verletzt, habe: %+v", rulesB) } engineA, err := NewEngine(rulesA) if err != nil { t.Fatalf("newengine mandant a: %v", err) } engineB, err := NewEngine(rulesB) if err != nil { t.Fatalf("newengine mandant b: %v", err) } msg := EmailMetadata{Sender: "ziel@lieferant.example"} resultA := engineA.Evaluate(msg) resultB := engineB.Evaluate(msg) if resultA.Category != "Kategorie-A" { t.Fatalf("mandant a: erwartete 'Kategorie-A', habe %q", resultA.Category) } if resultB.Category != "" { t.Fatalf("mandant b wendet fälschlich regel von mandant a an, kategorie %q", resultB.Category) } }