Add typed SSH remote URLs and optional Cargo feature wiring #113

Closed
opened 2026-08-24 20:17:05 +00:00 by hugo · 1 comment
Owner

Goal

Extend the storage-owned remote model from HTTPS-only URLs to a typed HTTPS-or-SSH contract without weakening rejection of local, helper, or executable transports.

Scope

  • Replace the assumption that every configured remote is a url::Url with a typed remote endpoint owned by crates/storage.
  • Accept both Git SSH spellings:
    • ssh://[user@]host[:port]/path
    • [user@]host:path, including the requested git@host:path form
  • Preserve Git path semantics: an ssh:// path beginning with / is absolute, an scp-like path without / is relative to the remote account, and the documented ~user form remains distinguishable.
  • Parse IPv4, DNS names, bracketed IPv6 where Git permits it, explicit ports for ssh://, usernames, and non-empty repository paths into validated fields. Never recover transport state from display text.
  • Reject missing or ambiguous hosts/paths, control bytes, embedded secrets, query/fragment data, URL rewrites, separate push URLs, ext::, git://, file://, local paths, and every helper transport before connection work.
  • Preserve existing credential-free HTTPS configuration and behavior. Make transport-specific configuration fields explicit so HTTPS server/application credential references are not confused with SSH identity/trust references.
  • Add an optional ssh feature in crates/storage containing only the Rust SSH/runtime dependencies. The endpoint model must remain available without that feature so an unavailable build returns a typed unsupported-transport error instead of misparsing the config.
  • Keep russh and its async runtime behind the optional feature. Select a current patched Apache-2.0-compatible release and one deliberate crypto backend; do not enable legacy/insecure algorithms accidentally.
  • Update the architecture and configuration documentation from HTTPS-only to HTTPS plus feature-gated SSH while retaining the no-subprocess rule.

Tests and verification

  • Add table-driven parser/round-trip tests for both spellings, absolute/relative/tilde paths, ports, IPv6, Unicode policy, and malicious command/path inputs.
  • Prove existing HTTPS TOML and repository remotes load unchanged.
  • Prove a build without ssh contains no russh dependency and reports SSH as unsupported before DNS, socket, credential, or repository mutation work.
  • Run all repository-required Rust gates.

Acceptance criteria

  • The two requested SSH spellings map to one typed endpoint contract with correct Git path semantics.
  • Invalid/helper/local transports remain fail-closed and cannot reach a transport implementation.
  • HTTPS behavior and existing configurations do not regress.
  • SSH code and dependencies are absent when the feature is disabled.
  • crates/storage remains the only owner of remote parsing and transport selection.

References: https://git-scm.com/docs/git-clone#_git_urls and https://docs.rs/russh/latest/russh/

## Goal Extend the storage-owned remote model from HTTPS-only URLs to a typed HTTPS-or-SSH contract without weakening rejection of local, helper, or executable transports. ## Scope - Replace the assumption that every configured remote is a `url::Url` with a typed remote endpoint owned by `crates/storage`. - Accept both Git SSH spellings: - `ssh://[user@]host[:port]/path` - `[user@]host:path`, including the requested `git@host:path` form - Preserve Git path semantics: an `ssh://` path beginning with `/` is absolute, an scp-like path without `/` is relative to the remote account, and the documented `~user` form remains distinguishable. - Parse IPv4, DNS names, bracketed IPv6 where Git permits it, explicit ports for `ssh://`, usernames, and non-empty repository paths into validated fields. Never recover transport state from display text. - Reject missing or ambiguous hosts/paths, control bytes, embedded secrets, query/fragment data, URL rewrites, separate push URLs, `ext::`, `git://`, `file://`, local paths, and every helper transport before connection work. - Preserve existing credential-free HTTPS configuration and behavior. Make transport-specific configuration fields explicit so HTTPS server/application credential references are not confused with SSH identity/trust references. - Add an optional `ssh` feature in `crates/storage` containing only the Rust SSH/runtime dependencies. The endpoint model must remain available without that feature so an unavailable build returns a typed unsupported-transport error instead of misparsing the config. - Keep `russh` and its async runtime behind the optional feature. Select a current patched Apache-2.0-compatible release and one deliberate crypto backend; do not enable legacy/insecure algorithms accidentally. - Update the architecture and configuration documentation from HTTPS-only to HTTPS plus feature-gated SSH while retaining the no-subprocess rule. ## Tests and verification - Add table-driven parser/round-trip tests for both spellings, absolute/relative/tilde paths, ports, IPv6, Unicode policy, and malicious command/path inputs. - Prove existing HTTPS TOML and repository remotes load unchanged. - Prove a build without `ssh` contains no `russh` dependency and reports SSH as unsupported before DNS, socket, credential, or repository mutation work. - Run all repository-required Rust gates. ## Acceptance criteria - The two requested SSH spellings map to one typed endpoint contract with correct Git path semantics. - Invalid/helper/local transports remain fail-closed and cannot reach a transport implementation. - HTTPS behavior and existing configurations do not regress. - SSH code and dependencies are absent when the feature is disabled. - `crates/storage` remains the only owner of remote parsing and transport selection. References: https://git-scm.com/docs/git-clone#_git_urls and https://docs.rs/russh/latest/russh/
hugo added this to the 07 - Pure-Rust Git-over-SSH remotes milestone 2026-08-24 20:17:05 +00:00
hugo added the enhancement label 2026-08-24 20:17:05 +00:00
Author
Owner

Implemented in commit f636f3b.

  • Added storage-owned RemoteEndpoint, SshEndpoint, SshRepositoryPath, and RemoteTransport types for ssh:// and scp-like SSH remotes, including absolute, relative, and tilde path semantics, ports, IPv4, bracketed IPv6, IDNA hosts, usernames, and strict fail-closed validation.
  • Kept HTTPS credential references transport-specific and preserved existing HTTPS configuration and operations. Helper, local, executable, rewrite, push-URL, embedded-secret, query, fragment, ambiguous, and control-byte inputs remain rejected.
  • Added the optional storage ssh feature with Russh 0.63.1 and Tokio behind it. Default and Apple graphs contain no Russh; the enabled graph selects Ring only. Feature-disabled SSH returns a typed unsupported-transport error before repository, credential, DNS, socket, or transport work.
  • Updated affected Rust callers, architecture/configuration/synchronization documentation, and parser/config/repository regression tests.

Verification: cargo fmt --all -- --check; warnings-as-errors workspace check; Clippy with warnings denied; full workspace tests; feature-enabled storage check and focused tests; feature-tree inspection; and release desktop bundle build all passed. Computer Use on the exact target/release/IronStorage.app opened Git Status successfully and confirmed the existing HTTPS origin remained clean at 0 ahead / 0 behind. No Apple source changed, so iPhone Simulator/device validation was not applicable.

Installed cargo-audit 0.22.2 and audited the final lockfile. The audit found and this commit fixes h2 RUSTSEC-2026-0258 by updating 0.4.15 to 0.4.16. The only remaining vulnerability is pre-existing rsa 0.9.10 RUSTSEC-2023-0071 through pgp/apple-codesign; RustSec currently lists no fixed release. The new SSH feature does not enable Russh RSA.

Implemented in commit f636f3b. - Added storage-owned RemoteEndpoint, SshEndpoint, SshRepositoryPath, and RemoteTransport types for ssh:// and scp-like SSH remotes, including absolute, relative, and tilde path semantics, ports, IPv4, bracketed IPv6, IDNA hosts, usernames, and strict fail-closed validation. - Kept HTTPS credential references transport-specific and preserved existing HTTPS configuration and operations. Helper, local, executable, rewrite, push-URL, embedded-secret, query, fragment, ambiguous, and control-byte inputs remain rejected. - Added the optional storage ssh feature with Russh 0.63.1 and Tokio behind it. Default and Apple graphs contain no Russh; the enabled graph selects Ring only. Feature-disabled SSH returns a typed unsupported-transport error before repository, credential, DNS, socket, or transport work. - Updated affected Rust callers, architecture/configuration/synchronization documentation, and parser/config/repository regression tests. Verification: cargo fmt --all -- --check; warnings-as-errors workspace check; Clippy with warnings denied; full workspace tests; feature-enabled storage check and focused tests; feature-tree inspection; and release desktop bundle build all passed. Computer Use on the exact target/release/IronStorage.app opened Git Status successfully and confirmed the existing HTTPS origin remained clean at 0 ahead / 0 behind. No Apple source changed, so iPhone Simulator/device validation was not applicable. Installed cargo-audit 0.22.2 and audited the final lockfile. The audit found and this commit fixes h2 RUSTSEC-2026-0258 by updating 0.4.15 to 0.4.16. The only remaining vulnerability is pre-existing rsa 0.9.10 RUSTSEC-2023-0071 through pgp/apple-codesign; RustSec currently lists no fixed release. The new SSH feature does not enable Russh RSA.
hugo closed this issue 2026-08-25 17:13:18 +00:00
Sign in to join this conversation.