Enable SSH remotes in native frontends (#117)

This commit is contained in:
2026-08-25 21:39:35 +02:00
parent 76e707f645
commit a737e74aae
22 changed files with 1214 additions and 140 deletions

View File

@@ -68,10 +68,13 @@ test requires an upstream executable at runtime.
The executable audit checks project Rust sources for process construction and
permits it only in the editor adapter. Every project crate forbids unsafe Rust.
Git repository configuration rejects executable helpers and all non-HTTPS,
credential-bearing or rewritten remote forms before transport. Error and debug
models redact secret bytes; CLI presentation tests assert clipboard, QR, OTP
and generated values do not appear on unintended streams.
Git repository configuration rejects executable helpers, unsupported schemes,
credential-bearing URLs, and rewritten remote forms before transport. The
normal CLI build accepts typed HTTPS, `ssh://`, and scp-like remotes. Unknown SSH
hosts require an explicit fingerprint confirmation on standard error; encrypted
keys use hidden terminal input and no command-line passphrase option. Error and
debug models redact secret bytes; CLI presentation tests assert clipboard, QR,
OTP, generated values, and SSH passphrases do not appear on unintended streams.
The activated dependency graph was reviewed with `cargo tree -e features` and
`cargo metadata --locked`. Gix default features are disabled and only the

View File

@@ -95,7 +95,8 @@ Private-key passphrases are stored by fingerprint in the operating-system
secret store and never appear in TOML. IronStorage does not read OpenSSH
configuration, try additional keys, prompt for passwords or
keyboard-interactive authentication, launch an agent, or invoke proxy/helper
commands. In builds with the `ssh` feature, the same configuration drives
commands. The normal CLI, TUI, and desktop builds enable the storage `ssh`
feature, so the same configuration drives
branch discovery, clone, fetch, and pull over the embedded upload-pack channel;
push and full pull-then-push synchronization use the matching embedded
receive-pack channel.
@@ -103,7 +104,10 @@ receive-pack channel.
The typed endpoint model is always available so an SSH remote remains readable
through the Rust API even when the binary was built without SSH. Such a build
returns a typed unsupported-transport error before connection or repository
mutation. The optional storage `ssh` feature contains `russh` 0.63.1 and Tokio;
mutation. The Apple bridge explicitly enables the storage `full` feature set
without `ssh`, keeping the iPhone, AutoFill, and Watch dependency graph
HTTPS-only until an Apple target opts in. The optional storage `ssh` feature
contains `russh` 0.63.1 and Tokio;
`russh` default features are disabled and the Ring backend plus RSA key support
are selected explicitly.

View File

@@ -111,7 +111,7 @@ remain native-host smoke checks because CI cannot emulate those OS services.
| Authentication expiry | Storage authentication leases own the clock and policy. Passive ticks, rendering, pointer movement, and window events do not renew activity; deterministic tests cover expiry during protected state. |
| Dirty documents and conflicts | Every entry/vault/window/Git worktree replacement routes through one Save/Discard/Cancel decision. Failed saves and conflicts keep the complete draft. |
| Background and window lifecycle | Generation counters reject stale asynchronous results. Lock cancels Git/clipboard work and clears OTP, QR, URI, entry, and editor state. Close and quit use the same dirty guard. |
| Repository and domain ownership | The executable source audit rejects repository/Git construction, process launch, OTP/QR parsing, filesystem writes, unsafe blocks, and non-HTTPS literals in production desktop modules. The folder picker may read only a user-selected QR image; all password-store I/O remains in `crates/storage`. |
| Repository and domain ownership | The executable source audit rejects repository/Git construction, process launch, OTP/QR parsing, filesystem writes, unsafe blocks, and insecure HTTP literals in production desktop modules. HTTPS and SSH endpoint parsing, host trust, authentication, and protocol behavior remain in `crates/storage`; desktop only presents typed state and native confirmation or masked-passphrase prompts. The folder picker may read only a user-selected QR image; all password-store I/O remains in `crates/storage`. |
Run the complete repository gate after the desktop-specific checks:

View File

@@ -60,6 +60,15 @@ commands. SHA-1 host signatures and `ssh-rsa` authentication are excluded.
Cancellation interrupts connection and authentication without changing Git,
known hosts, or secure storage.
The standard CLI, TUI, and desktop applications compile this transport and pass
their Git actions through storage's typed endpoint selection. They display both
SSH URL forms without reparsing them. An unknown key opens an explicit native
confirmation showing the host, port, algorithm, and fingerprint; a changed key
is a non-bypassable error. Encrypted-key prompts use hidden or masked input and
retain a supplied passphrase only after SSH authentication and the requested Git
operation succeed. Cancelling either prompt leaves the repository, known hosts,
and secure storage unchanged.
## SSH upload-pack
With the same feature enabled, branch discovery, clone, fetch, and pull open a
@@ -110,3 +119,6 @@ counts, pack checksums, non-fast-forward behavior, and server status. SSH tests
use a pure-Rust in-process Russh server and upload-pack fixture to exercise
chunked reference and pack streams, end-to-end clone/fetch/pull, command
quoting, cancellation, and rollback without an external Git or SSH executable.
Frontend tests cover typed transport display, prompt masking and cancellation,
retry routing, conflicts, authentication failures, and successful HTTPS
regression paths without duplicating protocol logic.

View File

@@ -49,7 +49,11 @@ caller explicitly selects `SecretCachePolicy::Timed`. Timed policies are capped
at 128 entries and 15 minutes, expire lazily, and are always cleared on lock.
The same unlocked store implements the OpenPGP `SecretProvider`, HTTPS Git
`GitCredentialProvider`, and SSH `SshPassphraseProvider`. The CLI uses it for
terminal `show` and embedded Git, proving that protected keys and remote
authentication are resolved only through opaque references. Tests inject a
memory backend and never access a developer or CI user keyring.
`GitCredentialProvider`, and SSH `SshPassphraseProvider`. CLI, TUI, and desktop
pass one prompted SSH passphrase as zeroizing bytes for one retry. Storage binds
that override to the requested key fingerprint, and the authentication handle
persists it only after the Git operation succeeds; cancellation, rejection, and
other failures never create or replace a record. Prompts are hidden or masked,
and secret values are excluded from arguments, history, normal output, debug
models, notifications, and the clipboard. Tests inject a memory backend and
never access a developer or CI user keyring.