Commit Graph

220 Commits

Author SHA1 Message Date
adlee-was-taken
2df636e454 fix(ext/login): dispatch input event after regenerate sets password (B1)
Programmatic input.value = newPassword does not fire input events, so
the strength-meter listener at shared/form-affordances/password-tools.ts:65
never re-rates the new value — meter stays stuck on the prior reading.

Extract applyGeneratedPassword(input, value) helper that sets value, type,
then dispatches new InputEvent('input', { bubbles: true }). Vitest covers
the dispatch + a sanity check that bubbling listeners fire.
2026-05-02 16:46:06 -04:00
adlee-was-taken
575343dc19 refactor(ext/vault): event delegation for error-cta + CSS variable consistency 2026-05-02 16:41:39 -04:00
adlee-was-taken
1c641b4911 fix(ext/vault): friendly error block in fullscreen tab (closes B2)
Replaces raw escapeHtml(state.error) renders with lookupErrorCopy()-driven
title/body/CTA blocks. vault_locked specifically gets an 'Unlock vault'
CTA that refocuses the passphrase input. Other CTAs route to setup.html
or chrome.runtime.reload().

Closes B2; concludes P4.
2026-05-02 16:37:16 -04:00
adlee-was-taken
214e1e49f8 test(ext/shared): pin fallback title assertion in error-copy test 2026-05-02 16:30:09 -04:00
adlee-was-taken
648dcf386e feat(ext/shared): centralize error-message copy in ERROR_COPY map
Replaces the popup's regex-chain humanizeError with a total lookup over
every error code returned by extension/src/service-worker/router/. A
generated test discovers codes via grep so the registry can't drift.
The popup keeps its small set of regex translators for Rust/serde error
phrasing that doesn't go through the router's error vocabulary.

Subsumes B2 — fullscreen consumer lands in the next commit.
2026-05-02 16:26:01 -04:00
adlee-was-taken
f1c615c0ed feat(ext/vault): fullscreen form header with dirty-state subtitle
Title left ('new login' / 'edit login'), subtitle below cycles between
'no changes' and 'unsaved · esc to cancel' on input events. Right side
shows the platform-aware save hint ('⌘+S to save' / 'Ctrl+S to save').
The actual ⌘+S keymap arrives in Phase 3 — this is a visual hint only.
2026-05-02 15:06:42 -04:00
adlee-was-taken
b270dfedb4 feat(ext/vault): sticky save bar in fullscreen forms
The form pane gets a flex column layout: scrollable content above,
sticky save bar at bottom. Bar uses translucent fill with backdrop-blur
and a 24px gradient fade so content scrolls under it. Save / cancel
buttons reuse the form's existing handlers via externalActions flag.
2026-05-02 15:05:09 -04:00
adlee-was-taken
a28b456191 feat(ext/login): add surface flag for two-column fullscreen form
renderForm() takes an optional { surface: 'popup' | 'fullscreen' }
parameter. When 'fullscreen', the Identity and Credentials field
groups render as glass cards inside a .form-grid (two columns,
stacks at <=720px). Popup keeps its single-column layout.
2026-05-02 15:01:35 -04:00
adlee-was-taken
058a49f68b style(ext/vault): apply .surface-backdrop to fullscreen body
Subtle radial top-glow + grid texture behind the existing vault shell.
No layout changes — existing panes sit above the backdrop's ::before.
2026-05-02 14:55:37 -04:00
adlee-was-taken
97e351fa61 feat(ext/setup): apply polish vocabulary to setup wizard
- Wraps setup content in .surface-backdrop
- Each wizard step gets a .glass card
- Mode-picker cards become glass cards
- 'next' / 'continue' buttons get the ▸ glyph
- Migrate from .btn .btn-primary to the new .btn-primary class
2026-05-02 14:52:14 -04:00
adlee-was-taken
7371eff0bb feat(ext/popup): polish unlock view with logo lockup + glass card
Restructures the unlock screen so the form sits in a glass card with
a primary 'unlock vault' button. Logo, brand, and tagline are grouped
as a lockup. Open-vault and settings are demoted to secondary buttons.
Body gets the .surface-backdrop wrapper.
2026-05-02 14:21:04 -04:00
adlee-was-taken
308ef2c974 feat(ext): add GLYPH_NEXT and replace ASCII arrows with ▸
Replaces the ASCII rightwards arrow → with U+25B8 ▸ in settings-vault
buttons. Matches the existing ▾/▸ disclosure-glyph family.
2026-05-02 14:17:55 -04:00
adlee-was-taken
60d7c074c3 style(ext): add .btn-primary and .btn-secondary classes
Two-tier button hierarchy. .btn-primary uses patina gold fill; .btn-secondary
is a ghost button with muted border. Existing .btn class kept for
backwards compatibility.
2026-05-02 13:33:18 -04:00
adlee-was-taken
91536ee50d style(ext): add .glass card class
Translucent fill, soft border, inner highlight, drop shadow. Used for
the unlock card, setup step cards, and form section panels.
2026-05-02 13:32:55 -04:00
adlee-was-taken
da61529de6 style(ext): add .surface-backdrop class
Subtle radial top-glow + 18px grid texture. Used as the backdrop for
the login popup, setup wizard, and fullscreen vault shell.
2026-05-02 13:32:39 -04:00
adlee-was-taken
7370f119ee style(ext/vault): add patina palette tokens
Mirrors popup/styles.css token block so the two surfaces share a
consistent color vocabulary.
2026-05-02 13:31:33 -04:00
adlee-was-taken
479e5848f5 style(ext/popup): add patina palette tokens
Replaces bright amber #d2ab43 with patina gold #a88a4a as the new base.
Keeps --accent as alias for backwards compatibility. Adds --bg-card
and --border-soft for upcoming glass card class.
2026-05-02 13:29:22 -04:00
adlee-was-taken
d6d07a19c1 docs(spec): expand Phase 2B to polish foundation + form layout
Bundles patina palette shift, logo update (translucent gradient gem),
glass-card vocabulary across login/setup/fullscreen, and the original
two-column form layout. Updates relicario-logo.svg and -16.svg to the
patina palette.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 13:19:54 -04:00
adlee-was-taken
d0047e751f fix(ext): capitalize Relicario in Firefox manifest, bump to 0.2.0
The Chrome manifest was already updated; the Firefox manifest still
showed lowercase 'relicario' as the extension name and was pinned at
0.1.0.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 13:02:01 -04:00
adlee-was-taken
c67d484152 feat(extension): update devices UI for new auth model
- Show revoked devices in collapsible section with strikethrough styling
- Fetch revoked.json via new list_revoked message + router case
- Registration flow uses register_device WASM API (private keys internal)
- Display revoked_by and timestamp for each revoked entry
- Update setup wizard to use new register_device API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 12:29:31 -04:00
adlee-was-taken
520f6ec72c feat(extension): update devices.ts for revoked.json + deploy keys
- Add createDeployKey/deleteDeployKey to GiteaHost
- Add RevokedEntry interface and readRevoked() to devices.ts
- Update revokeDevice() to write revoked.json alongside devices.json
- Update router to use new register_device WASM API (private keys internal)
- Pass revokedBy device name when revoking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 12:27:14 -04:00
adlee-was-taken
9845febb74 feat(extension): update wasm.d.ts for secure device API
New WASM bindings that keep private keys internal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 12:26:13 -04:00
adlee-was-taken
315967f4a1 Merge feature/fullscreen-ux-phase-2a: smart-input affordances
Phase 2A of the fullscreen UX redesign — 8 form-level smart-input
affordances (URL fill-from-tab + hostname chip, group autocomplete,
password reveal + strength bar, TOTP live preview + QR decode, notes
monospace toggle), shared between popup and fullscreen vault tabs via
the new extension/src/shared/form-affordances/ module set.

CLI parity:
- relicario rate <passphrase> (zxcvbn score / guess estimate)
- relicario completions <SHELL> (bash/zsh/fish via clap_complete)
- --group <TAB> dynamic enumeration via .relicario/groups.cache
  (plaintext leak surface; opt out with RELICARIO_NO_GROUPS_CACHE=1)
- --totp-qr <path> on add login + edit (rqrr decode)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 22:37:18 -04:00
adlee-was-taken
b450ecd1cc ext(login): wire 8 smart-input affordances into renderForm()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 22:32:14 -04:00
adlee-was-taken
e6eb698c4c ext(affordances): wireNotesMonoToggle with chrome.storage.local persistence 2026-05-01 22:23:56 -04:00
adlee-was-taken
bd8102c9ad ext(affordances): wireTotpQr (jsqr lazy-load) for QR -> otpauth:// fill
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 22:14:05 -04:00
adlee-was-taken
c91b31a7ca ext(affordances): wireTotpPreview live ticker 2026-05-01 19:56:55 -04:00
adlee-was-taken
bb8b86f0d5 ext(sw): add preview_totp_from_secret popup handler 2026-05-01 19:55:24 -04:00
adlee-was-taken
7bd1a9dd7d ext(affordances): wirePasswordStrength via scheduleRate
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 19:50:18 -04:00
adlee-was-taken
026b94092e ext(affordances): wirePasswordReveal toggle 2026-05-01 19:48:32 -04:00
adlee-was-taken
e452d8df02 ext(affordances): wireGroupAutocomplete via <datalist> 2026-05-01 18:09:33 -04:00
adlee-was-taken
5fbdd30a19 ext(sw): add list_groups popup handler 2026-05-01 18:08:34 -04:00
adlee-was-taken
61dbb4d3a3 ext(affordances): wireHostnameChip with debounced URL parse 2026-05-01 18:06:15 -04:00
adlee-was-taken
8eff96da9d ext(affordances): tighten FillFromTabOpts.sendMessage return type 2026-05-01 17:54:57 -04:00
adlee-was-taken
39ae2ecbf3 style: capitalize "Relicario" in prose / UI / CLI help
Brand name uses capital R in user-facing text — extension UI strings,
CLI clap help / descriptions / error prose, markdown docs. Lowercase
preserved for the binary command, crate names, npm package, file
paths, env vars, and code identifiers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 17:29:10 -04:00
adlee-was-taken
4be0bcff83 ext(affordances): wireFillFromTab + .glyph-btn CSS 2026-05-01 17:07:01 -04:00
adlee-was-taken
918fdef519 ext(sw): expand active-tab URL filter; isolate chrome stub in tests
Expand get_active_tab_url protocol filter regex to include view-source:,
data:, devtools:, and other browser-internal/extension contexts that would
misbehave if autofilled. Add third regression test for view-source: URLs.

Wrap get_active_tab_url tests in dedicated describe block with beforeEach/
afterEach to snapshot/restore globalThis.chrome, preventing stub leakage
between tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 17:01:36 -04:00
adlee-was-taken
f872ab5183 ext(sw): add get_active_tab_url popup handler 2026-05-01 16:57:18 -04:00
adlee-was-taken
6eeb292fd0 ext(affordances): seed shared/form-affordances/ + barrel test 2026-05-01 16:53:58 -04:00
adlee-was-taken
ef7bd5b848 refactor(ext/popup): renderFormHeader takes options object
Whole-branch review recommendation: switch renderFormHeader's signature
from positional (titleText) to options ({ titleText }) so Phase 3 can
add 'dirty' (and any future hooks like a save-keybinding hint) without
touching all 7 call sites in lockstep with the unsaved-guard work.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 14:33:29 -04:00
adlee-was-taken
1454cd8165 refactor(ext/popup): extract renderFormHeader + .form-header CSS
Code-review feedback on Task 8: the conditional empty
<div style="margin-bottom:16px;"> spacer was an inline-styled magic
number and the 6-line header pattern was duplicated across all 7 typed
forms.

Now:
- .form-header class owns the bottom margin in both stylesheets.
- :has(+ .form-subtitle) selector drops the margin when a subtitle
  follows, so spacing tokens stay in CSS instead of inline styles.
- renderFormHeader(titleText) shared helper collapses the 6-line
  duplication to a one-liner per form. item-form.ts (type-selection
  screen) is unaffected — it uses a different header structure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 14:26:16 -04:00
adlee-was-taken
381e8ed496 feat(ext): static 'esc to cancel' subtitle in fullscreen form headers
All seven type forms plus the type-selection screen now show a small
'esc to cancel' subtitle under the heading when rendered in the
fullscreen vault tab (isInTab() === true). The subtitle is suppressed
in the popup, where esc has the more general meaning of closing the
popup. .form-subtitle class is shared between popup and vault
stylesheets so future hooks can reuse it.

Dynamic dirty-state ('unsaved · esc to cancel') wiring is deferred to
Phase 3 (unsaved-changes guard).

Plan 2026-04-30 fullscreen UX phase 1 task 8.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 14:17:59 -04:00
adlee-was-taken
38ba31768a refactor(ext/test): extract TYPED_FORMS shared list for it.each tests
Code-review feedback on Task 7: the same Array<[name, renderForm]> of
all 7 typed forms appeared in three test files (required-pill,
popout-button, popout-button-fullscreen). A new typed form would have
required updating all three.

Now defined once in __tests__/_typed-forms.ts. Future typed-form
additions get regression coverage automatically.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 14:14:21 -04:00
adlee-was-taken
71ad91592d feat(ext/popup): hide popout-to-tab button in fullscreen forms
The ⤴ popout button is meaningless when the form is already in
vault.html — gate it on !isInTab(). Affects all seven type forms plus
the type-selection screen. Regression tests cover both popup (button
present) and fullscreen (button absent) contexts via it.each across
all 7 forms.

Plan 2026-04-30 fullscreen UX phase 1 task 7.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 21:01:47 -04:00
adlee-was-taken
05b1fae9f4 style(ext/popup): replace settings nav emoji with shared glyphs
▦ trash and ⌬ devices in the popup settings panel now match the
fullscreen sidebar's glyph language. Lowercased labels match the brand.

Plan 2026-04-30 fullscreen UX phase 1 task 6.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:57:00 -04:00
adlee-was-taken
e2260e9df4 style(ext/vault): replace sidebar emoji nav with monochrome glyphs
▦ trash · ⌬ devices · ⚙ settings · ⏻ lock — all imported from the new
shared/glyphs module so popup and fullscreen stay in sync. Regression
test scans the source for the old escape-coded emoji to prevent
backsliding.

Plan 2026-04-30 fullscreen UX phase 1 task 5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:53:50 -04:00
adlee-was-taken
a634b6c745 refactor(ext): broaden required-pill test + drop dead .label .req CSS
Code-review feedback on Task 4:
- Test expanded from login-only to it.each across all 7 type forms
  (14 assertions total). A future revert to <span class="req">*</span>
  in any form now fails CI.
- .label .req rule removed from popup/styles.css and vault/vault.css —
  zero consumers after the REQUIRED_PILL_HTML migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:52:26 -04:00
adlee-was-taken
e2381ed2ec refactor(ext/popup): migrate required-field markers to REQUIRED_PILL_HTML
Replaces ten <span class="req">*</span> sites across all seven type
forms with the shared REQUIRED_PILL_HTML snippet ('required' badge).
Adds a regression test pinning the new HTML in the login form.

Plan 2026-04-30 fullscreen UX phase 1 task 4.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:46:07 -04:00
adlee-was-taken
6e720554fa style(ext/vault): migrate .btn:focus to :focus-visible + var(--focus-ring)
Code-review feedback on Task 3: vault button focus was the last
hardcoded #d2ab43 + bare :focus rule not yet migrated. Brings vault
button focus into parity with popup (which Task 2 already migrated)
and removes the last raw accent literal from the focus-related rules.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:42:24 -04:00
adlee-was-taken
f0d8758a80 style(ext/vault): mirror color tokens, focus ring, required-pill class
Same :root block and .req-pill rule as popup/styles.css so the two
stylesheets share visual tokens. Vault input focus migrated to
:focus-visible + box-shadow ring.

Plan 2026-04-30 fullscreen UX phase 1 task 3.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:39:46 -04:00