Files
bare/docs/decisions/028-client-state-texts.md
mayatnikovandClaude Opus 5 597c55301c Этап 1: аккаунты — argon2id, сессии, ключевой блоб, вход и регистрация
Сервер: миграция 001 со всей схемой storage.md, store на modernc.org/sqlite
(WAL, foreign_keys, один писатель), фоновая чистка раз в час, argon2id
с параметрами ADR-021 и сверкой constant-time, сессии по SHA-256 токена,
cookie bare_session, глобальная проверка Origin, девять эндпоинтов аккаунта.
Ник в журнал не попадает: для /api/ пишется шаблон маршрута.

Клиент: crypto.js по crypto.md построчно — мастер из пароля, два независимых
ключа из мастера, ключевой блоб с ником в AAD, отпечаток от сырой точки;
db.js со всеми хранилищами версии 1; экран входа и регистрации, настройки
со сменой пароля, выходом и удалением аккаунта.

Пароль не покидает клиент: проверено на боевом сервере — ни пароля, ни priv.d
ни в одном теле запроса, вход на втором устройстве даёт тот же отпечаток.

ADR-027: код internal для 500, причина только в журнале.
ADR-028: тексты состояний клиента сведены в ui.md.
ADR-029: вход под другим ником стирает историю только после подтверждения.
ADR-030: верхняя граница итераций KDF, проверка границ на обеих сторонах.
ADR-031: служебный выход перед повторным входом не заканчивает сеанс.
ADR-032: каталог состояния 0700, файлы базы 0600.

Прямые зависимости: modernc.org/sqlite, golang.org/x/crypto.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DbCjVfTFq4ZFG8juD45YJ
2026-08-22 14:06:07 +03:00

3.7 KiB

ADR-028: Тексты состояний клиента

Контекст

docs/ui.md задаёт пять ошибок формы входа и тексты экранов. Этап 1 упёрся в состояния, которых в этих перечнях нет, а показать их надо:

  • запрос не дошёл (сети нет, сервер молчит) и ответ с кодом, на который у клиента нет сценария, — 500 internal (ADR-027), 429, too_large;
  • ключевой блоб не разбирается или не расшифровывается;
  • iter в блобе расходится с ответом GET /api/kdfdocs/crypto.md прямо требует показать это ошибкой;
  • пароль короче 12 символов: проверить длину может только клиент, сервер пароля не видит (ADR-013, ADR-015);
  • в настройках — несовпадение нового пароля с повтором, подтверждение опасной операции не тем паролем, ответ об успешной смене пароля.

Придумывать эти строки в коде молча нельзя: тексты — часть интерфейса, а не деталь реализации.

Решение

Перечни docs/ui.md дополняются разделом «Тексты состояний». Правила прежние: строчные, коротко, говорят, что случилось. Ошибка — строкой цветом mark, ответ об успехе — той же строкой цветом mute.

  • «нет соединения» — запрос не дошёл. Тот же текст, что у полосы в чате: состояние одно.
  • «сервер не справился, попробуйте позже» — код ответа, на который у клиента нет сценария.
  • «слишком часто, попробуйте позже» — 429 rate_limited.
  • «пароль: не короче 12 символов» — проверка клиента при регистрации и смене пароля.
  • «пароли не совпадают» — новый пароль и повтор различаются.
  • «ключ аккаунта повреждён» — блоб не разобран, не расшифрован или не соответствует публичному ключу аккаунта.
  • «параметры ключа не совпали» — iter блоба не равен ответу GET /api/kdf.
  • «неверный пароль» — 401 invalid_credentials в настройках, где ник заведомо свой.
  • «пароль изменён» — ответ на успешную смену.
  • «аккаунт и вся история будут удалены навсегда.» — подтверждение удаления аккаунта.

Следствия

  • docs/ui.md остаётся единственным местом, где живут тексты интерфейса.
  • Клиент разбирает error по перечню docs/protocol.md; всё, чего в перечне нет, и всё, что случилось до ответа, сводится к двум строкам — «нет соединения» и «сервер не справился, попробуйте позже».
  • Новый экран приносит свои тексты в docs/ui.md тем же порядком: сначала документ, потом код.