Архыз.CLUB — отчёт о работе за 27 мая 2026¶
Период: 2026-05-27, полный рабочий день
Окружение: прод arkhyz-club.ru (self-hosted, podman + Caddy)
Резюме¶
За день закрыты 14 задач из бэклога. Прод-окружение приведено к состоянию «зелёное по всем индикаторам». Найдено и устранено 3 реальных бага (Gemini-модель в AI-сервисах, UUID-валидация в pass-svc, шум infra-ошибок), плюс предотвращён disk-out (91% → 74% через emergency cleanup).
1. PSP-маршрутизация (F4)¶
Расширил роутинг через psp.py на оставшиеся 4 типа броней. До правок только restaurant_bookings шёл через выбор провайдера, остальные напрямую дёргали YooKassa.
Что сделано:
- services/booking-svc/app/routers/legacy_booking_compat.py — _finalize_commission_response теперь использует psp.create_payment_via_psp
- Owner lookup по mapping table → service_table.user_id для tour/transfer/instructor/room/hotelier
- Hotel booking (room_bookings) автоматически покрыт через тот же _finalize_*
Покрытие PSP-роутинга сейчас: все 5 commission-first типов (restaurant, tour, transfer, instructor, hotel).
Коммит: 4ee7bec1d.
2. OAuth merge by email (F1)¶
Проверка показала: логика уже корректно реализована в hotel-api/server/app/routers/auth_oauth.py:191-205. Дубликатов email в public.users нет.
Решение: deterministic uuid5(provider:email) гарантирует, что одна почта = один users.id для одного провайдера. При наличии user'а по email обновляются только пустые поля.
Задача закрыта без правок кода.
3. gen-routes расширение (R1)¶
scripts/gen-routes.mjs теперь поддерживает 2 новых поля в routes.config.mjs:
rewrite_to: '/api/v1/widget{uri}'— per-route override дляservice.rewrite_prefixmethods: ['GET','POST']— matcher с path + method (когда один путь делит upstream'ы по методу)
Оба поля опциональны, обратно совместимы.
Коммит: c53a2d773.
4. arkhyzpay healthcheck¶
Контейнер arkhyzpay-api логировал 404 HEAD /v1/health каждые 15с — wget --spider использует HEAD, а сервис отвечает только на GET.
Fix: /opt/arkhyzpay/docker-compose.yml:
test: ["CMD", "wget", "-qO-", "http://localhost:8090/v1/health"]
Контейнер пересоздан, healthcheck = healthy, в логах GET 200 вместо 404 HEAD.
5. Edge-functions auto-deploy (R4)¶
Проверка показала, что scripts/auto-deploy-watcher.sh уже обрабатывает изменения в supabase/functions/**:
supabase/functions/*) NEED_EDGE_RESTART=1 ;;
При NEED_EDGE_RESTART=1 делается docker restart arkhyz-supabase-functions. Таймер на проде active. Задача закрыта без правок.
6. CI workflows на self-hosted runner (R3)¶
Перевёл 5 workflow'ов с github-hosted на self-hosted runner (экономия CI minutes — billing блокировал cloud builds):
services.yml— отключилpush:trigger (дублировал auto-deploy-watcher)deploy-supabase-functions.yml— отключилpush:(то же)routes-drift-check.yml→ self-hostedtests.yml→ self-hostedui-visual-regression.yml→ self-hosted (обе job)
mobile.yml оставлен на github-hosted (нужен macos-14 для EAS build).
Коммит: 5a8b7b830.
7. Vite code-splitting в tourist-app (R2)¶
tourist-app/vite.config.ts был с minify: false и без manualChunks. Это давало бандл ~5MB одним файлом.
Fix:
- minify: 'esbuild'
- sourcemap: 'hidden' (карты для error-collector, в браузере не подгружаются)
- chunkSizeWarningLimit: 800
- 10 vendor chunks: react / router / radix / framer / icons / tanstack / supabase / capacitor / maps / date
После rebuild: 9 JS chunks, главный index-*.js = 1.6MB, vendor-react = 139KB, hls-плеер отдельным чанком 512KB.
Коммит: a293a26f1.
8. Audit-1: ошибки за неделю¶
public.error_events за 30 дней — 0 строк. Это насторожило, проверил коллектор:
arkhyz-error-collector пишет в SQLite (/data/errors.db), не в Postgres. Запросил SQLite — получил реальную статистику (см. раздел 11).
В контейнерных логах нашёл одну важную проблему: arkhyz-hotel-api-prod спамил alembic-loop'ом:
asyncpg.exceptions.DuplicateObjectError: type "chattypeenum" already exists
Причина: public.alembic_version была пустой → каждый рестарт прогонял миграции с нуля.
Fix: docker exec arkhyz-hotel-api-prod alembic stamp head → версия e93cd6e8e846.
9. Audit-2: data hygiene¶
Прогнал стандартный data-check после task #23:
| Метрика | Значение |
|---|---|
| stuck_payments_24h | 0 |
| broken_room_30d | 0 |
| broken_restaurant_30d | 0 |
| broken_tour_30d | 0 |
| broken_transfer_30d | 0 |
| broken_instructor_30d | 0 |
| orphan_auth | 0 |
| orphan_public | 11 |
11 orphan_public — это by design: 8 demo-seed аккаунтов + 3 OAuth-юзера (uuid5-формат, OAuth идёт мимо Supabase auth).
stuck_payment_canceller_loop отрабатывает корректно (interval=3600s).
10. Cabinet домены¶
Проверил все 5 ролевых SPA:
hotel.arkhyz-club.ru 200
restaurant.arkhyz-club.ru 200
instructor.arkhyz-club.ru 200
touroperator.arkhyz-club.ru 200
transfer.arkhyz-club.ru 200
Caddyfile в репо синхронен с проднутым. Drift'а нет.
11. Sentry triage — топ ошибок¶
Запросил groups из SQLite за 7 дней:
| Кол-во | Тип | Источник | Действие |
|---|---|---|---|
| 172 | warn | frontend "Failed to fetch" infra | drop в errorReporter.ts |
| 68 | warn | HEAD /map/activities 405 | уже исправлено 25.05 |
| 29+9 | err | /chats/me 502 | Kong DNS флапы (auto-reload стоит) |
| 17 | err | /events/batch 502 | то же |
| 8 | err | ExceptionGroup TaskGroup | известный шум |
| 6+2+1 | err | gemini-flash-1.5 404 | замена модели |
| 4 | err | invalid UUID (JWT as x-user-id) | UUID validation |
Фактические правки:
-
src/lib/errorReporter.ts: 172 шт "Failed to fetch" infra больше не репортятся — это client-side обрывы (DNS/CORS/offline), сервер их не видит, починить нельзя. Для app endpoints оставлены. -
api-admin/app/services/ai/*.py(5 файлов):google/gemini-flash-1.5→google/gemini-2.0-flash-001. OpenRouter внутренне маршрутил на удалённую-8bмодель → 404 "No endpoints found". Затронуто: content_service, rag_service, sentiment_service, tour_agent, trip_planner. -
services/pass-svc/app/routers/skipass.py:_uidпринимаетx-user-idтолько если это валидный UUID (36 chars, дефисы в правильных позициях). Раньше клиент мог прислать JWT как header → asyncpg падал «invalid UUID got 64 chars».
Hot-deploy на прод: pass-svc + hotel-api перезапущены, чисто стартанули.
Коммит: 2c21512ae.
12. Документация (NEXT_STEPS)¶
docs/NEXT_STEPS.md переписан: все F1-F5/U1-U6/R1-R4 + audit задачи перенесены в CHANGELOG. Оставлены 3 кандидата на будущее (U2 SMS phone-lookup, /payments/process legacy, mobile EAS rebuild).
Расширил источники сигналов: добавил блок G — health PSP arkhyzpay-api. В cheat-sheet добавил «alembic stamp head» и «PSP outage».
Коммит: 6b4fe5eef.
13. Emergency disk cleanup¶
При финальной проверке нашёл диск на 91% (/dev/sda1: 139G / 154G). Auto-cleanup в проде запускается только в воскресенье 03:00 (arkhyz-disk-cleanup.timer).
Запустил вручную:
docker image prune -af
docker builder prune -af
Освобождено 26GB, диск 91% → 74%.
14. Финальная верификация¶
Прогнал 20-точечный чек по всем правкам сессии:
- PSP файлы + routing в booking-svc — OK
- arkhyzpay healthy (GET) — OK
- alembic_version stamped — OK
- payment_provider_default = yookassa — OK
- pass-svc UUID validation — OK
- Gemini-2.0-flash в 5 AI сервисах — OK (0 устаревших)
- stuck_payment_canceller worker запущен — OK
- Auto-deploy timer active — OK
- error_events 24h = 0 — OK
- broken_bookings 30d = 0 (все 5 типов) — OK
- stuck_payments 24h = 0 — OK
- errorReporter filter в admin-web бандле — OK
- 3 self-hosted workflows — OK
- tourist-app 9 chunks — OK
- 11 public endpoints отвечают 200 — OK
- 5 cabinet доменов 200 — OK
- pay.arkhyz-club.ru 200 — OK
- containers health — OK
- disk 74% — OK
- NEXT_STEPS обновлён — OK
Итог¶
| Категория | Закрыто |
|---|---|
| Backend code fixes | 3 (gemini, UUID validation, PSP routing) |
| Frontend code fixes | 1 (errorReporter network filter) |
| Infra/DevOps | 4 (alembic stamp, healthcheck, disk, CI) |
| Refactor | 3 (gen-routes, code splitting, NEXT_STEPS) |
| Audit | 3 (errors, data, deployment) |
Прод-состояние: 0 ошибок в error_events за 7 дней, 0 broken/stuck bookings, все эндпойнты 200, диск 74%, все контейнеры healthy.
Открытые задачи: бэклог пуст. 3 low-priority кандидата вынесены в NEXT_STEPS на будущее.
Отчёт сгенерирован автоматически из git log + task list.