приём и чтение записей сведены к одному контракту приложения
- адреса приложения переехали в своё пространство `/app/`, опрос готовности убран целиком: рубеж и причину остановки владелец узнаёт карточкой записи, текст — отдельным адресом названного вида - заведена единая точка отображения доменной ошибки и слой, приводящий к той же форме отказы библиотеки: тело несёт машиночитаемый код рядом с сообщением - у записи появились имя файла отправителя, длительность и размер своими колонками, а у ленты владельца — свой индекс: без него страница сканировала весь архив сервиса
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# Приложение живёт своим пространством адресов, а не общим с хранилищем
|
||||
|
||||
- **Дата:** 2026-08-15
|
||||
- **Источник:** openspec/changes/archive/2026-08-15-app-json-contract/design.md,
|
||||
раздел «Переезд в `/app/`, а слой сессии — на корень»
|
||||
|
||||
## Решение
|
||||
|
||||
Все адреса приложения переехали из `/api/` в собственный корень `/app/`, а слой
|
||||
предъявления сессии повешен на **группу корня**, а не на перечень адресов.
|
||||
|
||||
## Почему
|
||||
|
||||
Пространство `/api/` принадлежит хранилищу: оно вешает туда собственные наборы
|
||||
адресов, и поменять этот префикс нельзя — он литерал библиотеки, а не настройка.
|
||||
Свободных имён сегодня хватает, но соседство остаётся: обновление библиотеки
|
||||
вправе занять новое имя рядом с нашим, и разойдутся они молча — тем же адресом
|
||||
начнёт отвечать не тот обработчик.
|
||||
|
||||
Прецедент в проекте уже принят тем же доводом: адреса входа вынесены на `/auth/*`
|
||||
решением от 2026-08-12.
|
||||
|
||||
Слой на корень, а не на перечень: «перечень рос бы с каждым новым адресом
|
||||
приложения, и забытый в нём адрес молча перестал бы принимать куку».
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` соседство с чужими адресами кончилось: имя, занятое библиотекой, наших
|
||||
адресов больше не задевает;
|
||||
- `+` новый адрес приложения получает слой предъявления по построению, а не по
|
||||
памяти того, кто его добавил;
|
||||
- `−` правило неизвестного пути перечисляет теперь четыре корня сервиса вместо
|
||||
одного: `/api/`, `/app/`, `/auth/` и `/_/`;
|
||||
- `−` ограничитель частоты хранилища, настроенный на его собственный корень,
|
||||
наших адресов не покрывает — своё правило заводится нами, и его включение
|
||||
вводит в действие заодно умолчательные правила хранилища;
|
||||
- `−` ломка полная: прежние адреса приёма и опроса отвечают `404`. Оплачено
|
||||
стадией — на сервере данных нет, внешней программы на прежнем контракте не
|
||||
существует.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Страница архива задаётся ключом, а не номером
|
||||
|
||||
- **Дата:** 2026-08-15
|
||||
- **Источник:** openspec/changes/archive/2026-08-15-app-json-contract/design.md,
|
||||
раздел «Страница задаётся ключом, а не номером»
|
||||
|
||||
## Решение
|
||||
|
||||
Постраничное чтение своих записей идёт непрозрачным ключом по паре «время
|
||||
заведения и идентификатор». Номер страницы отвергнут.
|
||||
|
||||
## Почему
|
||||
|
||||
«Приём пишет в голову той же таблицы записей, которую читает список, и человек,
|
||||
загрузивший запись и листающий свой архив, — штатный сценарий. Номер страницы
|
||||
сдвинул бы окно на единицу: последний элемент первой страницы пришёл бы вторым
|
||||
разом первым элементом второй, а один элемент между ними не пришёл бы никогда.
|
||||
Отказ молчаливый — ни кода, ни строки в журнале, — и человек видел бы архив, в
|
||||
котором записи нет.»
|
||||
|
||||
Ключ полный: у записей, принятых одним запросом, время совпадает, и порядок
|
||||
между ними одним лишь временем не определён.
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` запись, заведённая между двумя страницами, не даёт ни повтора, ни
|
||||
пропуска;
|
||||
- `+` порядок между записями с равным временем устойчив;
|
||||
- `−` экран с нумерацией страниц так не сделать — листать можно только
|
||||
«дальше». Архиву это не нужно;
|
||||
- `−` ключ приходит от клиента и потому разбирается: время приводится к виду
|
||||
хранилища, иначе побайтовое сравнение молча обращает условие в постоянную
|
||||
истину или ложь.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Длительность и размер лежат колонками записи, и равенство со строкой файла не поддерживается
|
||||
|
||||
- **Дата:** 2026-08-15
|
||||
- **Источник:** openspec/changes/archive/2026-08-15-app-json-contract/design.md,
|
||||
раздел «Три новых колонки записи и один шаг схемы»
|
||||
|
||||
## Решение
|
||||
|
||||
Длительность и размер принятого легли колонками аудиозаписи, хотя обе величины
|
||||
уже есть у строки её файла. Равенство между ними не поддерживается никем —
|
||||
намеренно. «Неизвестно» эти колонки не выражают: ноль означает ноль.
|
||||
|
||||
## Почему
|
||||
|
||||
Обе величины показываются в списке, а список по норме `storage` читается без
|
||||
содержимого. Ревью дизайна возражало: величины станут копиями, которые некому
|
||||
держать равными. Решением владельца колонки остались, а равенство объявлено
|
||||
**ненужным**: «на записи лежит снимок принятого, взятый приёмом один раз; на
|
||||
файле — величины той копии, которой файл является сейчас». Уточнение
|
||||
длительности — перечитали метаданные, сменили источник, нарезали длинную запись
|
||||
— меняет вторые и не трогает первые. Это разные вопросы: «что человек прислал» и
|
||||
«что лежит сейчас».
|
||||
|
||||
Отличимость «неизвестно» от нуля снята после ревью кода и по замеру: числовая
|
||||
колонка хранилища пустого значения не держит вовсе и кладёт пустое нулём.
|
||||
Платить за отличимость четвёртой колонкой-признаком либо текстовым типом у чисел
|
||||
не за что — обе величины ставит приём и ставит всегда, а запись с непрочитанными
|
||||
метаданными отвергается отказом и не заводится.
|
||||
|
||||
## Последствия
|
||||
|
||||
- `+` страница списка не читает по строке файла на каждую запись;
|
||||
- `+` смысл у двух пар чисел разный и записан нормой, а не подразумевается;
|
||||
- `−` в применённом шаге схемы навсегда остаются две колонки, повторяющие
|
||||
величины строки файла; расхождение между ними — не поломка, и заметить его
|
||||
нечем;
|
||||
- `−` запись, заведённая рукой в панели без величин, покажет человеку ноль.
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
| Дата | Запись | Статус |
|
||||
| --- | --- | --- |
|
||||
| 2026-08-15 | [Приложение живёт своим пространством адресов, а не общим с хранилищем](ADR-2026-08-15-app-namespace.md) | |
|
||||
| 2026-08-15 | [Страница архива задаётся ключом, а не номером](ADR-2026-08-15-cursor-paging.md) | |
|
||||
| 2026-08-15 | [Длительность и размер — снимок принятого колонками записи](ADR-2026-08-15-record-snapshot-columns.md) | |
|
||||
| 2026-08-15 | [Вход Telegram убран целиком, а не выключен признаком](ADR-2026-08-15-telegram-intake-removed-temporarily.md) | |
|
||||
| 2026-08-15 | [Обязательность владельца держит схема, а не приём](ADR-2026-08-15-owner-required-by-schema.md) | |
|
||||
| 2026-08-15 | [Метка убранного входа не выставляется вовсе, а не обнуляется](ADR-2026-08-15-removed-intake-has-no-metric-label.md) | |
|
||||
|
||||
Reference in New Issue
Block a user