Commit Graph

496 Commits

Author SHA1 Message Date
adlee-was-taken
dd0010db62 feat(relay): expand to dev-c role + python/ts MCP fallback shims
queue.ts and server.ts now know about dev-c alongside pm/dev-a/dev-b
so the four-role coordination paradigm works end-to-end. start.sh
opens a fourth window for dev-c. call.py and call.ts are HTTP shims
that agents can use when the MCP relay tools aren't registered in
their session (the kickoff prompts reference call.py by path as a
fallback).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 17:49:21 -04:00
adlee-was-taken
29146439bb fix(ext): glyph + vault polish — distinct identity glyph, sticky-bar form-actions hidden
GLYPH_TYPE_IDENTITY changed from ⌬ to ◍ so it's visually distinct from
GLYPH_DEVICES (also ⌬). Adds a CSS rule asserting [hidden] over the
.form-actions display:flex so the fullscreen sticky save bar can hide
the inner action row by attribute.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 17:49:16 -04:00
adlee-was-taken
cf66bd97b7 chore: bump crate and extension versions to 0.5.0
Catches the workspace and the extension manifests up to the v0.5.x
release line (was still showing 0.2.0).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 17:49:09 -04:00
adlee-was-taken
061facd5a9 docs(reviews): whole-codebase architecture audit 2026-05-04
Three-reviewer architecture audit (DEV-A: core, DEV-B: cli/server/wasm,
DEV-C: extension/relay) plus PM synthesis. Lens: make the codebase
readable for a smart developer who doesn't know Rust but wants to learn
by tinkering.

Top synthesis findings (P1):
- SessionHandle has no impl Drop; .free() is a cleanup no-op (cross-cutting Rust+JS)
- cli/main.rs is a 2641-line monolith with no submodule boundaries
- setup.ts (1220 LOC) bypasses the SW and orchestrates WASM directly
- vault.ts (1027 LOC) owns shell + sidebar + list + drawer + routing
- shared/state.ts is fully any-typed
- recovery_qr.rs is undocumented vs. rest of crypto-adjacent core
- duplicated SW router helpers (storage + itemToManifestEntry)
- pure parsers (parse_month_year, base32_decode_lenient) belong in core
- 16x duplicated git invocation boilerplate with one-line errors

CLI/extension parity: 22/23 capabilities ✓; only true gap is `relicario
status` (no get_vault_status); `detach` is partial via update_item.

Also fixes tools/relay/queue.test.ts:54 to match the dev-c role
expansion already in queue.ts (was failing 1/4; now 5/5 pass).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 23:27:26 -04:00
adlee-was-taken
bd6a30155e Merge feature/v0.5.1-stream-b-settings: unified left-nav settings (Autofill/Display/Security/Generator/Retention/Backup/Import) 2026-05-03 21:51:43 -04:00
adlee-was-taken
8baef5b3cb fix(ext/settings): restore settings-security.ts from main (Stream C real implementation) 2026-05-03 21:51:08 -04:00
adlee-was-taken
ddfb95d683 fix(ext/settings): call teardownSettings in popup render to prevent listener leak 2026-05-03 21:47:46 -04:00
adlee-was-taken
7df76c692a feat(ext/settings): settings left-nav skeleton with section routing
Two-panel layout (148px nav sidebar + content area) with 7 nav items
(Autofill, Display, Security, Generator, Retention, Backup, Import),
stub section functions, and settings layout CSS classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:46:11 -04:00
adlee-was-taken
b4d253c60b chore(ext/settings): stub settings-security.ts (DEV-C replaces implementation) 2026-05-03 21:45:14 -04:00
adlee-was-taken
c16adc4335 Merge feature/v0.5.1-stream-a-layout: 3-column vault layout, toast system, glyph constants, emoji sweep 2026-05-03 21:41:57 -04:00
adlee-was-taken
9a8cdf8e4f fix: replace all remaining emoji with monochrome glyph constants
- trash.ts TYPE_ICONS map uses GLYPH_TYPE_* constants
- field-history.ts copy button uses GLYPH_COPY
- attachments-disclosure.ts thumbnail/icon uses GLYPH_TYPE_DOCUMENT
- settings.ts sync button uses GLYPH_SYNC
- document.ts thumb/sigblock/preview use GLYPH_TYPE_DOCUMENT + GLYPH_PREVIEW
- glyphs.ts adds GLYPH_COPY, GLYPH_SYNC, GLYPH_PREVIEW
- vault.ts adds GLYPH_DEVICES import + devices sidebar nav button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:37:23 -04:00
adlee-was-taken
ade44b4ea1 feat(ext/vault): wire renderSettings / teardownSettings from settings component 2026-05-03 21:37:23 -04:00
adlee-was-taken
1d4b018f9a feat(ext/vault): bottom sheet type picker for new item 2026-05-03 21:37:23 -04:00
adlee-was-taken
882a89bedd feat(ext/vault): detail drawer — open/close state + core fields display 2026-05-03 21:37:23 -04:00
adlee-was-taken
37c20b28a6 feat(ext/vault): 3-column shell — sidebar category nav + list pane 2026-05-03 21:37:23 -04:00
adlee-was-taken
3553150a53 feat(ext/vault): 3-column layout CSS — drawer, bottom sheet, list rows, responsive 2026-05-03 21:37:23 -04:00
adlee-was-taken
b50f49b597 fix(ext/vault): replace emoji typeIcon with glyph constants 2026-05-03 21:37:23 -04:00
adlee-was-taken
1ec8965910 feat(ext): shared toast notification system 2026-05-03 21:37:23 -04:00
adlee-was-taken
ad6e4a2cd9 feat(ext/popup): polished 2-column type-picker with glyph icons 2026-05-03 21:37:23 -04:00
adlee-was-taken
b768f649a2 feat(ext/popup): empty states with glyph icons in item-list 2026-05-03 21:37:23 -04:00
adlee-was-taken
8b197a7525 fix(ext/popup): replace emoji in SETTINGS_OPTIONS with glyph constants 2026-05-03 21:37:23 -04:00
adlee-was-taken
117716f6cf fix(ext/popup): replace emoji typeIcon with glyph constants in item-list 2026-05-03 21:37:23 -04:00
adlee-was-taken
c5e8b52e12 fix(ext/popup): replace inline &#x2934; vault-tab button with GLYPH_VAULT_TAB 2026-05-03 21:37:23 -04:00
adlee-was-taken
a1b66a9147 feat(ext/glyphs): add GLYPH_VAULT_TAB and per-type icon constants 2026-05-03 21:37:23 -04:00
adlee-was-taken
934dfe05c2 Merge feature/v0.5.1-stream-c-recovery-qr: Recovery QR (Rust core + WASM + CLI + settings-security.ts + setup wizard) 2026-05-03 21:26:40 -04:00
adlee-was-taken
33d2a4a311 feat(ext/setup): wizard Style C progress track, glyph mode icons, recovery QR banner
- Replace dot-based progress indicator with colored horizontal segment track
  (completed=green, active=gold, pending=border) via renderProgressTrack()
- Add SETUP_STEP_NAMES constant for track segment titles
- Update Step 0 mode cards with glyph icons (◈ create, ⌥ attach)
- Add recovery QR banner in Step 5 (new-vault only, verifiedHandle present)
  with Generate now / Skip buttons wired in attachStep5()
- Add CSS for .setup-progress-track, .setup-progress-segment variants,
  and .recovery-qr-banner to styles.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:17:05 -04:00
adlee-was-taken
f17944a404 fix(core,wasm): correct QR version comment, expect msg, zeroize image_secret in closure 2026-05-03 21:09:02 -04:00
adlee-was-taken
4851857070 feat(ext/settings): settings-security.ts three-state recovery QR + devices component
- Add settings-security.ts with renderSecuritySection / teardownSecuritySection
- Three states: amber warning (no QR), green status (QR set up), modal overlay (show/print SVG)
- Device list with inline revoke; passphrase collected via prompt()
- QR payload never written to chrome.storage; only recovery_qr_generated_at timestamp stored
- Add generate_recovery_qr / unwrap_recovery_qr message types to messages.ts + POPUP_ONLY_TYPES
- Add SW handlers in popup-only.ts delegating to wasm_generate_recovery_qr / wasm_unwrap_recovery_qr
- Declare wasm_generate_recovery_qr and wasm_unwrap_recovery_qr in wasm.d.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:06:43 -04:00
adlee-was-taken
a6071b4c0c feat(cli): recovery-qr generate / unwrap subcommands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 21:01:29 -04:00
adlee-was-taken
ada00895d4 feat(wasm): expose generate_recovery_qr and unwrap_recovery_qr bindings 2026-05-03 20:57:55 -04:00
adlee-was-taken
42b746f9af feat(wasm): session stores image_secret for recovery QR generation 2026-05-03 20:56:39 -04:00
adlee-was-taken
762a008171 test(core): recovery_qr roundtrip + error cases 2026-05-03 20:53:59 -04:00
adlee-was-taken
f93bce7388 chore(core): re-export recovery_qr module 2026-05-03 20:51:36 -04:00
adlee-was-taken
8eabaf5f31 feat(core): recovery_qr generate + unwrap + SVG functions 2026-05-03 20:51:33 -04:00
adlee-was-taken
04142dc116 feat(core): add derive_master_key_raw + RecoveryQr error variant 2026-05-03 20:51:29 -04:00
adlee-was-taken
8739f1f67b chore(core): add qrcode dependency for recovery QR 2026-05-03 20:48:38 -04:00
adlee-was-taken
7d6fd76e86 feat: v0.5.1 multi-agent coordination plans (PM + DEV-A/B/C)
- coordination/v0.5.1-pm-prompt.md — PM coordinates 3 streams, enforces
  interface contracts (A-B settings signature, B-C security component),
  owns merge order and pre-tag checklist
- coordination/v0.5.1-dev-a-prompt.md — Stream A: fullscreen 3-column
  layout, sidebar category nav, detail drawer, bottom sheet, popup type-
  picker polish, per-type glyph icons, empty states, toast system (13 tasks)
- coordination/v0.5.1-dev-b-prompt.md — Stream B: settings left-nav
  redesign (Autofill, Display, Security, Generator, Retention, Backup,
  Import sections), security component stub (10 tasks)
- coordination/v0.5.1-dev-c-prompt.md — Stream C: recovery_qr.rs core,
  WASM session expansion, CLI subcommand, settings-security.ts three-state
  component, setup wizard Style C redesign + QR banner (12 tasks)
- Archive v0.5.0 coordination files to coordination/archive/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:26:19 -04:00
adlee-was-taken
4dc034d846 docs(spec): v0.5.x UX polish, settings redesign, and recovery QR design
Three-stream spec for the next release train:
- Stream A: fullscreen 3-col layout, popup type-picker polish, glyphs, toasts, empty states
- Stream B: settings UX redesign with left-nav sections (Device/Vault split)
- Stream C: recovery QR crypto (Rust/WASM), setup wizard redesign (Style C), security settings tab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 19:32:43 -04:00
adlee-was-taken
3021ef9d9f feat(ext/vault): sidebar logo before "Relicario" wordmark
Renders the 16-optimized SVG (icons/relicario-logo-16.svg) inline
before the brand text in .vault-sidebar__header. Sized to 20×20 px
with flex-shrink: 0 so it survives narrow-pane wraps. The header
already had display: flex + gap: 8px, so the layout absorbed the new
element without further changes. Popup surface is untouched (this
override is scoped to .vault-sidebar__header .brand-logo).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 18:53:09 -04:00
adlee-was-taken
b2749826b1 docs: CHANGELOG entry for v0.5.0
Three release trains roll into one tag — v0.3.0 backup/restore +
LastPass import, v0.4.0 device authentication, and the v0.5.0
polish + harden bundle.

Renames the existing "Unreleased" heading to v0.5.0 — 2026-05-02
and prepends the polish + harden additions:

- Security: S1 pre-receive hook fix (HIGH-severity authentication
  bypass), S2 tar-restore path-traversal hardening, S3 RELICARIO_*
  env-var audit + cfg-gate.
- Fixed: B1 strength-meter regenerate desync, B2/P4 raw error-code
  leakage in the fullscreen tab.
- Added: P1 password coloring (four reveal surfaces + settings UI),
  P2 setup → fullscreen vault tab handoff. Existing v0.3.0/v0.4.0
  Added entries (sync, register-from-popup, generator-defaults, edit
  TOTP, history, detach, status, backup/restore, vault-tab panel,
  LastPass import + popup deep link, status export age) preserved
  verbatim.
- Changed: P3 form-layout envelope, doc-audit refresh across
  overview / CLAUDE / SECURITY / ARCHITECTURE / foundational spec.
- Internal: C1 stale-branch prune, clippy cleanup, Cargo.lock
  regenerated, CLI/extension refactors preserved from prior trains.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 20:48:22 -04:00
adlee-was-taken
a332a9e80d Merge feature/v0.5.0-plan-a-security-cleanup: Plan A security + cleanup
v0.5.0 Plan A — Security Fixes + Repo Cleanup. 7 commits, ~800 net
insertions across the Rust workspace. Four items delivered:

- S1 (HIGH-severity authentication bypass fix): rewrite verify_commit
  in relicario-server. The previous implementation accepted any
  GOODSIG/Good signature line on stderr, ignoring whether the signing
  key was registered or revoked. The new implementation:
  * builds a temp gpg.ssh.allowedSignersFile from devices.json at the
    commit (no global git-config mutation)
  * parses the SHA-256 fingerprint from `git verify-commit --raw`
    stderr via regex
  * checks revocation FIRST (revoked entries may have been removed
    from devices.json), with the historical-commit case
    (committer_ts < revoked_at) explicitly allowed
  * uses committer date (GIT_COMMITTER_DATE / `git show -s
    --format=%ct`), not author date or wall clock
  * tightened the bootstrap guard to require BOTH devices and revoked
    to be empty (closes an empty-devices.json privilege-escalation
    route present in the original code)
  * 4 acceptance integration tests build real on-disk repos with
    SSH-signed commits and verify each scenario

- S2 (tar archive path-traversal hardening): replace
  tar::Archive::unpack with safe_unpack_git_archive. Located in
  relicario-core (per-spec, so integration tests can reach it without
  the bytes-in/bytes-out invariant breaking). Validates each entry's
  type (rejects symlinks/hardlinks), path components (rejects '..',
  RootDir, Windows drive Prefix), and declared size (rejects
  individual or cumulative > 100×compressed-or-1-GiB whichever is
  lower). The CLI's restore path adds a paranoid OS-level
  starts_with(.git/) check on the joined destination as
  defense-in-depth even after textual validation. 5 acceptance tests
  cover path traversal, symlinks, oversized headers (header claim of
  2 GiB tested without allocating disk).

- S3 (RELICARIO_* env-var audit): docs/SECURITY.md gains a
  "Configuration env vars" section enumerating each variable, its
  purpose, and trust assumption. Active-in-all-builds variables
  (RELICARIO_IMAGE, RELICARIO_GITEA_*) are documented; debug-only
  variables (RELICARIO_NO_GROUPS_CACHE, RELICARIO_TEST_*) are gated
  behind cfg(debug_assertions) so the env-var lookup is removed from
  --release binaries.

- C1 (stale feature branch prune): 5 merged feature branches and
  3 worktrees pruned interactively per dev report.

- Bonus: 4d02a50 fixes pre-existing clippy warnings across
  crates/relicario-{core,cli} (deref operators, Option::is_none_or
  vs map_or(true, ...), iter_mut().enumerate() patterns,
  div_ceil()) so the workspace builds clean under `-D warnings`.

Merge resolution: docs/SECURITY.md had a conflict where main's F11/F12
(Device Authentication paragraph naming relicario-server + simplified
"Device registration is optional" line) collided with Plan A's S3
section. Resolved by keeping both — F11/F12's wording for the
Device Authentication section, then Plan A's "Configuration env vars"
section appended below.

Cargo.lock regenerated. The previous committed lock was stale since
commit 8855078 (--totp-qr); cargo test on both devs' worktrees
produced identical regenerated locks. Plan A genuinely added regex +
tempfile to relicario-server (both already transitively present from
relicario-cli), so no new top-level deps; the Cargo.lock churn is
catch-up of crate-version bumps that have happened since the last
commit-of-record.

Tests: 248 cargo tests pass; extension tests unchanged (336/8 with 8
pre-existing device-auth scaffolding failures).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 19:54:12 -04:00
adlee-was-taken
d45dd10917 Merge feature/v0.5.0-plan-b-extension-ux: Plan B extension UX
v0.5.0 Plan B — Extension UX Polish + Bug Fixes. 15 commits, 22 files,
+853/-33 lines, all in extension/. Five features delivered:

- P4: ERROR_COPY centralized map; popup humanizeError now a thin shell
  over lookupErrorCopy; fullscreen tab gets friendly title/body/CTA blocks
  (closes B2). Generated test enumerates every grep'd error code so the
  registry can't drift.
- B1: applyGeneratedPassword dispatches a synthetic input event after
  the regenerate handler sets the password value, so the strength-meter
  listener re-rates the new value.
- P1: end-to-end password coloring — pure colorizePassword utility,
  chrome.storage.sync round-trip via applyColorScheme, CSS rules with
  custom properties, four reveal surfaces (popup item-detail, vault
  item-detail, field-history, generator preview), boot wiring + storage
  listener, Display section in settings with color pickers + swatch +
  reset.
- P3: .form-lower wrapper constrains lower form sections (notes,
  custom-fields, attachments, actions) to the same max-width: 960px
  envelope as .form-grid above, gated on surface === 'fullscreen' so
  the popup is unaffected.
- P2: finishSetup() opens the fullscreen vault tab and best-effort
  closes the setup tab after successful device registration. Both
  create-new and attach-existing flows funnel through it.

Implementation notes:
- vault.ts uses event delegation on the stable #vault-app root for
  .error-cta clicks (better than the plan's per-render handler attach;
  survives re-renders without leaking listeners).
- fields.ts gained a kind: 'password' | 'concealed' option on
  ConcealedRowOpts so wireFieldHandlers can apply colorizePassword
  selectively at the shared rendering layer.
- New WASM stub at src/__stubs__/relicario_wasm.stub.ts + vitest config
  alias lets unit tests import setup.ts without exploding on the
  runtime-only WASM module.

Tests: +28 (336/8 vs main's 308/8); 8 pre-existing device-auth
scaffolding failures unchanged. Builds clean: cargo wasm + Chrome
bundle + Firefox bundle.

Manual acceptance items (P3 viewport sweep at 1920/1440/1024/768,
P2 setup-flow smoke) deferred to user's pre-tag smoke walk.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 19:42:22 -04:00
adlee-was-taken
4d02a50cc8 chore(core): fix pre-existing clippy warnings (-D warnings gate)
Resolves pre-existing lint issues in imgsecret.rs, time.rs, totp.rs,
and crypto.rs that blocked the cargo clippy --workspace -D warnings
gate. No logic changes: loop-index → iterator, manual div_ceil →
.div_ceil(), manual range contains → .contains(), auto-deref cleanup.

Also fixes pre-existing warnings in relicario-cli (main.rs, session.rs,
device.rs, gitea.rs, helpers.rs, test helpers): dead_code suppression,
too_many_arguments, literal_with_empty_format_string, manual_char_cmp,
map_or → is_none_or, and repeat().take() → vec! in test helpers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 19:32:45 -04:00
adlee-was-taken
4e9d834920 feat(ext/setup): hand off completion to fullscreen vault tab (P2)
After successful device registration (state.configPushed = true), the
wizard now opens vault.html in a new tab and closes the setup tab.
Both create-new and attach-existing flows funnel through the same
finishSetup() handler. Closing the setup tab is best-effort --
chrome.tabs.remove failures don't block the vault open.

Add src/__stubs__/relicario_wasm.stub.ts + vitest.config alias so
setup.ts can be imported in unit tests without the runtime WASM file.
Exclude the stubs dir from the webpack/tsc build in tsconfig.json.
2026-05-02 19:15:35 -04:00
adlee-was-taken
631e9af470 fix(ext/login): constrain lower form sections to .form-grid envelope (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 .form-grid above. Removes
the visual rhythm break at the 2-col -> full-width transition.

Popup keeps its current single-column behavior (gated on surface flag).
2026-05-02 19:07:33 -04:00
adlee-was-taken
b2fc56709a feat(ext/settings): Display section with color pickers + swatch + reset
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 19:03:23 -04:00
adlee-was-taken
b928ed407b feat(ext): apply color scheme on popup + vault startup
Import applyColorScheme in popup.ts and vault.ts, await it at boot,
and register a chrome.storage.onChanged listener so live color-picker
changes take effect without a reload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 18:55:28 -04:00
adlee-was-taken
5d9a7ee8d3 docs(multi-agent): expand kickoff section with full spec→plans→launch workflow 2026-05-02 18:51:52 -04:00
adlee-was-taken
006e67c361 fix(cli): cfg-gate RELICARIO_NO_GROUPS_CACHE to debug builds (audit S3)
The groups-cache opt-out is a developer debugging knob, not a
user-facing config. Gating the env-var lookup behind cfg!(debug_assertions)
makes release builds ignore the variable; the optimiser removes the
lookup entirely, so the variable name doesn't appear in release binary
strings output.

Doc-comments updated to reflect the new behaviour.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-02 18:51:15 -04:00
adlee-was-taken
95d1ff833c docs: enumerate RELICARIO_* env vars in SECURITY.md (audit S3)
Adds a "Configuration env vars" section listing every RELICARIO_*
variable read by production code, with purpose and trust boundary.
Splits user-facing vars from debug-only ones (cfg(debug_assertions))
to make the attack surface explicit for security reviewers.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-02 18:50:44 -04:00