docs: refresh README, ARCHITECTURE, overview for current state

Apply trivial-fix findings from the 2026-05-02 doc audit:
- README: items/ vs entries/, settings.enc + attachments/ +
  revoked.json in vault layout, full crate tree (relicario-wasm
  + relicario-server + typed-items modules), 16-char hex IDs,
  roadmap reflects shipped trains
- ARCHITECTURE.md: git-server box reflects items/ + 16-char IDs;
  relicario-core inner box lists typed-items modules
- architecture/overview.md: ID width / 128-bit AttachmentId

8 deeper findings still proposed for v0.5.0 release prep.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-05-02 16:04:02 -04:00
parent 3caa7af194
commit 900ccf1cf4
3 changed files with 64 additions and 36 deletions

View File

@@ -33,7 +33,9 @@ To unlock the vault, you provide your passphrase and point the client at the ref
A git repository containing: A git repository containing:
- `manifest.enc` — opaque binary blob - `manifest.enc` — opaque binary blob
- `entries/*.enc` — more opaque binary blobs - `items/*.enc` — more opaque binary blobs
- `attachments/<item-id>/*.enc` — encrypted attachment blobs
- `settings.enc` — encrypted vault settings
- `.relicario/salt` — a random 32-byte value (not secret) - `.relicario/salt` — a random 32-byte value (not secret)
- `.relicario/params.json` — Argon2id parameters (not secret) - `.relicario/params.json` — Argon2id parameters (not secret)
- `.relicario/devices.json` — authorized device public keys - `.relicario/devices.json` — authorized device public keys
@@ -114,12 +116,23 @@ relicario/
│ ├── relicario-core/ # Platform-agnostic library (no filesystem, no network) │ ├── relicario-core/ # Platform-agnostic library (no filesystem, no network)
│ │ ├── crypto.rs # Argon2id KDF + XChaCha20-Poly1305 AEAD │ │ ├── crypto.rs # Argon2id KDF + XChaCha20-Poly1305 AEAD
│ │ ├── imgsecret.rs # DCT steganography: embed/extract 256-bit secrets in JPEGs │ │ ├── imgsecret.rs # DCT steganography: embed/extract 256-bit secrets in JPEGs
│ │ ├── entry.rs # Entry, Manifest data model (serde) │ │ ├── item.rs # Item, Field, Manifest data model (serde)
│ │ ── vault.rs # Encrypt/decrypt entries and manifests │ │ ── item_types/ # Per-type cores (Login, SecureNote, Card, Identity, Key, Document, Totp)
└── relicario-cli/ # CLI binary: filesystem, git, terminal I/O │ ├── attachment.rs # Encrypted attachment helpers (content-addressed)
│ │ ├── settings.rs # VaultSettings (retention, generator defaults, caps)
│ │ ├── backup.rs # `.relbak` encrypted-backup envelope
│ │ ├── device.rs # ed25519 device keys + revocation entries
│ │ └── vault.rs # Encrypt/decrypt items, manifest, settings
│ ├── relicario-cli/ # CLI binary: filesystem, git, terminal I/O
│ ├── relicario-wasm/ # Thin wasm-bindgen wrapper for the browser extension
│ └── relicario-server/ # Pre-receive hook: device-signature verification
├── extension/ # Chrome MV3 / Firefox WebExtension (TypeScript)
└── docs/ └── docs/
├── ARCHITECTURE.md # System overview + flow diagrams
├── SECURITY.md # Manifest integrity model + threat notes
├── architecture/ # Cross-codebase + per-codebase architecture docs
└── superpowers/ └── superpowers/
└── specs/ # Design specification with full threat model └── specs/ # Design specifications with full threat model
``` ```
`relicario-core` takes bytes and returns bytes. It has no knowledge of filesystems, git, or networks. This makes it portable to WASM (browser extension), Android (JNI), and iOS (Swift bridge). `relicario-core` takes bytes and returns bytes. It has no knowledge of filesystems, git, or networks. This makes it portable to WASM (browser extension), Android (JNI), and iOS (Swift bridge).
@@ -144,17 +157,22 @@ Every write generates a fresh random nonce. The version byte allows future forma
``` ```
my-vault.git/ my-vault.git/
├── manifest.enc # Encrypted entry index (names, URLs, timestamps) ├── manifest.enc # Encrypted item index (names, URLs, timestamps)
├── entries/ ├── settings.enc # Encrypted vault settings (retention, caps, generator defaults)
│ ├── a1b2c3d4.enc # One encrypted entry per file ├── items/
── e5f6a7b8.enc ── a1b2c3d4e5f6a7b8.enc # One encrypted item per file
│ └── …
├── attachments/
│ └── <item-id>/
│ └── <aid>.enc # Content-addressed encrypted attachment blob
└── .relicario/ └── .relicario/
├── salt # 32-byte random salt (not secret) ├── salt # 32-byte random salt (not secret)
├── params.json # KDF parameters ├── params.json # KDF parameters
── devices.json # Authorized device public keys ── devices.json # Authorized device public keys
└── revoked.json # Revoked device records (when device auth is enabled)
``` ```
Entry IDs are random hex strings. Git history is preserved — every add/edit/delete is a commit. "When was this password last rotated?" is answered by `git log`. Item IDs are random 16-char hex strings (64 bits of entropy). Git history is preserved — every add/edit/delete is a commit. "When was this password last rotated?" is answered by `git log` and by the per-item field history.
## Device management ## Device management
@@ -183,13 +201,17 @@ The binary is at `target/release/relicario`.
## Roadmap ## Roadmap
- [ ] WASM build + Chrome browser extension (inline crypto, no native messaging) - [x] WASM build + Chrome MV3 browser extension (inline crypto, no native messaging)
- [ ] Secure notes (free-form encrypted text entries) - [x] Firefox WebExtension build
- [ ] Secure document storage (encrypted file attachments up to 5-10 MB) - [x] Typed items: Login, SecureNote, Identity, Card, Key, Document, TOTP
- [x] Secure document storage (encrypted file attachments)
- [x] Backup & restore (`.relbak` encrypted envelope)
- [x] LastPass CSV import
- [x] Device authentication (ed25519 commit signing + pre-receive hook)
- [ ] Import from Bitwarden / 1Password
- [ ] `relicario unlock` daemon (ssh-agent-style, holds master key for a TTL) - [ ] `relicario unlock` daemon (ssh-agent-style, holds master key for a TTL)
- [ ] Android/iOS clients (Rust core compiles to ARM) - [ ] Android/iOS clients (Rust core compiles to ARM)
- [ ] Import from LastPass/Bitwarden/1Password - [ ] Safari extension
- [ ] Firefox/Safari extensions
## License ## License

View File

@@ -42,15 +42,19 @@
┌──────────────────────────────────────────────────────────────────┐ ┌──────────────────────────────────────────────────────────────────┐
│ GIT SERVER (untrusted) │ │ GIT SERVER (untrusted) │
│ │ │ │
│ relicario-vault.git/ │ relicario-vault.git/ │
│ ├── manifest.enc ← opaque ciphertext │ │ ├── manifest.enc ← opaque ciphertext
│ ├── entries/ │ ├── settings.enc ← opaque ciphertext
│ ├── a1b2c3d4.enc ← opaque ciphertext ├── items/
│ │ ── e5f6a7b8.enc ← opaque ciphertext │ │ ── a1b2c3d4e5f6a7b8.enc ← opaque ciphertext │
└── .relicario/ │ └── …
│ ├── attachments/ │
│ │ └── <item-id>/<aid>.enc ← opaque ciphertext │
│ └── .relicario/ │
│ ├── salt ← 32 bytes (not secret) │ │ ├── salt ← 32 bytes (not secret) │
│ ├── params.json ← KDF params (not secret) │ │ ├── params.json ← KDF params (not secret) │
── devices.json ← device public keys (not secret) │ ── devices.json ← device public keys (not secret) │
│ └── revoked.json ← revoked device records (not secret) │
│ │ │ │
│ The server sees NOTHING useful. No keys, no plaintext, │ │ The server sees NOTHING useful. No keys, no plaintext, │
│ no metadata about what's inside. │ │ no metadata about what's inside. │
@@ -217,21 +221,23 @@ Input JPEG (possibly re-encoded or cropped)
│ uses │ uses
┌────────────────────────────────────────────────────────────┐ ┌────────────────────────────────────────────────────────────┐
│ relicario-core │ relicario-core │
│ Platform-agnostic: bytes in, bytes out │ │ Platform-agnostic: bytes in, bytes out │
│ No filesystem, no network, no git │ │ No filesystem, no network, no git │
│ │ │ │
│ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐ │ │ ┌──────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐
│ │ crypto │ │ imgsecret│ │ entry │ │ vault │ │ │ │ crypto │ │ imgsecret│ │ item + │ │ vault │
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ types │ │ │
│ │ KDF │ │ DCT │ │ Entry │ │ encrypt_ │ │ │ │ KDF │ │ DCT │ │ Item │ │ encrypt_ │
│ │ encrypt │ │ embed │ │ Manifest│ │ entry() │ │ encrypt │ │ embed │ │ Manifest│ │ item()
│ │ decrypt │ │ extract │ │ search │ │ decrypt_ │ │ │ │ decrypt │ │ extract │ │ Settings│ │ decrypt_ │
│ │ │ │ QIM │ │ │ │ manifest() │ │ │ │ │ │ QIM │ │ Backup │ │ manifest() │
└──────────┘ └──────────┘ └─────────┘ └────────────┘ │ │ │ │ │ Device │ │ ... │
│ └──────────┘ └──────────┘ └─────────┘ └────────────┘ │
│ │ │ │
Future: relicario-wasm wraps this for browser extension Consumed by: relicario-cli, relicario-wasm (extension),
Future: JNI/Swift wrappers for Android/iOS relicario-server (pre-receive hook).
│ Future: JNI/Swift wrappers for Android/iOS. │
└────────────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────────────┘
``` ```

View File

@@ -177,8 +177,8 @@ Core tests use **fast Argon2id params** (m=256, t=1, p=1) so they don't take for
|---|---|---| |---|---|---|
| Master key only in `Zeroizing<[u8;32]>` | core types; CLI follows; extension WASM follows | Drop-on-scope-exit zeroization; never leaves stack | | Master key only in `Zeroizing<[u8;32]>` | core types; CLI follows; extension WASM follows | Drop-on-scope-exit zeroization; never leaves stack |
| AEAD ciphertext starts with version byte | `core/crypto.rs` | Format identification; reject v1 blobs cleanly | | AEAD ciphertext starts with version byte | `core/crypto.rs` | Format identification; reject v1 blobs cleanly |
| Item IDs are random 8-char hex | `core/ids.rs` | Stable, short, no information leak | | Item IDs are random 16-char hex (64 bits) | `core/ids.rs` | Stable, short, no information leak |
| Attachment IDs are content-addressed (SHA-256) | `core/ids.rs` | Dedup; integrity check | | Attachment IDs are content-addressed (first 32 hex chars / 128 bits of SHA-256) | `core/ids.rs` | Dedup; integrity check |
| KDF input is length-prefixed | `core/crypto.rs` | Prevents `passphrase || image_secret` collisions | | KDF input is length-prefixed | `core/crypto.rs` | Prevents `passphrase || image_secret` collisions |
| Git history is preserved as audit log; never squash | CLI commits; SW commits | Per-action history is a feature | | Git history is preserved as audit log; never squash | CLI commits; SW commits | Per-action history is a feature |
| Per-action git commits with structured messages | `cli` (via `commit_paths`); SW (via vault.ts helpers) | Greppable, useful as audit log | | Per-action git commits with structured messages | `cli` (via `commit_paths`); SW (via vault.ts helpers) | Greppable, useful as audit log |