# Конвенции кода

Кросс-каттинг правила того, **как** мы пишем код (логирование, ошибки,
именование) — в отличие от `docs/specs/` и `openspec/specs/`, которые
описывают, **что** система делает.

Конвенции **не** переносятся в OpenSpec: это не capability. Короткие
инварианты дублируются в [CLAUDE.md](../../CLAUDE.md) (агент читает его
всегда) и кратко в `openspec/config.yaml` → `context` (подмешивается в
генерацию артефактов); детали — здесь. Обоснование «почему» — в `docs/adr/`.

## Записи

- [logging.md](logging.md) — логирование: уровни, поля, что не логируем.
- [config.md](config.md) — конфигурация: TOML, секреты через деплой
  (Ansible+Vault), валидация на старте.
- [errors.md](errors.md) — ошибки: stdlib, обёртка `%w`, `errors.Is`/`As`,
  трансляция на внешней границе.
- [database.md](database.md) — БД и идентификаторы: TEXT ULID PK через
  `internal/ident` (без AUTOINCREMENT), lowercase + нормализация на границах,
  естественные ключи у деталей.
- [web-ui.md](web-ui.md) — веб-UI на htmx: единый партиал = страница = фрагмент,
  ветвление `isHTMX`, деградация без JS, ошибка = 200 + фрагмент, самозавершающийся
  поллинг, вендоринг/кэш статики.
