Skip to content
C.W.K.
Stream
Lesson 01 of 04 · published

A New Door, Not the Sibling Door

~11 min · gateway, sibling-door, loopback, phone, audience

Level 0Spark
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Two Audiences, Two Mouths, One Daemon

The sibling door is loopback, for apps on the same Mac. Waygate knocks. Watchfire knocks. They are local, authenticated, typed launches with receipts. The phone cannot use that door, and must not be given it. A phone is not a same-Mac app. Publishing the sibling door so a pocket client can "just HTTP like the others" would turn every local caller contract into a network contract. A network contract that can type is a remote-control surface. Track 4 refused the generic input verb. This lesson refuses to put the remaining verbs on the public air.

The phone gets a separate gateway: a bounded WebSocket to approved devices on the family's tailnet. Different mouth, same daemon, same sessions, same leases. The language of the wire from Track 5 is what travels — session identity, journal chunks, leased input, never AppKit, never a screenshot. The mouth is new because the audience is new. Collapsing the mouths is how a helpful debug flag becomes the product, and then a model, or a laptop on a cafe network, is one misbind away from a keyboard.

Do Not Publish the Sibling Door

"Just for a week, bind it so I can test the phone" is how weeks become the architecture. The sibling door's types are launches and receipts, which already must not include raw input — but they also assume a same-Mac caller, a family process, a local clerk. Stretching them onto a network stretches the assumption. Even if the bytes are "only a launch," a launch from the wrong audience is a shell you did not mean to start, on a host that thought the caller was Waygate.

The gateway can launch too, under its own rules: operator permission, device identity, spectator default. That is a different code path on purpose. Reusing the sibling door's handler because it is nearby is how an iPad creates a seat with a Waygate-shaped request and no receipt the phone knows how to hold. Two doors. Two handlers. One daemon behind both. The duplication you are tempted to delete is the boundary.

Named by Role, Not by Coordinate

This quest will not give you a port, a bind address, or a host name. It will give you roles. Loopback sibling door: Mac apps, launches, receipts. Tailnet mobile gateway: approved devices, attach, watch, take control. If a design doc starts leading with coordinates, it has already lost the audience. Coordinates change. Audiences do not. A later brain that "finds the door" by scanning local services is a later brain that will publish whichever one answered.

Keep the sibling door unlisted, unadvertised, uninteresting to a phone. Keep the gateway uninteresting to Waygate. If a caller is confused about which mouth to knock on, the types should not compile: a KitTerminalClient does not speak WebSocket, a pocket client does not speak the sibling launches. That compile error is the product, wearing a compiler.

The sibling door is loopback. The phone gets a different door. Do not publish the sibling door. Two audiences, two mouths, one daemon. Coordinates are not the name of the product.

Code

Roles, not coordinates — which mouth is which·text
loopback sibling door
  audience:  family apps on this Mac (Waygate, Watchfire, ...)
  speaks:    typed launches, receipts, stable target IDs
  never:     raw input, a phone, a browser, a published bind

tailnet mobile gateway
  audience:  approved devices on the family's tailnet
  speaks:    attach, journal, leased input, spectator default
  never:     the sibling door's handler, a model credential, LAN-wide publish

# Illegal collapses
  "bind the sibling door so the phone can test"
  "one HTTP API for everyone"
  "the phone uses KitTerminalClient over the network"
  leading a design with a port number

External links

Exercise

Write two knock stories: Waygate wants a folder in a new leaf; a phone wants to watch a session. Name the door each uses, and one type each is not allowed to send. Then write the one-week debug proposal you would refuse, and the compile error you want instead of that week.
Hint
Waygate's door does not speak attach-as-spectator. The phone's door does not speak KitTerminalClient launches. The debug proposal is always "bind the sibling door." The compile error is the real lock.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.