Making an identity
Identities live in Settings, in a section of their own. Each row has a colour picker, the name typed in place, a "Default" mark or a "Make Default" link, and a remove button. Under the rows is a field whose placeholder reads "New identity (Work, Family, a second account…)" and an Add button. A new identity takes its colour from a palette of seven, picked by how many identities already exist, and Dad can change it afterwards. The footnote says what an identity is for: "Each identity keeps its own cookies and sign-ins."
Renaming and recolouring touch only the book. The id never changes, so the store never changes, and every sign-in survives a rename.
The identity menu
In every normal window the toolbar has a person button tinted with the colour of the front tab's identity. It opens one menu:
- "Open This Site as …", one item per identity, when the front tab shows an http or https page.
- "New Tab as …", one item per identity, each with a round swatch of its colour and a check beside the current one.
- "Save Account Shortcut…", for the front page in its identity.
- "Manage Accounts and Identities…", which opens Settings.
None of these changes the identity of a live tab. Every item in the two lists opens a new tab; "Save Account Shortcut…" opens a sheet that asks for the shortcut's title, and the last item opens Settings. That is invariant 7's "a tab has exactly one" made visible: a tab is born in its identity and dies in it.
Account shortcuts on Home
The native Home has a section called "Account shortcuts". A shortcut is three things, a title, a URL and an existing identity id, stored in workspace.json. Its type's comment calls it "A user-owned launch preference, not a credential or a family registry."
WorkspaceModel.save refuses a shortcut with an empty title, one for the private identity, one whose scheme is not http or https, one with no host, and one whose URL carries a user name or password. Saving the same URL in the same identity again only retitles it. Opening one is just as strict: never in a private window, never for an identity that no longer exists, and always as a new tab in the shortcut's own identity. The UX review states the intent: a shortcut "cannot silently substitute a missing account, change a live tab's identity, copy cookies, or use a private identity." A shortcut whose identity is gone shows "Account unavailable" and does nothing.
The test shortcutsKeepIndependentStoresAndDoNotGuessMissingAccounts saves two shortcuts for the same https://same.example/ in two identities, reloads the file, opens both, and expects two tabs in two identities. It also checks the refusals: an unknown identity, the private one, a URL with a password in it, and a javascript: address. Home's tab search matches on identity names too, so typing "second" finds the tabs of an identity called Second.
One more sentence from the review: "User-entered names do not establish a subscription tier." A shortcut titled for a paid plan is a label Dad typed. Nothing in Voyager reads plans from labels.
The mark on the tab
Invariant 7 ends with "The identity is always visible on the tab." The code is more careful. The tab strip draws a 3-point bar down a tab's leading edge, in its identity's colour, only when Dad has more than one identity and the window is not private. The comment on that field gives the reason: the colour is drawn only when "the mark therefore tells him something." With a single identity every tab would wear the same grey bar and say nothing. The toolbar's person button, though, is there in every normal window, even with one identity. The doc says always; the code says when it informs. Here the code is right.
Removing an identity
Removal sits behind a confirmation that does not soften it: "Every cookie and sign-in held by this identity is deleted. Tabs of this identity must be closed first." removeIdentity then refuses three cases before it touches anything: an identity already being removed, the last one left (counting those mid-removal as gone), and one with a tab open in any window.
The order after that is the lesson. The store goes first. If WebKit cannot remove it, the entry is kept and the reason is shown. If a tab of that identity opened while WebKit was working, the entry is kept too. Only then does the entry leave the book, and if the removed identity was the default, the default moves to the first identity left. Any other default stays where it was. Why that way round? An entry whose store is gone is harmless: its id would simply mint an empty store. A store whose entry is gone has lost its only name (lesson 1), and nothing in Voyager could find it again.
Afterwards, nothing guesses. A saved session tab whose identity is gone reopens in the default identity without its page state, and a shortcut to it shows "Account unavailable".
Clearing one site is a smaller tool beside it. The site information popover clears the data WebKit files under that site in the tab's identity only, and the same site in another identity keeps its sign-in.