Redesing Autofill setup and key storage#14
Merged
Merged
Conversation
window.open from a PWA standalone window was opening URLs in a new standalone PWA context, causing scheme-less URLs like "paperlesspost.com" to resolve relative to the PWA base path instead of opening in the browser. Adding 'noopener,noreferrer' severs the opener relationship so Chrome treats the new window as an independent browser tab. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Request readwrite permission explicitly in showOpenFilePicker and requestPermission calls. On Android, createWritable() requires write permission to be granted upfront — it cannot silently prompt the way desktop Chrome does. Falls back to read permission if readwrite is denied, preserving read-only vault support. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove legacy unauthenticated popup postMessage handler (hello/query
via window.opener) that bypassed delegate verification entirely; the
same-profile BC flow with ECDSA auth is the only supported path now
- Fix same-profile BC hello: import ECDH key from signed msg.ecdhSpki
(SPKI) instead of unsigned msg.pubkey (JWK), closing the key-binding
gap where an attacker could substitute their own ECDH key
- Fix cross-profile switchboard signatures: extend canonical signed
payload from {url,nonce,ecdh,ts} to include msgType, uuid, vaultUuid,
and query so a compromised relay cannot redirect operations or swap
target records after signature verification
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…value Track OriginalName in JS custom field state and use it in Go's lookup so a name change doesn't break the match against the stored field value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The short-header guard checked fieldStart > len(records) (needs 1 byte) but the next two slices need 5 bytes. Match the fieldStart+5 guard already used by UnmarshalHeader, and add a regression test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For both saveRecord and deleteRecord, conflict detection was running after WASM memory and UI state were already mutated. Cancelling the dialog left the edit/delete silently stranded in WASM — a later save would apply it on top of the external change the user chose not to overwrite. Also fixes web+portpass intent URLs being replayable indefinitely by enforcing the same 60s freshness window used in the switchboard WebSocket path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
saveSvAndBack() was updating WASM and the in-memory store but never writing the vault file. Add onsvdbsave callback (parallel to ondbsave for primary vault) that Dashboard implements via saveSecondaryDBFields, which serialises and writes the secondary vault after a metadata save. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
saveFile() now returns true on an actual write or download, false on conflict cancellation, AbortError, or write failure. saveDBFields() guards clearing vaultDirty and showing "Vault info saved" on that return value, so a conflict cancel or permission denial no longer falsely marks the vault as clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Go's writeToClipboard and copyTOTP called navigator.clipboard.writeText and ignored the returned Promise, so clipboard rejections were silently swallowed and the UI reported success regardless. Move the async write to JS: WASM now returns the plaintext value as JSON, and the wasm.js wrappers (copyFieldToClipboard, copyCustomFieldToClipboard, copyTOTP) are now async and own the await so rejections propagate to callers. Dashboard await-s all three call sites; tests updated to match the new raw-WASM API contract. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Five timestamp fields (headerLastSave, recordCreateTime, recordAccessTime, recordPasswordExpiry, recordModTime) called binary.LittleEndian.Uint32 without first checking len(data) >= 4, allowing a valid-password corrupted vault to panic rather than returning a clean error. Guards now match the pattern already used for Version, UUID, DoubleClickAction, ProtectedEntry, and PasswordExpiryInterval. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
randomFrom() and cryptoShuffle() used Uint32 % n which gives a slight bias toward low indices when 2^32 is not divisible by n. Replace with rejection sampling via unbiasedBelow(n): values in the biased tail [floor(2^32/n)*n, 2^32) are discarded and redrawn. Expected extra draws per call is less than one, and pools are small enough that the limit computation is exact in 64-bit JS arithmetic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Selection, keyboard navigation, copy-on-tap, context menu, and auto-expand all used UUID alone to identify records. With UUID collisions across simultaneously-open vaults the wrong vault could be targeted. Fixes all functional paths; clipboard drain animation (cosmetic only) still matches on UUID alone as that requires a separate change to clipboardContext. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
lockVault/lockAllVaults now clear selectedFile, dbItems, clipboard session/context,
and cancel the pending clipboard timer before calling onclosed(). Prevents stale
vault UUID from being used by App.svelte's handleIntent after lock.
Fix keyboard test: after openVault a recent handle is stored in IDB, so locking
returns to the re-unlock UI ("Vault is locked" + Master password field), not the
fresh "Open vault file" screen. Check for the password field instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UnknownFields was map[byte][]byte in both header and Record, so a second field with the same type ID silently overwrote the first. Changed to []unknownField to preserve all occurrences in the order they appear in the file, matching the forward-compatibility intent. Marshal now emits them in that same order rather than sorted-by-key. Adds a header test for the duplicate case; updates the existing single unknown-field test to use the new struct accessor. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Redesigns the vault sheet autofill setup so same-profile and cross-profile setup are presented as parallel option cards.
SIMPLESTfor same-profile andMOST ISOLATEDfor cross-profile.Pair everyday profile.Check tokenstep.