# ADR-074: Версия — короткая ревизия, «время сборки» — время коммита

Уточняет [ADR-022](022-deploy-nginx-systemd.md) (подлинность бинаря проверяется сверкой хеша со сборкой из тега) и [ADR-057](057-version-marks-dirty-tree.md) (`+dirty` у сборки из изменённого дерева).

Доведён до интерфейса [ADR-067](067-version-in-sidebar-foot.md): версия и время коммита стоят в подвале сайдбара.

## Контекст

Интерфейс должен называть версию, которая сейчас работает: иначе разговор о поломке начинается с угадывания, обновилось ли то, что человек видит.

Ревизия у сервера уже есть — `revision()` в `cmd/bare` читает `vcs.revision` и `vcs.modified` (ADR-057), — но живёт в `main` и снаружи недоступна. `internal/api` до неё не дотягивается.

Второй вопрос — «время сборки». Естественный ответ, штамп момента компиляции через `-ldflags -X`, ломает ADR-022: артефакт деплоя — один файл, и его подлинность проверяется тем, что сборка из тега даёт тот же хеш. Со временем компиляции внутри каждая пересборка одного и того же коммита даёт другой файл, и сверка перестаёт что-либо значить. Рядом с ревизией лежит `vcs.time` — время коммита, приходящее из git вместе с ней. Оно воспроизводимо и отвечает на настоящий вопрос: какой код работает, а не когда его компилировали.

## Решение

- Чтение build info переезжает в `internal/build`: полная ревизия, признак изменённого дерева, время коммита. `cmd/bare` и `internal/api` берут версию оттуда — двух форматов у одной величины не заводится.
- Версия — семь символов ревизии. У сборки из изменённого дерева к ним дописывается `+dirty` (ADR-057), без ревизии вовсе — `unknown`.
- «Время сборки» — это `vcs.time`, время коммита. Штампа момента компиляции в бинаре нет и не появится.
- `GET /api/config` отдаёт `version` (строка) и `commitAt` (миллисекунды Unix, `0` если времени нет). Отдельного `/api/version` нет: конфигурацию клиент читает до входа и так, а второй эндпоинт ради двух полей — лишний маршрут. В других ответах версии тоже нет.
- `bare version` печатает то же самое: короткую ревизию и время коммита в UTC одной строкой.

## Следствия

- Сверка «хеш файла на сервере против сборки из тега» остаётся проверяемой: в бинаре не осталось ничего, что менялось бы от пересборки.
- `bare version` больше не печатает полный хеш. Семи символов хватает и человеку, и `git show`; `docs/deploy.md` говорит то же.
- Время в интерфейсе отстаёт от момента деплоя ровно настолько, насколько деплой отстал от коммита. Это и спрашивают.
- Сборка не из git — `go run`, `go build -buildvcs=false`, тестовый бинарь — показывает `unknown` и `0`. Тесты видят именно её: `vcs.*` тестовому бинарю не проставляются, и это состояние проверяется ими прямо.
- Клиенту остаётся показать два поля; где именно и какими словами — `docs/ui.md`.
