Выдача
Замер от: 2026-08-14 · чем проверено: ZAMER-KARTY-BLOKOV-2026-08-14.md, ZAMER-BAZY-2026-08-14.md, прогон
data_api/testsДля кого: кто добавляет маршрут к данным или чинит 401/403/429 — прежде чем трогать что-либо из блока.
Что делает
Блок отдаёт собранные и посчитанные данные наружу. Штатная HTTP-дверь целевого
/new — Data API (data_api/): сайт читает витрины через него, а не из базы
сбора; на 14.08 это 190 маршрутов под /api/v1. Блок начинается в
data_api/main.py и кончается ответом с типизированной ошибкой (envelope.error).
⚠️ Data API — не единственная дверь. Обходов три, и они разного веса:
| Обход | Размер | Чем является |
|---|---|---|
routes/api.php | 41 маршрут | отдельный слой Laravel (legacy REST) |
data_api/routers/compat.py | один модуль | слой совместимости для прежних договоров рейтинга, оборачиваемости и отгрузок |
DB::connection('kernel') | одно место: app/Filament/Pages/ShipmentCalcApiPage.php:444 | запись отгрузки |
Третий обход — запись отгрузки, то есть он в неприкосновенной области (см. «Чего делать нельзя»). Прежняя формулировка «прямые соединения Laravel» преувеличивала: соединение одно.
Точка входа в код
data_api/main.py — сборка приложения: app = FastAPI(...), мидлварь гостевого
предела и подключение роутеров status, facts, dims, control, reports,
compat под префиксом /api/v1. Запуск: uvicorn main:app --port 8080 из data_api/.
Чем задаётся
data_api/config.py— окружение:DATA_API_TOKENS(токены → области доступа),DATA_API_RATE_LIMIT_PER_MIN(предел гостевых ключей),V3_MYSQL_*(адрес базы). Токенов нет — проверка прав выключена (AUTH_DISABLED), и это состояние для разработки, в бою оно недопустимо.data_api/routers/*.py— сами маршруты; каждый маршрут данных под/api/v1требует свою область доступа. Технический/healthживёт отдельно вmain.py.data_api/errors.py— таксономия ошибок источника:SourceUnavailable→ 503,MandatorySourceError/QuerySourceError→ честный 500 с кодом. Тихая пустота вместо ошибки запрещена решением DNR-007.specs/reports/*.yaml— 42 описания отчётов и 49 их вариантов; из них собираются маршруты/api/v1/reports/*.
Какие правила обязан соблюдать
- Области доступа объявлены в
data_api/auth.py:data:read(факты и витрины),status:read(свежесть, прогоны, сверки),control:read(реестр эндпоинтов и карты полей),control:write,run:write. Последние две входят в словарь токенов, но ни один маршрут их сейчас не требует:control.pyцеликом read-only. Ответы 501 существуют отдельно у ещё не реализованных чтений и защищеныdata:read; выдавать их за записывающие мутации нельзя. - Гостевой предел. Токен, помеченный полномочием
guest, ограниченRATE_LIMIT_GUEST_PER_MINзапросами в минуту (data_api/rate_limit.py, мидлварь вmain.py). Предел намеренно не распространяется на служебные ключи: у боевого сайта всплески законны. - Порядок чтения (канон «всё через Data API»): сайт не читает базу сбора напрямую. Исключение — одно место записи отгрузки, см. выше.
- Согласованное чтение. При
DATA_API_READ_COHERENCE_MODE=observe|enforceчитающие маршруты идут однимREPEATABLE READснимком (data_api/read_coherence.py).
Чем проверяется
cd data_api && python3 -m pytest tests -q
Отказ в правах проверяют тесты data_api/tests по require_scope (401 без токена,
403 без области) и по гостевому пределу. Сверка ссылок документации —
python3 scripts/docs/check_doc_links.py.
Чего делать нельзя
- Не добавлять обходы. Новый маршрут к данным — только в Data API.
routes/api.phpиcompat.pyсуществуют ради переезда со старого контура, а не как второй вход. - Не трогать отгрузку.
ShipmentCalcApiPage.php:444— единственное прямое соединение Laravel сkernel, и оно в неприкосновенной области (RULES.md). Менять его — значит трогать ежедневно используемый расчёт. - Не глушить ошибки источника. 500 с кодом ошибки — честнее пустого списка: пустой список читается как «данных нет», хотя данных просто не удалось добыть.
- Не выключать проверку прав в бою и не помечать боевые ключи
guest: предел поставит сайт на 429 в его же законный всплеск. - Не менять предел гостевых ключей молча — окно фиксированное минутное, выбор
осознанный и описан в шапке
rate_limit.py.
Что НЕ установлено
- Доля из 190 маршрутов «живые чтения / заглушки 501» по-прежнему не
установлена. По коду поимённо установлена только конечная часть заглушек:
7 семейств фактов
(
data_api/routers/facts.py:18), 6 измерений (dims.py:34), 4 compat-представления (compat.py:29) — всего 17 имён. Отвечает им по одному обобщающему маршруту на модуль (501 — только перечисленным именам, иначе 404):facts.py:73,dims.py:187,compat.py:706, плюсreports/__init__.py:42(501 любому незарегистрированному пути). Наличие 121 маршрутного декоратора вdata_api/routers/reports/доказывает регистрацию в исходниках, но не успешное чтение данных каждым маршрутом и не даёт требуемую долю. Записывающих маршрутов сcontrol:writeилиrun:writeсейчас нет. Известно поdata_api/README.md, что живы чтенияstatus/*,facts/stocks-daily,control/*,compat/turnover|ratingиreports/*. - Перечень токенов и их областей — секреты, живут в env боевого сервера.
- Как именно наружный трафик доходит до Data API (nginx/прокси
mp.hyp.ru→/api/v1) — на серверы не ходим, не замерено.
Куда за подробностью
- data_api/README.md — контракт, запуск, список живых срезов.
- docs/backend/generated/ENDPOINTS-CATALOG.md — 81 файл описаний, окна, лимиты адресов площадок.
- docs/guards/app-guards.md — сторожа A3 (области доступа) и A6 (согласованное чтение).
- docs/data-api-endpoint-matrix.md — соответствие endpoints интерфейса маршрутам Data API.
data_api/auth.py,data_api/rate_limit.py,data_api/errors.py— сами механизмы.