Where a second account leaks
Keeping two tabs apart is half the job. Pages open more pages: a sign-in window, a link with target="_blank", a result that opens in a new tab. If any of them landed in a different store, the second account would quietly become the first, or a sign-in finished in a pop-up would never reach the tab that asked for it. Architecture invariant 7 closes all of these in two sentences: "Links, pop-ups and redirects opened from a tab stay in its identity. Nothing moves cookies between identities."
Voyager meets that rule in a different way on each path a new page can take.
Redirects: nothing to decide
A redirect, whether the server sends it or a script sets location, is a navigation inside the same web view. A WKWebView takes its configuration, data store included, when it is made, and a live view's store cannot be swapped. So a redirect cannot leave its identity, and Voyager has no code for it. The one place a navigation needs a different configuration is between an extension's own page and an ordinary one, and there the page is replaced with a new view (track 8).
Pop-ups: WebKit hands over the configuration
When a page calls window.open or follows a target="_blank" link, WebKit asks its UI delegate for a new web view and passes a configuration along. Apple's documentation states the condition: "The web view returned must be created with the specified configuration." That configuration carries the opener's data store, and with it the link back to the opener that a sign-in pop-up needs in order to report to the page that opened it.
Voyager's child builds the new page from exactly that configuration and labels it with the opener's identity. Its comment says why no lookup is needed: the child is in the opener's identity "by construction". It then asks the parent whether to keep the page. A refusal closes the child and returns nil, which is what the page sees as window.open returning null.
The parent checks anyway
BrowserTab hands the child to its window, and the window's adopt refuses any child whose identity differs from its opener's. With the WebKit child that guard never fires, since the identity was copied from the opener a few lines earlier. It is there because the parent cannot see WebKit. The rule has to exist in the parent's own vocabulary, where the fake engine can test it without a browser.
aPageOpenedByAPageJoinsOnlyInTheSameIdentity does exactly that. It hands an opener a "stranger" page with a fresh identity; the window refuses it and still holds one tab. A child in the opener's identity becomes the next tab and comes to the front. One more fact from the code: the child always becomes a tab right after its opener, even when the page asked for a sized window. The request records wantsOwnWindow from the window features, and the window model does not act on it today.
Links in a new tab
Command-click, a middle click and the context menu's "Open Link in New Tab" never touch WebKit's pop-up path. For the two clicks, the child cancels the navigation and tells the parent wantsNewTabAt, and the tab answers by opening a tab after itself in its own identity. The menu command never reaches the engine at all: the shell calls model.openTab itself, naming the tab's identity, placing the new tab after it and leaving it behind. Command alone opens the link behind, Shift brings it to the front, and the middle button opens it behind, as Chrome does. aLinkedTabKeepsItsOpenersIdentity opens a link from a tab in a "Work" identity and expects two Work tabs. Duplicating a tab keeps its identity too.
Only a click opens a window
Every configuration the engine builds sets javaScriptCanOpenWindowsAutomatically to false, which Apple defines as whether JavaScript may open windows "without user interaction". The comment beside it: "A page opens a window only when Dad's own click asked for one."
The real-WebKit test aPageOpenedByAPageIsInItsIdentityAndCanBeRefused first checks that the preference is off, then turns it on in its own configuration "to stand in for the click". It opens a 400 by 300 window and checks three things: the child's identity is the opener's, the child's data store is the very same object as the opener's (===), and wantsOwnWindow is true. The child then closes itself with window.close() and the parent hears it. Last, with the parent refusing children, window.open returns null.
One seam, named
Not every way out of a tab carries its identity. The context menu's "Open Link in New Window" opens a fresh window, and a fresh window's first tab takes the default identity. A link from a Work tab opened that way arrives signed in as whoever the default is. The implementation plan still lists "open a link or reopen a tab in another identity" and a default identity per site as open items. A tab dragged into another window does keep its identity, because a moved tab carries its saved identity along; a drag never lands in a window of the other kind, private or normal, and lesson 3 shows how the model guards that line anyway.