# ING-09 — Rate-Limiting auf Protokollebene: Prüfprotokoll Datum: 2026-09-01 Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh Pakete: `mail/internal/ratelimit` (neu, gemeinsam genutzt), `mail/internal/imap`, `mail/internal/pop3`, `mail/internal/smtp` ## Umsetzung Neues Paket `ratelimit`: Token-Bucket-Rate-Limiting, je (Mandant, Quelle)-Schlüssel ein eigener Bucket. `ConfigProvider`/`StaticConfig` liefern die Konfiguration (Burst, Nachfüllrate) je Mandant, mit Fallback auf eine Default-Konfiguration (Akzeptanzkriterium 1/2: begrenzt UND konfigurierbar; Akzeptanzkriterium 3: je Mandant getrennt konfigurierbar). `Limiter.Allow(tenant, source)` liefert bei Ablehnung eine konkrete, positive Wartezeit statt nur `false` — Grundlage für Akzeptanzkriterium 3: "definierte Ablehnung MIT Wartezeit-Hinweis, nicht Verbindungsabbruch ohne Erklärung". **IMAP** (`LOGIN`) und **POP3** (`PASS`) begrenzen Anmeldeversuche pro (Mandant, Quell-IP) — Akzeptanzkriterium 1. **SMTP** (`MAIL FROM`) begrenzt die Annahmerate pro (Mandant, Absenderadresse+Quell-IP) — Akzeptanzkriterium 2. Bei Überschreitung antwortet der Server mit einer Fehlermeldung, die die Wartezeit in Sekunden nennt (POP3 `-ERR`, IMAP `NO`, SMTP `451` — temporärer Fehlercode, "versuch es später erneut"), die Verbindung bleibt in allen drei Fällen offen und weiter nutzbar (Akzeptanzkriterium 3). `loginLimiter`/`acceptLimiter` sind optional (`nil` = kein Rate-Limiting, Rückwärtskompatibilität zu ING-01..ING-08); neue Konstruktoren `NewServerWithGuardTLSLoggerAndRateLimit` (IMAP/POP3) und `NewServerWithMaxMessageBytesTLSLoggerAndRateLimit` (SMTP). Jeder `Server` bekommt eine `tenantID` — konsistent mit dem in ING-10 etablierten Muster "ein Server-Prozess/Instanz je Mandant" — und ein `*ratelimit.Limiter`, der über mehrere Server-Instanzen (Mandanten) hinweg geteilt werden kann, aber intern strikt nach `tenantID` trennt. ## Pflichtprüfung 1: Lasttest bestätigt greifendes Limit bei Überschreitung `TestRateLimit_LoadExceedingLimitGetsRejectedWithRetryHint` in allen drei Protokollpaketen: Burst=5, 20 reale, aufeinanderfolgende Anmelde-/Annahmeversuche über echte TCP-Verbindungen gegen den laufenden Server. Ergebnis in allen drei Protokollen identisch: exakt 5 Versuche akzeptiert (der konfigurierte Burst), exakt 15 Versuche mit der erwarteten Fehlermeldung inkl. Wartezeit-Hinweis abgelehnt — kein Verbindungsabbruch, jede Ablehnung kommt als reguläre Protokollantwort. Ergebnis: **BESTANDEN** in allen drei Protokollen. ## Pflichtprüfung 2: legitime Nutzung unterhalb der Schwelle bleibt unbeeinträchtigt `TestRateLimit_LegitUsageBelowThresholdUnaffected` in allen drei Protokollpaketen: Burst=10, nur 3 Versuche — alle drei erfolgreich, keine Ablehnung. Ergebnis: **BESTANDEN** in allen drei Protokollen. ## Pflichtprüfung 3: Limit ist je Mandant getrennt konfigurierbar und wirksam `TestRateLimit_PerTenantIndependentAndEffective` in allen drei Protokollpaketen: EIN gemeinsamer `*ratelimit.Limiter`, aber zwei Server-Instanzen mit unterschiedlicher `tenantID` (`mandant-knapp` → Burst 2, `mandant-grosszuegig` → Burst 8, per `StaticConfig.PerTenant`). 10 Versuche je Mandant: `mandant-knapp` akzeptiert exakt 2, `mandant-grosszuegig` akzeptiert exakt 8 — beweist sowohl die Trennung (unterschiedliche Werte wirken unabhängig) als auch die Wirksamkeit (jeweils exakt der konfigurierte Burst, nicht mehr, nicht weniger). Ergebnis: **BESTANDEN** in allen drei Protokollen. ## Akzeptanzkriterien 1. **Login-Versuche pro Quelle/Zeitfenster sind begrenzt und konfigurierbar**: IMAP/POP3, durch Pflichtprüfung 1+2 belegt. 2. **SMTP-Annahmerate pro Absender/Quelle ist begrenzt und konfigurierbar**: SMTP, durch Pflichtprüfung 1+2 belegt. 3. **Überschreitung führt zu definierter Ablehnung mit Wartezeit-Hinweis, nicht zu Verbindungsabbruch ohne Erklärung**: durch Pflichtprüfung 1 belegt (Verbindung bleibt in jedem Testlauf offen, jede Ablehnung enthält die Wartezeit in Sekunden). ## Build/Vet/Lint/Test — Gesamtmodul ``` go build ./... → OK go vet ./... → OK golangci-lint run ./... → 0 issues go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL gesetzt) → alle Pakete ok, inkl. neuem internal/ratelimit ``` Keine Regression in den bestehenden ~31 Paketen — insbesondere die QA-07-Lasttests bleiben grün: Rate-Limiting ist standardmäßig deaktiviert (`loginLimiter`/`acceptLimiter` nil), bis explizit über die neuen Konstruktoren aktiviert. ## Ergebnis ING-09 erfüllt alle Akzeptanzkriterien mit echten, ausgeführten Nachweisen — in allen drei Protokollen (IMAP, POP3, SMTP) einzeln geprüft. Freigeschaltet: QA-04.