Public Access
Merge branch 'main' into claude/m3-implementation-57f9d7
ci / build and test (push) Failing after 2s
ci / build and test (push) Failing after 2s
Three files conflicted, and two of the resolutions are more than a choice of side. QuickConnectTests had both branches fixing the same build break — main's M2 merge left the shell's constructor with an ISftpSessionFactory nobody passed. Main's version wins because it carries a comment saying why the palette never needs a session. VaultSession's conflict is adjacent edits: main added the remembered sign-in members and this branch changed SyncAsync's summary from "the active vault" to "one vault". Both kept. VaultViewModel is the one that matters. Main taught the background pass to report a sync that had to start over, on the grounds that a machine which silently re-read a whole vault has had something happen to it; this branch turned a pass into one report per readable vault. Taking either side alone would have lost the other, so ResyncedFromStart is now one of the conditions IsWorthReporting checks, per vault. Merging also broke something neither branch could have caught alone, and the build would not have said a word. SyncOnceAsync cleared LastSyncFailed unconditionally, which was right while a pass was one vault and a failure was an exception that never reached that line. A failure is now a report — one unreachable team vault must not stop the others syncing — so the flag was being cleared over a vault that had just failed, lighting the titlebar SYNCED. It is computed from the report instead, in the one place both callers go through, so the manual command gets it as well as the loop. The background pass still swallows the message and keeps the fact, which is what AnAutomaticPassThatFails_LeavesTheStatusAlone is there to hold it to. Two comments the auto-merge left describing a world with one vault in it: the SCOPES rail's, which said team vaults are refused by the access service, and the host sidebar's "One heading, for one vault".
This commit is contained in:
@@ -132,8 +132,9 @@ dotnet run --project src/DodoSSH.Client.App
|
||||
|
||||
In the app, enter `http://localhost:5233` as the server. Your browser opens for sign-in — the realm ships
|
||||
`alice` / `alice` — then choose a vault passphrase and **write down the recovery code**, which cannot be
|
||||
skipped and cannot be recovered from the server. You can then add a host and open a shell on it. Keycloak's
|
||||
admin console is at `http://localhost:18080` (`admin` / `admin`).
|
||||
skipped and cannot be recovered from the server. You can then add a host and open a shell on it — double-click
|
||||
it in the sidebar, or select it and press **CONNECT**, which is the same command with the password box beside
|
||||
it. Keycloak's admin console is at `http://localhost:18080` (`admin` / `admin`).
|
||||
|
||||
You can also add an SSH key, which is stored in the vault like a host and synced the same way: paste the
|
||||
private key, then edit a host and pick that key from its **key** dropdown. From then on that host
|
||||
@@ -146,6 +147,29 @@ the next sync. If a server is legitimately rebuilt and offers a new key, the con
|
||||
with no way to continue from the warning — edit the host and choose **Forget host key**, which is deliberately
|
||||
somewhere you have to go on purpose.
|
||||
|
||||
**Deleting asks first, and the question is worth reading.** DELETE on a host, an SSH key or a stored password
|
||||
puts a question where the buttons were, and what it says is counted rather than generic: how many hosts
|
||||
authenticate with the key about to go — they refuse to connect afterwards rather than falling back to a typed
|
||||
password — whether a terminal is open on the host about to go, and whether this machine can push the deletion
|
||||
yet or is queuing it. There is no undo, which is the other thing it says. Withdrawing host key trust is the
|
||||
deliberate exception: it costs one fingerprint check on the next connection, and the dangerous button there is
|
||||
the one that *adds* trust.
|
||||
|
||||
**Signing in once is enough.** The refresh token is kept in the local cache, sealed under the vault's own
|
||||
key, so a later launch resumes the session itself and no browser opens — and because it is sealed under that
|
||||
key, resuming can only happen *after* the vault is unlocked. A machine that unlocks with no network keeps
|
||||
trying: every synchronisation pass asks for a connection, so a laptop opened on a train is online again
|
||||
within a minute of finding a network, with nothing pressed. Unlock takes **Enter** in the passphrase box,
|
||||
and nothing about unlocking ever waits on the network.
|
||||
|
||||
**Signing out** is under Preferences → *Account*, and again on the unlock screen, where it is the only
|
||||
answer to a forgotten passphrase — nothing can recover one. It asks first, and says what it costs: it
|
||||
empties this machine's cache (the profile, the cached items, and anything still queued to be sent) and
|
||||
withdraws this machine's device key from the account. The vault itself is on the server and is untouched, so
|
||||
signing in again brings it all back; the count in the confirmation is the one thing that exists nowhere
|
||||
else. Your session at the identity provider is *not* ended — DodoSSH has no way to end it — so on a machine
|
||||
that is not yours, sign out there too.
|
||||
|
||||
Two of M1's known gaps are visible immediately, so they are worth expecting rather than diagnosing: password
|
||||
authentication asks for the password every time, because nothing in the interface can create a vault
|
||||
credential yet (they do sync — there is just no editor for one); and unlock asks for the passphrase on every
|
||||
@@ -171,6 +195,9 @@ beside its destination and is renamed into place at the end, so an interrupted t
|
||||
mistaken for a finished one — which matters most for what people actually use this for, which is copying a
|
||||
build artefact onto a server and then running it. A destination that already exists is refused outright
|
||||
rather than overwritten; the remote pane has **DELETE** and **MKDIR** so that refusal is not a dead end.
|
||||
DELETE asks first and names the full path, and it carries the strongest warning in the application on
|
||||
purpose: everything else DodoSSH deletes is a tombstone against a copy the server still holds, and a file on
|
||||
somebody's host is bytes with nothing behind them.
|
||||
**RESUME** on a stopped transfer carries on from what the part file already holds.
|
||||
|
||||
Resume works within a run of the application and not across a restart, and that limit is deliberate: nothing
|
||||
|
||||
Reference in New Issue
Block a user