Features
- attach buildable source to the AMO listed submission
- Firefox ships listed to AMO; GitHub release carries source only
- metadata:firefox pushes by default, --dry-run to preview
- metadata:firefox pushes the localized AMO listing
- translate web store listings (Chrome + AMO) from the repo
- passkey provider via MAIN-world content-script transport
- relay-forward transport as a negotiated WebRTC fallback
- Firefox WebRTC host iframe — probe increment (option a step 1)
- request persistent storage so the only vault copy isn't evicted (Firefox port, phase 5)
- float current-site matches to the top of the list
- search, filter, sort, and lifecycle timestamps for the vault list
- attach SHA256SUMS to chromium releases (parity with android)
- registration (create) + pending handoff (step 3)
- assertion flow - sign in with a stored passkey (step 2b)
- vault passkey read + W3C response JSON builder (step 2a)
- register a Credential Manager provider (skeleton)
- finalize Bramble AAGUID; TODO to register it in the community list
- make a freshly-created passkey usable without opening the app
- register (create) passkeys + persist via a pending handoff
- assert stored passkeys (sign-in) in the credential provider
- surface stored passkeys to the OS credential store
- passkey rows in the login item edit + view
- get-time passkey picker for multiple accounts
- confirmation toast when the provider saves a passkey
- account picker when saving a passkey to an ambiguous domain
- differentiate save-passkey card for an existing login
- pause passkey proxy during Bramble's own WebAuthn unlock
- Settings toggle for the passkey provider (General)
- save-passkey corner prompt + create/get wiring
- webAuthenticationProxy passkey handler (orchestration)
- passkey provider vault logic (find + placement)
- WebAuthn JSON helpers for the passkey provider
- expose passkey crypto through TS adapter + transports
- passkey authenticator crypto + entry model (provider role)
- black splash with Bramble logo lockup, no white flash
- full internationalization across all targets
- modality-aware copy in the biometric Settings row
- label biometric unlock by modality (Face ID vs Touch ID)
- enforce matching master password when enrolling a device
- add ios release lane (versioning + TestFlight, build-tagged)
- native iOS WebRTC data channel via webrtc-rs
- surface transport status + state for on-device diagnosis
- native sync crypto on Android too (uniffi handshake/nostr)
- native iOS sync crypto so pairing works under Lockdown Mode
- per-device remove (revoke) with roster propagation
- stop streaming transport status into the Settings log box
- pre-fill + space the ICE/relay settings; tolerate more ICE shapes
- TURN relay + state-aware device UI, with relay diagnostics
- add Android system AutofillService at iOS parity
- build, sign, and publish Android APKs via
release android - add Android app launcher icon
- source app version natively and add per-target version bumping
- add ios:metadata script; lane pushes screenshots when present
- target the project marketing version in the metadata lane
- iOS autofill domain filtering + QuickType opt-in
- Android native crypto (uniffi Kotlin NativeCrypto plugin)
- "Immediately" auto-lock option (mobile default) replaces keep-unlocked toggle
- opt-in "keep autofill unlocked" window (15 min, off by default)
- autofill authenticates before revealing entries; encrypt the bundle
- autofill master-password unlock in the extension + passcode cache
- native iOS crypto + real autofill provider via shared uniffi core
- set the iOS app icon from icon/ios
- auto-resolve JDK 21 for android run/dev scripts
- iOS autofill credential-provider probe (Phase 3 go/no-go: GO)
- hide security-key unlock on mobile; biometric takes its slot
- re-probe biometric availability when Settings opens
- native BiometricVault plugin (iOS + Android) + adapter
- device-local biometric unlock seam (optional Platform.biometric)
- secure-storage substrate; move sync device keypair to Keychain/Keystore
- buffer recent sync status so the panel shows current state on open
- ongoing roster sync (continuous merge after enrollment)
- show status log + explicit success message on join
- hide pop-out affordance (supportsPopOut capability)
- route Settings import to in-app ImportShell with close-to-app
- camera QR scanning (getUserMedia + jsQR) for sync pairing + TOTP
- wire P2P sync enrollment (in-webview, via @core/sync/transport)
- inactivity auto-lock honoring autoLockMinutes (not lock-on-pause)
- lock vault on app background (lifecycle pause)
- streamline vault setup screen (hide file-location, pill tabs, compact)
- in-app vault setup navigation + safe-area insets
- upgrade Capacitor 7 -> 8 (SPM iOS project)
- scaffold Capacitor platform-mobile POC (Phase 0 walking skeleton)
- cap message size and subscriptions per connection
- default to hosted relay, fold URL under Advanced
- cloudflare worker relay; reorganize into node/ + cf-worker/
- cross-device P2P vault sync, with architecture, crypto, and UX hardening
- build, sign, and publish releases locally for CWS verified uploads
- support logins inside open shadow DOM (web components)
- inject content script in all frames for iframed logins (e.g. Apple ID); add reddit fixture/tests + screenshot seed
- gate release on lint + tests so a failure blocks the release
- tag releases as - with " Extension " name
- tagged-release workflow + platform-aware version-bump script
- theme-aware monochrome icon, light/dark/system selector, and entry-detail header actions
- harden the autofill UI behind an extension-origin iframe
- replace placeholder Shield logo with Bramble glyph
- Chrome toolbar/install icons + icon source bundle
- KeePass KDBX4 import — key files + WASM-side decrypt
- webauthn unlock with hmac-secret + 26 crypto/policy tests
- corner-prompt save/update card for captured logins
- a login can cover multiple websites (url:string → urls:string[])
- show the OpenSSH SHA-256 fingerprint on SSH-key entries
- lock the vault when the OS locks the screen (idle.onStateChanged)
- declare a lock-vault keyboard command (unbound by default)
- import from 1password, bitwarden, keepass and proton pass
- harden TOTP autofill and skip auto-submit on captchas
- typed entry modes with cards, notes, ssh keys + custom-field autofill
- retain state on pop-out, react to background locks, ui polish
Bug Fixes
- set the AMO category on listed submissions
- set the GPLv3 license on listed AMO submissions
- resolve web-ext signed .xpi basename against artifactsDir
- pass amoBaseUrl to web-ext sign (8.x makes it required)
- close the unlock window after a locked passkey unlock
- wrap content scripts in an IIFE so they don't clobber each other's globals
- keep-alive alarm so background sync survives event-page suspension
- localize manifest via _locales (default_locale + MSG)
- Firefox testing round 1 (popup close, FSA/security-key/theme gating, sync log)
- set Firefox gecko id to firefox@bramble.app
- gate passkey provider off on Firefox (Firefox port, phase 4)
- preserve \n/\t escapes; escape stray quotes in it/es strings
- escape backslash in strings.xml encoder (CodeQL #30)
- sync screenshots instead of overwrite to stop duplicates
- replace deprecated kSecUseOperationPrompt with LAContext
- squash duplicate toasts (same message + variant)
- sign in with a single unlock (bridge list->sign)
- use a freshly-created passkey before the app drains it
- sign the browser-provided clientDataHash (fixes sign-in)
- empty save toast - use i18n._(msg
…) not the useLingui macro - rename usePendingPasskeys to .tsx so its lingui macro is transformed
- registration response needs response.publicKey (SPKI)
- set BE+BS backup flags on synced passkeys
- registration response needs authenticatorData + publicKeyAlgorithm
- attach a new passkey to the right account by username
- route background passkey crypto through the offscreen
- render the passkey card account row as markup, not text
- resolve passkey request origin from the active tab
- generate notes from conventional commits, not PRs
- skip keychain access group on iOS Simulator for biometric VEK
- run build-crypto-ffi.sh under the macOS system bash (3.2)
- release script
- hide security-key pairing option on mobile
- native iOS QR scanner for pairing/TOTP codes
- clean up helper copy and gate platform-specific rows
- trim App Store subtitle to the 30-char limit
- harden QuickType identity-store population
- flatten the 1024 marketing app icon (remove alpha)
- fastlane uses a monotonic timestamp build number (race-free)
- keep-autofill-unlocked window reuses the auto-lock timeout
- autofill unlock shows the device's biometry (Face ID / Touch ID) + passcode
- autofill UI matches the app auth screen + list (logo, card, padding)
- autofill biometric via Keychain prompt + visible error alerts
- autofill persists while locked, app-styled list, biometric hint
- autofill App Group JSON + extension Face ID, fastlane internal DerivedData
- add AutoFill entitlement to the main app target (App Store validation)
- inset safe area at #root so screens keep their own padding
- lock viewport scale to stop WKWebView rendering content off-screen
- sort imports to satisfy
biome ci - re-tag an already-bumped version instead of failing on an empty commit
- disable happy-dom resource loading so fixture fetches don't fail CI
- clear unconditionally instead of reading it back
- cap untrusted KDBX Argon2 params to prevent OOM/hang on import
Performance
- lazy-load jsqr to halve the service-worker bundle
- code-split the import flow into an on-demand chunk
Refactors
- transport-select the crypto+sync host (Firefox port, phase 2)
- cross-browser
apishim for chrome.* (Firefox port, phase 1) - split vault context into state + actions; share prefs provider
- centralized reusable Toast (success/error/info)
- rename packages/crypto-wasm to packages/core-rust
- resolve the Keychain team prefix at runtime
- dedupe shared autofill identifiers + tidy native plugins
- SwiftUI autofill UI styled from the app design tokens
- share the wasm->CryptoAdapter mapping via buildCryptoAdapter (mobile + offscreen) + unit test
- hoist VaultCrypto type to @core/wasm; split mobile vault-session lifecycle off the crypto adapter
- extract EntriesBlobStore as the one entries-format writer; build VaultSyncPort over it
- move pure P2P transport/host modules from extension to core
- rename manifests/chrome dir to chromium for accurate cross-browser naming
- move content-only detection into content/
- rename folder entry index.ts to match its folder name
- move entries into background/ and content/, point vite at them
- decompose content-script into concern modules under content/
- split background into concern modules under background/
- replace onMessage if-chain with a typed handler registry
- extract card-brand and ssh key-type helpers to util
- lean on tanstack router for route guards + ui fixes
Documentation
- Firefox ships listed on AMO (release-signing + firefox-port)
- current state (passkey verified, i18n done); export/import is what's left
- add Status section + specifics for passkey provider & security-key unlock
- mark relay-forward hardening implemented (timeout, reaper, epoch room, padding)
- decide relay-forward transport + privacy hardening
- correct the WebRTC-in-event-page assumption (RTCPeerConnection absent in FF background)
- fix Vivaldi typo; move file attachments + iframe/shadow-DOM autofill to shipped
- broaden README to mobile + passkeys, add passkeys to iOS store metadata
- correct passkey + P2P sync findings
- Android provider built (assertion + registration), compile-verified
- Android dep check — androidx.credentials is Play-Services-free
- mark iOS provider device-verified (register + sign-in on webauthn.io)
- document the seamless-create refinements (foreground drain + immediate-use bridge)
- mark iOS provider built (assertion + registration + handoff)
- record the device-verified registration-response field set
- spec item edit (passkey row below TOTP + remove) and view badge
- update phased route with shipped status
- plan passkey-provider role across extension + mobile
- native iOS WebRTC sync, ipa slimming, Android autofill done
- mark TURN, configurable relays, and device management as built
- update privacy policy for iOS app + P2P sync
- add Bramble support page + set App Store privacy/support URLs
- record build 204423099 (iOS autofill filtering + QuickType opt-in)
- iOS autofill working on device; refresh status + next steps
- refresh 'Next steps' handoff after autofill confirmation
- autofill confirmed end-to-end on real hardware (TestFlight)
- autofill probe confirmed on real device (OS discovers the provider)
- iOS Lockdown Mode disables JIT -> WASM crypto fails on device
- add a consolidated 'Next steps (where to resume)' section
- record iOS verification, security-key hiding, mobile test harness
- record biometric unlock (OS-gated) in port plan + dev guide
- bring mobile-port.md up to date with what's built (status, plan markers, answered questions)
- TODO for device management UI + revocation
- add development guide + sim:reset script
- add README with run instructions and live-reload gotcha
- switch mobile-port plan from Tauri to Capacitor
- add security policy and point README to it
- note Firefox storage.local durability (unlimitedStorage, uninstall, eviction)
- add P2P device-to-device vault sync design
- add Firefox-port feasibility findings
- disclose the optional HIBP breach check; tighten wording
- collapse to a single unstyled privacy-policy page
- add static site to host the Web Store privacy policy
- add design docs and function docblocks
- PLAN — multi-URL logins and the legacy-url normalizer
Other
- i18n(store): Firefox listing translations (de hand-polished, es/fr/it/pt-BR first pass)
- i18n: translate the content-script UI via _locales + browser.i18n
- i18n: translate the 12 missing vault-list strings (de/es/fr/it/pt-BR)
- polish(ext): explain what unlocking is for on the locked passkey card
- polish(ext): passkey rows act on click; chevron instead of checkmark
- polish(ext): passkey card — Bramble glyph, account list, gradient bg
- polish(ext): passkey corner card gets a key-glyph badge in the header
- chore: reconcile pnpm-lock after rebase onto main
- build(release): firefox bundle + AMO-signed .xpi release pipeline
- harden(sync): epoch-rotating sync room so the relay can't link a group across time
- harden(sync): reap stale relay peers (liveness for the connectionless transport)
- harden(sync): relay-forward handshake timeout + payload size padding
- chore(ext): remove throwaway FF WebRTC-context probes + sync-frame iframe
- chore(ext): probe content-script + page-main-world WebRTC contexts (Firefox)
- chore(ext): surface an RTCPeerConnection probe in the Device-sync panel (Firefox diag)
- build(ext): output Chromium build to dist-chromium (symmetry with dist-firefox)
- chore(ext): rename build/bundle -> build:chromium/bundle:chromium
- build(ext): Firefox manifest + TARGET build wiring (Firefox port, phase 3)
- chore(ios): make app iPhone-only (drops 13-inch iPad screenshot requirement)
- chore(ios/metadata): add 7th App Store screenshot, reorder to sequence
- i18n(extension): localize manifest description + lock command via Chrome _locales
- chore(i18n): translate passkey strings (web catalogs + iOS String Catalog)
- test(extension): cover the passkey ceremony flow (incl. the account picker)
- i18n(passkeys): extract + compile the passkey provider setting strings
- chore(ios): add App Store screenshots (en-US, 6.5")
- test(core-rust): serialize the global-VEK-slot round-trip tests
- build(ios): drop webrtc from the autofill extension binary
- chore(settings): hide debug sync status log
- chore(mobile): set App Store category to Productivity / Utilities
- chore(mobile): manage App Review info in ASC, not fastlane
- chore(mobile): optimize App Store subtitle + keywords (no title overlap)
- chore(mobile): scaffold App Store Connect metadata (en-US) + deliver lane
- chore: update .gitignore to ignore app bundles
- chore(mobile): commit shared Xcode schemes, gitignore android .idea
- chore(mobile): fastlane lanes for iOS TestFlight + IPA builds
- chore(mobile): declare ITSAppUsesNonExemptEncryption=false
- test: stand up mobile test harness + cover biometric paths
- style(mobile): inset setup pills from edges + black active border
- style(mobile): full-width, larger Create vault button
- style(mobile): wider pill gap + thicker active border on setup tabs
- chore(mobile): auto-target newest iPhone sim for cap run (skip picker)
- chore(mobile): make dev:* the live-reload scripts, bundled run under run:*
- chore(mobile): rename mobile:build script to core:build
- chore(mobile): add live-reload dev scripts
- build(mobile): commit generated iOS + Android native projects
- test: migrate DOM test environment from happy-dom to jsdom
- build(deps): bump esbuild, ws, wrangler for security advisories
- ci: set least-privilege GITHUB_TOKEN permissions
- chore(lint): migrate biome config to 2.5.0 and apply safe fixes
- build: block commits/releases on type errors (pre-commit + release gate)
- chore(build): migrate from bun to node/pnpm
- chore(dev): local/CI lint parity hook + bump to Node 24 LTS
- add web store link
- chore(fixtures): repassword kdbx imports to 123456, add keyfile variant, fix key-file label spacing
- chore: add tag:delete script to remove a tag locally and from all remotes
- chore(biome): exclude import fixtures folder
- test(fixtures): add sample import files for every supported provider
- release: set extension version to 1.0 for the initial Web Store submission
- build(ext): add 'bundle' script (build + zip dist to bramble.zip)
- ci: deploy only website/ to GitHub Pages via Actions
- style(manifest): biome-format permissions array (one line after activeTab drop)
- chore(manifest): drop redundant activeTab, add use_dynamic_url to WAR
- test(crypto): add an ignored benchmark for the vault Argon2id cost
- test(bg): move the chrome-mock harness to src/test/
- test(bg): add handler unit tests for the background modules (73 tests)
- update readme
- ci: exclude vendored icon/ export from biome
- add monero qr code image
- style: biome format fixes for ci
- recovery codes, optional master password, and settings cleanup
- test: extract detection helpers, add 10 real-world site fixtures, fix bmo card-vs-login bug
- ci: pin wasm-pack version and cache cargo deps between runs
- ci: pin Rust to rust-toolchain.toml and add a WASM verify gate
- brand: rename app to Bramble
- chore: centralize the user-facing brand on the manifest, swap Vault→Titanpass
- ui: show real extension version in Settings (was hardcoded 0.0.1)
- security: make HIBP breach check opt-in, with a clearer disclosure (L6)
- security: stop persisting the decrypted autofill index (M2)
- security: gate every autofill on user focus, never on page load (M1)
- chore: prune unused shadcn/Radix UI scaffold and supporting deps (M6b)
- data-integrity: snapshot-and-recover writes + verify-after-rotate (H1, H2)
- security: quick-wins audit batch (M3, M4, M5, M6a, L2, L3, L4, L5, L7)
- move to multi-key vault slots, full rotation on password change
- wire settings, clipboard auto-clear, hibp checks, per-entry overrides
- add crud elements and manage window size
- update plan
- implement autofill in website fields
- implement vault crypto, vault creation and loading
- set up fe arch: screens, router, rhf
- wire up ui
- initial commit