diff --git a/docs/design-import-gaps.md b/docs/design-import-gaps.md index 03f34a8..b873f14 100644 --- a/docs/design-import-gaps.md +++ b/docs/design-import-gaps.md @@ -510,7 +510,7 @@ field cannot be removed and stays as a permanently refused member; `SyncEndpoint | Org chip `dodotech / platform` | contracts + server | An *organisation* above teams, which does not exist — `VaultSummary.TeamId` is no longer always null since M3, but a team is not an org and there is exactly one tenant per deployment. | The vault's own name, and the account this machine is enrolled as. Team names are on the VAULTS screen, where they are about something. | | `SYNCED` dot, always green | client-app | Nothing — the design's claim is simply unconditional. | Green **only** when a connection is held, the last sync pass actually reached the server, and the outbox is empty; otherwise `UNREACHABLE`, the count of changes still waiting, or `OFFLINE`. Holding an `IVaultServer` proves a sign-in once succeeded and nothing more, so a laptop whose lid has been shut all afternoon still has one — reachability comes from the outcome of the last pass. A permanently green light is the same as no light. | | `VAULT SYNCED 11:02` | client-session | `StoredSyncState.LastPulledAt`/`LastPushedAt` are persisted, but `VaultSession` exposes the store as `internal`. A property away. | Omitted. The one honest sync fact — the outbox depth — is in the titlebar and the status bar. | -| `⌘K` command palette running commands | client-domain | A snippet or saved-command item type (`SyncEntityType.Snippet = 8` is reserved). | Ctrl+K opens a real host search that connects on Enter. The box says "search hosts", not "search hosts · run command". | +| `⌘K` command palette running commands | client-domain | A snippet or saved-command item type (`SyncEntityType.Snippet = 8` is reserved). | Ctrl+K opens a real host search that connects on Enter, and reads a typed `user@host[:port]` as a machine to connect to with a password, without saving it. The box says "search hosts, or type user@host", not "search hosts · run command". | | Status bar `· via bastion-eu` | client-ssh | Jump-host execution. See below. | Omitted. | | Status bar port forwards | client-ssh | — | **Shipped** on the session status bar as a count of listening forwards; the ports themselves are in the session sidebar. | | Status bar `sftp · 2 transfers` | client-app | Nothing now — file transfer is built. What is missing is the count reaching the status bar, which is a screen away from where the queue lives. | Omitted from the status bar. The queue itself is on the FILES screen, with a row per transfer. | diff --git a/docs/manual-checks.md b/docs/manual-checks.md index d49fc09..61a3d7e 100644 --- a/docs/manual-checks.md +++ b/docs/manual-checks.md @@ -1388,6 +1388,39 @@ Ctrl+K, then click a result with the mouse rather than pressing Enter. **Pass:** the palette closes and the connection starts. +### 7.10a Connecting to a machine that is not saved + +Ctrl+K, type `user@host` for a reachable machine that is **not** on HOSTS, press Enter, type its password and +press Enter again. Do it once against a machine whose host key this vault has never seen. + +**Pass:** the palette asks for the password in place, with the caret already in the box. On the second Enter +it closes, a tab named `user@host` opens, and the fingerprint card asks about the key; approving it connects. +Afterwards HOSTS has nothing new on it, and the connection log has an entry for `user@host:22`. Escape from +the password box goes back to the address with what was typed still in it. + +**Failure means:** a new row on HOSTS is the palette saving what it promised not to. A tab that fails with +"authentication failed" for a password known to be right is worth comparing against the phone's CONNECT TO A +MACHINE box, which takes the same path — `VaultViewModel.ConnectToEndpointAsync` — so a difference between +the two is in how the palette hands the password over, not in the connection. The headless half of this is +`QuickConnectTests`; what it cannot do is dial. + +### 7.10b Pressing Terminal with nothing open asks what to connect to + +Close every terminal tab, then press **Terminal** on the rail. + +**Pass:** the terminal's frame holds a prompt — `connect to:` with the caret already on it, so typing works +without a click. Type part of a saved host's name: the matching hosts appear under the line, Tab completes to +the first, and Enter connects to it — asking `user@host:port's password:` first only if that host has no key +or saved password. Type `user@host` for a machine that is not saved instead: Enter asks for its password, and +the second Enter opens a tab for it. Escape steps back from the password to the name. Afterwards HOSTS has +nothing new on it, and no credential was saved — even with "remember" ticked in a host's drawer earlier. + +**Failure means:** a prompt that needs a click before it takes typing is the terminal's WebView still holding +the native keyboard focus — see `NativeKeyboardFocus`, which `ConnectPrompt.TakeKeyboard` calls. Anything drawn +*under* a blank rectangle is the occlusion rule broken: the prompt may only show while no tab exists. A new +credential in KEYS after connecting is the prompt's attempt acting on the drawer's tick, which +`ShellFlowTests.ThePrompt_NeverSavesAPassword_EvenWithTheDrawersTickLeftOn` exists to stop. + ### 7.11 A host or a bucket made now can be picked on FILES now With the files screen's picker open on an empty or short list, go to HOSTS and add a host — or to KEYS and @@ -1421,7 +1454,7 @@ time)" — is the worse failure of the two: it rebinds a host as a side effect o ## Phase 8 — Adding and removing on the phone's host list -Twenty-one checks, and the reason there are twenty-one rather than none is worth stating: **the layout suite +Twenty-two checks, and the reason there are twenty-two rather than none is worth stating: **the layout suite cannot see any of this and structurally never will.** `DodoSSH.Client.App.Layout.Tests` targets `net10.0` and `DodoSSH.Client.Android` targets `net10.0-android`, so a project reference is impossible; Avalonia's application, dispatcher and platform are one-shot process globals, so a second head cannot share the @@ -1794,6 +1827,23 @@ follow, and try disconnecting and reconnecting instead. --- +### 8.20 Connecting from the search box to a machine that is not saved + +With a terminal already open on some other machine, go back to HOSTS and type `user@host` for a reachable +machine that is **not** in the list into the search box at the top. Type its password into the card that +appears, and press CONNECT. + +**Pass:** the card appears only once there is an `@` in the box, names the address with `:22` on the end, and +says NOT SAVED. CONNECT opens a second tab for `user@host` — the first is still there — and the fingerprint +card asks about an unknown key over the terminal. Back on HOSTS the search box is empty, the list is the whole +list again, and there is no new host in it. A port the parser refuses (`root@box:70000`) gives a sentence in +amber under the box rather than a card. + +**Failure means:** the card sitting *over* the list rather than pushing it down is the panels' arrangement +having been lost — see the remark above `IsSendingChosenHostsToAVault` in `HostsScreen.axaml`. A password that +shows in the keyboard's suggestion strip is `Classes="secret"` missing from the box. Everything behind the +card is `ShellFlowTests`' hosts-search cases; this is the rectangles, and the software keyboard. + ## Phase 9 — Tag chips and the picker The desktop half is measured by the layout suite, which now seeds three tags and puts all of them on one @@ -2049,14 +2099,16 @@ that dialled it taken away. See `MainWindowViewModel.OnVaultConnectionFailed`. With at least one keychain host and one machine connected to by hand in the log, open Connections with nothing running. -**Pass:** tapping the keychain one lands on HOSTS with that host **ticked and the action bar up**, ready -for CONNECT out of the ⋯. Tapping the hand-typed one puts its address back in the box on this screen and -leaves the password box **empty**. Neither one dials anything on its own. +**Pass:** tapping the keychain one puts **its name** on the `connect to:` line and carries on as typing that +name would — its password line, or straight into a terminal for a host with a key or a saved password. +Tapping the hand-typed one puts its `user@host:port` on the line and asks for its password with the password +line **empty**. Neither one leaves this screen, and the hand-typed one dials nothing until a password is +given. -**Failure means:** if the hand-typed one navigates to HOSTS, the log entry is carrying a host id it should -not have. If the password came back, something is storing it — it never was. And if the keychain one arrives -at a list with nothing marked, `ConnectToRecent` is setting the selection rather than going through -`AskAboutHost`: nothing on that list means "selected" any more, so that is a screen with nothing to press. +**Failure means:** if the hand-typed one shows a host's name rather than its address, the log entry is +carrying a host id it should not have. If the password came back, something is storing it — it never was. +And if the keychain one shows the logged address rather than the host's name, the host id is not being +matched against the keychain — see `MainWindowViewModel.ChoosePromptRecentAsync`. ### 11.9 The keychain and snippets are the vault's, and back walks out of them @@ -2285,6 +2337,23 @@ Android is not delivering the click as a `contextmenu` event, and the gesture ne `WebView` instead of a page one. Neither costs this head anything it has today: a phone without a pointer has no right button to miss. +### 11.14 Connections with nothing open asks what to connect to + +Close every shell, then press **Connections**. Type part of a saved host's name into the `connect to:` line. + +**Pass:** the matching hosts appear under the line as buttons a thumb can hit; tapping one asks for that +host's password on a line of its own under ssh's wording — or connects at once, for a host with a key or a +saved password. Then type `user@host` for a machine that is not saved and press CONNECT: the password line +appears with the keyboard already on it, and BACK — or the system back gesture — steps off it onto the +address rather than leaving the screen. A tap on a RECENT row lands on the prompt and asks whatever it needs +to before anything is dialled. Nothing new appears on HOSTS or in the keychain afterwards. + +**Failure means:** a password line that appears with the keyboard still on the first line is the posted focus +in `ConnectPrompt.axaml.cs` arriving before the box has bounds. Back that leaves Connections from the password +line is `PhoneShell.OnBackRequested`'s prompt step having been reordered below the surface check. The +decisions themselves — which name matches, what is refused, what is saved — are `ShellFlowTests`' prompt +cases, shared with the desktop; this is the rectangles and the keyboard. + --- ## Phase 12 — Shared vaults: the operations that span two accounts diff --git a/src/DodoSSH.Client.Android/Theme/Phone.axaml b/src/DodoSSH.Client.Android/Theme/Phone.axaml index c6b42b7..37d7f8d 100644 --- a/src/DodoSSH.Client.Android/Theme/Phone.axaml +++ b/src/DodoSSH.Client.Android/Theme/Phone.axaml @@ -843,6 +843,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +