- install_forwarded_surface registers register_tunnel_forwarded_openable_with_establisher (ADR-008 Amendment 2's recommended shape) with a ForwardedGate capturing the ListenRouter: a stale/missing listen token fails the open typed at the call plane (channel:open_failed, unknown_resource) BEFORE any channel is born — the phantom-channel shape is closed at the open; malformed arrivals are likewise typed (handler_error) instead of success-then-silent-birth-teardown. - the arrival pump's handler-side correlation re-lookup stays as the residual-race + cap-admission teardown-at-birth fallback (the base shape's posture, retained; the narrow gate-pass->handler-run race documented on the pump). - the unscoped-arrival ACL row double-pins the pinned gate order (ACL before establisher — a genuinely minted token refused by ACL alone). - rows: a_correlation_miss_fails_the_open_typed_before_any_channel (miss: typed refusal, no phantom channel, no acceptor row), a_gate_pass_arrival_serves_the_route_unchanged (the serving flow unchanged), and the lib unit pin the_pump_residual_miss_teardown_at_births_the_fabric_half. - the harness opener now maps the wire refusal's details.reason back into the TunnelEstablishError taxonomy (the real opener's map) — the flat HandlerError swallow would erase exactly what the gate rows pin. Verification: cargo test --all-features --test tunnel_mapping (22, incl. both real-tool smokes), cargo test --features tunnel --lib tunnel_map, full cargo test (default + --all-features), clippy x2 -D warnings, fmt.
alkssh
SSH adapter for the alk family: a thin wrapper around
russh terminating the vanilla-ssh wire and
bridging to/from alkcall channels — the SSH counterpart of the
alkhttp adapter (family ADR-003). Vanilla clients terminate vanilla
ssh; family protocol halves (alktty, alktunnels, alkgit) receive their
own chunk planes; the door itself speaks no family protocol and owns
no deployment policy.
The crate is a door, not a backend: no binary, no front doors — a
downstream app (alkforge) embeds it, enables the features it wants,
and brings identity/ACL configuration and the family fabric handles.
It is two-directional: a server mount serves vanilla ssh into the
family, and a dial points family ops at a vanilla sshd.
The feature graph — fail-closed
default = [] by design: a default build has no capabilities and
can serve nothing but clean declines. Every channel-type mapping is
a cargo feature; each feature is flat and independent (no feature
implies another):
| Feature | Maps | Family protocol |
|---|---|---|
session |
pty / shell / exec (pipe) rows → chunk-framed session | alktty |
git |
the exec-only git rows (git-{upload,receive}-pack) |
alkgit |
tunnel |
direct-tcpip / direct-streamlocal, the -R legs |
alktunnels |
sftp |
reserved decline placeholder (OQ-13) — always declines until the alkfs mapping lands | — |
Non-mapped surface (x11, auth-agent, the env request, git subsystem
requests, sftp until alkfs) declines fail-closed in every build:
never a half-capability, never a silent fallback, and never advertised
— an unfeatured channel type is declined, not advertised. A request
whose config fields are unset declines too (an unset seam or shell
argv configures nothing — the feature alone is not a capability).
Usage
The assembly injects the seams: an alkcall
IdentityProvider (verified fingerprint → identity), key sources, and
the per-feature family handles. The examples below are the crate's
compile-checked doctests (see the crate docs in src/lib.rs).
A server mount — per accepted TCP connection, run the door:
use std::sync::Arc;
use async_trait::async_trait;
struct Identity;
impl alkcall::core::auth::IdentityProvider for Identity {
fn resolve_from_fingerprint(&self, _: &str) -> Option<alkcall::core::auth::Identity> {
None // the assembly's registry decides
}
fn resolve_from_token(&self, _: &alkcall::core::auth::AuthToken) -> Option<alkcall::core::auth::Identity> {
None
}
}
struct HostKeys;
#[async_trait]
impl alkssh::HostKeySource for HostKeys {
async fn load(&self) -> Result<Vec<russh::keys::PrivateKey>, alkssh::KeySourceError> {
Err(alkssh::KeySourceError::Absent) // sketch; vault-backed in prod
}
}
let serve = alkssh::ServeConfig::new(Arc::new(Identity), Arc::new(HostKeys));
let adapter = alkssh::SshAdapter::new(serve).await?;
// per accepted TCP connection from the assembly's listener:
// adapter.handle(stream).await?;
A dial — family ops pointed upstream at a vanilla server:
use std::sync::Arc;
use async_trait::async_trait;
struct DialKey;
#[async_trait]
impl alkssh::KeySource for DialKey {
async fn load(&self) -> Result<russh::keys::PrivateKey, alkssh::KeySourceError> {
Err(alkssh::KeySourceError::Absent) // sketch; vault-backed in prod
}
}
let conn = alkssh::dial(alkssh::DialConfig::new(
"hub.example:22",
"runner",
Arc::new(DialKey),
Arc::new(alkssh::RejectAll),
))
.await?;
// op rows (under their features): conn.exec, conn.tunnel_direct,
// conn.git_service, conn.reverse_listen — see the crate docs.
conn.close().await; // clean disconnect — drop is never the clean path
Minimal builds compile and doctest with no features enabled —
$ cargo build
$ cargo test
— and every capability row additionally rides its feature build (the
matrix: no features / git / session / tunnel / sftp /
--all-features).
Key custody and security posture
- Keys are sources, never static material (alknet-main's
mainkey model, ADR-005): the dial/host key seams are decrypt-at-use handles over an injectedalkvaultservice — keys held encrypted at rest, decrypted at use, zeroized through the seam. The vault is a secret store on this path, not a key generator. - No env vars, no config-file key material, no secrets on the wire. The standing family posture (family ADR-002 decision 5).
- Publickey-only authentication, exactly one attempt — no password, keyboard-interactive, cert, or fallback methods exist on the surface.
- Host-key trust is assembly policy: the crate ships a
HostKeyPolicyseam with a fail-closed default (RejectAll— a dial with it connects to nothing) and no accept-all built-in; any permissive policy is the assembly's to write. - Injected identity: every wire-exposed op is checked against
alkcall's
AccessControl::check(peer_identity); internal ops are never wire-callable; there is no unauthenticated capability. - Bounded resources everywhere (
Limits— wall clock always set, channel caps, listener caps, window/packet budgets, auth attempt limit): the crate never constructs an unbounded session. Known, recorded limits ride the published docs (the crate-root rustdoc §Known limits). - Every disabled feature declines: the decline matrix is contract territory tested in every build.
Documentation
- Crate docs:
cargo doc --open(the crate-root docs carry the feature graph and the known-limits records). docs/architecture/— the authoritative contract: the spec (overview.md,mapping.md,client.md,auth.md), ADRs 001–006, and the open-questions tracker.
License
MIT OR Apache-2.0 — see LICENSE-MIT / LICENSE-APACHE.