16-1: Locking für Rate-Limit und CAPTCHA ausrollen
Stand: 2026-03-18
Contents key
This page
- Ziel
- Verbindlich zu übernehmen
- Verbindlich nicht blind zu übernehmen
- Zielbereiche und Lock-Granularität
- Wiederverwendung aus J01-21
- Öffentlicher Ausführungsnachweis
- Execution
- Delta 2026-03-20
- Links
Related pages
Public steps
- 16-2: Roll out locking for token rotation
- 16-3: Add race-adjacent tests
- 16-4: Update operational note
Schrittspezifischer öffentlicher Arbeitsstand für
16-1 unter
J01-16.
Diese Seite bündelt nur den Zuschnitt für Rate-Limit- und CAPTCHA-Locking und
trennt ihn bewusst von den weiteren offenen Schritten 16-2 bis 16-4.
Ziel
Den bewährten Runtime-Rahmen aus
J01-21 auf die noch offenen
Rate-Limit- und CAPTCHA-Pfade ausrollen, ohne die vollständige IP_SALT-
Fachlogik zu kopieren.
Verbindlich zu übernehmen
RuntimeLockRunnerals gemeinsamer Lock-Helfer für kritische SchreibabschnitteRuntimeAtomicWriterfür atomische Dateischreibmuster- Locking über
symfony/lockmit begrenztem Erwerb per Polling und Timeout - deterministische Fehlerpfade statt verdeckter Nebenwirkungen
- prüfbare, bereichsspezifische Lock-Key-Zuschnitte
Verbindlich nicht blind zu übernehmen
- die vollständige Fachlogik des
IP_SALT-Pfads - Markerfolgen wie
IN_PROGRESSundREADY, wenn der Zielpfad keine gleichartige Zustandsmaschine braucht - Token-Rotation; sie gehört in
16-2 - race-nahe Gesamttests; sie gehören in
16-3 - die Betriebsnotiz; sie gehört in
16-4
Zielbereiche und Lock-Granularität
| Bereich | Zieloperation | Lock-Zuschnitt | Write-Verhalten |
|---|---|---|---|
| Rate-Limit | allow(key, max, window) |
pro key |
Counter-Datei unter Lock lesen, fortschreiben, atomisch schreiben |
| CAPTCHA | verify(captchaId, answer, ipHash) |
pro captchaId |
Challenge-Datei unter Lock lesen, bewerten, fail_count oder used_at atomisch schreiben |
| CAPTCHA | createChallenge(ipHash) |
kein Lock zwingend bei eindeutiger ID | neue Challenge-Datei atomisch anlegen |
| CAPTCHA | cleanupExpired() |
optional globaler Wartungs-Lock | abgelaufene oder verbrauchte Dateien gezielt löschen |
Wiederverwendung aus J01-21
Für 16-1 wird der Referenzpfad aus
J01-21 nicht über komplette
Fachschichten kopiert, sondern über einen gemeinsamen Runtime-Rahmen
wiederverwendet:
- derselbe Lock-Mechanismus
- dieselbe atomische Write-Disziplin
- derselbe Fail-Fast-Grundsatz
- dieselbe Trennung zwischen gemeinsamem I/O-Rahmen und bereichsspezifischer Fachentscheidung
Damit wird 16-1 als Ausrollung bewährter Module geschnitten, nicht als
zweite IP_SALT-Implementierung unter anderem Namen.
Öffentlicher Ausführungsnachweis
16-1 gilt fachlich erst dann als sauber ausgeführt, wenn öffentlich
nachvollziehbar ist:
- welche Zieloperationen unter Lock laufen
- welcher Lock-Key-Zuschnitt gilt
- welche Pfade nur atomisch schreiben, aber keinen Write-Lock brauchen
- welche race-nahen Tests diese Zuschnitte später in
16-3absichern
Execution
Implemented in two commits on feature/j01-17 (upstream: feature/j01-9-preview).
Commit 1 — folder move:
RuntimeLockRunner and RuntimeAtomicWriter moved from Http\Security to Http\Runtime;
namespace updated; all import sites adjusted (ISS-012, point 4). 26/26 tests green.
Commit 2 — locking rollout:
| Target operation | Lock key | Write behaviour |
|---|---|---|
RateLimiter.allow(key, ...) |
ratelimit_{safeKey} per key |
atomic under lock |
CaptchaService.verify(captchaId, ...) |
captcha_{captchaId} per ID |
fail_count or used_at atomic under lock |
CaptchaService.createChallenge(ipHash) |
no lock | new challenge file written atomically |
CaptchaService.cleanupExpired() |
no lock | deletes expired / used files only |
AppContext shares a single lockRunner and writer instance across all three services.
26/26 tests green.
Delta 2026-03-20
The previously still open app-side remainder for 16-1 is now explicitly
closed in the source repo:
- Commit
ee45a62movesCaptchaServiceandRateLimiteronto the same locking and atomic-write state described on this page. php bin/cli config lint devis green.CaptchaServiceTest,RateLimiterTest, and the relatedConcurrencyTestcases are green withTMPDIRset.
Remaining sub-steps: 16-2 (token rotation), 16-3 (race tests), 16-4 (operations note).