Prod Connectivity Audit — 2026-05-15¶
Время прогона: 2026-05-15 ~07:00–07:15 UTC
Метод: 2 прохода curl-смоук по всем основным маршрутам из infra/routes.config.mjs на двух хостах (api.arkhyz-club.ru, admin.arkhyz-club.ru). Анонимные запросы без токена — цель не валидация бизнес-логики, а roundtrip: Caddy → правильный микросервис → корректный HTTP-код.
Скрипт: /tmp/prod_probe.sh (60 эндпоинтов × 2 хоста = 120 проб).
Сводка¶
| Статус | Значение | Кол-во |
|---|---|---|
| ✅ Работает | 200 / 401 / 422 / 307 — Caddy роутит, сервис отвечает корректно | ~50 / 60 эндпоинтов |
| ⚠️ Транзиент 502 | После рестартов контейнеров — на втором проходе исчезли | 0 (на финальном проходе) |
| ❌ Реальные баги | Подтверждённые root cause-ы | 3 |
| 🤷 «404 в тестовом пути» | Мой тестовый путь не соответствует реальному эндпоинту (param, slug) | ~10 |
Открытые баги (что ещё чинить)¶
🔴 PR #84 — не смержен¶
Фиксы готовы, ждут мержа + ребилда контейнеров:
| Эндпоинт | Сейчас | После мержа |
|---|---|---|
GET /api/v1/recommendations/slopes |
404 (Caddy → catalog-svc, эндпоинта нет) | 200 (resort-svc) |
GET /api/v1/recommendations/plan-day |
404 (тот же баг) | 200 (resort-svc) |
GET /api/v1/tracking/sessions/me (с auth) |
404 (FastAPI ловит me как session_id) |
200 (после reorder) |
GET /api/v1/progress/me |
200 ✅ (после ранее запущенной миграции + ребилда) | 200 (защищено) |
🟡 Новый баг найден в обходе — /admin/ski/slopes¶
admin_ski.py:12 в docstring обещает «Аналогично для /admin/ski/slopes», но slopes-роуты не реализованы — есть только /lifts/*. Поэтому GET /api/v1/admin/ski/slopes → 404.
Админ-страница /admin/ski/slopes сейчас тянет /recommendations/slopes (см. отчёт юзера) — этот хак работал, пока Caddy не переехал на catalog-svc. После PR #84 /recommendations/slopes снова жив, и страница /admin/ski/slopes начнёт показывать данные из resort-svc. Полноценные admin-CRUD для трасс — отдельная задача (если они вообще нужны).
🟢 Транзиентные 502 — причина выявлена¶
На первом проходе 12 эндпоинтов на admin.arkhyz-club.ru отдали 502 (hotel_api_v2 fallbacks: /docs, /openapi.json, /admin/dashboard, /lifts, /modules и platform-svc /files/*, /settings/*, /push/register). Все они на втором проходе через 1–2 минуты вернули корректные коды. Причина — мой же apply-sql-migration workflow в 06:53 UTC дёрнул arkhyz-deploy.sh marker, который перезапустил backend-контейнеры. resort-svc запустился в 06:56:32, остальные следом. Окно деплоя ≈3–4 минуты — все ошибки в нём.
Урок: рассмотреть migration workflow без Pull latest main on host шага. Применение SQL не требует рестарта всего стека.
Полный результат — api.arkhyz-club.ru¶
| Path | Service | Code | X-Service | Note |
|---|---|---|---|---|
/api/v1/resort/lifts |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/webcams |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/webcams/list |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/weather/current |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/weather/forecast |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/tracking/sessions/me |
resort-svc | 401 | resort-svc | ⚠️ Без auth. С auth → 404 (PR #84) |
/api/v1/friends/locations |
resort-svc | 401 | resort-svc | ⚠️ Auth required |
/api/v1/skipass/active |
resort-svc | 404 | resort-svc | 🤷 Probe path mismatch (нужен ?user_id=) |
/api/v1/leaderboard |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/recommendations/slopes |
resort-svc | 404 | catalog-svc | 🔴 PR #84 |
/api/v1/recommendations/plan-day |
resort-svc | 404 | catalog-svc | 🔴 PR #84 |
/api/v1/badges |
resort-svc | 200 | resort-svc | ✅ |
/api/v1/admin/ski/lifts |
resort-svc | 401 | resort-svc | ✅ Caddy роутит, auth нужен |
/api/v1/admin/ski/slopes |
resort-svc | 404 | resort-svc | 🟡 Эндпоинт не реализован |
/api/v1/auth/me |
auth-svc | 401 | auth-svc | ✅ |
/api/v1/users |
auth-svc | 401 | auth-svc | ✅ Auth required |
/api/v1/roles |
auth-svc | 200 | auth-svc | ✅ |
/api/v1/auth/sms/send POST |
auth-svc | 404 | auth-svc | 🤷 Возможно другой путь (/sms/request?) |
/api/v1/hotels |
catalog-svc | 307 | catalog-svc | ✅ Trailing-slash redirect |
/api/v1/hotels-native |
catalog-svc | 200 | catalog-svc | ✅ |
/api/v1/tours |
catalog-svc | 200 | catalog-svc | ✅ |
/api/v1/restaurants |
catalog-svc | 200 | catalog-svc | ✅ |
/api/v1/recommendations |
catalog-svc | 200 | catalog-svc | ✅ |
/api/v1/transfers |
catalog-svc | 200 | catalog-svc | ✅ |
/api/v1/bookings |
booking-svc | 200 | booking-svc | ✅ |
/api/v1/availability/h1 |
booking-svc | 404 | booking-svc | 🤷 Param required |
/api/v1/payments |
booking-svc | 404 | booking-svc | 🤷 Auth/param |
/api/v1/favorites |
social-svc | 401 | social-svc | ✅ Auth required |
/api/v1/chats |
chat-svc | 401 | chat-svc | ✅ Auth required |
/api/v1/messages |
chat-svc | 404 | chat-svc | 🤷 Нужен ?chat_id= |
/api/v1/forums/categories |
chat-svc | 200 | chat-svc | ✅ |
/api/v1/public-profile/u1 |
chat-svc | 404 | chat-svc | 🤷 Конкретного юзера нет в seed |
/api/v1/progress/me |
gamification-svc | 200 | gamification-svc | ✅ Guest payload |
/api/v1/badges/me |
resort-svc | 401 | resort-svc | ✅ Auth required |
/api/v1/targets/today |
resort-svc | 401 | resort-svc | ✅ Auth required |
/api/v1/sos/status |
rtc-svc | 404 | rtc-svc | 🤷 Возможно /sos/incidents |
/api/v1/analytics/track POST |
hotel_api_v2 | 401 | - | ✅ Auth/body required |
/api/v1/dashboard/hotelier/hotels |
hotel_api_v2 | 401 | - | ✅ Auth required |
/api/v1/dashboard/user-stats |
hotel_api_v2 | 401 | - | ✅ Auth required |
/api/v1/push/devices |
platform-svc | 200 | platform-svc | ✅ Миграция накатана |
/api/v1/push/register POST |
platform-svc | 422 | platform-svc | ✅ Validation OK |
/api/v1/settings/app |
platform-svc | 404 | platform-svc | 🤷 Возможно /settings/global |
/api/v1/notifications |
platform-svc | 307 | - | ✅ Redirect to /notifications/ |
/api/v1/notifications/templates |
hotel_api_v2 | 401 | - | ✅ Auth required |
/api/v1/files/test |
platform-svc | 404 | platform-svc | 🤷 Конкретного файла нет |
/api/v1/stories |
stories-svc | 200 | stories-svc | ✅ |
/api/v1/stories/me |
hotel_api_v2 | 401 | - | ✅ |
/api/v1/bookings/statistics |
hotel_api_v2 | 401 | - | ✅ Auth required |
/api/v1/bookings/types |
hotel_api_v2 | 200 | - | ✅ |
/api/v1/categories |
hotel_api_v2 | 404 | - | 🤷 |
/api/v1/locations |
hotel_api_v2 | 307 | - | ✅ Trailing-slash |
/api/v1/lifts |
hotel_api_v2 | 404 | - | 🤷 Legacy, могло уйти в resort-svc |
/api/v1/ski-passes |
hotel_api_v2 | 307 | - | ✅ |
/api/v1/tour-operators |
hotel_api_v2 | 307 | - | ✅ |
/api/v1/modules |
hotel_api_v2 | 307 | - | ✅ |
/api/v1/menu-items |
hotel_api_v2 | 307 | - | ✅ |
/api/v1/docs |
hotel_api_v2 | 200 | - | ✅ Swagger UI |
/api/v1/openapi.json |
hotel_api_v2 | 200 | - | ✅ |
/api/v1/admin/dashboard |
hotel_api_v2 | 401 | - | ✅ Auth required |
/api/v1/health |
platform-svc | 200 | platform-svc | ✅ |
Полный результат — admin.arkhyz-club.ru¶
Все коды совпадают с api.arkhyz-club.ru на финальном проходе. Различия — только в безопасностных заголовках, которые admin-блок добавляет (HSTS, X-Frame-Options DENY, и т.д.).
Что было сделано в этой сессии¶
- PR #75 + #76 (уже смержены до сессии): Caddy-роутинг для
/progress/*и/push/*, восстановление FCM-плагина в мобилке. - Запуск
apply-sql-migrationworkflow (run #25904756022): накатилservices/_seed/sql/03_platform_svc.sql— создал схемуplatform.*с таблицамиpush_devices,push_prefs,app_config,feature_flags,push_sends. После этого/api/v1/push/devicesотдаёт 200 вместо 500. - PR #84 (открыт, ждёт мержа):
services/gamification-svc/app/routers/gamification.py:prefix="/api/v1"→prefix=""— превентивный фикс на случай ребилда.services/resort-svc/app/routers/tracking.py: переставлены/sessions/meи/sessions/me/statsПЕРЕД/sessions/{session_id}.infra/routes.config.mjs+ регенерированныеCaddyfile/Caddyfile.prod:/recommendations/slopesи/recommendations/plan-dayдобавлены вresort_svcmatcher.
Следующие шаги¶
- Мерж PR #84 → авто-deploy →
/recommendations/slopes,/recommendations/plan-day,/tracking/sessions/me↦ 200. - Проверить /admin/ski/slopes в браузере после мержа — должна показать данные из
/recommendations/slopes. - (Опционально) Реализовать настоящий админ-CRUD
/admin/ski/slopesв admin_ski.py, если бизнес-логика требует. - (Опционально) Доработать
apply-sql-migration.yml— отделить применение SQL от полного ребилда стека (избежать транзиентных 502 в проде при будущих миграциях).