Задачи 025-030: ёмкость префиксов, политика входа, дерево префиксов
Повторный анализ кодовой базы (docs/reviews/2026-09-26-codebase-review-2.md) и доработки:
025 Ёмкость префикса — размер его подсети (а не сумма листьев); «Обзор» считает ёмкость
по корневым активным IPv4-префиксам и адреса внутри них.
026 Политика блокировки входа: 5 неудач на логин+IP, 20 на IP, 50 на логин со всех IP,
кроме известных IP (known_logins, миграция 0009) — владельца нельзя заблокировать анонимно.
027 Сериализация попыток входа по IP (advisory-lock после блокировки логина).
028 UI «Префиксы»: загрузка всех страниц (до 20 000), счётчики по total, предупреждение об усечении.
029 Advisory-lock по VRF для операций, меняющих дерево префиксов и раскладку адресов.
030 Исправление замечаний ревью 025-029: _lock_prefix (VRF блокируется до чтения префикса,
409 при одновременном переносе), константы политики входа перенесены в app/services.py.
Тесты: 14 passed (проверка ёмкости родителя приведена к семантике 025); сквозные сценарии
и гонки — docs/reviews/2026-09-26-changes-025-029-review.md, 2026-09-27-changes-030-review.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
13e17fbb47
commit
03d727e496
25 files changed
+877
-78
No files matched your search
+3
-2
@@ -7,8 +7,8 @@ from sqlalchemy import delete, func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db import SessionLocal
|
||||
from app.models import AppSetting, AuditLog, LoginAttempt
|
||||
from app.services import SYSTEM, audit
|
||||
from app.models import AppSetting, AuditLog, KnownLogin, LoginAttempt
|
||||
from app.services import KNOWN_IP_DAYS, SYSTEM, audit # KNOWN_IP_DAYS — из app.services, не из API-слоя (изменение 030, ревью 025-029 находка №2)
|
||||
|
||||
log = logging.getLogger("ipam.rotation")
|
||||
DEFAULTS = {"retention_days": 90, "max_entries": 100_000}
|
||||
@@ -50,6 +50,7 @@ def rotate(db: Session) -> dict | None:
|
||||
rest = n - noisy
|
||||
by_count = noisy + (db.execute(delete(AuditLog).where(AuditLog.id.in_(select(AuditLog.id).order_by(AuditLog.id).limit(rest)))).rowcount if rest > 0 else 0)
|
||||
db.execute(delete(LoginAttempt).where(LoginAttempt.ts < datetime.now(timezone.utc) - timedelta(days=1)))
|
||||
db.execute(delete(KnownLogin).where(KnownLogin.last_seen < datetime.now(timezone.utc) - timedelta(days=KNOWN_IP_DAYS))) # изменение 026
|
||||
if by_age or by_count:
|
||||
parts = []
|
||||
if by_age:
|
||||
|
||||
Reference in new issue
Block a user