diff --git a/CHANGELOG.md b/CHANGELOG.md index 64660c8..135a5df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,7 +96,7 @@ ### Fixed - **Setup wizard could silently overwrite an existing vault.** Pointing the - wizard at a remote that already contained a relicario vault would clobber + wizard at a remote that already contained a Relicario vault would clobber `manifest.enc`, `.relicario/salt`, and friends with no warning. The wizard now probes the remote after the connection test and refuses to create a new vault on top of an existing one. Affected users whose vault was wiped diff --git a/CLAUDE.md b/CLAUDE.md index 442af63..3a6a857 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -# CLAUDE.md — relicario +# CLAUDE.md — Relicario ## Working with the user @@ -8,7 +8,7 @@ ## What is this -relicario is a git-backed, self-hostable password manager with a Rust core. Two-factor vault decryption: passphrase + a reference JPEG carrying a 256-bit secret embedded via DCT steganography. The server only ever sees opaque ciphertext. +Relicario is a git-backed, self-hostable password manager with a Rust core. Two-factor vault decryption: passphrase + a reference JPEG carrying a 256-bit secret embedded via DCT steganography. The server only ever sees opaque ciphertext. ## Build and test diff --git a/README.md b/README.md index 4fd8a8a..da1b5c8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@

- relicario + Relicario

-# relicario +# Relicario A git-backed, self-hostable password manager where decryption requires two independent factors: a passphrase you memorize and a reference JPEG that carries a hidden secret. Compromise of either factor alone is insufficient. @@ -23,7 +23,7 @@ Your reference photo (something you have) your device (opaque ciphertext) ``` -At vault creation, relicario embeds a random 256-bit secret into a carrier JPEG using DCT steganography. This photo becomes your **reference image** — a second factor that lives on your devices (and optionally as a "dead drop" on social media, since it survives JPEG re-encoding and mild cropping). +At vault creation, Relicario embeds a random 256-bit secret into a carrier JPEG using DCT steganography. This photo becomes your **reference image** — a second factor that lives on your devices (and optionally as a "dead drop" on social media, since it survives JPEG re-encoding and mild cropping). To unlock the vault, you provide your passphrase and point the client at the reference image. The client extracts the hidden secret, concatenates it with your passphrase, and runs Argon2id to derive the master key. Everything else follows from there. @@ -58,7 +58,7 @@ No single point of failure. The two-factor design means the passphrase alone can | LastPass | ~40-60 bits (master password only) | 1 | | Bitwarden | ~40-60 bits (master password only) | 1 | | 1Password | password + 128-bit Secret Key | 2 | -| **relicario** | **password + 256-bit image secret** | **2** | +| **Relicario** | **password + 256-bit image secret** | **2** | ### What we don't protect against diff --git a/crates/relicario-cli/src/main.rs b/crates/relicario-cli/src/main.rs index 6153420..825ad06 100644 --- a/crates/relicario-cli/src/main.rs +++ b/crates/relicario-cli/src/main.rs @@ -1,4 +1,4 @@ -//! relicario CLI — the platform layer for the relicario password manager. +//! Relicario CLI — the platform layer for the Relicario password manager. //! //! See module docs for the unlock flow and vault layout. @@ -14,7 +14,7 @@ use clap::{Parser, Subcommand}; #[command( name = "relicario", version, - about = "Git-backed password manager with reference-image two-factor unlock" + about = "Relicario — git-backed password manager with reference-image two-factor unlock" )] struct Cli { #[command(subcommand)] @@ -462,7 +462,7 @@ fn cmd_init(image: PathBuf, output: PathBuf) -> Result<()> { ".relicario/salt", "manifest.enc", "settings.enc", ]).status()?; let status = crate::helpers::git_command(&root, &[ - "commit", "-m", "init: new relicario vault (format v2)", + "commit", "-m", "init: new Relicario vault (format v2)", ]).status()?; if !status.success() { anyhow::bail!("git commit failed"); } @@ -1477,7 +1477,7 @@ fn cmd_backup_restore(input: PathBuf, target: PathBuf) -> Result<()> { if target.join(".relicario").exists() { anyhow::bail!( - "target dir already contains a relicario vault; restore refuses to overwrite — use an empty directory: {}", + "target dir already contains a Relicario vault; restore refuses to overwrite — use an empty directory: {}", target.display() ); } diff --git a/crates/relicario-cli/tests/backup.rs b/crates/relicario-cli/tests/backup.rs index 2f5d028..2be8e74 100644 --- a/crates/relicario-cli/tests/backup.rs +++ b/crates/relicario-cli/tests/backup.rs @@ -66,7 +66,7 @@ fn restore_refuses_non_empty_target() { .unwrap(); assert!(!out.status.success()); let err = String::from_utf8(out.stderr).unwrap(); - assert!(err.contains("already contains a relicario vault"), "stderr: {err}"); + assert!(err.contains("already contains a Relicario vault"), "stderr: {err}"); } #[test] diff --git a/crates/relicario-core/src/error.rs b/crates/relicario-core/src/error.rs index 8fb19bf..bbe9aa9 100644 --- a/crates/relicario-core/src/error.rs +++ b/crates/relicario-core/src/error.rs @@ -1,4 +1,4 @@ -//! Unified error type for the relicario-core crate. +//! Unified error type for the Relicario core crate. //! //! Every fallible function in this crate returns [`Result`], which is an alias //! for `std::result::Result`. Using a single error enum keeps the @@ -7,7 +7,7 @@ use thiserror::Error; -/// All errors that can originate from relicario-core operations. +/// All errors that can originate from Relicario core operations. /// /// Variants are ordered roughly by the pipeline stage where they occur: /// KDF -> encryption -> decryption -> format parsing -> item lookup -> image @@ -40,15 +40,15 @@ pub enum RelicarioError { UnsupportedFormatVersion { found: u8, expected: u8 }, /// Backup file's first 4 bytes don't match the "RBAK" magic. - #[error("not a relicario backup file")] + #[error("not a Relicario backup file")] BackupBadMagic, /// Backup format version is newer than this binary supports. - #[error("backup created by a newer relicario; upgrade required")] + #[error("backup created by a newer Relicario; upgrade required")] BackupUnsupportedVersion { found: u8, expected: u8 }, /// Backup envelope schema version doesn't match. - #[error("backup envelope schema v{found}; this relicario reads v{expected}")] + #[error("backup envelope schema v{found}; this Relicario reads v{expected}")] BackupSchemaMismatch { found: u32, expected: u32 }, /// CSV header doesn't match the LastPass column layout. @@ -157,7 +157,7 @@ mod tests { #[test] fn backup_errors_carry_useful_messages() { let bad = RelicarioError::BackupBadMagic; - assert!(format!("{}", bad).contains("not a relicario backup file")); + assert!(format!("{}", bad).contains("not a Relicario backup file")); let ver = RelicarioError::BackupUnsupportedVersion { found: 0x02, expected: 0x01 }; let s = format!("{}", ver); diff --git a/crates/relicario-core/src/lib.rs b/crates/relicario-core/src/lib.rs index d5bb99f..d4caeae 100644 --- a/crates/relicario-core/src/lib.rs +++ b/crates/relicario-core/src/lib.rs @@ -1,6 +1,6 @@ //! # relicario-core //! -//! Platform-agnostic core library for the relicario password manager. +//! Platform-agnostic core library for the Relicario password manager. //! //! This crate is intentionally **bytes-in/bytes-out** -- it performs no filesystem //! access, no network I/O, and no git operations. All inputs arrive as byte slices diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index f033b4d..f415380 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# relicario — Architecture +# Relicario — Architecture ## System Overview diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 963f8ee..0662179 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -1,6 +1,6 @@ -# Architecture overview — relicario +# Architecture overview — Relicario -This is the cross-codebase entry point. It describes how the three relicario codebases fit together, the contracts that flow between them, and the conventions they share. It is **deliberately thin**; the deep content lives in per-codebase docs. +This is the cross-codebase entry point. It describes how the three Relicario codebases fit together, the contracts that flow between them, and the conventions they share. It is **deliberately thin**; the deep content lives in per-codebase docs. > If you are about to make a change in a single codebase, read its `ARCHITECTURE.md` first: > diff --git a/docs/superpowers/audits/2026-04-18-initial-security-audit.md b/docs/superpowers/audits/2026-04-18-initial-security-audit.md index 074f583..3ff2f29 100644 --- a/docs/superpowers/audits/2026-04-18-initial-security-audit.md +++ b/docs/superpowers/audits/2026-04-18-initial-security-audit.md @@ -1,4 +1,4 @@ -# relicario Security Audit Report +# Relicario Security Audit Report **Date:** 2026-04-18 **Scope:** Full static review of `crates/relicario-core/`, `crates/relicario-cli/`, `crates/relicario-wasm/`, `extension/src/`, both manifests, both webpack configs, and the design spec at `docs/superpowers/specs/2026-04-11-relicario-design.md`. diff --git a/docs/superpowers/plans/2026-04-11-relicario-core-cli.md b/docs/superpowers/plans/2026-04-11-relicario-core-cli.md index 7438912..85e6f09 100644 --- a/docs/superpowers/plans/2026-04-11-relicario-core-cli.md +++ b/docs/superpowers/plans/2026-04-11-relicario-core-cli.md @@ -1,4 +1,4 @@ -# relicario Core + CLI Implementation Plan +# Relicario Core + CLI Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-12-relicario-credential-capture.md b/docs/superpowers/plans/2026-04-12-relicario-credential-capture.md index ceeff94..15acf5e 100644 --- a/docs/superpowers/plans/2026-04-12-relicario-credential-capture.md +++ b/docs/superpowers/plans/2026-04-12-relicario-credential-capture.md @@ -1,4 +1,4 @@ -# relicario Credential Capture Implementation Plan +# Relicario Credential Capture Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-12-relicario-firefox-extension.md b/docs/superpowers/plans/2026-04-12-relicario-firefox-extension.md index 2ea1ca5..07a84f4 100644 --- a/docs/superpowers/plans/2026-04-12-relicario-firefox-extension.md +++ b/docs/superpowers/plans/2026-04-12-relicario-firefox-extension.md @@ -1,4 +1,4 @@ -# relicario Firefox Extension Port Implementation Plan +# Relicario Firefox Extension Port Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-12-relicario-init-wizard.md b/docs/superpowers/plans/2026-04-12-relicario-init-wizard.md index adae01f..12c618d 100644 --- a/docs/superpowers/plans/2026-04-12-relicario-init-wizard.md +++ b/docs/superpowers/plans/2026-04-12-relicario-init-wizard.md @@ -1,8 +1,8 @@ -# relicario Vault Initialization Wizard Implementation Plan +# Relicario Vault Initialization Wizard Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Build a browser-based wizard that creates a new relicario vault, pushes it to Gitea/GitHub via API, downloads the reference image, and optionally configures the Chrome extension. +**Goal:** Build a browser-based wizard that creates a new Relicario vault, pushes it to Gitea/GitHub via API, downloads the reference image, and optionally configures the Chrome extension. **Architecture:** Single HTML page (`extension/setup.html`) bundled by webpack as a new entry point. Reuses the existing git API layer and WASM module. New `embed_image_secret` function added to the WASM crate. The wizard runs entirely client-side — all crypto happens in the browser via WASM. diff --git a/docs/superpowers/plans/2026-04-12-relicario-wasm-extension.md b/docs/superpowers/plans/2026-04-12-relicario-wasm-extension.md index ad54cd0..452dbb4 100644 --- a/docs/superpowers/plans/2026-04-12-relicario-wasm-extension.md +++ b/docs/superpowers/plans/2026-04-12-relicario-wasm-extension.md @@ -1,4 +1,4 @@ -# relicario WASM + Chrome MV3 Extension Implementation Plan +# Relicario WASM + Chrome MV3 Extension Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-20-relicario-extension-1c-alpha.md b/docs/superpowers/plans/2026-04-20-relicario-extension-1c-alpha.md index 7a27e10..47063e4 100644 --- a/docs/superpowers/plans/2026-04-20-relicario-extension-1c-alpha.md +++ b/docs/superpowers/plans/2026-04-20-relicario-extension-1c-alpha.md @@ -1,4 +1,4 @@ -# relicario Extension 1C-α (Foundation) Implementation Plan +# Relicario Extension 1C-α (Foundation) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-22-relicario-extension-1c-beta1.md b/docs/superpowers/plans/2026-04-22-relicario-extension-1c-beta1.md index d577d61..72646e0 100644 --- a/docs/superpowers/plans/2026-04-22-relicario-extension-1c-beta1.md +++ b/docs/superpowers/plans/2026-04-22-relicario-extension-1c-beta1.md @@ -1,8 +1,8 @@ -# relicario Extension 1C-β₁ (Typed-Item Forms) Implementation Plan +# Relicario Extension 1C-β₁ (Typed-Item Forms) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Add the 5 remaining typed-item forms (SecureNote, Identity, Card, Key, Totp incl. Steam Guard) so the relicario extension can daily-drive every typed item the Rust core supports except Document. +**Goal:** Add the 5 remaining typed-item forms (SecureNote, Identity, Card, Key, Totp incl. Steam Guard) so the Relicario extension can daily-drive every typed item the Rust core supports except Document. **Architecture:** 5-slice bottom-up sequencing. Slice 1 patches the Rust core's `compute_totp_code` to emit Steam's 5-char alphabet output. Slice 2 extracts a shared `popup/components/fields.ts` helper module (row / concealed-row / signature-block primitives) and refactors Login onto it as the reference implementation. Slices 3-5 land the 5 new types in pairs: SecureNote+Identity (no signature block), Card+Key (signature block, no live state), Totp (signature block + countdown + Steam toggle). diff --git a/docs/superpowers/plans/2026-04-24-relicario-extension-1c-beta2.md b/docs/superpowers/plans/2026-04-24-relicario-extension-1c-beta2.md index 0869a81..6048d4d 100644 --- a/docs/superpowers/plans/2026-04-24-relicario-extension-1c-beta2.md +++ b/docs/superpowers/plans/2026-04-24-relicario-extension-1c-beta2.md @@ -1,8 +1,8 @@ -# relicario Extension 1C-β₂ (Custom Fields + Settings + Generator UI) Implementation Plan +# Relicario Extension 1C-β₂ (Custom Fields + Settings + Generator UI) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Add custom-fields editing, a full vault-settings view, and an inline generator popover to the relicario browser extension. Completes the β phase of Plan 1C. +**Goal:** Add custom-fields editing, a full vault-settings view, and an inline generator popover to the Relicario browser extension. Completes the β phase of Plan 1C. **Architecture:** 5-slice bottom-up. Slice 1 adds read-only `Item.sections` rendering in every type-detail view via a new `fields.ts` helper. Slice 2 adds the collapsible "▸ custom sections & fields" disclosure + add/remove UI in every type form. Slice 3 wires new popup-only messages (`get_vault_settings` / `update_vault_settings`, plus `generate_passphrase` for BIP39) — landing BEFORE the popover so Slice 4's "save as default" action is fully functional the moment it ships. Slice 4 builds the generator popover and wires it to every "gen" button. Slice 5 builds the Settings screen, wires the ⚙ picker, and connects the popover to Settings via the save-as-default action. diff --git a/docs/superpowers/plans/2026-04-27-relicario-backup-restore.md b/docs/superpowers/plans/2026-04-27-relicario-backup-restore.md index b0a6b48..eb6d961 100644 --- a/docs/superpowers/plans/2026-04-27-relicario-backup-restore.md +++ b/docs/superpowers/plans/2026-04-27-relicario-backup-restore.md @@ -1,4 +1,4 @@ -# relicario Backup & Restore — Implementation Plan (v0.3.0 — Plan 3A) +# Relicario Backup & Restore — Implementation Plan (v0.3.0 — Plan 3A) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/plans/2026-04-29-relicario-lastpass-import.md b/docs/superpowers/plans/2026-04-29-relicario-lastpass-import.md index 1119a0c..9677a81 100644 --- a/docs/superpowers/plans/2026-04-29-relicario-lastpass-import.md +++ b/docs/superpowers/plans/2026-04-29-relicario-lastpass-import.md @@ -1,4 +1,4 @@ -# relicario LastPass Importer — Implementation Plan (v0.3.0 — Plan 3B) +# Relicario LastPass Importer — Implementation Plan (v0.3.0 — Plan 3B) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/docs/superpowers/specs/2026-04-11-relicario-design.md b/docs/superpowers/specs/2026-04-11-relicario-design.md index b17a016..c94e09a 100644 --- a/docs/superpowers/specs/2026-04-11-relicario-design.md +++ b/docs/superpowers/specs/2026-04-11-relicario-design.md @@ -1,10 +1,10 @@ -# relicario — Design Specification +# Relicario — Design Specification A git-backed, self-hostable password manager with a Rust core, CLI, and Chrome browser extension. The reference image as a DCT-embedded secret carrier is the core differentiator. ## Overview -relicario is a password manager where vault decryption requires two independent factors: a passphrase the user memorizes and a reference JPEG that carries a 256-bit secret embedded via DCT steganography. The vault lives in a git repository (self-hosted on the user's own Gitea instance), and the server only ever sees opaque ciphertext. Compromise of either factor alone is insufficient to decrypt the vault. +Relicario is a password manager where vault decryption requires two independent factors: a passphrase the user memorizes and a reference JPEG that carries a 256-bit secret embedded via DCT steganography. The vault lives in a git repository (self-hosted on the user's own Gitea instance), and the server only ever sees opaque ciphertext. Compromise of either factor alone is insufficient to decrypt the vault. Primary goals: portfolio project for adlee.work, architectural elegance, legibility-as-security (the README should read as the security proof), learning Rust, and fun to tinker with. @@ -23,7 +23,7 @@ A collection of credentials (usernames, passwords, URLs, TOTP seeds, notes) belo | Stolen device | Filesystem: reference image, device key, cached vault | Decrypt vault | Attacker has image_secret but not passphrase. Argon2id makes brute-force expensive. | | Stolen device + weak passphrase | Same + feasible brute-force | Decrypt vault | Enforce minimum passphrase strength at vault creation. Universal worst case. | | Shoulder surfer | Observed passphrase | Decrypt vault (if they also get image) | Passphrase alone insufficient — still need image_secret. | -| Credential stuffing | Leaked email/password from other breaches | Access user's accounts | relicario generates unique passwords per site. Breach of site A doesn't compromise site B. | +| Credential stuffing | Leaked email/password from other breaches | Access user's accounts | Relicario generates unique passwords per site. Breach of site A doesn't compromise site B. | ### Out of scope @@ -79,7 +79,7 @@ With a 4-word diceware passphrase (~51 bits) and Argon2id at 64 MiB, brute-force Compared to competitors: - LastPass/Bitwarden: server breach exposes ~40-60 bits (master password only) - 1Password: server breach exposes password + 128-bit Secret Key -- relicario: server breach exposes password + 256-bit image_secret +- Relicario: server breach exposes password + 256-bit image_secret ### Authenticated encryption diff --git a/docs/superpowers/specs/2026-04-12-relicario-credential-capture-design.md b/docs/superpowers/specs/2026-04-12-relicario-credential-capture-design.md index 91aea54..366d6ee 100644 --- a/docs/superpowers/specs/2026-04-12-relicario-credential-capture-design.md +++ b/docs/superpowers/specs/2026-04-12-relicario-credential-capture-design.md @@ -1,4 +1,4 @@ -# relicario — Credential Capture Design +# Relicario — Credential Capture Design Experimental feature that detects login form submissions and prompts the user to save or update credentials in the vault. Configurable prompt style (notification bar or toast). Off by default. @@ -60,7 +60,7 @@ A fixed-position bar at the top of the page, injected into the DOM: ``` ┌──────────────────────────────────────────────────────────────────┐ -│ relicario: Save login for github.com? (alee) [Save] [Never] [✕] │ +│ Relicario: Save login for github.com? (alee) [Save] [Never] [✕] │ └──────────────────────────────────────────────────────────────────┘ ``` @@ -77,7 +77,7 @@ A floating element in the bottom-right corner: ``` ┌─────────────────────────────────┐ -│ relicario │ +│ Relicario │ │ Save login for github.com? │ │ alee │ │ [Save] [Never] [✕] │ diff --git a/docs/superpowers/specs/2026-04-12-relicario-firefox-extension-design.md b/docs/superpowers/specs/2026-04-12-relicario-firefox-extension-design.md index 79646aa..c859c30 100644 --- a/docs/superpowers/specs/2026-04-12-relicario-firefox-extension-design.md +++ b/docs/superpowers/specs/2026-04-12-relicario-firefox-extension-design.md @@ -1,4 +1,4 @@ -# relicario — Firefox Extension Port Design +# Relicario — Firefox Extension Port Design Port the existing Chrome MV3 extension to Firefox. Shared TypeScript source, separate manifests, separate build outputs. No code changes to components, popup, or content script. diff --git a/docs/superpowers/specs/2026-04-12-relicario-init-wizard-design.md b/docs/superpowers/specs/2026-04-12-relicario-init-wizard-design.md index 449dd99..2617fb7 100644 --- a/docs/superpowers/specs/2026-04-12-relicario-init-wizard-design.md +++ b/docs/superpowers/specs/2026-04-12-relicario-init-wizard-design.md @@ -1,6 +1,6 @@ -# relicario — Standalone Vault Initialization Wizard Design +# Relicario — Standalone Vault Initialization Wizard Design -A browser-based wizard that guides new users through creating an relicario vault from scratch. Lives at `extension/setup.html`, uses the same WASM module as the extension, same terminal dark aesthetic. No server, no Rust toolchain required. +A browser-based wizard that guides new users through creating a Relicario vault from scratch. Lives at `extension/setup.html`, uses the same WASM module as the extension, same terminal dark aesthetic. No server, no Rust toolchain required. ## Scope @@ -81,9 +81,9 @@ Two things happen: - Show warning: "Keep this image safe. You need it alongside your passphrase to unlock the vault. Store it somewhere you won't lose it." **Push config to extension (if available):** -- Try to detect the relicario extension via `chrome.runtime.sendMessage` with a `get_setup_state` message +- Try to detect the Relicario extension via `chrome.runtime.sendMessage` with a `get_setup_state` message - If extension responds: push `save_setup` message with `{ config: { hostType, hostUrl, repoPath, apiToken }, imageBase64 }`. Show "Extension configured! You can now open the extension and unlock your vault." -- If extension not detected: show the config as a copyable JSON blob with instructions: "Install the relicario extension, then paste this into the setup wizard." (Or just tell them to run through the extension setup manually with the same host/token/repo.) +- If extension not detected: show the config as a copyable JSON blob with instructions: "Install the Relicario extension, then paste this into the setup wizard." (Or just tell them to run through the extension setup manually with the same host/token/repo.) ## WASM Crate Change diff --git a/docs/superpowers/specs/2026-04-12-relicario-wasm-extension-design.md b/docs/superpowers/specs/2026-04-12-relicario-wasm-extension-design.md index 338184e..a1c7e20 100644 --- a/docs/superpowers/specs/2026-04-12-relicario-wasm-extension-design.md +++ b/docs/superpowers/specs/2026-04-12-relicario-wasm-extension-design.md @@ -1,6 +1,6 @@ -# relicario — WASM + Chrome MV3 Extension Design +# Relicario — WASM + Chrome MV3 Extension Design -The browser extension for relicario. Compiles `relicario-core` to WASM, wraps it in a Chrome MV3 extension with a terminal-aesthetic popup, conservative autofill, and direct Gitea/GitHub API access. No CLI dependency, no native messaging bridge. +The browser extension for Relicario. Compiles `relicario-core` to WASM, wraps it in a Chrome MV3 extension with a terminal-aesthetic popup, conservative autofill, and direct Gitea/GitHub API access. No CLI dependency, no native messaging bridge. ## Scope @@ -330,7 +330,7 @@ No shadow DOM traversal. No heuristic scoring. No iframe inspection. If the form ### 2. Field Icon Injection When a password field is detected: -- Small relicario icon (16x16, inline SVG) appears at the right edge of the password field +- Small Relicario icon (16x16, inline SVG) appears at the right edge of the password field - Click triggers: send page URL to service worker → get matching entries - Single match: fill immediately - Multiple matches: show inline picker (small dropdown below the icon) diff --git a/docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md b/docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md index 194186f..f8e01d9 100644 --- a/docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md +++ b/docs/superpowers/specs/2026-04-18-relicario-typed-items-design.md @@ -1,6 +1,6 @@ -# relicario — Typed Item Data Model Design +# Relicario — Typed Item Data Model Design -Foundational data-model rewrite for relicario. Replaces the single `Entry` type with a polymorphic typed-item system supporting Login, SecureNote, Identity, Card, Key, Document, and TOTP — with sections, custom fields, attachments, password history, soft-delete, and the security architecture needed to support 1Password-style daily-driver UX. +Foundational data-model rewrite for Relicario. Replaces the single `Entry` type with a polymorphic typed-item system supporting Login, SecureNote, Identity, Card, Key, Document, and TOTP — with sections, custom fields, attachments, password history, soft-delete, and the security architecture needed to support 1Password-style daily-driver UX. This is **Phase 1** of the broader 1Password-parity roadmap. Phase 0 (audit remediation) is the precursor implementation pass; Phase 2+ (admin portal, importers, Watchtower checks, etc.) build on top of this model. diff --git a/docs/superpowers/specs/2026-04-20-relicario-extension-1c-alpha-design.md b/docs/superpowers/specs/2026-04-20-relicario-extension-1c-alpha-design.md index 8938926..36fcff0 100644 --- a/docs/superpowers/specs/2026-04-20-relicario-extension-1c-alpha-design.md +++ b/docs/superpowers/specs/2026-04-20-relicario-extension-1c-alpha-design.md @@ -1,4 +1,4 @@ -# relicario — Extension Plan 1C-α (Foundation) Design +# Relicario — Extension Plan 1C-α (Foundation) Design First of three sub-plans that port the browser extension from the v1 single-`Entry` data model to the typed-item model landed in Plans 1A + 1B. 1C-α is the **foundation slice**: rebuild the WASM artifact, migrate shared types, rewrite the service worker against the opaque `SessionHandle` surface, split the message router with sender checks, wire the full security architecture from the typed-items spec, and achieve Login-parity on the new stack. Other six item types show "Coming in 1C-β" placeholders. diff --git a/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta1-design.md b/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta1-design.md index 45be2b5..2e14ef7 100644 --- a/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta1-design.md +++ b/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta1-design.md @@ -1,4 +1,4 @@ -# relicario — Extension Plan 1C-β₁ (Typed-Item Forms) Design +# Relicario — Extension Plan 1C-β₁ (Typed-Item Forms) Design Second of three sub-plans porting the extension to the typed-item core. 1C-α (foundation) shipped Login-parity; 1C-β₁ adds the **other 5 typed-item forms** so the extension can daily-drive every typed item the Rust core knows about (except Document, deferred to γ for attachment dependencies). Custom-fields editor, vault-settings view, and advanced generator UI move to **β₂**. diff --git a/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta2-design.md b/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta2-design.md index 7ad610b..e8cfb0b 100644 --- a/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta2-design.md +++ b/docs/superpowers/specs/2026-04-22-relicario-extension-1c-beta2-design.md @@ -1,4 +1,4 @@ -# relicario — Extension Plan 1C-β₂ (Custom Fields + Settings + Generator UI) Design +# Relicario — Extension Plan 1C-β₂ (Custom Fields + Settings + Generator UI) Design Third of three β sub-plans porting the extension to the typed-item core. 1C-α shipped the security architecture + Login parity; 1C-β₁ added the 5 remaining typed-item forms; **1C-β₂** (this spec) adds the cross-cutting UI surfaces: custom fields editor, full vault-settings view, and an inline generator popover. diff --git a/docs/superpowers/specs/2026-04-24-relicario-logo-refresh-design.md b/docs/superpowers/specs/2026-04-24-relicario-logo-refresh-design.md index 0771228..6a052e3 100644 --- a/docs/superpowers/specs/2026-04-24-relicario-logo-refresh-design.md +++ b/docs/superpowers/specs/2026-04-24-relicario-logo-refresh-design.md @@ -5,7 +5,7 @@ ## Goal -The current logo reads as "modern shrine with a blue diamond" — visually correct in concept (a vessel that holds something precious) but blue-techy enough that the project's name (*relicario* — Spanish/Italian for *reliquary*) no longer comes through. The user wants more catholic-reliquary authenticity (gold, deep red, decorative finial) without the cross — closer to the user-supplied references of round-chapel theca reliquaries. +The current logo reads as "modern shrine with a blue diamond" — visually correct in concept (a vessel that holds something precious) but blue-techy enough that the project's name (*Relicario* — Spanish/Italian for *reliquary*) no longer comes through. The user wants more catholic-reliquary authenticity (gold, deep red, decorative finial) without the cross — closer to the user-supplied references of round-chapel theca reliquaries. The popup currently uses GitHub's dark-blue accent palette throughout. Once the logo shifts to gold, leaving the popup's blue accents in place would create visual whiplash between the toolbar icon and the popup body. The palette shift converts blue → gold and tunes the danger red toward the logo's theca tone, while keeping the dark backgrounds, monospace-ish text, and CLI restraint that define the project's voice. diff --git a/docs/superpowers/specs/2026-04-27-attach-existing-vault-design.md b/docs/superpowers/specs/2026-04-27-attach-existing-vault-design.md index 55eaccc..2a1973d 100644 --- a/docs/superpowers/specs/2026-04-27-attach-existing-vault-design.md +++ b/docs/superpowers/specs/2026-04-27-attach-existing-vault-design.md @@ -7,7 +7,7 @@ ## Background -Today the setup wizard (`extension/src/setup/setup.ts`) has one flow: create a brand-new vault. Step 2 only checks that the configured remote is reachable; it does not detect whether that remote already contains a relicario vault. Step 3's "create vault" then writes `.relicario/salt`, `.relicario/params.json`, `.relicario/devices.json`, and `manifest.enc` unconditionally — silently overwriting any existing vault on the remote. +Today the setup wizard (`extension/src/setup/setup.ts`) has one flow: create a brand-new vault. Step 2 only checks that the configured remote is reachable; it does not detect whether that remote already contains a Relicario vault. Step 3's "create vault" then writes `.relicario/salt`, `.relicario/params.json`, `.relicario/devices.json`, and `manifest.enc` unconditionally — silently overwriting any existing vault on the remote. **Observed failure:** uninstalling and reinstalling the extension while pointed at a populated test repo wipes the manifest with no warning. The user's test entries are gone. @@ -64,7 +64,7 @@ The progress bar grows from 5 to 6 segments; Step 0 is the new leading segment. Two large buttons. No host configuration, no other inputs. Sets `state.mode` to `'new'` or `'attach'`. Helper copy under each: -- *create new vault* — "I'm setting up relicario for the first time. This will create a fresh encrypted vault on a new or empty git repository." +- *create new vault* — "I'm setting up Relicario for the first time. This will create a fresh encrypted vault on a new or empty git repository." - *attach this device* — "I already have a vault on another device. Connect this browser to it using my passphrase and reference image." ### Step 1: host type @@ -93,7 +93,7 @@ The "switch mode" buttons preserve all entered host config so the user does not **Warning card copy (mode=new, vault present):** -> ⚠ This repository already contains a relicario vault. +> ⚠ This repository already contains a Relicario vault. > Last commit: `` by `` on ``. > > Creating a new vault here would overwrite the existing one and **destroy all data inside**. To use this vault on this device, switch to *attach* mode instead. diff --git a/docs/superpowers/specs/2026-04-27-relicario-import-export-design.md b/docs/superpowers/specs/2026-04-27-relicario-import-export-design.md index d87d00e..72d697f 100644 --- a/docs/superpowers/specs/2026-04-27-relicario-import-export-design.md +++ b/docs/superpowers/specs/2026-04-27-relicario-import-export-design.md @@ -1,12 +1,12 @@ -# relicario import / export — design +# Relicario import / export — design Date: 2026-04-27 Status: design (not yet implemented) -Scope: backup / restore (round-trippable to relicario itself) + LastPass CSV import. Migration **out** to other tools is explicitly out of scope. +Scope: backup / restore (round-trippable to Relicario itself) + LastPass CSV import. Migration **out** to other tools is explicitly out of scope. ## Motivation -Self-hosting a password vault without a backup story is unacceptable for production use. Today, a relicario user has no way to: +Self-hosting a password vault without a backup story is unacceptable for production use. Today, a Relicario user has no way to: 1. **Snapshot** their vault for disaster recovery (git remote going away, repo corruption, account loss). 2. **Onboard** from an existing manager — there's no migration path for a user with credentials in another tool. @@ -18,13 +18,13 @@ The following choices were brainstormed and approved before this spec was writte | # | Decision | |---|---| -| D1 | Two features, one spec: backup/restore round-trippable to relicario, plus a LastPass CSV importer. Migration out is out of scope. | +| D1 | Two features, one spec: backup/restore round-trippable to Relicario, plus a LastPass CSV importer. Migration out is out of scope. | | D2 | Backup file format: single-file `.relbak` container. Magic header + version + salt + nonce + AEAD-encrypted, zstd-compressed JSON envelope with base64'd binary blobs. | | D3 | AEAD: XChaCha20-Poly1305 (same primitive used for vault items, but the backup format uses its own envelope with magic header + version byte; it does **not** reuse the `crypto.rs` `encrypt`/`decrypt` helpers, which assume the vault-master-key format). KDF: Argon2id with the same parameters as v1 of the live vault (m=64MiB, t=3, p=4) — but the params are tied to **backup format version**, not read from the vault's `params.json`. | | D4 | Backup passphrase is independent of the vault passphrase. User picks one at export; user types it at restore. Reusing the vault passphrase is allowed but not auto-filled. | | D5 | Reference image inclusion is optional. `--include-image` flag (CLI) / checkbox (UI). When included, the image is base64'd into the encrypted envelope — never in the clear inside the file. | | D6 | Git history (`.git/`) is included **by default**. `--no-history` opt-out for users who want a smaller file at the cost of audit trail and remote URL. | -| D7 | Restore semantics: refuse if the target directory already contains a relicario vault. Restore is a fresh round-trip operation, not a merge. | +| D7 | Restore semantics: refuse if the target directory already contains a Relicario vault. Restore is a fresh round-trip operation, not a merge. | | D8 | Backup passphrase strength: zxcvbn score ≥ 3, same gate as `init`. Backup is single-factor (one passphrase decrypts the container), so it must be at least as strong as a vault factor. | | D9 | The user is responsible for deleting the backup file after restore is verified. The encryption protects it in transit / at rest while it exists; it is not a defense against forensic recovery of deleted copies. Documented in CLI help text and the extension UI. | | D10 | LastPass import: parse the standard LastPass CSV (`url,username,password,totp,extra,name,grouping,fav`). Logins → `Login` items (with embedded TOTP if present); rows with `url == http://sn` → `SecureNote`; structured LastPass notes (cards, SSH keys, addresses) are **not** auto-parsed — they fall through as `SecureNote` with `extra` as the body. | @@ -215,7 +215,7 @@ Future format v2 may change these; v1 readers will see `version != 0x01` and pro ## LastPass field mapping -| LastPass column | relicario destination | Notes | +| LastPass column | Relicario destination | Notes | |---|---|---| | `name` | `Item.title` | Required; row skipped with warning if missing | | `grouping` | `Item.group` | `None` if empty | @@ -246,11 +246,11 @@ Atomicity: output uses the existing `atomic_write` helper (write `.tmp` → rena | Error | Detection | User-facing message | Recovery | |---|---|---|---| -| Bad magic | First 4 bytes ≠ `"RBAK"` | `"not a relicario backup file"` | Verify file | -| Unsupported version | Version byte > current (1) | `"backup created by a newer relicario; upgrade required"` | Update binary | +| Bad magic | First 4 bytes ≠ `"RBAK"` | `"not a Relicario backup file"` | Verify file | +| Unsupported version | Version byte > current (1) | `"backup created by a newer Relicario; upgrade required"` | Update binary | | Wrong backup passphrase | AEAD authentication fails | `"wrong backup passphrase, or the file is corrupt"` (deliberately ambiguous) | Retry | -| Target dir already has a vault | `target/.relicario/` exists | `"target dir already contains a relicario vault; restore refuses to overwrite — use an empty directory"` | Choose empty dir | -| Schema mismatch | envelope.schema_version != current | `"backup is schema v; this relicario reads v"` | Use matching binary | +| Target dir already has a vault | `target/.relicario/` exists | `"target dir already contains a Relicario vault; restore refuses to overwrite — use an empty directory"` | Choose empty dir | +| Schema mismatch | envelope.schema_version != current | `"backup is schema v; this Relicario reads v"` | Use matching binary | | Mid-restore crash | (no detection) | — | User deletes target dir, retries | Atomicity: best-effort. If interrupted mid-write, target dir has partial files — user cleans up and retries. Documented limitation. Restore is rare enough that engineering atomic-rename of multiple files is not worth the complexity. diff --git a/docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md b/docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md index d6c1729..f64c891 100644 --- a/docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md +++ b/docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md @@ -24,7 +24,7 @@ Sidebar + detail pane, similar to 1Password's desktop app: ``` ┌──────────────────────────────────────────────────┐ -│ 🔒 relicario [lock] [settings] │ +│ 🔒 Relicario [lock] [settings] │ ├────────────────┬─────────────────────────────────┤ │ [search...] │ │ │ │ (detail view for selected │ diff --git a/docs/superpowers/specs/2026-05-01-recovery-qr-design.md b/docs/superpowers/specs/2026-05-01-recovery-qr-design.md index e5c31b0..4995928 100644 --- a/docs/superpowers/specs/2026-05-01-recovery-qr-design.md +++ b/docs/superpowers/specs/2026-05-01-recovery-qr-design.md @@ -7,7 +7,7 @@ ## Background -relicario's two-factor model derives `master_key = Argon2id(len-prefixed(passphrase) || image_secret, salt, params)` (`crates/relicario-core/src/crypto.rs:207`). Lose either factor and the vault is unrecoverable. The reference image is the more loseable factor — it lives outside the user's head, often as a "dead drop" on social media or a personal site, and a single platform takedown or accidental deletion permanently bricks the vault. +Relicario's two-factor model derives `master_key = Argon2id(len-prefixed(passphrase) || image_secret, salt, params)` (`crates/relicario-core/src/crypto.rs:207`). Lose either factor and the vault is unrecoverable. The reference image is the more loseable factor — it lives outside the user's head, often as a "dead drop" on social media or a personal site, and a single platform takedown or accidental deletion permanently bricks the vault. The original design spec already sketched a post-V1 recovery path (`docs/superpowers/specs/2026-04-11-relicario-design.md:342-349`): a small encrypted file containing only `image_secret`, locked under the passphrase via a separate Argon2id derivation, stored offline. This spec finalizes that sketch with three refinements landed during brainstorming: diff --git a/extension/manifest.json b/extension/manifest.json index dbfe28c..60dd33d 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,6 +1,6 @@ { "manifest_version": 3, - "name": "relicario", + "name": "Relicario", "version": "0.2.0", "description": "Two-factor encrypted password manager", "icons": { @@ -32,7 +32,7 @@ }, "commands": { "open-vault": { - "description": "Open relicario vault" + "description": "Open Relicario vault" } }, "web_accessible_resources": [] diff --git a/extension/src/content/icon.ts b/extension/src/content/icon.ts index eec7f1b..e8a12f1 100644 --- a/extension/src/content/icon.ts +++ b/extension/src/content/icon.ts @@ -66,7 +66,7 @@ export function injectFieldIcons( const icon = document.createElement('div'); icon.textContent = 'id'; icon.setAttribute('role', 'button'); - icon.setAttribute('aria-label', 'relicario autofill'); + icon.setAttribute('aria-label', 'Relicario autofill'); icon.style.cssText = [ 'width: 20px', 'height: 20px', 'line-height: 20px', 'text-align: center', 'font-size: 10px', 'font-weight: 700', @@ -177,7 +177,7 @@ function showPicker( /// TOFU origin-ack hint: credentials exist for this host but the user has /// never explicitly acknowledged autofill here. Instruct them to open -/// relicario to confirm — we do not (and cannot) fill until ack-autofill +/// Relicario to confirm — we do not (and cannot) fill until ack-autofill /// has been called from the popup. function showAckHint(hostname: string): void { closeOverlay(); @@ -201,7 +201,7 @@ function showAckHint(hostname: string): void { const title = document.createElement('div'); title.style.cssText = 'font-weight: 700; margin-bottom: 4px; color: #d2ab43;'; - title.textContent = 'relicario'; + title.textContent = 'Relicario'; hint.appendChild(title); const body = document.createElement('div'); @@ -209,7 +209,7 @@ function showAckHint(hostname: string): void { const hostSpan = document.createElement('strong'); hostSpan.textContent = hostname; body.appendChild(hostSpan); - body.appendChild(document.createTextNode(' — open relicario to confirm.')); + body.appendChild(document.createTextNode(' — open Relicario to confirm.')); hint.appendChild(body); const close = document.createElement('div'); diff --git a/extension/src/popup/components/unlock.ts b/extension/src/popup/components/unlock.ts index 27b5e59..dfcf21c 100644 --- a/extension/src/popup/components/unlock.ts +++ b/extension/src/popup/components/unlock.ts @@ -9,7 +9,7 @@ export function renderUnlock(app: HTMLElement): void { app.innerHTML = `
-
relicario
+
Relicario

two-factor vault

- relicario + Relicario
diff --git a/extension/src/popup/styles.css b/extension/src/popup/styles.css index 146e72a..02f6b02 100644 --- a/extension/src/popup/styles.css +++ b/extension/src/popup/styles.css @@ -1,4 +1,4 @@ -/* relicario extension — terminal dark theme */ +/* Relicario extension — terminal dark theme */ :root { /* Brand */ diff --git a/extension/src/service-worker/router/popup-only.ts b/extension/src/service-worker/router/popup-only.ts index 905e949..727867c 100644 --- a/extension/src/service-worker/router/popup-only.ts +++ b/extension/src/service-worker/router/popup-only.ts @@ -445,7 +445,7 @@ export async function handle( try { const meta = await vault.fetchVaultMeta(newHost); if (meta.salt && meta.paramsJson) { - return { ok: false, error: 'remote already contains a relicario vault' }; + return { ok: false, error: 'remote already contains a Relicario vault' }; } } catch { // No vault present — expected for a fresh remote. diff --git a/extension/src/setup/setup.ts b/extension/src/setup/setup.ts index a6aa5eb..9d1fcd6 100644 --- a/extension/src/setup/setup.ts +++ b/extension/src/setup/setup.ts @@ -191,7 +191,7 @@ function render(): void { app.innerHTML = `
-
relicario vault setup
+
Relicario vault setup
${progressHtml} ${state.error ? `
${escapeHtml(state.error)}
` : ''} ${stepHtml} @@ -215,15 +215,15 @@ function renderStep0(): string { const isAttach = state.mode === 'attach'; return `
-

set up relicario

+

set up Relicario

- How are you using relicario on this device? + How are you using Relicario on this device?

@@ -481,7 +481,7 @@ function renderProbeBanner(): string { if (state.mode === 'new' && probe.exists) { return `