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

- **Тип:** chore
- **Категория:** Очередь — Мелочи слоя хранилища разбираются, пока слой в руках.
- **Зачем:** Три мелочи ниже потолка триажа: цикл воркера пишет потерю захвата уровнем ERROR и считает её отказом, тип ошибки заведён там, где конвенция просит sentinel, а FileName несёт два разных смысла.

Все три пришли ревью задачи `pocketbase-storage` 2026-08-12 и остались ниже
потолка отчёта — то есть реальны, но не блокировали. Собраны одной задачей,
потому что живут в одном пакете и правятся одним заходом.

1. **Потеря захвата — не отказ шага.** Значение «задачу за время работы забрал
   другой» доезжает до цикла воркера, который пишет его уровнем `ERROR` и
   увеличивает счётчик отказов. `docs/conventions/logging.md` относит «задача
   досталась повторно» к `WARN`, а метрика отказов после этого считает не отказы.
2. **Тип ошибки против sentinel.** `docs/conventions/errors.md` просит sentinel
   там, где данных у ошибки не читает никто; у значения о потерянном захвате
   вызывающий читает только сам факт.
3. **Одно поле в двух смыслах.** У местной копии `entity.File.FileName` — имя в
   хранилище и последняя часть ссылки на скачивание, у внешней — ключ объекта.
   Различает их только соседнее поле, а совпадают они сегодня дословно: на этом
   совпадении держится верность строки `docs/architecture.md` про ключ объекта.

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

- `internal/contract/error.go` — значение о потерянном захвате;
- цикл воркера `internal/controller/worker` — уровень записи и счётчик отказов;
- `internal/entity/file.go` и его потребители в `internal/service`;
- строка про ключ объекта в `docs/architecture.md`, «Внешние границы и форматы».

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

- Потеря захвата не считается отказом и не пишется на уровне владельца сервиса.
  Оракул — тест воркера: после прогона с потерянным захватом счётчик отказов не
  вырос, а строка в журнале идёт уровнем `WARN`.
- Форма значения об отказе совпадает с конвенцией. Оракул — `golangci-lint run`
  плюс чтение `docs/conventions/errors.md` рядом с кодом.
- Два смысла имени файла разведены либо названы в документе. Оракул — `grep` по
  потребителям поля: каждый читает его в одном смысле, а `docs/architecture.md`
  говорит про ключ объекта то же, что делает код.

## Рамки

Раскладку файлов на диске и имена коллекций не трогаем: формат хранения объявлен
необратимым, а шаг схемы, уехавший на сервер, не переписывается.
