Compare commits
2 Commits
a30c04242f
...
2de250a41e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2de250a41e | ||
|
|
1758edd5c8 |
@@ -4,9 +4,9 @@ This is the cross-codebase entry point. It describes how the four Relicario code
|
||||
|
||||
> If you are about to make a change in a single codebase, read its `ARCHITECTURE.md` first:
|
||||
>
|
||||
> - [crates/relicario-core/ARCHITECTURE.md](../../crates/relicario-core/ARCHITECTURE.md)
|
||||
> - [crates/relicario-cli/ARCHITECTURE.md](../../crates/relicario-cli/ARCHITECTURE.md)
|
||||
> - [extension/ARCHITECTURE.md](../../extension/ARCHITECTURE.md)
|
||||
> - [crates/relicario-core/ARCHITECTURE.md](crates/relicario-core/ARCHITECTURE.md)
|
||||
> - [crates/relicario-cli/ARCHITECTURE.md](crates/relicario-cli/ARCHITECTURE.md)
|
||||
> - [extension/ARCHITECTURE.md](extension/ARCHITECTURE.md)
|
||||
>
|
||||
> If you want historical *why*, see `docs/superpowers/specs/` — those are time-stamped decision artifacts. This overview describes what *is*.
|
||||
|
||||
@@ -196,10 +196,10 @@ Core tests use **fast Argon2id params** (m=256, t=1, p=1) so they don't take for
|
||||
|
||||
| If you're working on... | Start with |
|
||||
|---|---|
|
||||
| Crypto, item types, manifest format | [`crates/relicario-core/ARCHITECTURE.md`](../../crates/relicario-core/ARCHITECTURE.md) |
|
||||
| A new CLI command or a CLI bug | [`crates/relicario-cli/ARCHITECTURE.md`](../../crates/relicario-cli/ARCHITECTURE.md) |
|
||||
| A new popup view, vault tab feature, or autofill change | [`extension/ARCHITECTURE.md`](../../extension/ARCHITECTURE.md) |
|
||||
| A new SW message type | `extension/src/shared/messages.ts` (capability sets), then [`extension/ARCHITECTURE.md § Invariants`](../../extension/ARCHITECTURE.md) |
|
||||
| Crypto, item types, manifest format | [`crates/relicario-core/ARCHITECTURE.md`](crates/relicario-core/ARCHITECTURE.md) |
|
||||
| A new CLI command or a CLI bug | [`crates/relicario-cli/ARCHITECTURE.md`](crates/relicario-cli/ARCHITECTURE.md) |
|
||||
| A new popup view, vault tab feature, or autofill change | [`extension/ARCHITECTURE.md`](extension/ARCHITECTURE.md) |
|
||||
| A new SW message type | `extension/src/shared/messages.ts` (capability sets), then [`extension/ARCHITECTURE.md § Invariants`](extension/ARCHITECTURE.md) |
|
||||
| A new GitHost (e.g. GitLab support) | `extension/src/service-worker/git-host.ts` (interface) and existing implementations |
|
||||
| The pre-receive hook / device-auth enforcement | `crates/relicario-server/src/main.rs`, then `docs/superpowers/specs/2026-05-02-device-authentication-design.md` for rationale |
|
||||
| Adding a new item type | core's `item_types/` mod, then CLI's `build_*_item`/`edit_*` helpers, then extension's `popup/components/types/<type>.ts` |
|
||||
@@ -135,7 +135,7 @@ two confirmed bugs).
|
||||
the `.form-grid` cards above. Removes the visual rhythm break at the
|
||||
2-col → full-width transition. The popup surface is unchanged.
|
||||
- **Documentation refreshed for v0.5.0 (doc audit, 14 findings).**
|
||||
`docs/architecture/overview.md` now describes four codebases (the
|
||||
`ARCHITECTURE.md` now describes four codebases (the
|
||||
`relicario-server` pre-receive hook crate is no longer invisible);
|
||||
`CLAUDE.md` project tree and roadmap reflect current state;
|
||||
`docs/SECURITY.md` names the server crate and its `verify-commit` /
|
||||
|
||||
30
CLAUDE.md
30
CLAUDE.md
@@ -86,10 +86,32 @@ passphrase (UTF-8 bytes) || image_secret (32 bytes from reference JPEG)
|
||||
|
||||
Source code: `ssh://git@git.adlee.work:2222/alee/relicario.git`
|
||||
|
||||
## Design spec
|
||||
## Planning & design specs
|
||||
|
||||
Full threat model, entropy analysis, and architecture: `docs/superpowers/specs/2026-04-11-relicario-design.md`
|
||||
**Before starting any planning or implementation task**, search `docs/superpowers/specs/` for a spec covering the feature area, and `docs/superpowers/plans/` for any existing implementation plan. The specs are the authoritative design record; plans track per-milestone implementation details.
|
||||
|
||||
## Roadmap
|
||||
Core references (read before touching crypto, data model, or architecture):
|
||||
- `docs/superpowers/specs/2026-04-11-relicario-design.md` — threat model, entropy analysis, crypto pipeline, crate layout
|
||||
- `docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md` — typed-item data model and envelope
|
||||
- `docs/superpowers/specs/2026-04-30-relicario-fullscreen-ux-redesign-design.md` — fullscreen UX phase plan
|
||||
|
||||
Next: v0.5.0 polish + harden (in progress). After that, Phases 3/4 of the fullscreen UX redesign (vault-tab shell + command palette), Plan 1C-γ (attachments + Document + trash/history/device UI), and the LastPass importer. Mobile (Rust core compiles to ARM) and recovery QR remain on the roadmap.
|
||||
After completing any dev iteration, update `STATUS.md` to reflect what shipped and what's now in flight. Update the component `ARCHITECTURE.md` for any area you changed (see table below).
|
||||
|
||||
## Roadmap & status
|
||||
|
||||
Current in-flight work: `STATUS.md`. Full roadmap with release targets: `ROADMAP.md`. Wire format reference: `FORMATS.md`.
|
||||
|
||||
## Living docs — update discipline
|
||||
|
||||
| File | What it documents | Update when... |
|
||||
|---|---|---|
|
||||
| `ARCHITECTURE.md` | Cross-codebase structure: four codebases, contracts, secrets map, build matrix, test strategy | Adding a codebase, changing inter-codebase contracts, new build targets |
|
||||
| `docs/ARCHITECTURE.md` | Crypto pipeline diagrams, vault creation/unlock flows, DCT embedding, encrypted file format | Changing crypto primitives, format version byte, or file format |
|
||||
| `crates/relicario-core/ARCHITECTURE.md` | Module map, invariants, key flows, test architecture for `relicario-core` | Adding/changing modules, item types, or crypto invariants in core |
|
||||
| `crates/relicario-cli/ARCHITECTURE.md` | Module map, invariants, key flows (init, unlock, all commands) for `relicario-cli` | Adding/changing CLI commands, helpers, or session behavior |
|
||||
| `extension/ARCHITECTURE.md` | Bundle structure, SW↔popup contract, component architecture | Adding bundles, changing the SW message protocol, or major UI flows |
|
||||
| `docs/SECURITY.md` | Threat model, device auth, env-var trust surface | Adding env vars, changing auth model, new security-relevant config |
|
||||
| `FORMATS.md` | Wire formats: `.enc` blobs, `params.json`, `devices.json`, manifest schema | Changing any serialized format, version number, or on-disk layout |
|
||||
| `STATUS.md` | In-flight work, recent landings, what's next | End of every dev iteration |
|
||||
| `ROADMAP.md` | Full roadmap with release targets | When milestones shift or new work is scoped |
|
||||
| `CHANGELOG.md` | User-facing release history | When tagging a release |
|
||||
|
||||
102
FORMATS.md
Normal file
102
FORMATS.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Relicario Wire Formats
|
||||
|
||||
> Quick-reference for the load-bearing binary and JSON formats. Check this file before touching serialization, versioning, or storage layout code. Full diagrams and invariants live in the per-crate `ARCHITECTURE.md` files.
|
||||
|
||||
## Encrypted blob (`.enc` files)
|
||||
|
||||
Every encrypted file — `manifest.enc`, `settings.enc`, `items/<id>.enc`, `attachments/<item-id>/<aid>.enc` — uses the layout produced by `relicario_core::crypto::encrypt` (`crypto.rs`):
|
||||
|
||||
```
|
||||
┌─────────┬────────────────────────┬──────────────────┬──────────────────┐
|
||||
│ version │ nonce │ ciphertext │ auth tag │
|
||||
│ 1 byte │ 24 bytes │ N bytes │ 16 bytes │
|
||||
│ 0x02 │ random per write │ XChaCha20 stream │ Poly1305 MAC │
|
||||
└─────────┴────────────────────────┴──────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
- `VERSION_BYTE = 0x02` (`crypto.rs:59`). Any blob starting with `0x01` is rejected with `UnsupportedFormatVersion { found: 0x01, expected: 0x02 }`.
|
||||
- Minimum valid blob length: 41 bytes (1 + 24 + 0 + 16).
|
||||
- Nonces are always fresh from `OsRng` — no caller-supplied nonces.
|
||||
- Full diagram: `docs/ARCHITECTURE.md` § "Encrypted File Format".
|
||||
|
||||
## `.relicario/params.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": 2,
|
||||
"aead": "xchacha20-poly1305",
|
||||
"salt_path": ".relicario/salt",
|
||||
"kdf": {
|
||||
"argon2_m": 65536,
|
||||
"argon2_t": 3,
|
||||
"argon2_p": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Parsed via `ParamsFile { kdf: KdfParams }` in `session.rs`. The `kdf` nesting is intentional — `format_version`, `aead`, and `salt_path` co-exist for forward-compat probing. Do not flatten. Production defaults: `m=65536` (64 MiB), `t=3`, `p=4`. Tests use `m=256, t=1, p=1`.
|
||||
|
||||
## `.relicario/salt`
|
||||
|
||||
32 raw bytes. Not secret. Generated once at vault init via `OsRng`. Feeds Argon2id as the KDF salt.
|
||||
|
||||
## Manifest (`manifest.enc`)
|
||||
|
||||
Decrypts to JSON matching the `Manifest` struct (`manifest.rs`).
|
||||
|
||||
- **Schema version:** `MANIFEST_SCHEMA_VERSION = 2` (`manifest.rs:12`). v1 manifests (pre-typed-items) fail to parse and are not supported.
|
||||
- **`ManifestEntry` fields:** `id`, `title`, `tags`, `favorite`, `group`, `icon_hint`, `modified`, `trashed_at`, `attachment_summaries`.
|
||||
- The manifest is rebuilt from scratch on every `upsert` — it can never drift from the source-of-truth item files.
|
||||
- Supports case-insensitive title/tag search without decrypting any item.
|
||||
|
||||
## `.relicario/devices.json`
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "laptop", "public_key": "<hex-encoded ed25519 public key>" }
|
||||
]
|
||||
```
|
||||
|
||||
An empty array (`[]`) puts the pre-receive hook in bootstrap mode (all pushes accepted). Both `devices.json` and `revoked.json` must be empty for bootstrap mode to activate — a non-empty `revoked.json` alone forces strict verification.
|
||||
|
||||
## `.relicario/revoked.json`
|
||||
|
||||
```json
|
||||
[
|
||||
{ "name": "old-laptop", "public_key": "<hex>", "revoked_at": 1746000000 }
|
||||
]
|
||||
```
|
||||
|
||||
Commits by `public_key` at or after `revoked_at` (Unix seconds) are rejected by the pre-receive hook. Commits before `revoked_at` remain valid (they were authorized at the time).
|
||||
|
||||
## Item IDs and Field IDs
|
||||
|
||||
| Kind | Length | Entropy | Source |
|
||||
|---|---|---|---|
|
||||
| `ItemId` | 16 hex chars | 64 bits | `OsRng` |
|
||||
| `FieldId` | 16 hex chars | 64 bits | `OsRng` |
|
||||
| `AttachmentId` | 16 hex chars | content-addressed | first 8 bytes of `SHA-256(plaintext)` |
|
||||
|
||||
`AttachmentId` is content-addressed — identical plaintexts deduplicate in git automatically.
|
||||
|
||||
## `.relbak` backup format
|
||||
|
||||
A zstd-compressed tar archive containing a bare git clone of the vault. Designed for `relicario backup export/restore`.
|
||||
|
||||
Full spec: `docs/superpowers/specs/2026-04-27-relicario-import-export-design.md`.
|
||||
|
||||
## `ItemCore` JSON (internal)
|
||||
|
||||
`ItemCore` uses `#[serde(tag = "type")]` — the outer JSON object gets a `"type"` discriminator key. No `*Core` struct may have a field named `"type"` (use `"kind"` instead — see `CardKind`, `TotpKind`).
|
||||
|
||||
Full item type inventory: `crates/relicario-core/ARCHITECTURE.md` § "Module map".
|
||||
|
||||
## KDF input construction
|
||||
|
||||
The password fed to Argon2id is length-prefixed to prevent extension attacks:
|
||||
|
||||
```
|
||||
u64_be(len(passphrase)) || passphrase_bytes || u64_be(32) || image_secret
|
||||
```
|
||||
|
||||
NFC-normalized before hashing. Covered in `crypto.rs:229-236` and tested in `tests/format_v2.rs:44-54`.
|
||||
54
ROADMAP.md
Normal file
54
ROADMAP.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Relicario Roadmap
|
||||
|
||||
> Living document — update alongside `STATUS.md` when milestones shift.
|
||||
> "Up next" items have specs; "Medium-term" items may have specs; "Long-term" items are direction, not committed scope.
|
||||
|
||||
## Shipped
|
||||
|
||||
| Version | Highlights |
|
||||
|---|---|
|
||||
| v0.5.0 (2026-05-02) | Security audit fixes, device auth, backup/restore, LastPass import, fullscreen UX phases 1+2A |
|
||||
|
||||
See `CHANGELOG.md` for full details.
|
||||
|
||||
## Up next (v0.5.x)
|
||||
|
||||
These are specced and either in progress or immediately queued:
|
||||
|
||||
- **Vault lock screen + container polish** — logo on lock screen, max-width viewport constraint *(in progress)*
|
||||
- **Phase 2B: form layout** — spacing, section headers, attachment previews in detail pane
|
||||
Spec: `docs/superpowers/specs/2026-05-02-phase-2b-form-layout-design.md`
|
||||
- **1C-γ: attachments + Document type** — attachment UI in popup + vault tab; Document item add/view/edit/extract
|
||||
Specs: `docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md`,
|
||||
`docs/superpowers/specs/2026-04-26-relicario-extension-1c-gamma2-design.md`
|
||||
- **v0.5.x UX polish** — recovery QR display in extension, password coloring refinements
|
||||
Spec: `docs/superpowers/specs/2026-05-03-v0.5.x-ux-polish-and-recovery-qr-design.md`
|
||||
|
||||
## Medium-term
|
||||
|
||||
- **Phase 3: vault-tab shell** — fullscreen sidebar with nav sections, pane routing
|
||||
Spec: `docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md`
|
||||
- **Phase 4: command palette** — ⌘K global search + action dispatch across the vault tab
|
||||
- **Trash & history UI** — trash view, item history viewer, field-history viewer
|
||||
- **Device manager UI** — device registration + revocation in vault tab
|
||||
- **CLI restructure** — subcommand reorganisation, interactive TUI mode
|
||||
Spec: `docs/superpowers/specs/2026-05-04-cli-restructure-design.md`
|
||||
- **Extension restructure** — bundle / message-routing cleanup
|
||||
Spec: `docs/superpowers/specs/2026-05-04-extension-restructure-design.md`
|
||||
- **Security polish** — `docs/superpowers/specs/2026-05-04-security-polish-design.md`
|
||||
|
||||
## Long-term / backlog
|
||||
|
||||
- **Relay server** — encrypted WebSocket relay for multi-device sync without a shared git server
|
||||
Spec: `docs/superpowers/specs/2026-05-02-relay-server-design.md`
|
||||
- **Recovery QR** — QR code encoding of the reference-image secret for printed cold backup
|
||||
Spec: `docs/superpowers/specs/2026-05-01-recovery-qr-design.md`
|
||||
- **Mobile** — Rust core compiles to ARM; JNI wrapper for Android, Swift wrapper for iOS
|
||||
- **Credential capture** — extension content-script form detection + autofill
|
||||
Spec: `docs/superpowers/specs/2026-04-12-relicario-credential-capture-design.md`
|
||||
|
||||
## Non-goals (explicitly deferred or cancelled)
|
||||
|
||||
- **Reference-image rotation** — changing the image factor without re-embedding. Back-burner, not cancelled.
|
||||
- **Per-entry subkeys** — no real-world benefit at family-vault scale; see design rationale in `docs/ARCHITECTURE.md`.
|
||||
- **libgit2 / gitoxide** — shell-out to `git` is intentional; see `crates/relicario-cli/ARCHITECTURE.md`.
|
||||
56
STATUS.md
Normal file
56
STATUS.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Relicario — Project Status
|
||||
|
||||
> Update this file at the end of every dev iteration. It is the single source of truth for what is done, in progress, and next.
|
||||
|
||||
## Version
|
||||
|
||||
**Current tag:** v0.5.0 (2026-05-02)
|
||||
**Active track:** v0.5.x UX polish + Plan B refactor continuation
|
||||
|
||||
## What shipped in v0.5.0 (2026-05-02)
|
||||
|
||||
Three release trains merged into one tag:
|
||||
|
||||
**Security hardening (Plan A):**
|
||||
- Pre-receive hook actually verifies signatures now — device-auth was a no-op before (S1)
|
||||
- Backup-restore tar unpacking hardened against path traversal and zip-bomb (S2)
|
||||
- `RELICARIO_*` env-var surface audited; `RELICARIO_NO_GROUPS_CACHE` gated to debug builds (S3)
|
||||
|
||||
**Bug fixes:**
|
||||
- Strength meter no longer goes stale after the regenerate button (B1)
|
||||
- Snake_case error codes no longer leak into the UI (B2)
|
||||
|
||||
**Features (originally v0.3.0 + v0.4.0):**
|
||||
- `relicario backup export/restore` with `.relbak` format
|
||||
- `relicario import lastpass` (LastPass CSV importer)
|
||||
- Device authentication: ed25519 commit signing + Gitea deploy-key management
|
||||
- Fullscreen UX Phase 1: visual foundation (sidebar + pane shell, dark theme)
|
||||
- Fullscreen UX Phase 2A: smart inputs (password coloring, inline generator popover, custom-fields editor)
|
||||
|
||||
## Recent work (post-v0.5.0, landed on main)
|
||||
|
||||
**Plan B multi-stream refactor (2026-05-09 to present):**
|
||||
- `prompt_or_flag<T>` + builder compression — compressed `build_*_item` helpers (Stream A)
|
||||
- `Vault::after_manifest_change` wrapper, single canonical `ParamsFile` in session (Stream B)
|
||||
- Core/WASM seam: `base32_decode_lenient`, `parse_month_year`, `guess_mime` added to WASM exports; CLI parsers migrated to `relicario-core::parse` (Stream C)
|
||||
- CLI: `gen` alias for `generate`, `-l`/`-w` short flags, batched purge
|
||||
- `base32` module extracted from core, two duplicate RFC-4648 impls deduplicated
|
||||
- License switched to GPL-3.0-or-later
|
||||
|
||||
## In progress (uncommitted on main)
|
||||
|
||||
- Vault lock screen logo (`extension/src/vault/vault.ts`)
|
||||
- Vault container max-width constraint + list-pane width fix (`extension/src/vault/vault.css`)
|
||||
- README name fix (Aaron D. Lee)
|
||||
|
||||
## Up next
|
||||
|
||||
1. **Phase 2B: form layout polish** — spacing, density, section headers, attachment previews
|
||||
Spec: `docs/superpowers/specs/2026-05-02-phase-2b-form-layout-design.md`
|
||||
2. **1C-γ: attachments + Document type** — attachment UI in popup + vault tab; Document item add/view/edit
|
||||
Specs: `docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma{1,2}-design.md`
|
||||
3. **Phase 3: vault-tab shell** — sidebar nav + command palette stub
|
||||
Spec: `docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md`
|
||||
4. **Trash & history UI** — trash view, item/field-history viewer in vault tab
|
||||
|
||||
See `ROADMAP.md` for the longer arc.
|
||||
Reference in New Issue
Block a user