Practices followed
- Client-side encryption only. No plaintext log data ever leaves your infrastructure. Encryption happens before data is written to the Sia network and registered via indexd.
- User-controlled keys. Key generation happens locally during
obsidianlog init. The encryption key and (if configured) the Sia app key are stored together as one bundled credential in your OS keychain via thekeyringcrate, with a direct macOS Keychain API call used only for the initial creation step (see ADR-0015), or an explicit local secrets file with0600permissions if the keychain is genuinely unreachable. There is no key escrow and no key transmission. - Authenticated encryption. AES-256-GCM provides both confidentiality and ciphertext integrity. Tampered ciphertext is rejected at decryption time. Each chunk is sealed under its own key, derived with HKDF-SHA256 from your encryption key and a random per-chunk salt, so a key/nonce pair is never reused, even after a failed write or a restore from backup (ADR-0016).
- Append-only storage model. Chunks are write-once. The storage model
prevents in-place modification, relying on append-only writes combined
with indexd-coordinated retrieval and SHA-256 hash chaining for
tamper-evidence (
obsidianlog verify). - No intermediary in the storage path. ObsidianLog connects to an indexd-backed Sia indexer for indexing and retrieval coordination, without any centralized intermediary. There is no ObsidianLog-operated proxy, gateway, or relay. ObsidianLog has zero access to user data. This holds whether you use the hosted default or bring your own indexer.
- Dependency audit. The Rust dependency tree is audited with
cargo auditin CI. Critical dependencies (zstd,aes-gcm,sha2) are maintained by the RustCrypto and zstd-rs communities with strong security track records.

