Files
bare/docs/plan.md
T
mayatnikovandClaude Fable 5 ae55c846aa ADR-015…024 и спецификации v1: криптография, протокол, хранение, UI, деплой, план
Закрыты все открытые вопросы проектирования. Пароль не покидает клиент
(два ключа из мастера), TOFU для публичных ключей, устройства и конверт,
атомарный rekey комнат, регистрация и контакты, схема SQLite и драйвер
без cgo, сессии и CSRF, деплой через nginx+systemd, правила пушей,
айдентика «Скобы» на системном mono. Иконки PWA в web/icons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015DbCjVfTFq4ZFG8juD45YJ
2026-08-22 10:53:24 +03:00

111 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План реализации v1
Документ для исполнителя — человека или агента. Всё, что здесь, выводится из ADR и спецификаций; при расхождении правы ADR. Этапы идут по порядку, каждый заканчивается работающим деплоем на `bare.xmatic.team` и коммитом.
## Источники истины
| вопрос | документ |
|---|---|
| что и почему | `philosophy.md`, `architecture.md`, `threat-model.md`, `decisions/` |
| криптография, байт в байт | `crypto.md` |
| HTTP-API, SSE, коды ошибок | `protocol.md` |
| схема SQLite, IndexedDB, формат `.bare` | `storage.md` |
| экраны, тексты, поведение | `ui.md`, `identity/` |
| сервер, nginx, systemd | `deploy.md` |
## Раскладка репозитория
```
cmd/bare/main.go подкоманды: serve, vapid, version
internal/config/ переменные BARE_*
internal/store/ SQLite, migrations/*.sql (embed), запросы
internal/auth/ argon2id, сессии, cookie
internal/hub/ SSE-соединения по deviceId
internal/push/ webpush-go, правила ADR-023
internal/api/ маршруты, валидация, лимиты, заголовки
internal/web/ embed web/, отдача статики
web/
index.html app.css manifest.json sw.js
icons/ уже в репозитории
js/main.js загрузка, роутинг, состояние
js/api.js fetch-обёртки, SSE, ACK
js/crypto.js всё из crypto.md
js/db.js IndexedDB из storage.md
js/ulid.js ULID
js/ui/*.js экраны из ui.md
js/export.js .bare
scripts/deploy.sh
```
Go — последняя стабильная версия, маршрутизация `net/http` с шаблонами методов (`"POST /api/messages"`). Прямые зависимости ровно три (ADR-020). Клиент — ES-модули, без сборки, без inline-стилей и скриптов, `innerHTML` запрещён.
## Этап 0 — скелет и деплой
- `go mod init`, `cmd/bare`, `serve` слушает `BARE_ADDR`, отдаёт `web/` из `embed`, `/healthz`, заголовки безопасности.
- `web/index.html` — страница со знаком и словом `bare`, `app.css` с переменными из `identity/brief.md`, `manifest.json`, пустой `sw.js` с версией.
- `scripts/deploy.sh`; на сервере — пользователь, каталоги, `env`, юнит, nginx, сертификат по `deploy.md`.
Готово, когда `https://bare.xmatic.team/` открывается с правильным CSP, `/healthz` отвечает `ok`, `journalctl -u bare` чист.
## Этап 1 — аккаунты
- Миграция 001, `store` с `user_version`, фоновая чистка.
- `auth`: argon2id с параметрами ADR-021, сессии, cookie, проверка `Origin`.
- Эндпоинты: `config`, `kdf`, `register`, `login`, `logout`, `me`, `password`, `DELETE /api/me`, `users/{nick}`.
- Клиент: `crypto.js` (мастер, authKey, kek, блоб, ключевая пара, отпечаток), экран входа и регистрации, сохранение `CryptoKey` в IndexedDB, автоповышение итераций, настройки с «сменить пароль» и «выйти».
- Тесты Go: миграции на пустой базе, регистрация и вход, неверный `authKey`, смена пароля с `logoutOthers`.
Готово, когда регистрация и вход работают на телефоне и десктопе, вход на втором устройстве расшифровывает тот же ключ (отпечатки совпадают), пароль в сетевых запросах не встречается.
## Этап 2 — чат 1:1
- `devices`, `hub`, `queue`, `POST /api/messages`, `ack`, `events` с воспроизведением очереди и пингом.
- Клиент: `ulid.js`, `db.js`, `api.js` с SSE и ACK после записи, шифрование сообщений, экран чата (десктоп и мобильный по эталону), список чатов, «новый чат», разделители дат и «новые», pending/failed, повтор после реконнекта.
- Контакты: `GET/POST/DELETE /api/contacts`, автосоздание при первом сообщении.
- Тесты Go: фан-аут по устройствам без эха отправителю, ACK удаляет, повтор очереди при реконнекте, `clock_skew`, лимит 30/мин.
Готово, когда два аккаунта переписываются в реальном времени, второе устройство получателя получает копию, офлайн-устройство получает очередь при открытии, в базе — только шифротекст.
## Этап 3 — ключи и комнаты
- TOFU: хранилище `peers`, карточка контакта, предупреждение о смене ключа, «доверять новому ключу», повторная расшифровка `raw`.
- Комнаты: `rooms` и `room_keys`, все эндпоинты из `protocol.md`, события `room`/`room_left`, передача владения, rekey при выходе.
- Клиент: создание комнаты, участники, заворачивание и разворачивание ключей, хранение `roomKeys`, отправка с текущим `keyId`, расшифровка любым известным.
- Тесты Go: `keys_mismatch`, `key_exists`, выход владельца, удаление пустой комнаты, обрезка ключей до двух.
Готово, когда трое переписываются в комнате, добавленный четвёртый читает только новое, вышедший не получает новых сообщений после rekey, подмена `public_key` в базе вручную вызывает предупреждение у собеседника.
## Этап 4 — PWA и пуши
- `sw.js`: кэш оболочки, `push`, `notificationclick`; `manifest.json` с иконками; `apple-touch-icon`.
- `PUT/DELETE /api/devices/{id}/push`, отправка по правилам ADR-023, обработка 404/410.
- Клиент: запрос разрешения после первого сообщения, настройки уведомлений, баннер установки на iOS, `beforeinstallprompt`.
Готово, когда закрытое PWA на iPhone и Android получает пуш и открывается на нужном чате; повторные сообщения до открытия пуш не порождают.
## Этап 5 — история
- Экспорт и импорт `.bare` по `crypto.md` и `storage.md`; идемпотентность; «архив создан другим аккаунтом».
- Настройки: устройства (список, удаление), занятое место, удаление аккаунта.
- Пагинация ленты по 50 с подгрузкой вверх.
Готово, когда экспорт с одного устройства и импорт на другом дают одинаковую ленту без дублей, повторный импорт ничего не меняет, чужой архив отклоняется до расшифровки.
## Этап 6 — закалка
- Rate limiting по всем правилам ADR-021, `413`, `429` с `Retry-After`.
- Проверка CSP в консоли браузера: ноль нарушений.
- Прогон модели угроз по коду: пароль не уходит, `from` ставит сервер, `Origin` проверяется, cookie с нужными флагами.
- Синхронизация документов с кодом: расхождение — правка документа через ADR или правка кода.
## Определение готовности v1
Все шесть этапов; тесты Go зелёные; ручной прогон сценариев из каждого «готово, когда» на iOS Safari (PWA), Android Chrome, десктопных Chrome, Firefox, Safari; `README.md` обновлён со статуса «проектирование».
## Правила для исполнителя
- Сомнение в спецификации — сначала ADR, потом код. Не дописывать спецификацию молча.
- Новая зависимость, новый эндпоинт, новое поле в конверте — только через ADR.
- Каждый этап — отдельный коммит или серия коммитов с деплоем; не копить.
- Не добавлять фич сверх `ui.md`: ни тем, ни аватаров, ни «печатает», ни статусов прочтения.