The family standing rule (anything worth fuzzing gets fuzzed) on the
crate's ingress surfaces, per the alkgit convention:
- fuzz_targets/{exec_parse,fingerprint,key_decode,terminal_params} —
thin fuzz_target! wrappers over four ingress surfaces:
- exec_parse: the production parse path (from_utf8-fallback ingress
shape), differentially paired against a from-spec grammar oracle;
typed routing classes + determinism.
- fingerprint: blob parse + the single fingerprint path; the
SHA256:/unpadded-base64 contract shape via a from-spec
base64 round-trip oracle; the committed ssh-keygen -lf vectors
replayed inside the gate.
- key_decode: the production decode arm (the #[doc(hidden)]
decode_key_arm exposure, routed through itself); typed-class +
bounded-fixed-message invariants; passphrase-shape robustness
drive on the underlying decode.
- terminal_params: the pty_request conversion via the #[doc(hidden)]
terminal_params exposure; exact clamp, verbatim term, the
reserved-modes {} JSON shape, serialized-shape determinism.
- shared/ — the invariant logic as a stable-clean library; the
corpus gate (cargo test --manifest-path fuzz/shared/Cargo.toml)
replays every committed seed through the batteries and joins
AGENTS.md's verification list.
- corpus/<target>/ committed seeds + the deterministic
gen_fuzz_seeds.py (no-op-diff verified).
- run-detached.sh + nightly pin; the sidecar excluded from the root
workspace (workspace + package excludes; publish dry-run clean).
Exposure shape decided + recorded per target (README + lib.rs doc
comments): fingerprint needs none (fully public ingress); the rest
are #[doc(hidden)] re-exports of the production surfaces, never
forks. Detached campaigns ran per target (600 s default budget, fork
mode): all four clean; the two findings of the first round are
recorded in the task file (the harness oracle's double-/-strip bug;
the PPK echo fixed in the preceding commit).
Verification: corpus gate green (11 tests); scripts/matrix.sh green;
taskgraph validate clean.
132 lines
5.7 KiB
Rust
132 lines
5.7 KiB
Rust
//! alkssh — the alk family's SSH adapter (the alkhttp-style door for the
|
||
//! SSH protocol): a thin wrapper around russh terminating the vanilla-ssh
|
||
//! wire and bridging to/from alkcall channels (the `alk/ssh` ALPN).
|
||
//!
|
||
//! No SSH framing is authored in-family (family ADR-003): russh owns the
|
||
//! wire, and the crate's substance is the channel-type mappings —
|
||
//! session/pty → alktty, direct/forwarded-tcpip → alktunnels, git exec →
|
||
//! alkgit, sftp → alkfs later (a declining placeholder until then), each
|
||
//! behind its cargo feature. Git over SSH is exec-only (ADR-006): a
|
||
//! subsystem request can never carry the repository, so it declines. A
|
||
//! client opening an unfeatured or unimplemented channel type gets a
|
||
//! clean decline — never a half-capability, never a silent fallback; the
|
||
//! default build (no features) is structurally incapable of serving
|
||
//! anything but declines.
|
||
//!
|
||
//! Identity is the family's, not SSH's: a verified key's fingerprint →
|
||
//! alkcall `IdentityProvider`. Keys the crate holds (client dial keys,
|
||
//! host keys) come from alkvault-backed sources — vault-encrypted at
|
||
//! rest, decrypted at use (ADR-005), never env vars.
|
||
//!
|
||
//! Architecture: `docs/architecture/` (phase 1 — ADRs 001–006 accepted;
|
||
//! the foundations, the server stack, the server-direction mappings, and
|
||
//! the client direction — dial, op rows, the `-R` acceptor leg, and the
|
||
//! lifecycle primitives — are landed through wave 4; the validation
|
||
//! suite and the release are wave 5). See also `docs/research/`,
|
||
//! `docs/plans/implementation.md`, and family ADR-003.
|
||
|
||
mod adapter;
|
||
mod channel_cap;
|
||
mod client;
|
||
#[cfg(feature = "tunnel")]
|
||
mod client_accept;
|
||
mod client_handler;
|
||
mod client_ops;
|
||
mod config;
|
||
mod dispatch;
|
||
mod error;
|
||
#[cfg(any(feature = "session", feature = "git"))]
|
||
mod exit_code;
|
||
mod fingerprint;
|
||
#[cfg(feature = "git")]
|
||
mod git_map;
|
||
mod handler;
|
||
mod host_key;
|
||
mod key_source;
|
||
mod observe;
|
||
mod serve;
|
||
#[cfg(feature = "session")]
|
||
mod tty_map;
|
||
#[cfg(feature = "tunnel")]
|
||
mod tunnel_map;
|
||
|
||
pub use adapter::SshAdapter;
|
||
pub use client::SshConnection;
|
||
pub use client::dial;
|
||
/// Contract-test surface (`#[doc(hidden)]`): the dial surface's
|
||
/// config-mapping and handler-skeleton mechanics (the `serve.rs`
|
||
/// §Test-surface mirror; see `client.rs` §Test surface). Not
|
||
/// documented API.
|
||
#[doc(hidden)]
|
||
pub use client::russh_client_config;
|
||
/// The `-R` leg's acceptor registry + the reverse-listen rows'
|
||
/// payload/acceptor types + the listener handles (`w4-reverse-listen`
|
||
/// / `w4-lifecycle` — under `tunnel`; the recorded decisions live in
|
||
/// the `client_accept` module docs).
|
||
#[cfg(feature = "tunnel")]
|
||
pub use client_accept::{
|
||
AcceptorHeld, AcceptorRegistry, ForwardedStreamlocal, ForwardedTcpip, ReverseEndpoint,
|
||
ReverseListener, StreamlocalForwardedAcceptor, TcpipForwardedAcceptor,
|
||
};
|
||
#[doc(hidden)]
|
||
pub use client_handler::ClientHandler;
|
||
/// The client op rows' surfaces (`w4-op-rows`):
|
||
/// [`RemoteSession`](client_ops::RemoteSession) — the exec/pty rows'
|
||
/// family chunk plane (under `session`),
|
||
/// [`TunnelChannel`](client_ops::TunnelChannel) — the direct
|
||
/// rows' byte duplex (under `tunnel`),
|
||
/// [`GitPackSession`](client_ops::GitPackSession) — the upstream git
|
||
/// row's pack duplex + consumed exit (under `git`). The op methods
|
||
/// live on [`SshConnection`] (the op-row surface). Not a re-export
|
||
/// here: the `sftp` row is [`SshConnection::sftp`] itself — the
|
||
/// every-build OQ-13 decline placeholder.
|
||
#[cfg(feature = "git")]
|
||
pub use client_ops::GitPackSession;
|
||
#[cfg(feature = "session")]
|
||
pub use client_ops::RemoteSession;
|
||
#[cfg(feature = "tunnel")]
|
||
pub use client_ops::TunnelChannel;
|
||
#[cfg(feature = "git")]
|
||
pub use config::GitSeam;
|
||
#[cfg(feature = "session")]
|
||
pub use config::SessionSeam;
|
||
#[cfg(feature = "tunnel")]
|
||
pub use config::TunnelListenSeam;
|
||
pub use config::{DialConfig, Limits, ServeConfig};
|
||
/// Fuzz-visible surface (`#[doc(hidden)]`, `w5-fuzz-harness`): the exec
|
||
/// grammar's parse path (`dispatch.rs`) — the `fuzz/` sidecar's
|
||
/// `exec_parse` target drives the production parse, never a fork. Not
|
||
/// documented API: the grammar is the dispatch seam's, not a public-API
|
||
/// promise.
|
||
#[doc(hidden)]
|
||
pub use dispatch::{ExecDecline, ExecRoute, GitServiceRoute, parse_exec};
|
||
pub use error::{AdapterError, DialError, KeySourceError, OpError, OpenDeclineReason};
|
||
pub use fingerprint::fingerprint;
|
||
/// Contract-test surface (`#[doc(hidden)]`): the per-connection auth
|
||
/// bridge handler — constructible so the tests drive its hooks directly
|
||
/// against the wave-1 doubles (see `handler.rs` §Test surface). Not
|
||
/// documented API: the wire-facing surface is exactly `SshAdapter` +
|
||
/// the config/error/host/key-source types.
|
||
#[doc(hidden)]
|
||
pub use handler::SessionHandler;
|
||
pub use host_key::{HostKeyPolicy, PresentedHostKey, RejectAll};
|
||
/// Fuzz-visible surface (`#[doc(hidden)]`, `w5-fuzz-harness`): the
|
||
/// decrypt-at-use chain's decode arm (`key_source.rs`, the production
|
||
/// `decrypt_and_decode` conversion). Not documented API.
|
||
#[doc(hidden)]
|
||
pub use key_source::decode_key_arm;
|
||
pub use key_source::{HostKeySource, KeySource, VaultHostKeySource, VaultKeySource};
|
||
/// Contract-test surface (`#[doc(hidden)]`): the spawn-and-return
|
||
/// plumbing (`ADR-006 decision 4`, see `serve.rs`) — the mechanics the
|
||
/// mechanics-proof rows in `tests/spawn_return.rs` compose over the
|
||
/// real wire to pin the constraint as tests. Not documented API.
|
||
#[doc(hidden)]
|
||
pub use serve::{report_exit_status_then_close, spawn_serving_path};
|
||
/// Fuzz-visible surface (`#[doc(hidden)]`, `w5-fuzz-harness`, under
|
||
/// `session`): the `pty_request` args → `TerminalParamsWire`
|
||
/// conversion (`tty_map.rs`, OQ-44's reserved modes). Not documented
|
||
/// API.
|
||
#[cfg(feature = "session")]
|
||
#[doc(hidden)]
|
||
pub use tty_map::terminal_params;
|