Licence is MIT, set solution-wide rather than only on the packable project:
DodoSSH.Contracts is published so clients can build against it, and a
package with no licence expression is one a corporate policy scanner
rejects outright.
The SSH.NET spike is the M1 client gate and it passes. SSH.NET 2025.1.0
exposes ShellStream.ChangeWindowSize, but a method existing is not the
remote observing it, so the tests read `stty size` back from a real sshd
after resizing rather than asserting the call did not throw. Repeated
resizes each take effect too, which matters because dragging a window edge
produces a stream of them. The IChannelSession fallback is not needed.
Also verified against a real sshd: password and public-key auth, that the
host key arrives as a raw blob we can fingerprint ourselves rather than
reading SSH.NET's MD5 property, and that refusing the key via CanTrust
actually aborts the connection -- without which the TOFU dialog would be
decoration.
Kept as a permanent suite, not deleted after the spike. An upgrade that
silently stopped sending the request would present as wrapped output only
after a resize, which is easy to misattribute to the terminal emulator.
Two bugs in the test itself, both worth naming because either would have
been read as "resize does not work":
- A PTY emits CRLF, and the anchored regex rejected the CR. The output
visibly contained `24 80` while the match failed.
- Each read can begin with output still buffered from the previous command,
including its size line. Taking the first match would have reported the
pre-resize size.
platform-flags.md now records window-change as resolved rather than
unverified -- a stale flag is worse than none -- plus the three real SSH.NET
limits found on the way: ShellStream does not override ReadAsync so every
idle session parks a pool thread, one connection cannot serve both
SshClient and SftpClient, and agent forwarding needs an upstream change.
Development and testing are Windows-only, so anything unverified elsewhere
needs to be written down or it gets assumed to work. Several of these have
already cost time once: PostgreSQL 18 moving its data directory silently
gives a carried-over compose file an empty volume, and a loopback-bound
Tomcat beat Docker's 0.0.0.0 publish for `localhost`, making every Keycloak
realm 404 while the container looked healthy.
The largest entry is the Avalonia WebView on Linux, which remains the
biggest risk in the plan and is why the terminal sits behind ITerminalHost.
Also records two things this milestone deliberately left undone -- no rate
limiting on the enrollment and sync write paths until M2, and /me not
touching last_seen_at_utc -- so neither reads later as an oversight.