Public Access
Move the shelf as well as what is on it, and ask what a deletion takes
Two things about a group, and they turn out to be the same argument twice. **A group can be moved to another vault, and it takes everything on it.** The host's move shipped last week and stopped one level too low: moving twenty machines into a shared vault meant twenty trips through a menu, and each one arrived stripped of the group it had been filed under, so the shelf had to be rebuilt by hand on the other side. Moving the shelf is what people were attempting. MOVE sits between EDIT and DELETE over the group cards, and on the card's own menu above the separator DELETE is below — the same place, and the same reasoning, as the host pane's ⋯ entry. **The whole subtree goes, and taking less was never coherent.** A group's children are items of the vault it is leaving, so a parent moved alone leaves them naming a tombstone and they surface as roots in the vault the user has just emptied: half a shelf here and half there, from one gesture that said "move this". The hosts are the same argument and are the half the request was about. The groups go first, top down, and the hosts last. Each item is re-sealed under the destination's key and takes a new id — VaultItemRepository.MoveAsync, which HostGroupRepository now exposes — so nothing pointing at a group can be written until that group has landed and its new id is known, and a child's parent must already be over there. What an interruption leaves is therefore hosts still in the vault they started in, under UNGROUPED: visible, and re-movable. The reverse order would leave hosts in the destination filed under nothing. The parent stays behind and the tags are dropped, which is the host move's rule one level up: both are items of the vault being left, so a reference carried across would resolve on the machine that moved it and dangle for everybody else in the destination. The moved group arrives at the top level, and the panel says so before the press rather than the status line saying it after. Keys and passwords are kept — those genuinely resolve across vaults, and clearing them would take a working host and make one that cannot connect — and any now outside the destination is named, because that is precisely what the other members of it will not be able to resolve. Refused as a whole where anything under the group was written by a newer client, rather than skipped item by item: a move that left behind what it could not re-encode would file some of the shelf in one vault and the rest in the other, which is the state this exists to prevent. Refused with a host editor open, as the drop gesture is, because it rewrites hosts. And the walk carries a visited set, for the reason every walk over this tree does: a group that is its own parent — which two offline clients can build and no editor was ever shown — would otherwise be appended to the move list for as long as there was memory. **Deleting a group now asks what should become of the hosts under it, and that reverses a decision this repository had written down.** The deletion did not touch them: the reference was left dangling, the list resolved it to nothing, and the machines turned up under UNGROUPED. That was right for one of the two things people delete a group for and wrong for the other — a heading being tidied away should leave its machines alone, and a project that has been decommissioned is a shelf and everything on it — and nothing in the code can tell which of the two it is looking at. So it is asked. A tick rather than a pair of options, because the two answers are not equally weighted: keeping the hosts is recoverable and deleting them is not, so the safe answer is the one that needs no decision. It is off on every question, including the one that disarms it, or a tick left standing would destroy the next group's machines on the strength of a decision about the last one's. Once the deletion knows which hosts it means, leaving them naming something that has gone is a state kept for no reason, so the unticked answer writes too: N hosts with the reference cleared, where the ticked one writes N tombstones. That is the N writes HostGroupRepository refuses to hide behind a DeleteAsync overload, made where somebody asked for them and where the count is on screen first. The nested groups take the deleted group's place in the tree rather than being orphaned to the top level. A read-only host is skipped, counted and named, because unfiling it would re-encode a payload this build cannot represent — and the cost of skipping is a dangling id, which every reader here already survives. **Both are the desktop's alone**, and that is not an omission. The phone draws groups as headings in the host list and has never had a way to delete or move one; the two panels take the row of buttons over the group cards, and there is no such row on a 360dp screen to take. One test had to change its premise rather than its assertion. EditingAHostWhoseGroupIsGone built its dangling reference by deleting the group, which now unfiles instead — so it imports a host naming an id nothing resolves, which is what a group deleted on another machine actually looks like and is the only way that state still arises. The picker's placeholder is still needed and still covered. Four places said an item could not be moved between vaults. Two were about a group and were true when written; the other two were left stale by the host's move. All four now say what is true, including the design gaps document, where the chevron beside the vault name stays undrawn for the reason it already had.
This commit is contained in:
@@ -352,6 +352,24 @@ vault it is leaving. A picker inside the form would do all of that as a side eff
|
||||
What a move cannot do is reach a machine that has already synced the host, which is the same limit
|
||||
everything else about revocation has. Keys, passwords and buckets take theirs from a standing "new items go
|
||||
to" picker on the Keychain screen and cannot be moved yet.
|
||||
|
||||
**A group can be moved too, and it takes its contents with it** — MOVE beside EDIT and DELETE over the group
|
||||
cards, or "Move to another vault…" on the card's own menu. That is the desktop only, because the phone draws
|
||||
groups as headings in the host list and has never had a way to delete or move one. It is the same re-seal
|
||||
and tombstone underneath, applied to every item involved: the group, the groups nested inside it, and every
|
||||
host filed under any of them, each taking a new id in the destination. Moving less than that was never
|
||||
coherent — the machines and the child groups are items of the vault the group is leaving, so a group that
|
||||
travelled alone would leave half a shelf behind. What stays is the group it was itself nested under, which
|
||||
belongs to the old vault, so it arrives at the top level; the hosts' tags stay for the same reason. Keys and
|
||||
passwords are kept, because those genuinely resolve across vaults, and the sentence afterwards names any
|
||||
that are now outside the destination.
|
||||
|
||||
**Deleting a group asks what should become of the hosts under it.** The default answer keeps them: the
|
||||
reference is cleared and they move to UNGROUPED. Ticking the box deletes them with it. Both answers are a
|
||||
change — the deletion used to leave the hosts holding an id that no longer resolved, which looked the same
|
||||
and cost nothing, and stopped being the right shape once the deletion could take them with it. A group with
|
||||
nothing filed under it is not asked. Whichever answer is given, the groups nested inside take the deleted
|
||||
group's place in the tree rather than being orphaned to the top level.
|
||||
Both default to your personal vault and neither moves on its own, because an item put in a shared vault is
|
||||
visible to everybody holding that vault's key. Choosing a vault in the host editor also decides which groups
|
||||
it can be filed under: a group is an item like any other and lives in exactly one vault.
|
||||
@@ -598,6 +616,16 @@ keychain plus a terminal — and the spike that gates all of it.
|
||||
than to a shell that never opens. Given a walk that had to be cycle-safe anyway, refusing to nest bought
|
||||
nothing.
|
||||
|
||||
Membership living on the host has one further consequence, and it took two goes to settle. Deleting a
|
||||
group could not clear it without rewriting every host under the heading, so at first it did not: the hosts
|
||||
kept an id that resolved to nothing and turned up under UNGROUPED, which reads identically and costs no
|
||||
writes. That held until the deletion had to be able to take the hosts *with* it — a group is sometimes a
|
||||
heading being tidied away and sometimes a project that has been decommissioned, and nothing in the code can
|
||||
tell which. Once a deletion knows which hosts it means, leaving them naming something that has gone is a
|
||||
state kept for no reason, so both answers now write: N deletions, or N hosts with the reference cleared.
|
||||
The dangling case still has to be survived everywhere it is read, because a group deleted on *another*
|
||||
machine arrives exactly that way.
|
||||
|
||||
Inserting a snippet types it at the prompt and stops. Pressing Enter is a per-snippet decision, off by
|
||||
default, and the reason is worth stating: a terminal is one input stream with no notion of being at a
|
||||
prompt — the remote may be in an editor, or at a password prompt with the echo off — so this client cannot
|
||||
|
||||
Reference in New Issue
Block a user