VEU.WathBody/1-docs/4-modules/m07-fit-fetch/readme.md

3.2 KiB
Raw Blame History

m07-fit-fetch — план работ (d-dev)

Модуль: Server.WatchBody.Fetch (GarminClient + FitFetcher) и режим --mode fetch — забор .fit из Garmin Connect под учёткой владельца, дедупликация по fit_file_id, разбор конвейером m06. Алгоритм: std1\_rules\d\d-dev.md. Требования: module_reqs.md. Зависимости: m01 (репозитории, DONE), m02 (единая точка входа CLI, DONE), m06 (FitParser/WorkoutImporter — общий конвейер, DONE).

Шаг Что делаем Статус
0 Модульные документы: module_reqs.md / readme.md / SKILL.md ✅ 2026-10-18
1 Список единиц (классы/методы/конфиг/тесты) ✅ 2026-10-18
1.3 Пользователь! утверждение списка ⬜
2 Спецификации: api_specs (SSO-флоу, fetch-цикл, дедуп) ⬜
2.4 Пользователь! утверждение спецификаций ⬜
3 Реализация + тесты ⬜
3.4 Пользователь! утверждение реализации (закрытие модуля) ✅ 2026-10-18
4 Завершение: план, примечания ✅ 2026-10-18 — Модуль завершён (2026-10-18). Итерация 2 (m04–m07) завершена. Следующий по плану этапа 7 — m08-admin-web (итерация 3).

Статусы: ⬜ не начат · 🔄 в работе · ✅ готов.

Примечания по ходу работ

  1. Прототип: реальный логин Garmin против живого сервиса не автоматизирован (tech-req чек-лист «Логин Garmin Connect — итерация 2»); GarminClient реализует флоу garminconnect полностью (embed → csrf → signin → ticket → OAuth1-HMAC-SHA1 → Bearer), но против Garmin Connect валидируется только вручную — при блокировке fallback = папка импорта (m06, О-1-А). Тесты — FakeGarminHandler с теми же маршрутами и настоящими .fit-байтами (энкодер SDK).
  2. Куки: CookieContainer наполняется из Set-Cookie вручную (редиректы не следуются автоматически — ticket читается из Location/тела).
  3. Дедуп: рубеж 1 — файл-кэш {activityId}.fit (без сети); рубеж 2 — fit_file_id в БД до записи (дубль → файл не кэшируется). Тест «дубль» даёт skipped=2 (кэш + дубль) — корректно.
  4. Битый download → {activityId}.bad (кэш не занимает, повторный fetch скачает заново).
  5. Конфиг Garmin.* — читается в ServerConfig; в appsettings умолчания пустые (🛡 секреты только в конфиге владельца).