Сервер: миграция 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
35 lines
3.7 KiB
Markdown
35 lines
3.7 KiB
Markdown
# ADR-028: Тексты состояний клиента
|
|
|
|
## Контекст
|
|
|
|
`docs/ui.md` задаёт пять ошибок формы входа и тексты экранов. Этап 1 упёрся в состояния, которых в этих перечнях нет, а показать их надо:
|
|
|
|
- запрос не дошёл (сети нет, сервер молчит) и ответ с кодом, на который у клиента нет сценария, — `500 internal` (ADR-027), `429`, `too_large`;
|
|
- ключевой блоб не разбирается или не расшифровывается;
|
|
- `iter` в блобе расходится с ответом `GET /api/kdf` — `docs/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` тем же порядком: сначала документ, потом код.
|