добавлены документация проекта и каркас разработки
- README, CLAUDE.md, docs: назначение и границы, архитектура, конвенции, план - docs/local-research.md — 36 находок по формату Health Auto Export, снятых на живых данных; документация приложения местами расходится с тем, что оно шлёт - Taskfile, .golangci.yml, самодокументируемый config.example.toml
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# CLAUDE.md
|
||||
|
||||
Памятка для работы над healthlog. Перед задачей прочитай также
|
||||
[README.md](README.md), [docs/architecture.md](docs/architecture.md),
|
||||
[docs/conventions.md](docs/conventions.md) и [docs/plan.md](docs/plan.md).
|
||||
|
||||
## Что это
|
||||
|
||||
Коллектор данных Apple Health. Принимает выгрузки из Health Auto Export,
|
||||
хранит их и отдаёт другим моим проектам через HTTP API. Это **хранилище, а не
|
||||
аналитика**: принять, дедуплицировать, сохранить, отдать. Не считать агрегаты,
|
||||
не переименовывать поля Apple, не интерпретировать значения.
|
||||
|
||||
## Стек
|
||||
|
||||
Go, один статический бинарь (`CGO_ENABLED=0`). SQLite (`modernc.org/sqlite`,
|
||||
чистый Go), `chi`, `sqlx`, `goose` (миграции), `pelletier/go-toml/v2`,
|
||||
`log/slog`, ULID через `internal/ident`.
|
||||
|
||||
Module path — `git.vakhrushev.me/av/healthlog`.
|
||||
|
||||
## Инварианты
|
||||
|
||||
- **Точки хранятся дословно.** Часовой объект держит точки ровно в том виде,
|
||||
в каком их прислал HAE. На этом инварианте держится всё остальное: сырой
|
||||
архив живёт лишь 14 дней, дальше истина — сами объекты. Начнём что-то
|
||||
отбрасывать внутри точки — срок хранения архива станет сроком жизни данных.
|
||||
- **Сохранили — значит приняли.** Код ответа отражает доставку, а не разбор:
|
||||
битый JSON — 400, непонятое содержимое — 200.
|
||||
- **Ничего не теряем молча.** Идентичность — хеш **канонизированного**
|
||||
(рекурсивно отсортированного) содержимого: повтор не меняет ничего,
|
||||
различие сохраняется. Изменение запечатанного часа — `WARN`, но данные
|
||||
всё равно пишутся.
|
||||
- **Дыры закрываются сами.** Три прохода синхронизации разной глубины
|
||||
(5 минут / час / сутки), настройки данных у всех одинаковы.
|
||||
- **Форма Apple не транслируется.** Значения отдаём как пришли, нормализовано
|
||||
только время (`ts_utc` + офсет исходной зоны).
|
||||
- **Своей агрегации нет — есть слои.** Метрика хранится в той подробности, в
|
||||
какой пришла (`raw`/`minute`/`hour`); слой выводится из выравнивания меток,
|
||||
а не из заголовка HAE — тот врёт. Клиенту показываем каталог разрезов, выбор
|
||||
за ним.
|
||||
- **Секреты не в логах** — токены приёма и чтения. Данные о здоровье
|
||||
чувствительны: тела запросов только на `DEBUG` и с обрезкой.
|
||||
|
||||
## Команды
|
||||
|
||||
Запуск через [Task](https://taskfile.dev) (`task --list` — полный список):
|
||||
|
||||
- `task run` — локальный запуск (`--config ./config.toml`)
|
||||
- `task build` — статический бинарь linux/amd64
|
||||
- `task test` / `task lint` — тесты и golangci-lint
|
||||
- `task tidy` — `go mod tidy`
|
||||
- `task setup` — установка golangci-lint
|
||||
|
||||
## Конвенции
|
||||
|
||||
Механизируемое проверяет `task lint` (`.golangci.yml`): форма логов
|
||||
(`sloglint`), `fmt.Print*` / `os.Getenv` / `time.Now` мимо единых точек
|
||||
(`forbidigo`), сравнение ошибок (`errorlint`), сторонние пакеты ошибок
|
||||
(`depguard`). Пересказывать эти правила не нужно — линтер скажет точнее.
|
||||
|
||||
Прозой остаётся то, что правилом не выражается:
|
||||
[docs/conventions.md](docs/conventions.md) — уровень лога по адресату,
|
||||
единственный логирующий чекпоинт на доменной границе, трансляция ошибки на
|
||||
внешней границе, самодокументируемый `config.example.toml`, время в БД в UTC
|
||||
RFC 3339, ULID через `ident`.
|
||||
|
||||
Отдельно: **тесты на разбор формата HAE держим на реальных пакетах** в
|
||||
`testdata`. Документация формата тонкая и местами расходится с тем, что
|
||||
приложение реально шлёт, — источником истины служат живые данные.
|
||||
|
||||
Что показал реальный поток — [docs/local-research.md](docs/local-research.md).
|
||||
Читать **до** работы над разбором: там же лежат находки, которых нет в
|
||||
документации HAE (поле `source` существует; порядок ключей в JSON нестабилен,
|
||||
поэтому хеш содержимого считается по канонической форме с рекурсивной
|
||||
сортировкой; мелкая группировка даёт интерполяцию, а не измерения). Файл
|
||||
пополняется по мере накопления доставок.
|
||||
|
||||
## Язык
|
||||
|
||||
- Документация, комментарии, сообщения коммитов — **русский**.
|
||||
- Код и идентификаторы — английский.
|
||||
Reference in New Issue
Block a user