Этап 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
This commit is contained in:
2026-08-22 14:06:07 +03:00
co-authored by Claude Opus 5
parent 32717cb7dd
commit 597c55301c
39 changed files with 4220 additions and 96 deletions
+7 -2
View File
@@ -16,8 +16,11 @@ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o bar
sudo useradd --system --home /var/lib/bare --shell /usr/sbin/nologin bare
sudo mkdir -p /opt/bare /var/lib/bare /etc/bare
sudo chown bare:bare /var/lib/bare
sudo chmod 0700 /var/lib/bare /etc/bare
```
Права закрыты намеренно (ADR-032): в базе лежат `argon2id(authKey)` и ключевые блобы, машина общая.
`/etc/bare/env` (владелец root, режим 0600):
```
@@ -48,6 +51,8 @@ ExecStart=/opt/bare/bare serve
Restart=on-failure
RestartSec=2
StateDirectory=bare
StateDirectoryMode=0700
UMask=0077
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
@@ -128,8 +133,8 @@ ssh xmatic 'sudo install -m 0755 -o root -g root /tmp/bare /opt/bare/bare && sud
## Бэкап
`sqlite3 /var/lib/bare/bare.db "VACUUM INTO '/var/lib/bare/backup.db'"` или копия файла при остановленном сервисе. В базе только шифротексты и метаданные — бэкап не содержит переписки.
`sqlite3 /var/lib/bare/bare.db "VACUUM INTO '/var/lib/bare/backup.db'"` или копия файла при остановленном сервисе. В базе только шифротексты и метаданные — бэкап не содержит переписки. Копия наследует режим 0600 (ADR-032); при восстановлении в другое место права надо выставить руками.
## Логи
Сервер пишет в stdout: время, метод, путь, статус, длительность; ник — только для ошибок аутентификации по лимитам; IP не пишется. journald хранит по своим правилам.
Сервер пишет в stdout: время, метод, путь, статус, длительность; для маршрутов `/api/` вместо пути пишется шаблон (`/api/users/{nick}`), чтобы ник не попадал в журнал, а если отказ случился до маршрутизации (`Origin`, предел тела) и шаблона ещё нет — просто `/api/`; ник — только для ошибок аутентификации по лимитам; IP не пишется. Причины ответов `500 internal` (ADR-027) пишутся отдельной строкой, без данных запроса. journald хранит по своим правилам.