## Why

Свёртка выполняется **внутри обработчика запроса**, поэтому время ответа равно
времени свёртки: 16 тысяч точек — 11 секунд. `WriteTimeout` в Go ставится в
`readRequest`, то есть до вызова обработчика, и его 30 секунд — общий бюджет на
всё: дочитать тело по мобильной сети, записать архив, вставить строку, свернуть.
Когда бюджет выходит, сервер считает, что отдал `200` (ошибки записи
обработчику не видно, ответ ушёл в буфер), клиент получает обрыв, а `accessLog`
пишет `status_code=200` — единственный канал наблюдаемости в этом сценарии врёт.

Бьёт это по **широким проходам** (`Today`, `Previous 7 Days`, ручной экспорт) —
ровно по тем, ради которых заведён инвариант «дыры закрываются сами».

## What Changes

- Приём отвечает `200` **после архивации тела и вставки строки `delivery`**.
  Свёртка из обработчика уходит: время ответа перестаёт зависеть от ширины
  доставки.
- Свёртку ведёт **фоновый воркер** — одна горутина, обработка в порядке журнала
  (`received_at`, `id`) среди доставок, видимых ему на момент выборки.
- **Очередью служит сама таблица**, а не список идентификаторов в памяти:
  доставка ждёт свёртки в статусе `pending`, канал несёт только сигнал «есть
  работа». Отсюда три следствия: переполнять нечего (доставка и так `pending`,
  это не отказ), падение процесса очередь не теряет, а «подбор `pending` при
  старте» перестаёт быть отдельным кодом — это обычный проход воркера.
- Классификация исхода свёртки (`folded` / слой не выведен / содержимое не
  разобрано / прочее / частичный разбор) становится **общей с пересборкой**:
  один проигрыватель в `internal/replay`, а не второй рядом.
- **Исход свёртки начинает отражать доставку, а не обстоятельства.** Сегодня
  `failed` пишется на любой ошибке, включая занятость базы; с воркером это
  означало бы, что доставка выбывает из очереди навсегда — а конкуренция за базу
  как раз становится штатной. Отмена и занятость статус больше не меняют,
  доставка остаётся `pending`; всё прочее по-прежнему `failed` и возвращается
  только пересборкой.
- Остановка сервиса формулируется **инвариантом**, а не обещанием досчитать:
  приём прекращается раньше воркера, и после остановки нет доставки, которая
  числится разобранной, а записана наполовину. Свёртка идёт на контексте,
  отвязанном от остановки.
- Наблюдаемость воркера: `WARN`, когда доставка ждала свёртки дольше периода
  быстрого прохода, и одна строка `INFO` о размере задолженности при старте.
  Метка считается на выборке прохода, а сам проход будит не только сигнал, но и
  тик — иначе «работа есть, прогресса нет» неотличимо от пустого потока.
  Счётчики в `/stats` — задача `stats-endpoint`, здесь только метки в логе.
- Убирается второй, оставшийся источник молчаливого обрыва: общий `write_timeout`
  (30 с) меньше `read_timeout` (5 мин), а он покрывает и чтение тела — то есть
  медленная загрузка 64 МиБ обрывается независимо от свёртки. Длинный бюджет
  даётся **маршруту приёма** собственным дедлайном ответа; общий таймаут и
  конфиг не меняются, и прочие маршруты защиту не теряют.
- Миграция: частичный индекс по неразобранным доставкам — воркер спрашивает их
  чаще, чем раз в минуту, а таблица растёт на ~300 строк в сутки.

## Capabilities

### New Capabilities

- `ingest`: приём доставки как самостоятельное поведение — что делает ответ
  `200` заслуженным, когда он отдаётся, кто и в каком порядке сворачивает
  принятое, что происходит с несвёрнутым при остановке и рестарте.

### Modified Capabilities

- `parsing`: требование «Разбор не влияет на код ответа приёма» уточняется —
  разбор идёт **после** ответа, поэтому исход становится виден не в ответе и не
  сразу, а асинхронно, в `parse_status` и в логе.
- `storage`: требование «Учёт частично разобранной доставки» уточняется — отказ
  обстоятельств (отмена, занятость базы) статуса не меняет вовсе, а прежняя
  формулировка «ошибка ⇒ `failed`» этого не допускала.
- `reindex`: требование «Отчёт, оракул и исход команды» получает четвёртый класс
  отказа — «работа отложена по обстоятельствам»: классы у пересборки и у фоновой
  свёртки общие.

## Impact

- `internal/ingest` — теряет зависимость от `internal/fold`: `Accept` кладёт
  тело, учитывает доставку и будит воркер.
- `internal/replay` — общий проигрыватель (свернуть доставку, классифицировать
  исход) и фоновый воркер поверх него.
- `internal/store` — выборка неразобранных доставок в порядке журнала с
  курсором, сентинел занятости базы; миграция `00006` с частичным индексом.
- `internal/fold` — отмена и занятость базы больше не переводят доставку в
  `failed`.
- `cmd/healthlog/serve.go` — жизненный цикл воркера и согласованная остановка.
- `internal/httpapi` — сборка `ingest.Service` без свёртки; собственный дедлайн
  ответа на маршруте приёма. `config.example.toml` — комментарий к
  `write_timeout`.
- `docs/architecture.md`, `docs/database.md` — путь приёма и новый индекс.
