# Single-crate protocol/door crate (the alktty template). No workspace: # the composition story is deferred — alkssh's substance is the mappings # (family ADR-003). [workspace] members = ["."] [package] name = "alkssh" version = "0.1.0" edition = "2024" rust-version = "1.89" license = "MIT OR Apache-2.0" description = "SSH adapter for the alk family: russh-wrapped vanilla-ssh termination bridged to/from alkcall channels — session/pty, tunnels, git exec — with every capability mapping a fail-closed cargo feature (no features: no capabilities)" repository = "https://git.alk.dev/alkdev/alkssh" keywords = ["ssh", "russh", "protocol", "alkcall", "network"] categories = ["network-programming", "asynchronous"] # The package policy (the sibling crates' convention): the published crate # ships the architecture docs (the authoritative contract) but not the # process surface — reviews, research, plans, task files, the working # agents' config, AGENTS.md. exclude = [".opencode/", "AGENTS.md", "docs/reviews/", "docs/plans/", "docs/research/", "docs/sdd_process.md", "tasks/"] [lib] name = "alkssh" [features] # ADR-003: flat and independent — no feature implies another; `default = []` # by design (a default build has no capabilities; every unfeatured open # declines fail-closed). The wave-2 decline core is the first `cfg` # consumer; the wave-3 seam-config handles are the second (each optional # sibling dep is gated feature-to-dep so a git-build never compiles # alktty and vice versa — the wave-1 manifest rule: per-feature sibling # deps land with their first consuming wave, which for alktty/alkgit is # the wave-3 config fields and for alktunnels `w3-tunnel-direct`, the # route-1 bridge). default = [] session = ["dep:alktty", "dep:serde_json", "dep:bytes"] git = ["dep:alkgit"] tunnel = ["dep:alktunnels"] sftp = [] [dependencies] # async-trait (the alkcall precedent) makes the injected handles # dyn-compatible (`Arc`) — the HostKeyPolicy dial handle needs # that, and native AFIT traits are not object-safe at this toolchain. async-trait = "0.1" # ADR-002: aws-lc-rs only; default features off — no flate2, no rsa # (ed25519-only; the tree stays RC-free except the ssh-key pin riding the # russh keys path). Never enable russh's `des`/`dsa` features. russh = { version = "0.65", default-features = false, features = ["aws-lc-rs"] } alkcall = "0.10" alkvault = "0.1" # Wave-3 seam-handle types (`config.rs`'s `SessionSeam`/`GitSeam`). # Pins verified against crates.io (2026-10-28): alktty 0.8.1, alkgit # 0.1.0 — both MIT OR Apache-2.0, both rust_version 1.88 ≤ our 1.89, # both over alkcall ^0.10 (shared with our `alkcall = "0.10"` → 0.10.1 # resolution). alktty's `local` feature stays off — alkssh never # touches a real backend; the `local` shapes stay alktty-side. alktty = { version = "0.8.1", default-features = false, optional = true } alkgit = { version = "0.1.0", default-features = false, optional = true } # tunnel-only: the route-1 bridge's consumer surface (`TunnelSession:: # open_direct`/`take_halves`, `SubstrateAddr`/`Substrate`). Pin # re-verified against crates.io at `w3-tunnel-direct` (2026-10-29): # 0.4.1 is `max_stable_version`/`newest_version`, MIT OR Apache-2.0, # rust_version 1.88 ≤ our 1.89, alkcall ^0.10.1 pinned exactly # (single-versioned against our `alkcall = "0.10"`). The `local` # feature stays off — the dial seam is injected (`DialFn`); the real # dial/backends belong to the assembly, and the tests hand-roll their # own dial/dial-fail seams (`tests/tunnel_mapping.rs`). alktunnels = { version = "0.4.1", default-features = false, optional = true } # session-only: the OQ-44 reserved ttymodes JSON (`TerminalParamsWire.modes`) # and the exit-chunk / negotiation-error-frame JSON reads in `tty_map.rs`. # Same pin alktty carries (crate resolution stays single-versioned). serde_json = { version = "1", optional = true } # session-only: the alktty chunk plane is `bytes`-based (`Chunk.bytes`) — # the bridge builds sentinel/ctrl chunks with it. Same pin russh/alktty # carry (crate resolution stays single-versioned). bytes = { version = "1", optional = true } tokio = { version = "1.54", features = ["full"] } thiserror = "2.0" tracing = "0.1" parking_lot = "0.12" zeroize = "1.9" [dev-dependencies] # The git-seam test doubles name `GitPackGen`'s `gix_hash::ObjectId` # parameters and alkgit does not re-export them — test-graph only, # version matched to alkgit's `^0.28` req (same crate in the lockfile). gix-hash = { version = "0.28", features = ["sha1"] } # The session shim's scripted stdout/stderr streams ride tokio's # `ReceiverStream` — test-graph only (the crate proper hand-rolls no # streams). tokio-stream = "0.1" # The leg-2 fabric double's establisher/params serialization # (`w3-tunnel-listen`) — test-graph only (the door's own lib code # stays serde-free under the `tunnel` feature; the double's # dynamic-bind producer serializes params/reply fields). serde_json = "1" # The real-tool pty smoke (`w3-tty-session`): alktty's `local` backend # composition — the dev-dep `features = ["local"]` unification applies # to the TEST graph only (feature unification folds `local` into the # optional alktty dep in test builds; the published lib never enables # it and `src/` never names a local shape). Same 0.8.1 pin. alktty = { version = "0.8.1", default-features = false, features = ["local"] } [profile.release] lto = "thin"