The Fast Wires Have No WireGuard
The last lesson's proof only works on the tailnet. But Track 3 sends most of the family's bytes somewhere else: a Thunderbolt bridge between two Macs on the same desk, or the house's 10GbE and Wi-Fi. The measured ones are about 27 times (10GbE) to 83 times (Thunderbolt) faster than the tailnet, and none of them carries WireGuard. A packet arriving on a Thunderbolt address says nothing trustworthy about who sealed it, because nobody sealed it.
So the fast routes need a credential. The obvious move is a shared secret in a config file on every Mac. Delta refuses it for the reason the track is named after: a secret you copy is a secret you have to rotate everywhere, and one leaked copy speaks for the whole fleet. Instead, each serving Mac mints a credential for one calling Mac, and it does so over the one channel where it already knows who is asking.
Mint on the Tailnet, Spend on the LAN
- The calling Mac needs a LAN or Thunderbolt route to a peer. Before its first request there, it sends
POST /v1/ticketsto that peer over the tailnet. - The peer's gateway authenticates the caller exactly as in lesson 1 (address, roster, label). Only then does it mint:
secrets.token_urlsafe(32), 32 random bytes in URL-safe base64. - The peer stores a row: the ticket's SHA-256, the caller's label, issued, expires (thirty days), last used. The ticket itself is returned once, in the response body, and never stored on the issuer.
- The caller keeps the ticket in its own state database, keyed by the peer's label, and presents it as
Authorization: Delta <ticket>on every Thunderbolt and LAN request to that peer.
The gateway enforces the first step structurally. /v1/identity and /v1/tickets on any route but the tailnet answer 403: "identity and tickets are served over the tailnet only". A ticket cannot be minted with a ticket, and it cannot be minted on a wire where the caller is anonymous. That is invariant 3, and it is why the scheme does not collapse into "whoever reaches the port".
Why the Issuer Keeps Only a Hash
The issuer has to recognise a ticket; it does not have to know it. Verification hashes the presented value and looks the hash up. If the serving Mac's state database is ever copied (a backup, a disk image, a curious process), the copy holds thirty days of hashes that open nothing. Because the secret is 256 random bits rather than a human password, a plain SHA-256 is enough: there is no dictionary to try, so a slow password hash would add cost and no safety.
The holder's side is different by necessity. To present a ticket you must have it, so the caller stores it in plain form. That row lives under Delta's state root, ~/cwk-dbs/delta-db, and that folder is in CREDENTIAL_DIRS: the home share refuses to serve or write it at any depth, to any Mac. Delta's own credentials are never data on Delta's own channel.
Thirty Days, Renewed a Week Early
| Moment | What happens |
|---|---|
| Ticket has more than 7 days left | Used as is, read from memory (no database read per request) |
| 7 days or fewer left | The holder treats it as gone and mints a new one over the tailnet |
| Issuer mints a new ticket for that label | Expired rows are pruned; the caller's older live ticket stays valid until it expires, so requests already in flight with it never fail |
Ticket refused (401: unknown, revoked, minted by another Mac, expired) | The holder drops it, mints again, and retries |
Renewing early turns expiry into a non-event: the boundary is crossed on a quiet request, a week before it could bite. Renewing on 401 handles everything else, including a peer whose state was reset or an issuer that revoked the label on purpose (Tickets.revoke deletes every row for it).
Eight Workers, One New Ticket
A transfer on Thunderbolt runs eight workers. If the peer has just forgotten this Mac's ticket, all eight get 401 within the same millisecond, and a naive client mints eight tickets. Delta's PeerClient.ticket takes a per-peer lock and passes along the ticket that was refused. The first worker through the lock mints; the other seven find a held ticket that is not the one they were refused with, and use it. One round trip on the tailnet, not eight.
On the issuer, verification is memoised for sixty seconds per ticket hash, so a busy route costs one database read and one last_used write per ticket per minute rather than per request. The memo also records expiry, so a ticket that expires inside the minute is refused on time.
What Never Happens
A ticket never rides in a URL, where proxies and access logs would keep it; it travels only in the Authorization header. It never leaves the two Macs it was minted between. It is never minted off the tailnet, and nothing ever copies one from Mac to Mac. If you ever find yourself shipping a ticket file with an installer, you have rebuilt the thing this lesson exists to avoid.