# Anvil
**Pure-Rust SSH stack for Git tooling — transport, keys, signing, agent.**
Anvil is the foundation library extracted from [Steelbore/Gitway](https://github.com/steelbore/gitway). It packages everything Git needs from SSH, and nothing it doesn't: pinned-host transport, key generation, SSHSIG commit signing, and an SSH agent (client + daemon). Pure Rust end to end. No C runtime at link time. `#![forbid(unsafe_code)]` in project-owned code.
## Status
`v0.1.0` — initial cold-start extraction from Steelbore/Gitway @ `28abee6`. Pre-1.0; the public type names will rename in `0.2.0` (see [CHANGELOG](CHANGELOG.md)). Full v1.0 scope and roadmap live in the [Gitway PRD](https://github.com/steelbore/gitway/blob/main/Gitway-PRD-v1.0.md).
## Use
```toml
[dependencies]
anvil-ssh = "0.1"
```
```rust,no_run
use anvil_ssh::{AnvilConfig, AnvilSession};
#[tokio::main]
async fn main() -> Result<(), anvil_ssh::AnvilError> {
let config = AnvilConfig::github();
let mut session = AnvilSession::connect(&config).await?;
session.authenticate_best(&config).await?;
let exit_code = session.exec("git-upload-pack 'steelbore/gitway.git'").await?;
session.close().await?;
Ok(())
}
```
The flat re-exports `AnvilSession` / `AnvilConfig` / `AnvilError` were renamed in `0.2.0` from the legacy `GitwaySession` / `GitwayConfig` / `GitwayError` (which were carried over from the source crate to keep the 0.1.0 extraction zero-rename). The legacy names remain available as `#[deprecated]` re-exports for one major version per [Gitway PRD §7.4](https://github.com/steelbore/gitway/blob/main/Gitway-PRD-v1.0.md); they will be removed in `1.0.0`. Migration is mechanical — `s/Gitway/Anvil/g` in your `use anvil_ssh::*;` imports.
## Modules
| Module | Purpose |
| --------------------- | ---------------------------------------------------------------- |
| `session` | russh-backed SSH session lifecycle |
| `auth` | Identity discovery (CLI flag → `~/.ssh` paths → SSH agent) |
| `hostkey` | Pinned host fingerprints (GitHub, GitLab, Codeberg) |
| `relay` | Bidirectional stdin/stdout/stderr relay over an exec channel |
| `keygen` | Ed25519 / ECDSA / RSA keypair generation in OpenSSH format |
| `sshsig` | SSHSIG sign / verify / `find-principals` / `check-novalidate` |
| `allowed_signers` | Parser for git's `allowed_signers` file format |
| `agent::client` | Blocking SSH agent client (`ssh-add` equivalent) |
| `agent::daemon` | Async SSH agent server (`ssh-agent` equivalent) |
| `agent::askpass` | `$SSH_ASKPASS`-driven interactive confirmation |
| `diagnostic` | Single-line stderr failure diagnostic helper |
| `time` | ISO 8601 timestamp helpers (no `chrono` / `time` crate dep) |
## Crypto backends
Anvil layers two pure-Rust crypto stacks:
- **Transport** — [`russh`](https://github.com/warp-tech/russh) with the `aws-lc-rs` backend (post-quantum-ready; no CMake on non-FIPS builds).
- **Keys + signing** — RustCrypto (`ed25519-dalek`, `rsa`, `p256/384/521`) via [`ssh-key`](https://github.com/RustCrypto/SSH).
`PrivateKey` values never cross the boundary between the two stacks.
## Build
```sh
cargo build --release
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check
```
`perl` is required by `aws-lc-rs` for assembly pre-processing on every platform; `nasm` is also required on Windows MSVC.
## License
GPL-3.0-or-later. Copyright © 2026 Mohamed Hammad. See [LICENSE](LICENSE).
## Related
- [Steelbore/Gitway](https://github.com/steelbore/gitway) — primary consumer; the full Git-over-SSH toolkit (`gitway`, `gitway-keygen`, `gitway-add` binaries) built on top of Anvil.