Public Access
Merge branch 'main' into claude/vault-unlock-logout-autosync-a84c35
ci / build and test (push) Failing after 3s
ci / build and test (push) Failing after 3s
Four files needed a hand, and all four were two branches adding something in the same place rather than either changing what the other did. The shell's constructor now takes both new parameters: main's SFTP session factory, which it must have because it builds the transfers view model, and this branch's optional resume handler, which stays last so every existing test that constructs a shell without one still gets a shell that can only be online because somebody signed in during this run. App.axaml.cs, ShellFlowTests and QuickConnectTests pass the pair; the layout suite keeps both of its new fields. Signing out now detaches the transfers screen exactly as locking does, and the confirmation says that an open transfer session survives it. That is the same policy both sides already argue for their own case: signing out destroys this machine's copy of the vault, not work that authenticated before it. QuickConnectTests did not compile on main — the SFTP commit added a constructor parameter and the quick-connect suite, merged from a parallel branch just before it, was still calling the old one. Fixed here rather than worked around, since the merged tree has to build. dotnet build, dotnet test and dotnet format --verify-no-changes are all clean: 980 tests, including the end-to-end suite against real containers.
This commit is contained in:
@@ -65,8 +65,9 @@ src/
|
||||
DodoSSH.Client.Storage the local cache: ciphertext mirror, outbox, offline unlock material
|
||||
DodoSSH.Client.Sync the pull/apply/push loop and the conflict policy
|
||||
DodoSSH.Client.Session where a profile lives, unlocking it, and getting one in the first place
|
||||
DodoSSH.Client.Ssh connections, PTY shells, host key trust
|
||||
DodoSSH.Client.Ssh connections, PTY shells, SFTP, host key trust
|
||||
DodoSSH.Client.Terminal the loopback data plane and credit-based flow control
|
||||
DodoSSH.Client.Transfer the transfer queue, part files and resume, and the local file listing
|
||||
DodoSSH.Client.App Avalonia; the only project that knows about a UI toolkit
|
||||
tests/ one test project per source project
|
||||
docs/adr/ architecture decision records
|
||||
@@ -165,6 +166,37 @@ authentication asks for the password every time, because nothing in the interfac
|
||||
credential yet (they do sync — there is just no editor for one); and unlock asks for the passphrase on every
|
||||
launch, because no device key is registered.
|
||||
|
||||
### Moving files
|
||||
|
||||
**FILES** in the nav rail is a two-pane browser: this machine on the left, the host on the right, and a
|
||||
queue underneath. Choose a host, press **CONNECT**, then select a file in either pane and press the arrow
|
||||
pointing the way you want it to go.
|
||||
|
||||
Two things about it are worth expecting rather than discovering.
|
||||
|
||||
**It is a second connection, not a second channel.** SSH itself would allow the SFTP subsystem to open
|
||||
beside a shell on the transport that is already up; SSH.NET does not offer that — its `SftpClient` owns its
|
||||
own transport — so pressing CONNECT here authenticates again. The host records a second login, and a host
|
||||
whose password you type each time will ask for it again on this screen. Host key trust is shared: a
|
||||
fingerprint approved for a terminal is approved here, and one approved here reaches your other machines with
|
||||
the next sync.
|
||||
|
||||
**Nothing is written at its final name until it is complete.** Every transfer goes to a `.dodossh-part` file
|
||||
beside its destination and is renamed into place at the end, so an interrupted transfer can never be
|
||||
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.
|
||||
**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
|
||||
records which source wrote a part file, and resuming one on the strength of its name matching is how a
|
||||
corrupt artefact gets delivered with nothing reporting a failure. A part file found at startup is started
|
||||
over.
|
||||
|
||||
What is not here: transferring a directory, dragging between the panes, and routing a transfer through a
|
||||
bastion — the last needs jump hosts the connection layer has not got. All three are in
|
||||
[`docs/design-import-gaps.md`](docs/design-import-gaps.md).
|
||||
|
||||
### End-to-end verification
|
||||
|
||||
One suite runs against a real server rather than a stub. It needs a Docker daemon and nothing else, so it
|
||||
@@ -245,7 +277,11 @@ off-Windows.
|
||||
a key are written at version 2 and become read-only on an older build. Hosts that do not are still
|
||||
written at version 1, byte-identically to before the field existed — which is what keeps upgrading one
|
||||
machine from making a team's whole vault uneditable everywhere else.
|
||||
- **M2 — full personal vault**, robust sync, relay.
|
||||
- **M2 — full personal vault**, robust sync, relay. *File transfer done:* an SFTP session, a two-pane file
|
||||
browser with a real remote listing — names, sizes, modification times and `drwxr-xr-x` permission bits —
|
||||
and a queue that moves one file at a time with progress, throughput and resume. See
|
||||
[Moving files](#moving-files) for the two things about it worth knowing before you use it, both of which
|
||||
are consequences rather than choices.
|
||||
- **M3 — teams**, sharing, ACLs.
|
||||
- **M4 — hardening and ops**, packaging, self-hosting guide.
|
||||
- **M5 — multi-provider OIDC**, key rotation, per-item content keys.
|
||||
|
||||
Reference in New Issue
Block a user