# 🧹 Разобрать мелочи хранилища на sqlite

- **Тип:** chore
- **Категория:** Очередь — Мелочи слоя хранилища разбираются, пока слой в руках
- **Зачем:** Четыре мелочи ниже потолка триажа в одном пакете: три репозитория не переводят sql.ErrNoRows в доменную ошибку, два числа задают один и тот же предел страницы порознь, Append не заполняет время, которое сам же кладёт в базу, а у selectList — мёртвый довод prefix.
- **Теги:** review-2026-08-23

Четыре мелочи ревью change `2026-08-23-storage-without-pocketbase`, оставшиеся
ниже потолка триажа. Собраны одной задачей: все живут в
`internal/adapter/repo/sqlite` и правятся одним заходом.

1. **Репозитории текста, структуры и попытки распознавания не переводят
   `sql.ErrNoRows` в доменную ошибку**, при том что репозиторий записи в том же
   пакете правило исполняет (`record_repo.go`). Вызывающий не отличает «записи
   нет» от отказа базы, потому что типизированного значения ему не приходит.
2. **Два числа об одном пределе страницы:** `defaultListLimit = 30` в слое
   хранилища и `DefaultPageLimit = 30` в контракте. Совпадают дословно, а
   меняются порознь.
3. **`RecordEventRepository.Append` не заполняет `event.CreatedAt`**, хотя само
   же значение кладёт в базу: вызывающий получает событие с нулевым временем.
4. **Мёртвый довод `prefix` у `selectList`** — ни один вызов его не читает.

Нашёл проход `review-code` (C6 и то, что осталось за его потолком конвенций).

## Затрагивает

- `internal/adapter/repo/sqlite` — `text_repo.go`, `recognition_repo.go`,
  `record_event_repo.go`, `record_list.go`;
- `internal/contract` — типизированное значение «записи нет» и константа
  предела страницы;
- конвенция [errors.md](../../docs/conventions/errors.md) — единая точка
  трансляции ошибки хранилища.

## Критерии приёмки

- «Записи нет» приходит вызывающему одним значением из всех репозиториев.
  **Оракул:** тест на каждый из трёх репозиториев — запрос несуществующего
  идентификатора отвечает значением, которое узнаётся `errors.Is`, а не
  `sql.ErrNoRows`.
- Предел страницы объявлен одним числом. **Оракул:** `grep -rn "= 30"
  internal/` — объявление одно, второе место ссылается на него.
- Приложенное событие приходит с временем, которое уехало в базу. **Оракул:**
  тест `Append` — у возвращённого события `CreatedAt` не нулевое и совпадает со
  строкой в базе.
- Мёртвого довода нет. **Оракул:** `go vet ./...` и `golangci-lint run`
  зелёные, `grep` по `selectList` не находит довода `prefix`.

## Рамки

Раскладку каталога данных и имена копий не трогаем — это разведка
`record-file-name-readability`. Применённые шаги схемы не переписываются.
