Where am I?
Before either surface can draw me, Voyager has to know where I am. That is a setting, PippaConnection, with three answers:
| Connection | Address | What it asks |
|---|---|---|
| This Mac | http://localhost at my port | nothing, because loopback asks no PIN |
| The tailnet | my Tailscale HTTPS twin on the service host | the family PIN |
| An address | any http or https host Dad types, cut down to scheme, host and port | the family PIN |
The default follows the machine. On the Mac that runs cwkPippa it is this Mac, and everywhere else it is the tailnet. Settings offer "This Mac" only on that machine, and a settings file that says "this Mac" on any other Mac is read as the tailnet twin. Which Mac plays that role comes from the kit's family registry, never from a machine's name; track 6 tells that story, along with the hub's own sign-in cookie. Dad's line on it was short:
다른 맥이면 알아서 주소가 달라져야지
"If it's another Mac, the address should change on its own."
The PIN, through the kit's door
A remote Pippa sits behind the family PIN, and Voyager does not implement that exchange itself. PippaConnector opens the kit's PippaDoor for the connection's host. Dad types the PIN in Settings, and the door has Firelink, the family's authority, verify it and mint a session. When Dad says to remember it, the PIN is filed in the Keychain under the host it belongs to, so a move between Macs never silently reuses the wrong one, and the next launch connects without asking. Settings show which of three states holds: connected, a PIN saved, or no PIN yet. The connector moved into the shared core when the phone app arrived, so the Mac and the phone open the same door.
Two sibling quests own the reasons. Solo Auth Quest explains why reaching a machine over Tailscale is the first line and still not permission by itself, and what the PIN layer adds. Sibling Kit Quest explains why the door is kit code that every family app consumes, so a fix to it lands in all of them at once.
A session in two places
The session reaches my page two ways at once.
- As a cookie. Before either surface loads, Voyager puts a
pippa_sessioncookie into the panel's store, and only then starts the load, so my first request already carries it. The kit builds it HttpOnly, for my host alone, and Secure when the address is https. - In the fragment. The Sidekick's address also carries the token after the
#, aspippa_session=and the token. My root, for Pippa herself, takes no fragment.
The fragment is there because a fragment never leaves the browser. A token in the query would reach the server and its access log, and it could ride out again in the Referer header of what the page loads next: under the browser's usual default referrer policy, every same-origin request carries the full address, query and all. The page reads the fragment and replays the token as a header on its own fetches. The cookie is there because not every request is the page's own fetch. An <audio> element playing my voice and an EventSource stream are requests the browser makes by itself, and they carry only cookies. Without the cookie, every voice take is a 401, my voice mode treats the failed take as finished and listens again at once, and to Dad it looks exactly like a phantom interruption. Another family app found that the hard way before Voyager existed, and the kit's door now offers the cookie to every host that asks. Both of my surfaces share the panel's store, so ⌘R on Pippa herself keeps the session too.
When the link drops
The tailnet is sometimes between networks, and Voyager is careful about what it calls that. PanelLoadFailure sorts a failed load: only a request that reached nothing, at a Pippa off this Mac, is "could not be reached", and only that one ends with the kit's hint to check Tailscale on this device. A local Pippa that is down, a TLS fault or a page error keeps its own words, because a Tailscale hint there would send Dad to fix the wrong thing. A test holds each case: a refused connection or a timeout at a tailnet address is unreachable, the same refused connection at loopback is not, and a failed TLS handshake is not.
An unreachable Pippa is then retried without Dad. The wait doubles from 2 seconds to 32 and then stays at a minute, and when the Mac's network path becomes usable again, a joined Wi-Fi or Tailscale back, she is tried at once. The table and the reasons are in track 4's lesson on crashes and recovery. The phone has no network-path monitor yet, so there the timer alone brings me back.
A check never talks to the real me
One more rule protects my store from Voyager's own tests. In a verification build the location is nil unless the script names a stand-in on loopback, so the panel cannot open against the real me at all. Voyager's house sign gives the reason: every context the panel receives is written into Dad's cwkPippa, and a message sent from my panel speaks as Dad. Opening the panel and answering its questions is safe to verify. Pressing send is his.