You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prove the load-bearing mechanics of the airship SSH hub design end-to-end with a throwaway PoC, before committing to the Transport trait / SshTransport refactor. The one round-trip to demonstrate:
operator (russh client) ──▶ BASTION (russh server + russh client) ──▶ PILOT (russh server, embedded sshd)
cert auth hop 1 terminate + re-originate cert auth hop 2
exposes a NO-PTY subsystem
If this round-trip works — cert-authenticated at both hops, terminating proxy in the middle, a constrained (non-shell) channel at the end, and per-operator attribution the hub cannot forge — every hard part of the hub design is de-risked.
Why (rationale)
The hub is the WAN/operator face of the mesh (long-haul, bastion traversal, Windows reachability — the gaps iroh/QUIC leaves open). Per the ownership decision in newt-agent docs/design/ssh-ca-trust-root.md §10, the Transport trait + SSH server live in agent-mesh, so the spike belongs here. The full hub design is in airship docs/design/ssh-hub.md. Reference bastion (same library, production): Warpgate (warp-tech/warpgate, russh-based) — quarry its SSH proxy path.
Current substrate (verified)
agent-mesh-transport exposes a concrete iroh Endpoint (bind/dial/accept, endpoint.rs) — no Transport trait yet. The spike does NOT need to build the trait; it proves russh mechanics standalone, informing the later refactor.
ssh-key 0.6 is already a workspace dep (Cargo.toml, used for GitHub cross-sign/verify) — the cert primitives (ssh_key::Certificate, CertType, principals, validity, signature verify) are already on hand.
Engine: russh 0.62 (Apache-2.0, tokio, client + server in one crate).
What the PoC must prove (the hard parts)
Dual-role russh in one process — a server::Handler accepting a connection AND a client opening an onward connection, spliced (the bastion terminates and re-originates; this is the Warpgate model, NOT direct-tcpip passthrough).
Cert-based mesh-membership auth at BOTH hops — validate an OpenSSH certificate in the server::Handler: signature chains to a test CA, valid_after/before current, principal matches, (stub) KRL check. russh does not wire certs end-to-end — this is our glue over ssh-key. Prove reject paths too: expired, wrong-CA, principal-mismatch, garbage.
NO PTY / NO shell — the pilot server exposes only a named subsystem channel (stand in for newt-remote); pty_request/shell_request are rejected/unregistered. Confirm a shell request fails.
ring crypto backend — build with russh's ring backend (not aws-lc-rs), to keep the "no C" posture and portability.
Per-operator attribution — end-to-end and hub-unforgeable (NON-NEGOTIABLE). Attribution must NOT collapse to the hub's identity. The operator signs the subsystem payload (an ed25519 envelope); the pilot verifies it against the operator's key; and a payload injected or altered by the terminating bastion is REJECTED at the pilot. The bastion authenticates the transport hop (its own attenuated cert) but cannot forge who acted. This is the operator directive (airship docs/design/ssh-hub.md §13) — prove it, don't stub it.
Watch-items to resolve (record findings in the issue)
MSRV. agent-mesh floor is 1.75; the russh spike in newt-agent passed on 1.88. Determine russh 0.62's actual MSRV and whether it forces bumping agent-mesh-transport's rust-version (or isolating the SSH code in a crate with a higher floor). This is the most likely blocker — check first.
Windows. SSH exists in this architecture partly because iroh/QUIC is flaky on Windows. Confirm the PoC (esp. the ring backend + any streamlocal/subsystem paths) builds and runs on Windows, or note what doesn't.
API churn. russh is 0.x (0.61→0.62 already broke APIs). Pin the exact version used.
Acceptance criteria
A single test binary runs all three roles (operator client, bastion, pilot server) in-process (or as three tasks) and completes a round-trip: operator sends bytes over the subsystem channel → bastion proxies → pilot echoes → operator receives.
Both hops reject a connection presenting an invalid cert (at least: expired + wrong-CA + principal-mismatch), and accept a valid one.
A shell/pty request is rejected by the pilot server.
Per-operator attribution proven: the pilot attributes a message to the operator via the operator-signed envelope; a message forged or altered by the bastion is rejected (the hub cannot impersonate the operator). This must pass even though the bastion terminates SSH and sees plaintext.
Builds on the ring backend.
Findings recorded for MSRV (does it force a floor bump?) and Windows (does it build/run?).
A short writeup (spike verdict: GO / GO-with-caveats / NO-GO) appended here or as a doc, feeding phase 2 (the Transport trait + SshTransport).
Out of scope (this is a spike)
The real Transport trait / IrohTransport refactor (phase 2 — informed by this).
Wiring to the real agent-mesh CA, KRL topic, or roster/discovery (use test fixtures).
The real newt-remote subsystem protocol (a stub echo subsystem stands in).
Session recording, routing-by-username, the airship deployment (later phases).
Production hardening — spike code is throwaway.
Refs
Design: airship docs/design/ssh-hub.md (the hub this de-risks)
Substrate: newt-agent docs/design/ssh-ca-trust-root.md (CA, member certs, SshCaveats, russh spike GO)
Goal
Prove the load-bearing mechanics of the airship SSH hub design end-to-end with a throwaway PoC, before committing to the
Transporttrait /SshTransportrefactor. The one round-trip to demonstrate:If this round-trip works — cert-authenticated at both hops, terminating proxy in the middle, a constrained (non-shell) channel at the end, and per-operator attribution the hub cannot forge — every hard part of the hub design is de-risked.
Why (rationale)
The hub is the WAN/operator face of the mesh (long-haul, bastion traversal, Windows reachability — the gaps iroh/QUIC leaves open). Per the ownership decision in newt-agent
docs/design/ssh-ca-trust-root.md§10, theTransporttrait + SSH server live inagent-mesh, so the spike belongs here. The full hub design is in airshipdocs/design/ssh-hub.md. Reference bastion (same library, production): Warpgate (warp-tech/warpgate, russh-based) — quarry its SSH proxy path.Current substrate (verified)
agent-mesh-transportexposes a concrete irohEndpoint(bind/dial/accept,endpoint.rs) — noTransporttrait yet. The spike does NOT need to build the trait; it proves russh mechanics standalone, informing the later refactor.ssh-key0.6 is already a workspace dep (Cargo.toml, used for GitHub cross-sign/verify) — the cert primitives (ssh_key::Certificate,CertType, principals, validity, signature verify) are already on hand.What the PoC must prove (the hard parts)
server::Handleraccepting a connection AND aclientopening an onward connection, spliced (the bastion terminates and re-originates; this is the Warpgate model, NOTdirect-tcpippassthrough).server::Handler: signature chains to a test CA,valid_after/beforecurrent, principal matches, (stub) KRL check. russh does not wire certs end-to-end — this is our glue overssh-key. Prove reject paths too: expired, wrong-CA, principal-mismatch, garbage.newt-remote);pty_request/shell_requestare rejected/unregistered. Confirm a shell request fails.ringcrypto backend — build with russh'sringbackend (notaws-lc-rs), to keep the "no C" posture and portability.docs/design/ssh-hub.md§13) — prove it, don't stub it.Watch-items to resolve (record findings in the issue)
agent-mesh-transport'srust-version(or isolating the SSH code in a crate with a higher floor). This is the most likely blocker — check first.ringbackend + any streamlocal/subsystem paths) builds and runs on Windows, or note what doesn't.Acceptance criteria
shell/ptyrequest is rejected by the pilot server.ringbackend.Transporttrait +SshTransport).Out of scope (this is a spike)
Transporttrait /IrohTransportrefactor (phase 2 — informed by this).newt-remotesubsystem protocol (a stub echo subsystem stands in).Refs
docs/design/ssh-hub.md(the hub this de-risks)docs/design/ssh-ca-trust-root.md(CA, member certs,SshCaveats, russh spike GO)warp-tech/warpgate(russh-based terminating SSH proxy)spike(transport): handshake transcript hash for SAS binding)Gilamonster-Foundation/newt-remote(the interactive attach surface the channel will carry)