VEU.WathBody/1-docs/4-modules/m09-phone-core/api_specs/04-contract-payloads.md

4.0 KiB
Raw Permalink Blame History

Спецификация 04: payload-контракт sync (фикстуры)

Источники: tech-req 2.1/2.2 (конверт, составы data), m02 spec 03 (серверный приёмник). Тест сериализации — каждый payload сравнивается с фикстурой (ключи/типы snake_case).

1. Конверт

{"client_guid": "<uuid>", "entity": "workout_set", "op": "upsert",
 "data": { …поля сущности… }}

2. data по сущностям (обязательные/опциональные поля)

entity data Примечание
workout program_version_id?, started_at (ISO UTC), ended_at?, status, session_kind, avg_hr? status: active/finished/cancelled
workout_set workout_id, exercise_id?, seq, weight_kg, reps, done_at, source, in_plan, rpe?, knee_pain? вес — число с точкой
command_log workout_id, t_offset_s, recognized_text, semantics (объект), accepted
daily_log date (yyyy-MM-dd), bp_sys?, bp_dias?, weight_kg?, hr_resting?, wellbeing? день уникален — сервер upsert
break kind?, source (только manual), started_on, planned_return?, ended_on?, note 🛡 авто — сервер
exercise name, group (push/pull/legs/core/cardio), is_base, is_active id = client_guid (серверу не передаётся)
program_version version (число, обязательно — значение считает БД), based_on_version?, author (user), rationale? + поля программы (weeks…) на верхнем уровне errata m10 2026-10-19: контракт m02 spec 03 — data хранится сервером целиком как body; вложенного body НЕТ; локальные draft (в v1 телефона нет писателя — решение гейта 1.3 m10)
profile sex?, birth_year?, weight_kg?, hr_max? singleton

Уточнения против m02 spec 03: exercise_id у workout_set — локальный UUID упражнения (Р2-Б, строкой); program_version_id — UUID версии; break.kind ∈ illness/vacation/workload/injury/other. profile.sex ∈ m/f (валидатор m02), null — не передаётся. Errata 2026-10-19 (смок против живого сервера): client_guid — UUID v4 для ВСЕХ сущностей, включая daily_log и profile (даты и строки-слова сервер отвергает — «client_guid отсутствует или не uuid»); поэтому в LocalDb у daily_log/profile есть стабильная колонка guid (spec 01) — WorkoutCore сохраняет существующий guid при повторных правках, client_guid = guid. Примечание: сервер (m02 spec 06: «лишние поля игнорируются») не разбирает break.ended_on — локальное закрытие перерыва в v1 на сервер не уходит (дату возврата выводит серверный BreakEngine по тренировкам); кандидат v2.

3. Даты/время

  • started_at/done_at/ended_at — yyyy-MM-dd'T'HH:mm:ss'Z' UTC (сервер парсит UtcDate);
  • date/started_on/planned_return/ended_on — yyyy-MM-dd.

4. Фикстуры теста

Проверки полей — инлайн в тест-классе SyncPayloadTest (app/src/test): PayloadFactory.* → JsonObject → assert ключей/типов/значений snake_case, optional-поля — только при наличии; отдельно недопустимые варианты: break.source="auto" → исключение фабрики (🛡); конверт envelope(Pending) — форма client_guid/entity/op/data.