Files
relicario/CHANGELOG.md
adlee-was-taken 7c7efa7c43 release: v0.7.0 — extension restructure complete (Plan C Phases 3/4/6)
Completes the extension restructure begun in v0.6.0. Phases 3 (setup
wizard SW migration + step registry), 4 (vault.ts split + vault_locked
lift), and 6 (get_vault_status + sidebar status indicator) all merged to
main (9df2fee, 3b8368d, 397cc78) via three parallel worktree streams.

This commit is the release-prep wrap-up:
- Version bump to v0.7.0 across the three relicario crates + Cargo.lock,
  extension/package.json, and both extension manifests (the manifests had
  lagged at 0.5.0 — corrected here).
- CHANGELOG.md v0.7.0 entry.
- STATUS.md: extension restructure moved to shipped; Phases 3/4/6 landing
  section added.
- ROADMAP.md: v0.7.0 row added; Up-next now command palette.
- extension/ARCHITECTURE.md: all three phases integrated (new vault-*
  modules, setup-steps.ts, get_vault_status protocol + status indicator,
  vault_locked lift, git-host sync cache).
- Plan completion checkboxes ticked.

Task 7.1 verification: done-criteria sweep all green; 423/423 vitest;
build:all clean (only the pre-existing 4MB WASM size warning).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:50:17 -04:00

23 KiB
Raw Permalink Blame History

Changelog

v0.7.0 — 2026-06-01

Completes the extension restructure (Plan C) begun under v0.6.0. Phases 1/2/5 (StateHost typing, SW storage extract, the P2 cluster) shipped 2026-05-30; this tag adds the remaining three phases — executed as three parallel worktree streams under PM coordination — which eliminate the two steepest learning cliffs in the extension and close the last relicario status CLI/extension parity gap. No crypto, wire-format, or Rust-API changes; this is an internal-architecture + one-feature release.

Added

  • relicario status parity in the extension. New get_vault_status service-worker message returns a cached sync summary { ahead, behind, lastSyncAt, pendingItems } with no network call — ahead/behind/lastSyncAt read straight off the cached git-host state (populated by the sync handler), pendingItems a live count of active (non-trashed) manifest entries. A sidebar-footer status indicator (vault-status.tsrenderStatusIndicator) renders N pending / N ahead / N behind / in sync plus a last sync … / never synced line, refreshed on mount and on a manual button — no timer polling, matching the no-network-without-user-intent discipline.

Changed

  • Setup wizard crypto moved into the service worker. The wizard no longer imports relicario-wasm or orchestrates the master key directly. New create_vault / attach_vault SW handlers own the full flow (image-secret embed/extract, unlock, manifest+settings encrypt + push, register_device + addDevice, persist config + reference image, session.setCurrent); on failure the SessionHandle is locked then freed, with ownership transferring only on success. setup.ts collapses from ~1230 LOC to a 58-LOC UI-only shell; the six render/attach step pairs become a SetupStep registry in the new setup/setup-steps.ts. Adds clearWizardState (bound to beforeunload and goto('mode')) to wipe sensitive Uint8Array fields when the wizard is abandoned. The non-extension copy-vault-config-JSON escape hatch is preserved.
  • vault.ts split from a 1037-LOC monolith to 194 LOC of routing + state. Extracted into five focused modules — vault-shell (DOM scaffolding, color-scheme, onMessage wiring), vault-sidebar (category nav, 80ms debounced search, bottom nav, status-indicator footer), vault-list (list + row rendering), vault-drawer (open/close/render + ensureDrawerClosedForRoute), vault-form-wrapper (wrapped form + sticky bar) — plus two support modules for an acyclic split (vault-context, the VaultController contract; vault-router, hash routing + pane dispatch).
  • vault_locked RPC intercept unified. Lifted out of vault.ts into the sendMessage wrapper in shared/state.ts, so both popup and vault-tab surfaces share one lock-redirect path.
  • state.gitHost now nulled on explicit lock, symmetric with the session-timer expiry path, so the new status indicator can't surface a stale lastSyncAt after a lock → re-unlock within one service-worker lifetime.

Internal

  • Three-stream parallel execution (Dev-A Phase 3, Dev-B Phase 4, Dev-C Phase 6) coordinated via the relay message bus; merges sequenced Phase 3 → 4 → 6 with per-phase done-criteria verification.
  • Final merged-tree validation: 423/423 vitest (62 files); npm run build:all clean for both Chrome and Firefox targets (only the pre-existing ~4 MB WASM asset-size warning). Task 7.1 done-criteria sweep all green. No change to wasm.d.ts.

v0.6.0 — 2026-05-30

Rolls up four weeks of post-v0.5.0 work into one tag: the Phase 2B polish foundation, the v0.5.1 train (Streams A/B/C — 3-column vault layout, left-nav settings, Recovery QR), the 1C-γ slice (Document type, attachments, device registration from popup, trash & history UI), the Plan B multi-stream refactor (Cycles 1+2), the vault-tab management surfaces revamp, and the doc-structure redesign. The in-flight scope outgrew the original v0.5.1 plan, so this cuts as a minor bump.

Added

  • Recovery QR — 1-of-2 disaster-recovery path. image_secret is encrypted under an Argon2id-derived key from the passphrase, packed into a 109-byte binary payload (magic RREC + version 0x01 + salt
    • nonce + AEAD ciphertext), and rendered as a QR code that is never written to disk. Surfaces:
    • Rust core: relicario-core/src/recovery_qr.rsgenerate_recovery_qr / unwrap_recovery_qr / recovery_qr_to_svg. Production KDF params (m=64MiB, t=3, p=4) live behind a private-fields type so they cannot drift.
    • WASM: generate_recovery_qr / unwrap_recovery_qr exported; the session now stashes image_secret so the QR can be regenerated without re-running steganography extraction.
    • CLI: relicario recovery-qr generate (TTY render) and relicario recovery-qr unwrap subcommands.
    • Extension: three-state Security settings card (no QR → amber warning; QR exists → green status + show/regenerate; explicit view → modal with print).
    • Setup wizard: skippable "generate before you go" banner on the final step.
  • Document item type. New typed item for storing a signed document with a primary attachment. Form takes signature + signed-on date; detail view renders a signature-block layout. Wired into the popup add/view/edit dispatchers. Refuses to drop its primary attachment (use purge instead).
  • Attachments end-to-end. Service worker uploads attachments via the GitHost putBlob path (GitHub + Gitea Git Data API with fallback); popup attachments-disclosure component handles add/remove/download inside all six item-type forms; 📎 indicator shows on item-list rows that have attachments. Per-vault attachment bytes cap is enforced both at attach-time and during backup restore.
  • Device registration from the popup. "Register this device" triggers an inline name input + WASM keypair generation + persisted device entry — no setup-wizard detour.
  • Trash + field-history UI. Trash view shows per-item purge countdown with restore / per-item purge / empty-all actions. Field-history view groups changes per field with reveal/copy glyph buttons. New top-level item-history-index pane lists every item that has captured history. #history/<id> route normalizes the legacy #field-history/<id> URL form.
  • 3-column fullscreen vault tab. Sidebar (200px, type-category nav) + list (flex) + detail drawer (440px, slides in on row click). Below 720px the drawer pushes the list full-pane. Bottom sheet for "new item" type picker uses a pane-only scrim so the sidebar stays interactive.
  • Left-nav settings page. Replaces the flat settings dump. Sections grouped Device (Autofill, Display — password coloring) vs Vault (Security — Recovery QR + trusted devices, Generator, Retention, Backup, Import). The standalone Devices sidebar entry is subsumed into Security.
  • Two-column login form in fullscreen. Identity (title / URL / group) and Credentials (username / password / TOTP) render as side-by-side glass cards above 720px viewport; single-column at narrow widths. Notes / custom sections / attachments stay full-width below the grid. Sticky save bar at the bottom of the form pane; header shows title + dirty subtitle ("unsaved · esc to cancel" or "no changes") + platform-aware save hint (⌘+S / Ctrl+S).
  • Polish vocabulary. Patina gold palette tokens (--gold-base #a88a4a replacing the brighter #d2ab43), .surface-backdrop (subtle radial top-glow + 18px grid texture) applied to popup body / setup body / vault body, .glass card class with backdrop-filter: blur(8px), .btn-primary / .btn-secondary button hierarchy, and GLYPH_NEXT = '▸' replacing ASCII in next/continue buttons.
  • Vault lock-screen logo. <img class="brand-logo"> added to the lock-screen render for parity with the popup unlock view and the setup wizard.
  • Setup wizard Style C. Centered hero card + colored progress track + glyph mode icons, replacing the prior vertical glass-card wizard.
  • Toast notification system. Shared showToast(message, type, durationMs) at extension/src/shared/toast.ts. Used for sync success/failure, copy confirmation, device registration result. Replaces the ad-hoc sync-status div.
  • Empty-state treatments. Popup item list (vault empty / search returns nothing), vault list (section empty) — each gets a centered glyph + headline + hint.
  • Per-type glyph icons in popup item rows. ◉ login, ◫ secure_note, ⊡ totp, ▭ card, ⌬ identity, ⊹ key, ≡ document.

Changed

  • Vault-tab management surfaces revamp (2026-05-24..05-30). Settings pane splits synced (cross-device via Chrome storage) from local (per-browser) controls and gains a session-timeout UI. Devices pane shows SHA-256 fingerprint + added-by display + inline two-step revoke confirm via glyph button. Trash pane shows per-item purge countdown via daysUntilPurge. Field-history pane gets section headers and reveal/copy glyph buttons. New shared utilities: relative-time.ts (consolidating five duplicate inline copies), webcrypto ssh-fingerprint.ts, shared section-header / glyph-btn / kv-row / fingerprint CSS.
  • Emoji sweep. Every remaining UI emoji replaced with a monochrome glyph constant from shared/glyphs.ts. The pop-out button is now (U+29C9, GLYPH_VAULT_TAB) instead of &#x2934;.
  • License switched to GPL-3.0-or-later. Was MIT for the early prototype phase. License headers + AUTHORS + crate Cargo.toml authors updated.
  • AttachmentId expanded to 128 bits with is_valid check. Backup restore now validates IDs (audit I2 / B4).
  • Per-vault attachment bytes cap enforced. Both CLI attach and backup restore (audit I3).

Internal

  • Plan B multi-stream refactor (Cycles 1+2). CLI main.rs split into per-command modules under crates/relicario-cli/src/commands/ with a shared git_run helper. New prompt_or_flag<T> and prompt_or_flag_optional<T> helpers compress all the build_*_item helpers. Vault::after_manifest_change wrapper plus a single canonical ParamsFile in the session avoid duplicated file-system rebuilds. Core/WASM seam: base32_decode_lenient, parse_month_year, guess_mime exported from WASM; CLI parsers migrated to relicario-core::parse. Extracted base32 module from core, deduplicated two RFC-4648 implementations.
  • Doc-structure redesign (2026-05-30). Renamed ARCHITECTURE.mdDESIGN.md, docs/ARCHITECTURE.mddocs/CRYPTO.md, FORMATS.mddocs/FORMATS.md. Added scope headers and "Next:" footers to all tour docs so the reading order is canonical. CLAUDE.md gains a living-docs table and four discipline rules (scope-boundary check, code-constant pinning, new-doc rule, plan-state hygiene).
  • CLI quality-of-life. gen alias for generate, -l/-w short flags, batched purge in cmd_purge and cmd_trash_empty.
  • Workspace audit cycle. Stale local branches and worktrees pruned. Several plan files moved into docs/superpowers/audits/ for the record.

v0.5.0 — 2026-05-02

Three release trains roll into one tag — backup/restore + LastPass import (originally v0.3.0), device authentication (originally v0.4.0), and the v0.5.0 polish + harden bundle (security fixes + UX fixes + two confirmed bugs).

Security

  • Pre-receive hook now actually verifies signatures (audit S1, HIGH). Earlier relicario-server builds accepted any commit with a Good signature line on stderr regardless of which key signed it — device-auth was a no-op. The hook now builds an allowed_signers file from devices.json at the commit (via GIT_CONFIG_* env, no global git-config mutation), parses the SSH SHA-256 fingerprint out of git verify-commit --raw stderr, and rejects unregistered keys or revoked keys whose committer-date is at or after the revocation timestamp. Bootstrap mode is preserved only when both devices.json AND revoked.json are empty (closes an empty-devices.json privilege-escalation route).
  • Backup-restore tar unpacking hardened (audit S2). relicario backup restore no longer trusts tar::Archive::unpack's defaults. A new relicario_core::safe_unpack_git_archive validates each entry's path components (rejects .., absolute paths, Windows drive prefixes), rejects symlinks/hardlinks, and caps total uncompressed size at the lower of 100×compressed-bytes or 1 GiB. The CLI restore path adds a paranoid dest.starts_with(.git/) check after path-joining as defense-in-depth.
  • RELICARIO_* env-var surface audited (audit S3). docs/SECURITY.md gains a per-variable trust table. RELICARIO_NO_GROUPS_CACHE (a developer escape hatch, not a user knob) is now cfg(debug_assertions)-gated and is a no-op in --release builds; the env-var lookup is removed from the binary by the optimiser.

Fixed

  • Strength meter no longer goes stale after the regenerate button (B1). Programmatic input.value = newPassword doesn't fire input events; the regenerate handler now dispatches a synthetic InputEvent('input', { bubbles: true }) so the meter listener re-rates the new value.
  • Snake_case error codes no longer leak into the UI (B2 / P4). Errors like vault_locked, origin_mismatch, unauthorized_sender used to render verbatim in the fullscreen vault tab and (in some cases) the popup. New extension/src/shared/error-copy.ts central registry maps every service-worker error code to friendly title/body/CTA copy; the popup and fullscreen tab consume the same map. The fullscreen lock screen's vault_locked block now reads Vault locked / Unlock your vault to continue. / [Unlock vault]. A generated test enumerates the live error codes via grep so the registry can't drift.

Added

  • Sidebar logo in the fullscreen vault tab. The vault-sidebar__header now renders the 16-optimized SVG logo inline before the "Relicario" wordmark (20×20 px, flex-shrink: 0 so it survives narrow-pane wraps). Popup unaffected.
  • Password coloring (P1). Revealed passwords in the popup item-detail, fullscreen item view, field-history viewer, and generator preview render digits and symbols in distinct colors. Defaults: blue digits, red symbols. Users can override via the new Display section in settings (color pickers + live preview swatch + reset). Defaults round-trip via chrome.storage.sync.password_display_scheme; cross-device when Chrome sync is enabled.
  • Setup wizard hands off to the fullscreen vault tab on completion (P2). Both create-new and attach-existing flows now open vault.html in a new tab and best-effort close the setup tab after device registration succeeds — replaces the prior setup-tab-stays-open terminal screen.
  • Sync now button in the extension settings view — surfaces the previously hidden { type: 'sync' } SW message to users with success / error feedback.
  • Device registration from the popup. The "Register this device" button on the devices view now opens an inline name input and (on confirm) generates a keypair via WASM, persists the private key + name locally, and writes the device to the remote — no setup-wizard detour. Backed by a new register_this_device SW message.
  • relicario settings generator-defaults — view-and-edit access to the generator defaults stored in VaultSettings. Flags: --random / --bip39 to switch mode, --length, --words, --symbols, --separator to update fields of the active mode.
  • relicario edit now supports TOTP items. Issuer, label, and secret rotation work; rotated secrets are pushed to field_history (key: core:totp_secret).
  • relicario history <query> — view captured field history. Values are masked by default; --show reveals them; --field <name> filters to one synthetic key (e.g. login_password, totp_secret).
  • relicario detach <query> <aid> — remove an individual attachment from an item. Refuses to drop a Document item's primary attachment (use purge instead).
  • relicario status — vault summary: root path, item count (active / trashed), attachment count + total bytes, registered device count, last commit (%h %s).
  • Backup & restore. New relicario backup export <out.relbak> and relicario backup restore <in.relbak> [<dir>] commands. The .relbak format is a single encrypted file: Argon2id-derived key from a user-chosen backup passphrase (independent of the vault factor), XChaCha20-Poly1305 ciphertext, zstd-compressed JSON envelope. Reference image and .git/ history are opt-in inclusions (--include-image, --no-history).
  • Vault-tab Backup & Restore panel. Export downloads the .relbak via chrome.downloads. Restore takes a file + backup passphrase + new-remote config and writes the vault into a fresh empty repo (refuses to clobber existing). Git history is never bundled from the extension — CLI is the source of full backups.
  • LastPass CSV import. New relicario import lastpass <csv> command + vault-tab Import panel (vault.html#import). Logins map to Login items; rows with url == "http://sn" map to SecureNote (extra column → body verbatim, structured data preserved as-is for manual re-categorization). TOTP secrets in the totp column are base32-decoded into LoginCore.totp; bad base32 surfaces a warning and the login is imported without TOTP. Failed rows (missing name, missing password on a login) are skipped with a per-row warning. Each row gets a freshly-minted ID — re-running the import creates duplicates rather than corrupting state.
  • Popup deep link to the Import panel. settings-vault gains an "import" section with a LastPass CSV → button next to the existing Backup & restore → button.
  • relicario status shows last export age. New Last export: <human-readable> line reading .relicario/last_backup (a marker file cmd_backup_export writes on success). Reads "never" for fresh vaults, "4 days ago" otherwise.

Changed

  • Form layout in the fullscreen vault tab is now visually consistent (P3). Notes, custom-fields disclosure, attachments disclosure, and form-actions in fullscreen logins now sit inside a .form-lower wrapper with the same max-width: 960px; margin: 0 auto envelope as 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). DESIGN.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 / generate-hook subcommands and notes the without-the-hook-it's- advisory caveat; docs/CRYPTO.md shows settings.enc as a parallel artifact in the vault-creation flow; the foundational design spec gains a "historical" status banner pointing readers at the current docs.
  • relicario generate now consults VaultSettings.generator_defaults when invoked inside an initialized vault. Explicit flags (--length, --bip39, --words, --symbols, --separator) override the vault default. Outside a vault, behavior is unchanged (length 20, safe symbol set, 5 BIP39 words, space separator).

Known limitations

  • Mid-restore failure leaves the target remote in a half-written state. cmd_backup_restore and the vault-tab Restore panel both write artifacts sequentially via writeFileCreateOnly. If the process is interrupted partway, a retry against the same remote refuses to clobber. Workaround: delete the partial repo and retry.
  • Cross-tool backup compatibility. CLI-exported backups stored attachments at <item_id>/<aid>.enc; extension stores at flat <aid>.bin. The .relbak envelope canonicalizes to <item_id>/<aid> keys and each tool translates at the boundary. Round-trip works in both directions.

Internal

  • 5 stale local feature branches and 3 worktrees pruned (audit C1).
  • Pre-existing clippy warnings cleaned up across relicario-{core,cli} (deref operators, Option::is_none_or over map_or(true, ...), iter_mut().enumerate() patterns, div_ceil()) so the workspace builds clean under -D warnings.
  • Cargo.lock regenerated and committed; was stale since the --totp-qr commit.
  • Refactored cmd_add and cmd_edit in the CLI: each ItemCore variant now has its own build_*_item / edit_* helper. Pure mechanical extraction; behavior unchanged. The dispatcher matches and delegates.
  • Extracted pure helpers (escapeHtml, ratePassphrase, scheduleRate, entropyText, STRENGTH_LABELS) from extension/src/setup/setup.ts into setup-helpers.ts. State-coupled updateStrengthUi stays in setup.ts since it walks live wizard state. Setup.ts went from 1205 → 1137 lines.

v0.2.0 — 2026-04-27

Fixed

  • Setup wizard could silently overwrite an existing vault. Pointing the 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 by this bug should restore from the git history of the affected repo (git log + git checkout <pre-init-sha> -- .).
  • New devices registered during initial setup were silently dropped. The wizard's Step 5 fired add_device over a service-worker channel that required an unlocked vault, which is unavailable mid-wizard. Device pubkeys now write directly to .relicario/devices.json from the wizard.
  • Wizard-created vaults were missing settings.enc. The CLI's init writes a default-VaultSettings settings.enc alongside manifest.enc, but the wizard skipped it, causing every get_vault_settings SW call to 404. The wizard now encrypts and writes settings.enc using a new default_vault_settings_json WASM helper that keeps defaults in sync with Rust core.

Added

  • Attach this device to an existing vault — purely from the GUI. New Step 0 mode picker splits the wizard into "create new vault" and "attach this device." The attach path takes a passphrase + reference image, fetches the existing manifest, verifies the credentials by decrypting it, and only then registers a new device key. No CLI required for multi-device setup.
  • GitHost.lastCommit(path) and GitHost.writeFileCreateOnly(path, ...).
  • default_vault_settings_json() WASM export.

v0.1.0 — 2026-04-22

Initial release.