Account Lockout (Brute-Force zaštita) — A12
Bilko — Account Lockout (Brute-Force zaštita) — A12 / MC #104687
Status: implementirano 2026-07-03, commit 13b3a729 na feat/task-104687 (Wave 1 — čeka merge u dev)
Vlasnik: CodeCraft backend · Proveo PASS (nezavisna verifikacija svih 5 AC)
Ponašanje
- Nakon 5 uzastopnih neuspješnih email/password login pokušaja, nalog se zaključava 15 minuta.
- 6. pokušaj vraća HTTP 423 (
BILKO-AUTH-005) čak i s tačnom šifrom — provjera zaključanosti ide PRIJE verifikacije šifre. - Uspješan login resetuje brojač na 0 (legitimni korisnici s povremenim tipfelerima se ne zaključavaju).
- Istekli
locked_untilse auto-čisti prije provjere šifre (cooldown se sam otključa). - Admin unlock:
PUT /api/v1/users/{id}/unlock(permisijausers:manage, org-scoped — cross-org pokušaj vraća 404). - Entra-only korisnici (
passwordHash = NULL, V66) nikad ne dotiču lockout logiku; Entra SSO put (markEntraLogin) ne konsultuje lockout.
Implementacija
| Sloj | Šta |
|---|---|
| Migracija | V108__account_lockout.sql — users.failed_login_attempts INT NOT NULL DEFAULT 0, users.locked_until TIMESTAMPTZ NULL (aditivno) + drop/recreate 3 bilko_auth.* SECURITY DEFINER lookup funkcije (RETURNS TABLE promjena; OWNER/GRANT identični V31/V66 originalima — diffano) |
| Servis | AuthService.kt — lock-check prije verifyPassword; brojač = jedan atomski parametrizovani UPDATE (nema izgubljenih inkremenata pod konkurencijom); adminUnlock(orgId, userId) |
| HTTP | LockedException → BILKO-AUTH-005 (423) u StatusPages.kt; ruta unlock u UserManagementRoutes.kt; dokumentovano u ERROR-CODES.md + openapi.yaml |
| Testovi | AuthServiceLockoutTest.kt — 5 scenarija (6. pokušaj s tačnom šifrom → 423; reset na uspjeh; cooldown expiry; admin unlock; cross-org 404). Izvršeno 5/5 + regresija AuthServiceTest 31/31, skipped=0 (XML ground truth) |
Bitno: javna login ruta je 410
POST /api/v1/auth/login vraća 410 Gone platformski (WP4/MC #103144 — Bilko je Entra-only, password login penzionisan). Lockout je time defense-in-depth: javna brute-force površina je ZATVORENA (Proveo live probe: 7×410 na api.bilko.cloud), a lockout se automatski primjenjuje ako se ruta ikad reaktivira. Odluka: rutu NE reaktivirati radi live-423 demonstracije.
Poznati follow-up
bilko_auth.find_user_by_email/find_user_by_idi dalje nemajuSET search_path = public, pg_temp(naslijeđeno iz V31, nije uvedeno ovim taskom) — hardening ticket.
Evidence
/Users/makinja/system/evidence/104687/build-report-20260703.md/Users/makinja/system/evidence/104687/proveo-verdict-20260703.md- P2P mesh:
mesh-thr-357b1180(builder) →mesh-thr-516f2df0/mesh-msg-ba98cc59(Proveo PASS)
Ops napomene (otkriveno tokom taska)
- Gitleaks pre-commit je gađao
../../.gitleaks.toml— rušio SVAKI commit iz nested.claude/worktrees/*(fail-closed "Secrets detected" bez skena). Fixano u.husky/pre-commit(commit13b3a729): config je tracked na repo root-u →--show-toplevel/.gitleaks.toml. - Testcontainers silent-skip:
~/.testcontainers.propertiesje pokazivao na legacydocker.raw.sockkoji Ryuk ne može bind-mountati na aktuelnom Docker Desktopu → SVI integration testovi tiho SKIPPED uz "BUILD SUCCESSFUL". Fix:unix:///var/run/docker.sock+ryuk.disabled=true. Lekcija: uvijek čitatitests=/skipped=iz testsuite XML-a, ne vjerovati zelenom buildu.
No comments to display
No comments to display