Public Access
Point a release build at the hosted server, and a debug build at the clone
The shipped default was http://localhost:5233, which is the address the API serves under dotnet run and a machine an installed application is not running. Somebody who installs a release and accepts the field unread is signing in to nothing. Two defaults now, because the two audiences never overlap. A release build offers https://ssh.dodotech.cloud, so a first launch needs no address typed at all. A debug build keeps the loopback address, and that half matters as much: shipping the hosted address into a clone would point every development launch at production, and sign-in is the call that provisions an account there. The remark carries the reason the schemes differ, since the pair now looks like an oversight rather than the deliberate thing it is — the API's first launch profile is plaintext on 5233, and an HTTPS client meeting a plaintext port reports a TLS failure that reads like a certificate problem. The test spells out both branches rather than asserting the constant, which would pass however it were edited. What it is really guarding is that a release never ships a developer's loopback address and a debug build never points a clone at production, and it can only guard those by naming them. Verified by running the shell suite in Debug and in Release. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -332,18 +332,33 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// </remarks>
|
||||
internal bool HasNoDeviceKeyOption => !CanRegisterDevice && !CanForgetDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The address offered on first launch, before anything is enrolled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The address <c>dotnet run --project src/DodoSSH.Api</c> actually serves, so the first launch after
|
||||
/// a clone works without the user having to know a port. This was <c>https://localhost:7217</c>, which
|
||||
/// is the API's <em>second</em> launch profile: the first is HTTP on 5233 and is the one both the
|
||||
/// README and a plain <c>dotnet run</c> select, so nothing was listening on 7217. Pointing an HTTPS
|
||||
/// client at a plaintext port fails as "The SSL connection could not be established", which sends
|
||||
/// people looking for a certificate problem — see <see cref="ExplainSignInFailure" />. A real
|
||||
/// deployment is HTTPS behind a proxy and its address is typed over this one; the placeholder in the
|
||||
/// setup card shows that shape.
|
||||
/// <para>
|
||||
/// Two defaults, because the two audiences never overlap. A release build is installed by somebody
|
||||
/// signing in to the hosted deployment, and typing its address is the only thing standing between
|
||||
/// them and a working application. A debug build is run from a clone, next to
|
||||
/// <c>dotnet run --project src/DodoSSH.Api</c>, and shipping the hosted address there would point
|
||||
/// every development launch at production — which is worse than an inconvenience, since sign-in is
|
||||
/// the step that enrolls a device.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note the schemes. <c>http</c> locally is not an oversight: the API's first launch profile — the
|
||||
/// one a plain <c>dotnet run</c> and the README both select — is plaintext on 5233, and pointing an
|
||||
/// HTTPS client at a plaintext port fails as "The SSL connection could not be established", which
|
||||
/// sends people looking for a certificate problem. See <see cref="ExplainSignInFailure" />.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
#if DEBUG
|
||||
internal const string DefaultServerUrl = "http://localhost:5233";
|
||||
#else
|
||||
internal const string DefaultServerUrl = "https://ssh.dodotech.cloud";
|
||||
#endif
|
||||
|
||||
[ObservableProperty]
|
||||
private string serverUrl = "http://localhost:5233";
|
||||
private string serverUrl = DefaultServerUrl;
|
||||
|
||||
[ObservableProperty]
|
||||
private string passphrase = string.Empty;
|
||||
|
||||
@@ -213,16 +213,28 @@ public sealed class ShellFlowTests : IAsyncLifetime
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The shipped default is a value a user is invited to accept unread, so it is worth one assertion.
|
||||
/// It was <c>https://localhost:7217</c> — the API's second launch profile — while the README, the
|
||||
/// API's appsettings and a plain <c>dotnet run</c> all use HTTP on 5233, and pointing an HTTPS client
|
||||
/// at a plaintext port reports a TLS failure that reads like a certificate problem. Nothing failed
|
||||
/// except the first thing a new user does.
|
||||
/// <para>
|
||||
/// The shipped default is a value a user is invited to accept unread — it is what the button under it
|
||||
/// will actually contact — so it is worth one assertion. It has twice been an address nothing was
|
||||
/// listening on: <c>https://localhost:7217</c>, the API's second launch profile, and then the first
|
||||
/// profile's <c>http://localhost:5233</c> in a release build, which is a machine an installed
|
||||
/// application is not running.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Both branches are written out rather than compared against the constant itself. Asserting a
|
||||
/// constant against itself would pass however it were edited, and the whole point of this test is
|
||||
/// that a release build must not ship a developer's loopback address — or, since the split, that a
|
||||
/// debug build must not point a clone at production.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public void TheDefaultServerUrl_IsTheAddressTheApiActuallyServes()
|
||||
public void TheDefaultServerUrl_IsTheHostedDeployment_ExceptInADebugBuild()
|
||||
{
|
||||
#if DEBUG
|
||||
shell.ServerUrl.ShouldBe("http://localhost:5233");
|
||||
#else
|
||||
shell.ServerUrl.ShouldBe("https://ssh.dodotech.cloud");
|
||||
#endif
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
Reference in New Issue
Block a user