You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .docs/remote-architecture.md
+80Lines changed: 80 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -93,6 +93,8 @@ Examples:
93
93
94
94
A known environment may or may not know the target `environmentId` before first successful connect.
95
95
96
+
In the hosted web app, known environments are browser-local. A hosted pairing URL can create the saved entry, but it does not give the hosted app a server-side control plane or a copy of the session state.
97
+
96
98
### AccessEndpoint
97
99
98
100
An `AccessEndpoint` is one concrete way to reach a known environment.
@@ -108,6 +110,67 @@ A single environment may have many endpoints:
108
110
109
111
The environment stays the same. Only the access path changes.
110
112
113
+
### AdvertisedEndpoint
114
+
115
+
An `AdvertisedEndpoint` is a server or desktop-authored candidate endpoint for an environment. It is how the backend tells the client which URLs may be useful for pairing and reconnecting.
116
+
117
+
`AdvertisedEndpoint` is deliberately narrower than the full access model:
118
+
119
+
- it describes a concrete HTTP and WebSocket base URL pair
120
+
- it can mark the endpoint as default, available, or unavailable
121
+
- it includes reachability hints such as loopback, LAN, private, public, or tunnel
122
+
- it includes compatibility hints such as whether the endpoint can be used from the hosted HTTPS app
123
+
124
+
Clients should treat advertised endpoints as hints, not as proof that a route works from the current device. The final connection attempt still decides whether the endpoint is reachable.
125
+
126
+
The UI presents one default advertised endpoint in the network-access summary and keeps the rest behind an expandable advanced list. The default controls pairing QR codes and primary copy actions. Users can override it, but that override is a UI preference, not backend configuration.
127
+
128
+
Persist the override by stable endpoint kind rather than raw URL whenever possible. For example, a LAN endpoint should be stored as the desktop LAN endpoint preference, not as `192.168.x.y`, because the address can change when the user switches networks. Provider endpoints should use provider-specific stable keys such as Tailscale IP or Tailscale MagicDNS HTTPS. Custom endpoints may fall back to their concrete identity.
129
+
130
+
When no user default is saved, endpoint selection should prefer:
131
+
132
+
1. endpoints compatible with the hosted HTTPS app
133
+
2. explicitly default endpoints
134
+
3. non-loopback endpoints
135
+
4. loopback endpoints only for same-machine clients
136
+
137
+
This keeps endpoint discovery centralized without making any one provider, such as Tailscale or a future tunnel service, part of the core environment model.
138
+
139
+
### Endpoint providers
140
+
141
+
Endpoint providers are add-ons that contribute advertised endpoints for the current environment.
142
+
143
+
The provider boundary is intentionally outside the core environment model:
144
+
145
+
- core owns `ExecutionEnvironment`, saved environments, pairing, and connection lifecycle
146
+
- providers discover or synthesize endpoints
147
+
- providers return normalized `AdvertisedEndpoint` records
148
+
- the UI and pairing logic select from those records without knowing provider-specific commands
149
+
150
+
The first provider is Tailscale. It can discover Tailnet IP and MagicDNS addresses from the local machine and publish them as additional endpoint candidates. Future providers, such as a hosted tunnel service, should plug into the same shape rather than adding a separate remote environment path.
151
+
152
+
Provider-specific confidence should remain a hint. A Tailscale endpoint still needs a successful browser or desktop connection before the client treats it as connected.
153
+
154
+
### Hosted pairing request
155
+
156
+
A hosted pairing request is a bootstrap URL for the static web app, not a transport.
The hosted app reads the `host` parameter and pairing token, exchanges the token directly with that backend, then saves the resulting environment record in browser local storage.
165
+
166
+
Important constraints:
167
+
168
+
- the hosted app does not proxy HTTP or WebSocket traffic
169
+
- the backend must still be reachable directly from the browser
170
+
- HTTPS pages can only connect to HTTPS/WSS backends
171
+
- HTTP LAN endpoints should keep using direct desktop or CLI pairing URLs
172
+
- the token belongs in the URL hash so it is not sent to the hosted app origin
173
+
111
174
### RepositoryIdentity
112
175
113
176
`RepositoryIdentity` remains a best-effort logical repo grouping mechanism across environments.
@@ -151,6 +214,8 @@ Benefits:
151
214
- no client-specific process management required
152
215
- best fit for hosted or self-managed remote T3 deployments
153
216
217
+
Browser security rules are part of this access method. A hosted HTTPS web client can connect to `wss://` backends, but it cannot connect to plain `ws://` or `http://` LAN backends because that would be mixed content.
218
+
154
219
### 2. Tunneled WebSocket access
155
220
156
221
Examples:
@@ -170,6 +235,8 @@ This is especially useful when:
170
235
- mobile must reach a desktop-hosted environment
171
236
- a machine should be reachable without exposing raw LAN or public ports
172
237
238
+
Tailscale-backed access sits here architecturally even though the current implementation is endpoint discovery rather than a T3-managed tunnel. It contributes private-network endpoints and lets the existing HTTP/WebSocket client path do the actual connection.
239
+
173
240
### 3. Desktop-managed SSH access
174
241
175
242
SSH is an access and launch helper, not a separate environment type.
@@ -185,6 +252,8 @@ After that, the renderer should still connect using an ordinary WebSocket URL ag
185
252
186
253
This keeps the renderer transport model consistent with every other access method.
187
254
255
+
The desktop main process owns the SSH bridge because it can spawn local SSH processes, manage askpass prompts, write temporary launch scripts, and clean up forwards. The renderer receives a saved environment record and connects through the forwarded URL; it should not need SSH-specific RPC paths for normal environment traffic.
256
+
188
257
## Launch methods
189
258
190
259
Launch methods answer a different question:
@@ -227,6 +296,15 @@ The recommended T3 flow is:
227
296
4. Desktop establishes local port forwarding.
228
297
5. Renderer connects to the forwarded WebSocket endpoint as a normal environment.
229
298
299
+
The saved environment should remember that it was created by desktop SSH launch only for reconnect and lifecycle UX. That metadata should not change the server protocol or the environment identity model.
300
+
301
+
Failure handling should be explicit:
302
+
303
+
- SSH authentication failure should surface before any environment is saved
304
+
- remote launch failure should include remote logs or the launcher command output when available
305
+
- forwarded-port failure should leave the saved environment disconnected rather than falling back to an unrelated endpoint
306
+
- reconnect should attempt to restore the SSH bridge before reconnecting the normal WebSocket client
307
+
230
308
### 3. Client-managed local publish
231
309
232
310
This is the inverse of remote launch: a local T3 server is already running, and the client publishes it through a tunnel.
@@ -267,6 +345,8 @@ T3 already supports a WebSocket auth token on the server. That should become a f
267
345
268
346
For publicly reachable environments, authenticated access should be treated as required.
269
347
348
+
Hosted pairing should be treated as a client-side convenience only. The hosted app must not receive pairing tokens through query parameters, must not store pairing state server-side, and must not imply that an HTTP backend is safe or reachable from an HTTPS browser context.
349
+
270
350
## Relationship to Zed
271
351
272
352
Zed is a useful reference implementation for managed remote launch and reconnect behavior.
0 commit comments