Stop the relay checkbox promising a connection this client cannot make
ci / build and test (push) Successful in 2m7s
ci / android head (push) Successful in 3m15s
ci / desktop nightly (push) Successful in 47s
ci / api image (push) Successful in 25s

Ticking "Connect through the server relay" moved the host's address and port out of the encrypted payload
into plaintext columns on the server — the single deliberate privacy concession in the design, per ADR 0004
— and then the client dialled the address directly, exactly as it does with the box clear. VaultViewModel
builds SshConnectionRequest(hostname, port, username, credential) and nothing on this side reads
RelayEnabled at all. The connection failed the way it always had, for a machine the laptop could not reach,
with nothing saying the box had done nothing.

The server half is built and shipped: tickets, the WebSocket, the deny list, the CHECK constraint that
enforces a non-null address for a relay-enabled host. What does not exist is the client's path to it, so
this is an unfinished feature rather than a broken one — but the control in front of it was collecting the
cost of the finished version.

Both heads now say so, in the label and in the first sentence of the paragraph under it. Not disabled, and
that is the one decision here worth stating: a host somebody has already ticked has to be able to lose the
flag, and a control greyed out with the concession switched on would trap it there. Tickable and honest
beats untickable and stuck.

This is step 0 of docs/reaching-a-host-you-cannot-dial.md, and the only step of it that should ship alone —
the sentence is written to be deleted when the bridge lands.

VERIFIED. Build clean, 112 layout tests. The drawer's paragraph is longer than it was and the host editor is
measured with the drawer open at the window's minimum, so the wrap is held inside the column rather than
assumed to fit.
This commit is contained in:
2026-08-07 08:47:02 +02:00
parent 6185d74800
commit 575a9a9f5e
3 changed files with 31 additions and 9 deletions
@@ -1099,13 +1099,20 @@
◆ The one control here that publishes something. Turning it on copies this host's address and
port into plaintext columns the server can read, which is the single deliberate concession in
the design — see ADR 0004 — so it says so rather than being a switch labelled "relay".
◆ AND IT SAYS, FIRST, THAT IT BUYS NOTHING TODAY. The relay's server half is built and this
client has no path to it — the connect path dials the address directly whether this is ticked or
not — so the box as it stood spent that concession and delivered nothing for it. Left tickable
rather than disabled, so a host already carrying the flag can lose it. See
docs/reaching-a-host-you-cannot-dial.md.
-->
<CheckBox IsChecked="{Binding EditorRelayEnabled}" MinHeight="44">
<TextBlock Classes="mono" FontSize="11.5" Text="Reach this host through the server relay"
<TextBlock Classes="mono" FontSize="11.5"
Text="Reach this host through the server relay (not wired up yet)"
TextWrapping="Wrap" />
</CheckBox>
<TextBlock Classes="body"
Text="The relay dials on your behalf, so this host's address and port are stored on the server in the clear. Everything else about it stays encrypted. A relayed host also needs a port of its own rather than its group's." />
Text="Not built yet: this app always dials the host itself, so ticking this stores the address on the server and changes nothing about how the host is reached. When it works, the relay will dial on your behalf — which is why the address and port have to be stored in the clear. Everything else about the host stays encrypted either way, and a relayed host needs a port of its own rather than its group's." />
<Grid ColumnDefinitions="*,8,*" Margin="0,6,0,0">
<Button Grid.Column="0" Classes="primary" Height="44" Content="SAVE"