Files
chanora/crates/chanora_storage/README.md
Edison Jwa 01a4a9ed28 docs: add README files to 9 crates and update verification plan (TODO-030,036)
Add purpose, architecture, and public API summary to each crate
README following chanora_resolver pattern. Update verification master
plan with new evidence sources and entry/exit criteria.
2026-06-11 11:09:12 +09:00

3.3 KiB

chanora_storage

Two strictly separated storage concerns per SAD-067:

  1. BookmarkRepository — non-secret bookmark state via SQLite with optional encrypted password fields (rusqlite bundled, DEC-013.1).
  2. IdentityFileStore — Beta fallback storage for identity material while platform secure-storage backends mature.

Architecture

IdentityFileStore

  • Persists a single TS3 identity to <dir>/identity.tskey encrypted with ChaCha20-Poly1305.
  • The Data Encryption Key (DEK) is 32 random bytes stored in the platform keyring (Linux Secret Service, macOS Keychain, Windows Credential Manager, iOS Keychain) when available, with a best-effort file fallback at identity.dek (mode 0600 on Unix).
  • Legacy plaintext files from pre-Beta are still readable; the next save() upgrades them to encrypted form.
  • Audio metadata (transmit_mode, release_tail_ms, PTT binding) is persisted alongside as audio_meta.json (plaintext, non-secret).

BookmarkRepository

  • SQLite-backed store at <dir>/chanora.db.
  • Schema v1: basic bookmark columns. Schema v2: adds password_blob for encrypted passwords.
  • When constructed via with_crypto(), the password column is replaced by a ChaCha20-Poly1305 envelope under the same per-install DEK.
  • Legacy plaintext passwords are transparently read and upgraded on the next update().

Crypto abstraction

  • Crypto trait: encrypt(plaintext) / decrypt(blob) — callers see only the encrypt/decrypt pair.
  • DekCrypto — concrete implementation sharing the same per-install DEK with IdentityFileStore.

Public API Summary

Types

Type Role
IdentityFileStore Encrypted identity file store
BookmarkRepository SQLite bookmark store with optional password encryption
Bookmark Bookmark DTO: id, display_name, host, nickname, password
PttBindingMeta Persisted PTT binding metadata
StorageError NotFound, Migration, Sqlite, SecureStore, Io, Crypto
Crypto trait Encrypt/decrypt abstraction

IdentityFileStore methods

  • new(dir) — create or open store, ensure DEK exists
  • load()Option<String> — read identity (handles legacy plaintext)
  • save(identity) — persist encrypted (ChaCha20-Poly1305, atomic write)
  • clear() — remove identity file
  • crypto() — obtain a Crypto handle sharing the DEK
  • set_transmit_mode(mode) / get_transmit_mode() — audio settings persistence
  • set_release_tail_ms(ms) / get_release_tail_ms() — release-tail persistence
  • set_ptt_binding(...) / get_ptt_binding() — PTT binding persistence

BookmarkRepository methods

  • new(dir) / with_crypto(dir, crypto) — open (plain or encrypted)
  • add(bookmark)i64 — insert, return id
  • update(bookmark) — replace by id
  • delete(id) — remove by id
  • list()Vec<Bookmark> — all bookmarks ordered by id
  • upsert_or_add(bookmark) — insert or update by host, preserves user's display name
  • encrypts_passwords() — whether password encryption is active

Platform notes

  • Unix: files written with mode 0600.
  • Keyring access can be disabled via CHANORA_DISABLE_KEYRING=1 for tests/headless environments.
  • Android: file in app-private storage (not encrypted at rest — documented Beta gap).
  • iOS/Windows/macOS: caller provides the storage directory; platform sandbox handles access control.