Guidelines for AI agents working in the Anvil codebase.
Pure-Rust SSH stack for Git tooling: transport, keys, signing, agent. Foundation library extracted from Spacecraft-Software/Gitway; primary consumer is the Gitway CLI binaries (gitway, gitway-keygen, gitway-add).
- Follow the Spacecraft Software Rust Guidelines (invoke
/rust-guidelinesskill before any Rust edit). - All new Rust files must begin with
// SPDX-License-Identifier: GPL-3.0-or-later. - All public types must implement
Debug(derive or custom). - Use
#[expect(..., reason = "...")]instead of#[allow(...)]for lint suppression. - Comments must be in American English.
- Passphrase-holding strings must always use
Zeroizing<String>.
- No
unsafecode. The crate enforces#![forbid(unsafe_code)]. - No
from_utf8_lossyon passphrase data — usefrom_utf8and return an error on non-UTF-8 output. - No relative
SSH_ASKPASSpaths — the code already enforces absolute paths; do not relax this check. - No new panic sites unless the invariant is genuinely unreachable (document why).
- No TOFU (Trust On First Use) for host key verification of known providers.
- Find the provider's official SSH host key fingerprint documentation page.
- Add
const DEFAULT_<PROVIDER>_HOST: &strandconst <PROVIDER>_FINGERPRINTStosrc/hostkey.rs. - Add a
fingerprints_for_hostmatch arm covering the new host constant. - Add a
AnvilConfig::<provider>()convenience constructor insrc/config.rs. - Add tests for the new provider in
hostkey.rs. - Update
CLAUDE.mdwith the new fingerprint rotation URL. - Open a PR; downstream consumers (Gitway and friends) bump their pinned
anvil-sshversion on next release.
- No new crates without discussion. The dependency tree is intentionally narrow.
serde(with derive) is intentionally absent — JSON output is the consumer's concern, not the library's.chronoandtimeare intentionally absent — ISO 8601 timestamps use the dependency-free helpers intime.rs.- Do not switch the russh crypto backend from
aws-lc-rstoring.
- Unit tests live inline in each module.
- Integration tests in
tests/:test_connection.rs— gated network test (GITWAY_INTEGRATION_TESTS=1)test_clone.rs— full git clone end-to-end (also network-gated)
- Run hermetic tests with
cargo test; network tests withGITWAY_INTEGRATION_TESTS=1 cargo test -- --ignored.
v0.1.x— types carried over from the source crate asGitwaySession/GitwayConfig/GitwayErrorto keep the lift-and-shift extraction zero-rename.v0.2.0— types renamed toAnvilSession/AnvilConfig/AnvilError. LegacyGitway*names retained as#[deprecated]re-exports.v1.0.0(current) — stabilization, cut concurrently with Gitway 1.0.0. DeprecatedGitway*aliases kept through the 1.x line. This is a deliberate softening of the original roadmap (which had proposed removing them at 1.0): the correspondinggitway-libshim re-exportsanvil_ssh::*glob-style and is preserved through Gitway 1.x per Gitway'sdocs/migration-from-v0.9.md. Removing the upstream aliases at 1.0 would silently break that shim.v2.0.0(planned) — deprecatedGitway*aliases removed.
SemVer. As of v1.0.0, the public API is frozen under SemVer:
- Patch bumps (
1.0.x) are bug fixes only — no API additions. - Minor bumps (
1.x.0) may add new public symbols; existing ones never change shape or behavior. - Major bumps (
x.0.0) are reserved for breaking changes and are coordinated with downstream consumers (primarily Gitway).
See CHANGELOG.md for the cumulative record.