Чистка: устаревшие комментарии и подсказки, export-скрипт, мусорный файл

Комментарии про методы входа приведены к факту (логин/пароль и Telegram везде,
stub только в development): config.py, .env.example, telegram.py, dev_stub.py,
dev_auth.py, login.py. admin_login.py больше не обещает «строже игроцкого» —
описаны реальные лимиты; client_ip — адрес за прокси уже даёт uvicorn.

Подсказки деплоя: run.ps1/run.sh (build-push на ПК, `up -d` на Pi), compose,
.env.example (build-push.ps1), Caddyfile (туннель-контейнер вместо autossh);
ratelimit.py ссылается на core/events.py вместо CLAUDE.md.

Удалены неиспользуемые scripts/export-prod.sh (с блоком export-ignore в
.gitattributes и упоминаниями в README), db/init_db.py и случайно закоммиченный
файл «h -u origin dev…». #70

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
This commit is contained in:
2026-09-19 03:12:16 +03:00
co-authored by Claude Opus 5
parent f7f74fee8c
commit ec1e94119c
18 changed files with 25 additions and 111 deletions
+3 -2
View File
@@ -2,8 +2,9 @@
Тонкий слой поверх `admin_service.authenticate_admin`: throttle по IP, по паре «IP + логин»
и по самому аккаунту через тот же `LoginThrottle`, что и вход игрока (`core/ratelimit`).
Сервис остаётся чистым от инфраструктуры лимитов. Пароль администратора — единственный
барьер к полному контролю приложения, поэтому перебор здесь ограничиваем строже игроцкого.
Сервис остаётся чистым от инфраструктуры лимитов. Лимиты те же, что у игрока (5 на пару,
20 на IP, 50 на аккаунт за 15 минут); отличие — при успешном входе снимаются все счётчики,
включая IP.
"""
from __future__ import annotations
+1 -1
View File
@@ -1,4 +1,4 @@
"""Dev-провайдер: вход без секрета по нику/идентификатору (только не-production)."""
"""Dev-провайдер: вход без секрета по нику/идентификатору (только development)."""
from __future__ import annotations
from typing import Any
+2 -2
View File
@@ -1,7 +1,7 @@
"""Общий вход: внешняя личность → пользователь → сессия.
Прод-безопасный модуль (без импортов dev-провайдера). Используется и Telegram-входом,
и dev-входом.
Прод-безопасный модуль (без импортов dev-провайдера). establish_session зовут вход через
Telegram, /auth/login, /auth/register и dev-вход.
"""
from __future__ import annotations
+1 -1
View File
@@ -2,7 +2,7 @@
Проверяет подпись данных виджета (HMAC-SHA256 ключом SHA256(BOT_TOKEN)) и свежесть
auth_date. Нужны TELEGRAM_BOT_TOKEN (+ TELEGRAM_BOT_USERNAME для виджета на фронте).
Доступен и в dev, и в prod (в prod — единственный метод входа).
Доступен во всех окружениях — наряду со входом по логину и паролю.
"""
from __future__ import annotations
+3 -3
View File
@@ -31,7 +31,7 @@ class Settings(BaseSettings):
)
# ── Главный переключатель окружения: development | production ─────────────
# development — нативный dev (uvicorn + vite), БД в ./data/dev/, вход Telegram+ник.
# development — нативный dev (uvicorn + vite), БД в ./data/dev/, есть stub-вход по нику.
# production — Docker на Pi; контейнер форсит это значение, игнорируя .env.
app_env: str = "development"
log_level: str = "INFO"
@@ -67,8 +67,8 @@ class Settings(BaseSettings):
# cookie_secure НЕ задаётся вручную — выводится из окружения (см. property ниже).
cookie_domain: str | None = None
# Аутентификация. Методы входа определяются окружением (dev: telegram+stub,
# prod: только telegram) — отдельного переключателя провайдера нет.
# Аутентификация. Методы входа определяются окружением (auth/registry.py): везде
# логин/пароль + Telegram, в development ещё stub — отдельного переключателя нет.
telegram_bot_token: str | None = None
telegram_bot_username: str | None = None
public_base_url: str | None = None
+1 -1
View File
@@ -6,7 +6,7 @@
* рестарт (в т.ч. деплой) сбрасывает окно — злоумышленник получает новую квоту после
перезапуска, но окно короткое, а рестарты редки;
* при уходе от одного воркера лимит делится между процессами (каждый считает своё) —
тогда счётчики нужно вынести во внешний стор (Redis pub/sub, как отмечено в CLAUDE.md
тогда счётчики нужно вынести во внешний стор (Redis pub/sub, как отмечено в core/events.py
про SSE-шину), общий для всех воркеров.
Помимо пары «IP + логин» и лимита по IP есть IP-независимый лимит на аккаунт
(`login-user:*` / `admin-login-user:*`), чтобы ротация X-Forwarded-For / многих адресов
+2 -2
View File
@@ -175,6 +175,6 @@ def is_session_revoked(payload: dict) -> bool:
def client_ip(request: Request) -> str | None:
"""IP клиента для журнала аудита.
Одна точка на всё приложение: за VPS-привратником адрес придётся брать из
X-Forwarded-For, и менять это в двух десятках роутеров — не вариант."""
Одна точка на всё приложение. Реальный адрес за VPS-привратником уже подставляет
uvicorn (--proxy-headers + --forwarded-allow-ips в entrypoint.sh) — отсюда он и берётся."""
return request.client.host if request.client else None
-21
View File
@@ -1,21 +0,0 @@
"""Инициализация схемы и справочников (для тестов и локального быстрого старта).
В production схема создаётся миграциями Alembic; этот модуль удобен для тестов,
где БД поднимается из чистого состояния.
"""
from __future__ import annotations
from sqlmodel import SQLModel
from app.db.session import engine
from app.seed.reference_data import seed_reference_data
from sqlmodel import Session
# Импорт моделей обязателен, чтобы они зарегистрировались в SQLModel.metadata.
import app.models # noqa: F401
def create_db_and_seed() -> None:
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
seed_reference_data(session)
+2 -2
View File
@@ -1,8 +1,8 @@
"""DEV-ТОЛЬКО роутер: вход по нику (stub) + тестовые пользователи.
Этот файл и app/auth/dev_stub.py ФИЗИЧЕСКИ исключены из прод-образа (.dockerignore),
а подключается роутер лишь когда APP_ENV != production (см. app/main.py). Так код
входа по логину остаётся только на деве.
а подключается роутер лишь при APP_ENV=development (см. app/main.py). Так вход
без пароля остаётся только на деве (по логину и паролю входят везде).
"""
from __future__ import annotations