# ADR-063: подтверждения копятся и уходят пачкой

Уточняет [ADR-055](055-limit-keys-and-bounds.md): «`POST /api/ack` приходит пачками» — теперь это правда и в живой доставке, а не только при подключении.

## Контекст

ADR-055 положил `POST /api/ack` в общее ведро «60 изменяющих запросов в минуту на пользователя» и обосновал это тем, что ACK приходит пачками после каждого подключения. Для воспроизведения очереди посылка верна: конверты приходят подряд, разбираются одним заходом и подтверждаются одним запросом.

В живой доставке она неверна. Разбор входящих откладывается на следующий такт цикла событий, поэтому конверты, пришедшие в разных тактах, разбираются по одному, и каждый разбор заканчивался своим подтверждением — один `POST /api/ack` на конверт.

Следствие достаётся получателю, и оно измерено. Четверо пишут одному по своему пределу в 30 сообщений в минуту, три минуты: 365 конвертов, 346 подтверждений в журнале сервера, из них 336 — ровно с одним идентификатором. Через 59 секунд ведро кончилось: 103 подтверждения получили `429`, десять пробных изменяющих запросов получателя — все десять `429`, три попытки выйти из комнаты — все три `429`. В очереди сервера осталось 103 неподтверждённых конверта: записаны у получателя, но сервер их не забудет.

Человек, которому пишут часто, теряет возможность уйти: `429` получает всё изменяющее — выход из комнаты, смена пароля, удаление аккаунта.

Второй путь — вынести `/api/ack` из общего ведра пятым правилом ADR-021 — отвергнут: лимит на подтверждения либо не существует вовсе, либо это ещё одно правило, ещё одно ведро и ещё одна карта. Пачка дешевле и не расширяет ADR-021.

## Решение

- Идентификаторы записанного копятся, `POST /api/ack` уходит не чаще раза в две секунды и несёт всё, что накопилось. Задержка ничего не стоит: подтверждение — учёт очереди сервера, а не доставка человеку, сообщение к этому моменту уже на экране.
- Правило `docs/storage.md` остаётся дословным: в накопитель попадает только то, что уже записано в IndexedDB. Неудачная запись не подтверждается ничем.
- Накопитель — множество: конверт, выданный очередью повторно, подтверждается один раз.
- Неудачная отправка бросает накопленное: сервер выдаст эти конверты заново, а `put` по тому же `id` дублей не создаёт (ADR-017).
- Выход гасит таймер и очищает накопитель. Неподтверждённое вернётся очередью при следующем подключении.
- Место лимита не меняется: `/api/ack` остаётся в общем ведре (ADR-055).

## Следствия

- Поток сообщений тратит на подтверждения не больше половины общего ведра — 30 запросов в минуту в худшем случае. Выйти из комнаты, сменить пароль и удалить аккаунт получатель может в любой момент. Тот же прогон после правки: 354 конверта, 83 подтверждения (одно раз в две секунды, по четыре идентификатора в каждом), ни одного `429`, десять пробных изменяющих запросов прошли, выход из комнаты прошёл с первой попытки, очередь сервера пуста.
- Конверт живёт в очереди сервера на пару секунд дольше. Реконнект в этот промежуток выдаёт его заново; запись по тому же `id` не даёт ни дубля в ленте, ни второго непрочитанного (ADR-034), и на экране это не видно.
- Закрытая вкладка уносит с собой до двух секунд неподтверждённого — те же конверты придут очередью в следующий раз.
- Новых текстов интерфейса решение не заводит.
