Files
transcriber/openspec/changes/archive/2026-08-15-remove-telegram-intake/specs/access/spec.md
T
av 8f7c3a057a удалён вход Telegram, владелец записи стал обязателен в схеме
- убраны клиент бота, транспорт обновлений, отправитель сообщений, сборка
  входа при старте, секция настроек и зависимость go-telegram-bot-api; из
  конвейера ушла доставка ответа отправителю — исход виден опросом готовности.
  Колонки адресата и значение источника остались в схеме: применённые шаги не
  переписываются
- шаг 202608140003 запрещает пустого владельца у аудиозаписи и у файла;
  существующие строки он не проверяет, и это принято сознательно — искать их
  надо запросом до выкладки
- ревью нашло два пред-существующих дефекта, оба закрыты: пустой второй ответ
  распознавателя стирал сохранённую расшифровку, а пустая расшифровка перестала
  быть заметной вместе с убранной доставкой. Попутно поднят golang.org/x/image
  до v0.45.0 — красный шаг vulns, воспроизводился и на чистом master
2026-08-15 07:24:35 +03:00

4.2 KiB

MODIFIED Requirements

Requirement: У записи есть владелец, и чужую ей не отдают

Сервис SHALL заводить у каждой принятой записи владельца — учётную запись, от имени которой запись принята, — и MUST отдавать данные такой записи только её владельцу. Запись без владельца MUST не заводиться ничем — ни приёмом, ни конвейером, ни рукой в панели: колонка владельца пустого значения не принимает, и норму эту держит capability storage.

Владелец назначается один раз, при приёме, и MUST не меняться: совместного доступа, ролей и передачи записи другому сервис не знает.

Владелец MUST браться из предъявленной сессии и ниоткуда больше. Владелец, пришедший полем запроса, дал бы всякому вошедшему право завести запись на чужое имя.

Обращение к чужой записи MUST быть неотличимо от обращения к несуществующей. Отдельный отказ «доступ запрещён» превращает опрос в перебор — по разнице ответов считывается, какие записи заведены, а идентификатор записи и есть то, что разграничение прячет. Каким именно ответом это выражено, нормирует capability intake: там живёт адрес опроса, и держатель нормы обязан быть один.

Пустой владелец MUST не совпадать ни с одной записью. Правило записано со стороны спрашивающего и остаётся в силе, хотя записей без владельца в хранилище больше нет: спрашивающий с пустым владельцем — это вызов, у которого нет учётной записи, и отвечать ему надо отказом, а не выборкой. Держится оно отдельно от схемы намеренно: схема запрещает заводить ничью запись, а это правило запрещает спрашивать ничьим именем, и одно другое не заменяет.

Scenario: Своя запись доступна

  • GIVEN человек вошёл и принял запись
  • WHEN он спрашивает состояние этой записи своей сессией
  • THEN ответ несёт состояние записи

Scenario: Чужая запись неотличима от несуществующей

  • GIVEN запись принята одним вошедшим
  • WHEN её состояние спрашивает другой вошедший
  • THEN ответ тот же, что и на неизвестный идентификатор, — и кодом, и телом

Scenario: Владельца не задают запросом

  • WHEN запрос на приём записи несёт своё значение владельца
  • THEN владельцем принятой записи становится предъявитель сессии

Scenario: Ничью запись завести нечем

  • WHEN запись пытаются завести с пустым владельцем
  • THEN хранилище её не сохраняет

Scenario: Пустой владелец не открывает ничего

  • GIVEN заведены две записи: своя и чужая
  • WHEN состояние каждой спрашивают с пустым владельцем
  • THEN ответ на обе тот же, что и на неизвестный идентификатор