fix(web): a claim closes one heir's share, not the whole vault - #351
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
One owner email and one owner key make one vault. Every row under it is
one heir's share, with its own descriptor, address, funds and timelock.
The UI had been treating a row as the whole vault, which made a single
heir's claim look like the end of everything.
Three fixes:
- The claimed card no longer says "This vault's work is done" and no
longer offers a Done button that hid the share. It names the heir
("Fola's share is claimed") and says the other shares are unaffected.
The share stays visible until the owner removes that heir.
- Sign-in lands on the oldest share. The recovery bundles are sorted by
created_at (id as tiebreak) before they are written, so "the first
heir" means the one set up first rather than whatever order the
server returned.
- getAllVaultMetas() sorts the same way. It was returning
Object.values(), which is storage insertion order, not creation
order. That was the root of the landing bug, and it disagreed with
getVaultsByGroup, which already sorted. Three tests cover it.
The empty-state button now says "Set up a vault", which is the only
thing that route has ever done. "Add an heir" needs the server to keep
the owner row when the last heir is removed, so it comes back with that
change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Jolah1
force-pushed
the
fix/vault-means-account
branch
from
August 19, 2026 14:34
afd988e to
fae17a3
Compare
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.
The problem
One owner email and one owner key make one vault. Every row underneath it is one heir's share, with its own descriptor, address, funds, timelock and claim link. The server already works this way (see the
prevent_conflicting_verified_owner_emailtrigger, which allows rows to share an owner email as long as they carry the same owner key).The UI did not. It treated a row as the whole vault, so when one heir claimed, the owner was told the vault's work was done and handed a button that hid the share, even with three other heirs still waiting.
What changed
A claim closes one share.
VaultClosedCardno longer says "This vault's work is done" and no longer has a Done button. It names the heir, and when there are siblings it says the other shares are unaffected. The share stays on screen marked claimed, and only leaves when the owner removes that heir. The dismiss handler and the now-unreachable"closed"empty reason went with it.Sign-in lands on the oldest share.
openGroupsorts the recovery bundles bycreated_at(id as tiebreak) before writing them. "The first heir" now means the one set up first, not whatever order the server returned. It still skips claimed shares and lands on the next live one.getAllVaultMetas()sorts the same way. It was returningObject.values(), which is storage insertion order, not creation order. That was the root of the landing bug, and it silently disagreed withgetVaultsByGroup, which already sorted. Three tests cover ordering, the agreement between the two functions, and the id tiebreak.The empty-state button tells the truth. It offered "Add an heir" or "Set up a vault" depending on why the screen was empty, but both went to
"setup", which is full new-email account setup. It now says "Set up a vault" in both cases.Not in this PR
"Add an heir" cannot be made real from the client.
PasswordSetupPortalalways mints a freshgroupId, andapi.deleteVaultdrops the row that carries the owner's email, key and verified status, so removing the last heir deletes the account. Once the server keeps that row and clears the heir fields instead, the second button comes back with a route that joins the existing vault.Testing
npx tsc --noEmitcleannpm run lintcleannpx vitest run125 passed, 16 files (was 122)🤖 Generated with Claude Code