Схема базы данных
Файлы:
backend/src/identity/manager.rs,vault/manager.rs,spaces/manager.rs,clouds/manager.rs
10 таблиц SQLite в 3 файлах БД. Без миграционного фреймворка — таблицы создаются через CREATE TABLE IF NOT EXISTS, миграции через ALTER TABLE ADD COLUMN.
Typed ID Newtypes
ID всех основных сущностей обёрнуты в newtype-обёртки (файл: backend/src/types/mod.rs):
| Тип | Генерация | SQL-тип |
|---|---|---|
IdentityId | blake3(public_key) | TEXT |
DeviceId | blake3(device_public_key) | TEXT |
SpaceId | Uuid::new_v4() | TEXT |
CloudId | Uuid::new_v4() | TEXT |
Все newtypes реализуют ToSql/FromSql для прозрачной работы с rusqlite, Serialize/Deserialize через #[serde(transparent)], и кросс-типовые сравнения (PartialEq<String>, PartialEq<str>).
Idempotency (INSERT OR IGNORE)
Все основные INSERT-операции используют INSERT OR IGNORE для идемпотентности при повторном выполнении (replay-safe):
| Таблица | Менеджер |
|---|---|
identity | IdentityManager |
devices | DeviceManager |
spaces | SpaceManager |
clouds | CloudManager |
vault_config | VaultManager |
Это предотвращает ошибки при повторной обработке P2P-сообщений или перезапуске операций.
Организация
| База данных | Менеджеры | Таблицы | Назначение |
|---|---|---|---|
identity.db | IdentityManager, DeviceManager | identity, devices | Пользователь и устройства |
vault.db | VaultManager | vault_config, encrypted_secrets, vault_pin_state, vault_settings | Шифрованные секреты |
spaces.db | SpaceManager, CloudManager | spaces, space_files, received_spaces, space_device_sync, sync_tombstones, sync_conflicts, clouds | Пространства и синхронизация |
Общие настройки:
PRAGMA busy_timeout=5000— ожидание при блокировке до 5 секPRAGMA foreign_keys = ON— дляspaces.dbArc<Mutex<Connection>>— потокобезопасный доступidentity.dbразделяется между IdentityManager и DeviceManagerspaces.dbразделяется между SpaceManager и CloudManager
ER-диаграмма
identity.db
identity
Управляется: IdentityManager
CREATE TABLE IF NOT EXISTS identity (
id TEXT PRIMARY KEY,
display_name TEXT NOT NULL,
public_key BLOB NOT NULL,
created_at INTEGER NOT NULL
)| Колонка | Тип | Описание |
|---|---|---|
id | TEXT, PK | blake3 hash публичного ключа (IdentityId newtype) |
display_name | TEXT | Имя пользователя |
public_key | BLOB | Ed25519 public key (32 bytes) |
created_at | INTEGER | Unix timestamp |
Одна identity на БД (одна строка, обновляется при паринге).
devices
Управляется: DeviceManager
CREATE TABLE IF NOT EXISTS devices (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
device_type TEXT NOT NULL,
identity_id TEXT NOT NULL,
public_key BLOB NOT NULL,
private_key BLOB,
peer_id TEXT,
last_seen INTEGER NOT NULL,
is_current INTEGER DEFAULT 0,
os TEXT,
ip TEXT,
storage_used INTEGER,
storage_total INTEGER,
storage_unit TEXT,
added_via TEXT
)| Колонка | Тип | Описание |
|---|---|---|
id | TEXT, PK | blake3 hash публичного ключа устройства (DeviceId newtype) |
name | TEXT | Имя устройства |
device_type | TEXT | laptop, phone, tablet, desktop, nas, server |
identity_id | TEXT | ID владельца |
public_key | BLOB | Ed25519 public key (32 bytes) |
private_key | BLOB | Ed25519 private key (только для текущего устройства) |
peer_id | TEXT | libp2p PeerId (base58) |
last_seen | INTEGER | Последняя активность (Unix timestamp) |
is_current | INTEGER | 1 = текущее устройство |
os | TEXT | Операционная система |
ip | TEXT | IP-адрес |
storage_* | INTEGER/TEXT | Информация о хранилище |
added_via | TEXT | Способ добавления (QR, PIN) |
Миграции:
ALTER TABLE devices ADD COLUMN os TEXT;
ALTER TABLE devices ADD COLUMN ip TEXT;
ALTER TABLE devices ADD COLUMN storage_used INTEGER;
ALTER TABLE devices ADD COLUMN storage_total INTEGER;
ALTER TABLE devices ADD COLUMN storage_unit TEXT;
ALTER TABLE devices ADD COLUMN added_via TEXT;vault.db
vault_config
Управляется: VaultManager
CREATE TABLE IF NOT EXISTS vault_config (
id INTEGER PRIMARY KEY CHECK (id = 1),
salt BLOB NOT NULL,
nonce BLOB NOT NULL,
wrapped_master_key BLOB NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
)Singleton-таблица (CHECK (id = 1)). Хранит master key, обёрнутый PIN'ом.
| Колонка | Тип | Описание |
|---|---|---|
salt | BLOB | Argon2 salt для derive PIN key (32 bytes) |
nonce | BLOB | Nonce для ChaCha20Poly1305 (12 bytes) |
wrapped_master_key | BLOB | Master key, зашифрованный PIN key'ом |
encrypted_recovery_phrase | BLOB | BIP39 фраза, зашифрованная master key'ом |
recovery_phrase_nonce | BLOB | Nonce для шифрования recovery phrase |
Миграции:
ALTER TABLE vault_config ADD COLUMN encrypted_recovery_phrase BLOB;
ALTER TABLE vault_config ADD COLUMN recovery_phrase_nonce BLOB;encrypted_secrets
Управляется: VaultManager
CREATE TABLE IF NOT EXISTS encrypted_secrets (
secret_id TEXT PRIMARY KEY,
salt BLOB NOT NULL,
nonce BLOB NOT NULL,
encrypted_data BLOB NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
)Зашифрованные секреты. Каждый секрет имеет индивидуальные salt и nonce.
Типичные secret_id:
identity_signing_key:{identity_id}— Ed25519 private key для подписиdevice_private_key:{device_id}— приватный ключ устройстваs3_access_key:{cloud_id}— S3 access keys3_secret_key:{cloud_id}— S3 secret key
vault_pin_state
Управляется: VaultManager
CREATE TABLE IF NOT EXISTS vault_pin_state (
id INTEGER PRIMARY KEY CHECK (id = 1),
failed_attempts INTEGER NOT NULL DEFAULT 0,
last_failed_attempt INTEGER,
is_locked INTEGER NOT NULL DEFAULT 0,
lockout_until INTEGER,
total_attempts INTEGER NOT NULL DEFAULT 0
)Singleton-таблица. Отслеживает попытки ввода PIN и lockout. Подробнее: PIN Rate Limiting.
vault_settings
Управляется: VaultManager
CREATE TABLE IF NOT EXISTS vault_settings (
id INTEGER PRIMARY KEY CHECK (id = 1),
auto_lock_timeout INTEGER NOT NULL DEFAULT 300,
background_operation_mode TEXT NOT NULL DEFAULT 'continue'
)Singleton-таблица. Хранит персистентные настройки vault: таймаут auto-lock и режим фоновых операций.
| Колонка | Тип | Описание |
|---|---|---|
auto_lock_timeout | INTEGER | Таймаут автоблокировки в секундах (0 = отключено, default = 300) |
background_operation_mode | TEXT | continue (default) или pause |
Настройки загружаются при создании VaultManager и применяются к SessionState. Обновляются через set_auto_lock_timeout() и set_background_operation_mode().
spaces.db
spaces
Управляется: SpaceManager
CREATE TABLE IF NOT EXISTS spaces (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
identity_id TEXT NOT NULL,
space_type TEXT NOT NULL DEFAULT 'own',
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
)| Колонка | Тип | Описание |
|---|---|---|
space_type | TEXT | own (создано), published (broadcast), shared (зашифровано) |
sync_mode | TEXT | auto или manual |
encryption | INTEGER | 1 = шифрование включено |
cloud_id | TEXT | Привязка к облачному хранилищу |
Миграции:
ALTER TABLE spaces ADD COLUMN icon TEXT;
ALTER TABLE spaces ADD COLUMN color TEXT;
ALTER TABLE spaces ADD COLUMN sync_mode TEXT DEFAULT 'auto';
ALTER TABLE spaces ADD COLUMN encryption INTEGER NOT NULL DEFAULT 1;
ALTER TABLE spaces ADD COLUMN versioning INTEGER NOT NULL DEFAULT 0;
ALTER TABLE spaces ADD COLUMN notifications INTEGER NOT NULL DEFAULT 1;
ALTER TABLE spaces ADD COLUMN cloud_id TEXT;space_files
Управляется: SpaceManager
CREATE TABLE IF NOT EXISTS space_files (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL REFERENCES spaces(id) ON DELETE CASCADE,
file_name TEXT NOT NULL,
file_path TEXT NOT NULL,
relative_path TEXT NOT NULL,
file_size INTEGER NOT NULL,
file_hash TEXT NOT NULL,
added_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
)file_hash — blake3 hash содержимого файла, используется для детекции конфликтов и файлового трансфера.
received_spaces
Управляется: SpaceManager
CREATE TABLE IF NOT EXISTS received_spaces (
space_id TEXT PRIMARY KEY REFERENCES spaces(id) ON DELETE CASCADE,
from_identity_id TEXT NOT NULL,
from_identity_name TEXT NOT NULL,
share_type TEXT NOT NULL,
received_at INTEGER NOT NULL,
accepted INTEGER NOT NULL DEFAULT 0,
accepted_at INTEGER
)Метаданные полученных пространств: кто отправил, тип шаринга, статус принятия.
space_device_sync
Управляется: SpaceManager
CREATE TABLE IF NOT EXISTS space_device_sync (
space_id TEXT NOT NULL,
device_id TEXT NOT NULL,
last_synced_at INTEGER NOT NULL,
PRIMARY KEY (space_id, device_id)
)Composite PK. Отслеживает, когда каждое устройство последний раз синхронизировало каждое пространство.
sync_tombstones
Управляется: SpaceManager, GC в SharingManager
CREATE TABLE IF NOT EXISTS sync_tombstones (
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
deleted_at INTEGER NOT NULL,
deleted_by_device_id TEXT NOT NULL,
PRIMARY KEY (entity_type, entity_id)
)Soft delete для state sync. TTL 30 дней — после этого tombstone удаляется garbage collector'ом.
sync_conflicts
Управляется: SpaceManager
CREATE TABLE IF NOT EXISTS sync_conflicts (
id TEXT PRIMARY KEY,
space_id TEXT NOT NULL,
file_id TEXT NOT NULL,
local_file_hash TEXT NOT NULL,
remote_file_hash TEXT NOT NULL,
local_device_id TEXT NOT NULL,
remote_device_id TEXT NOT NULL,
created_at INTEGER NOT NULL,
resolved INTEGER NOT NULL DEFAULT 0,
resolution TEXT,
resolved_at INTEGER
)Конфликты синхронизации — разные версии одного файла на разных устройствах.
clouds
Управляется: CloudManager
CREATE TABLE IF NOT EXISTS clouds (
id TEXT PRIMARY KEY,
identity_id TEXT NOT NULL,
name TEXT NOT NULL,
provider TEXT NOT NULL,
endpoint TEXT NOT NULL,
region TEXT NOT NULL,
bucket_name TEXT,
access_key_encrypted BLOB,
secret_key_encrypted BLOB,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
)Конфигурации S3-совместимых облачных хранилищ. Credentials зашифрованы vault master key'ом.