Root cause: when importing an encrypted sync code from another device,
_decryptFromSync was replacing the local encryption config (salt) with
the source device's salt. This caused:
1. Local key cache derived from wrong salt
2. Local data (encrypted with local salt) became unreadable
3. _applyData tried to write with the wrong key
Fixed with a complete refactor of cross-device decryption:
- authenticateForSync() derives a TEMPORARY key using the source salt
- Temporary key stored separately as 'tempSyncKey' in IndexedDB
- Local encryption config and cached key are NEVER modified
- After decryption, _applyData writes via _writeSecure using the
LOCAL key (which uses the local salt)
- _handleDecryptedMeta extracted for code reuse
Also:
- Options.js auth handler detects pending sync import and routes to
authenticateForSync instead of regular authenticate
- After auth success, automatically retries the import
- README updated: imported passwords are protected (dots in UI,
vault password to reveal, AES-256 encrypted at rest)
- Bumped to v2.0.9
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
ChatGPT (and potentially other AI services) calls fetch() with a
Request object as the first argument: fetch(new Request(url, opts))
instead of fetch(url, opts). The interceptor only handled the second
form, so ChatGPT's conversation requests passed through unmodified.
Fixed by handling both fetch signatures:
- fetch(url, options) — existing path
- fetch(Request) — new: extracts URL, method, headers, reads body
via request.text() for JSON/text content types
Also handles non-string body types:
- Blob → text via blob.text()
- ArrayBuffer → text via TextDecoder
- URLSearchParams → string via toString()
These cover the various ways modern frameworks call fetch().
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
Set Chrome, Firefox, and package.json all to version 2.0.0
(major bump reflecting encrypted storage, document scanning,
org/team features, sync improvements).
Sign script rewritten:
- Tries current version first instead of always bumping
- Only bumps on "version already exists" errors
- Handles rate limiting by parsing throttle duration from error
and waiting the exact time (not blindly retrying)
- Only updates source files on successful signing (not before)
- Reduced max attempts to 5 (with proper backoff, shouldn't need more)
- Commits version bump only after successful sign
https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
License: Changed from MIT to BSL 1.1. Free for personal use,
commercial use requires a paid license. Auto-converts to MIT
on March 26, 2030.
Export/Import: Options page now has "Transfer Data" section:
- Export All (plain) — JSON file with all identities, mappings, settings
- Export Encrypted — AES-256-GCM with PBKDF2 password derivation,
saved as .ssbackup file
- Import — handles both plain and encrypted backups, prompts for
password if encrypted
Crypto uses Web Crypto API (browser-native, no dependencies):
100k PBKDF2 iterations, random salt + IV per export.
https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
Add LICENSE file (MIT). Explain in README that reveal mode is a
local display change only — the AI never received the real data.
Reveal exists so users can copy paths/commands from AI responses
and paste them directly into their terminal without manually
translating fake values back to real ones.
https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
Identity fields now support multiple entries per type:
- Add unlimited names (first, last, middle, nickname), emails,
usernames, hostnames, and phone numbers per profile
- "+ Add" button on each section, "x" to remove rows
- Names have a type selector (1st/Last/Mid/Nick)
README now includes:
- First-time setup walkthrough (step by step)
- Icon color legend (gray/black/blue/red)
- Keyboard shortcuts table
- Note that extension does nothing until configured
Also bumps version to 0.3.0 for Firefox re-signing.
https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
The previous approach (source .env && npm run sign:firefox) failed
because npm subshells don't inherit env vars consistently, and
quoted values in .env weren't being stripped.
New approach: sign-firefox.sh reads .env itself, strips quotes,
and passes --api-key/--api-secret directly to web-ext sign.
Also renames web-ext-config.js → web-ext-config.cjs to fix the
deprecation warning, and bumps package.json version to 0.2.0.
https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw
Add package.json with web-ext dev dependency and npm scripts for
building, linting, signing, and running the Firefox extension.
Signing produces a self-hosted .xpi that persists across restarts
without needing the Mozilla store.
https://claude.ai/code/session_01Dvgwe7XMoSxnWXkih8p1Cw