gate
The tunnel’s in-app AUTH GATE - Express middleware + login routes the
AuthGatePlugin registers on the app’s OWN server via this.context.
The gate is MIDDLEWARE, not a reverse proxy - the app is the process, so there is
nothing to forward to. It either short-circuits (401, or answers the open login
routes) or calls next() to let the app’s real handlers run. It is the
“stands in for AppKit auth” path:
a portr caller authenticates with Better Auth OTP or a passkey, and on
success the gate injects the identity headers AppKit reads.
WHICH TRAFFIC IS GATED - the Host header, not the socket. portr’s client
forwards with Go’s httputil.NewSingleHostReverseProxy and a Director that
PRESERVES the original Host, so tunnel requests arrive with
Host: <subdomain>.<server> (the public domain). A local process hitting the
app directly sends Host: 127.0.0.1:<port> / localhost. So ONLY requests whose
Host matches the configured public domain are gated; the platform front door
and any other local client pass through untouched. There is no portr-injected
identifying header and no TCP/source-IP signal to use instead (the client dials
the target over plain loopback).