From 5089c2b7ea18cff1430bb2cd6879b5ce790742bd Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Mon, 27 Apr 2026 02:13:26 -0400 Subject: [PATCH] docs: vault tab UI + session timeout design spec Co-Authored-By: Claude --- .../2026-04-27-relicario-vault-tab-design.md | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md 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 new file mode 100644 index 0000000..d6c1729 --- /dev/null +++ b/docs/superpowers/specs/2026-04-27-relicario-vault-tab-design.md @@ -0,0 +1,154 @@ +# Vault Tab UI + Session Timeout — Design Spec + +**Date:** 2026-04-27 +**Scope:** New `vault.html` full-tab UI, shared session timeout, popup↔vault navigation + +## Problem + +Chrome extension popups close when focus leaves them (e.g., file picker dialogs). The popup is also too cramped for complex operations like editing identity/card items, managing attachments, or bulk vault operations. Currently we work around this with `popOutToTab()` which opens `popup.html` in a tab — a hack that reuses popup-sized UI in a full window. + +Additionally, there's no session timeout — users must re-enter their passphrase every time they interact with the extension. + +## Design + +### Two entry points, one shared core + +- **`popup.html`** — quick access: search, copy, autofill, add login/secure_note (without attachments) +- **`vault.html`** — full "desktop" UI in a browser tab: sidebar + detail pane, handles everything including attachments, bulk operations, trash, devices, settings, field history + +Both talk to the same service worker, share the same WASM session handle and unlock state. + +### vault.html layout + +Sidebar + detail pane, similar to 1Password's desktop app: + +``` +┌──────────────────────────────────────────────────┐ +│ 🔒 relicario [lock] [settings] │ +├────────────────┬─────────────────────────────────┤ +│ [search...] │ │ +│ │ (detail view for selected │ +│ ── logins ── │ item, or form when │ +│ GitHub 🔑 │ adding/editing) │ +│ AWS 🔑 │ │ +│ │ │ +│ ── notes ── │ │ +│ Recovery 📝 │ │ +│ │ │ +│ │ │ +│ │ │ +├────────────────┤ │ +│ 🗑 trash │ │ +│ 📱 devices │ │ +│ ⚙ settings │ │ +└────────────────┴─────────────────────────────────┘ +``` + +- **Left sidebar (~240px):** vault name/lock status at top, search input, item list grouped by type, nav links at bottom (trash, devices, settings) +- **Right pane:** detail view for selected item, or add/edit form. Empty state when nothing selected. +- URL hash tracks current selection (`#item/abc123`, `#add/login`, `#trash`, etc.) for browser back/forward + +### Session timeout + +Lives in the **service worker**, not in any UI. Shared across popup and vault tab. + +**Timer logic** — new `session-timer.ts` module alongside existing `session.ts`: +- Holds a `setTimeout` ID, reads config from `chrome.storage.local` +- Resets on every message routed through the SW (any popup or vault tab interaction) +- When it fires: calls `clearCurrent()` to zero the WASM handle, then broadcasts `{ type: 'session_expired' }` via `chrome.runtime.sendMessage` +- Both popup and vault tab listen for this broadcast and show the lock screen + +**Config shape** in `chrome.storage.local`: +```json +{ "session_timeout": { "mode": "inactivity", "minutes": 15 } } +``` +or: +```json +{ "session_timeout": { "mode": "every_time" } } +``` + +Default: `{ mode: 'inactivity', minutes: 15 }`. This is a **per-device setting** (stored in `chrome.storage.local`, not in the encrypted vault) since different devices have different risk profiles. + +**UI for timeout config:** In a "device settings" section, a simple toggle: +- "Lock after inactivity" with a minutes dropdown (5, 15, 30, 60) +- "Lock every time" (current behavior) + +Changing the setting sends an `update_session_config` message to the SW which immediately applies the new timer. + +### Navigation between popup and vault + +**Popup → vault:** +- "Open vault" link on the lock screen and item list toolbar +- `Shift+F` keydown listener in popup — opens/focuses the vault tab +- When navigating from popup with context (e.g., viewing an item), pass item ID via URL: `vault.html#item/abc123` +- `popOutToTab()` now redirects to `vault.html` instead of `popup.html` for types that need it + +**Global shortcut:** +- `chrome.commands` manifest entry (default unbound, user configures in `chrome://extensions/shortcuts`) +- SW listener opens or focuses existing vault tab + +**Vault → popup:** +- Not needed — vault tab is the superset + +### Shared components + +Form renderers (login, secure-note, identity, card, key, totp, document), field helpers, attachments disclosure, generator panel are currently in `popup/components/`. These get moved to `shared/components/` so both entry points can import them. + +The popup wrappers conditionally hide attachments (via `isInTab()`); the vault versions always show everything. + +### Keyboard shortcuts + +| Key | Context | Action | +|-----|---------|--------| +| `/` | Popup list, vault sidebar | Focus search | +| `+` | Popup list, vault sidebar | New item | +| `↑↓` | Popup list, vault sidebar | Navigate items | +| `Enter` | Popup list, vault sidebar | Open selected item | +| `Escape` | Popup | Close popup | +| `Escape` | Vault form/detail | Back to list | +| `Shift+F` | Popup | Open/focus vault tab | +| Global | Anywhere in Chrome | Open/focus vault tab (user-configured) | + +### New files + +``` +extension/ +├── src/ +│ ├── vault/ +│ │ ├── vault.ts # Entry point, state management, hash routing +│ │ ├── vault-shell.ts # Layout container, sidebar/pane split +│ │ ├── vault-sidebar.ts # Search, grouped item list, nav links +│ │ └── vault-pane.ts # Detail/form/settings renderer +│ ├── shared/ +│ │ └── components/ # Moved from popup/components/ +│ │ ├── types/ # login.ts, secure-note.ts, etc. +│ │ ├── fields.ts +│ │ ├── attachments-disclosure.ts +│ │ └── generator-panel.ts +│ ├── service-worker/ +│ │ └── session-timer.ts # Inactivity timeout logic +│ └── popup/ +│ └── components/ # Thin wrappers that import from shared/ +├── vault.html # New entry point +└── vault.css # Vault-specific layout styles (imports shared) +``` + +### What stays in popup + +The popup keeps its stacked-view navigation and compact layout. It imports form/detail components from `shared/` but wraps them in popup-specific chrome (back buttons, condensed headers). Login and secure_note forms render inline in the popup (without attachments); all other types redirect to `vault.html`. + +### Messages + +New message types: +- `update_session_config` — popup/vault → SW, updates timeout settings +- `get_session_config` — popup/vault → SW, reads current timeout settings + +New broadcast: +- `session_expired` — SW → all extension views, triggers lock screen + +### Out of scope + +- Grouping/tagging/export features (future work, mentioned as eventual goal) +- Mobile-style responsive layout for vault tab +- Theme customization +- Multi-vault support