feat(config): land the wave-3 per-feature family-seam handles (w3-seam-config)
- ServeConfig gains cfg-gated SessionSeam / GitSeam Option fields (whole-Option struct per seam — the shape decision recorded in the task notes): unset → the owned rows decline even though the feature is on, no construction-time validation - SessionSeam carries the alktty backends map + backend selector + ownership provider; GitSeam carries the alkgit backend quartet + caller-owned pipeline semaphore + push_options_negotiated - optional deps alktty 0.8.1 / alkgit 0.1.0 wired feature-to-dep (pins verified against crates.io: licenses, MSRV, shared alkcall resolution); gix-hash 0.28 as dev-dep only (alkgit does not re-export ObjectId for the trait doubles) - per-feature construction/unset-declines/Debug rows in config.rs; accessors session_seam_configured / git_seam_configured; docs state what each seam handle carries Verified: cargo test (per-feature + --all-features), clippy ×2 (-D warnings), fmt, cargo doc --no-deps, cargo tree feature isolation (git-build: no alktty; session-build: no alkgit), taskgraph validate
This commit is contained in:
1 parent
d1f755f2d9
commit
270365ea4c
5 files changed
+1351
-21
No files matched your search
Generated
+788
-4
@@ -83,13 +83,40 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alkgit"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f81d274e66dc4977171951a3cdf63f7a1b87179387a486e58130662d4b456ab6"
|
||||||
|
dependencies = [
|
||||||
|
"alkcall",
|
||||||
|
"async-trait",
|
||||||
|
"bstr",
|
||||||
|
"bytes",
|
||||||
|
"futures",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-packetline",
|
||||||
|
"gix-protocol",
|
||||||
|
"gix-transport",
|
||||||
|
"gix-validate",
|
||||||
|
"parking_lot",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkssh"
|
name = "alkssh"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alkcall",
|
"alkcall",
|
||||||
|
"alkgit",
|
||||||
|
"alktty",
|
||||||
"alkvault",
|
"alkvault",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"gix-hash",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"russh",
|
"russh",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -98,6 +125,26 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alktty"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2265167842b7d3ea09bc235f48450d3dcf22049a2ca71f8155de00acbf97c226"
|
||||||
|
dependencies = [
|
||||||
|
"alkcall",
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"futures",
|
||||||
|
"futures-core",
|
||||||
|
"libc",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alkvault"
|
name = "alkvault"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -258,6 +305,12 @@ dependencies = [
|
|||||||
"hex-conservative",
|
"hex-conservative",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.13.2"
|
version = "2.13.2"
|
||||||
@@ -317,6 +370,17 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c"
|
checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.3"
|
version = "3.20.3"
|
||||||
@@ -560,6 +624,46 @@ version = "2.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
|
checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "0.3.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4deef977660e373c458df605a913d4ab121db0ccd18d1ad6976dff7d37cddb53"
|
||||||
|
dependencies = [
|
||||||
|
"defmt 1.2.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4a0795ac740cb54d7b3775c9c17345f6aaecf884c01733b39d6017738e0e3e1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"defmt-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-macros"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "840bb056bd99c495c9188198a258ab787c79f306d864db3e6e8451442d6d8366"
|
||||||
|
dependencies = [
|
||||||
|
"defmt-parser",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.9",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-parser"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71958f69fb2de856c5dd51ac9377e986ca1aa5919f931bf5395a807277f889a0"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "delegate"
|
name = "delegate"
|
||||||
version = "0.13.5"
|
version = "0.13.5"
|
||||||
@@ -751,6 +855,24 @@ dependencies = [
|
|||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "faster-hex"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04839bdf9d8c10f66806fad16b852fc72aab80873aebc3cb69d85b4fa41543ed"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"defmt 0.3.101",
|
||||||
|
"heapless",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ff"
|
name = "ff"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
@@ -854,6 +976,19 @@ version = "0.3.34"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
|
checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-lite"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"parking",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.34"
|
version = "0.3.34"
|
||||||
@@ -964,6 +1099,440 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-actor"
|
||||||
|
version = "0.44.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78243d3371019288a40a75ba1a58de2815c32591fc87b9f7cb01918bce364ca8"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-chunk"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc6a775aba54f0d65698126cc4214b6bf8ddb208312e4ef4240dfe34b0697b87"
|
||||||
|
dependencies = [
|
||||||
|
"gix-error",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-command"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df63215f103299169e239dfe76f5cfa4a3d6d4adf69a01774085e3e0423cba34"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-path",
|
||||||
|
"gix-quote",
|
||||||
|
"gix-trace",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-commitgraph"
|
||||||
|
version = "0.41.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfede9936d4b789867c09722576aea4ceb0e3aacf962eef035ebab0686b41a80"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-chunk",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"memmap2",
|
||||||
|
"nonempty",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-config-value"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6cdada8bd9c97dc6522505c08226d9c88f0a1286f2c06b9e1bf51c3bf7ad7b2b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.2",
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-path",
|
||||||
|
"gix-utils",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-credentials"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8487f709886267337ee39231a5e68f3c6a4e28fd59e056fc9e66e9638941c633"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-command",
|
||||||
|
"gix-config-value",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
"gix-path",
|
||||||
|
"gix-prompt",
|
||||||
|
"gix-quote",
|
||||||
|
"gix-sec",
|
||||||
|
"gix-trace",
|
||||||
|
"gix-url",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-date"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c538190012dbb536df54734ec38cc1109270c73f2f76585c011dd5b0c9f087c"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"itoa",
|
||||||
|
"jiff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-error"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d87ff4b3f3daf01234d38d176b0ec00e92de514cc0e3fb8a8898c5cb7ccd22bb"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-fs"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "808f23d897ddfe847d9b7206bda947901885be623bdf96b226a2dccf87f018c7"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-parallel",
|
||||||
|
"gix-path",
|
||||||
|
"gix-utils",
|
||||||
|
"libc",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-hash"
|
||||||
|
version = "0.28.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4802ffb87e051795822bfdaa8ab9075b23e316684f7054e6ce4a246b2b76f4e"
|
||||||
|
dependencies = [
|
||||||
|
"faster-hex",
|
||||||
|
"gix-error",
|
||||||
|
"gix-utils",
|
||||||
|
"sha1dc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-hashtable"
|
||||||
|
version = "0.18.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f66822aee11ccb28d6a2e63b587254e578fb52a138bd5806b58d8560125592b"
|
||||||
|
dependencies = [
|
||||||
|
"gix-hash",
|
||||||
|
"hashbrown 0.17.1",
|
||||||
|
"parking_lot",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-lock"
|
||||||
|
version = "26.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64783de116c477c5ea4a7f3b56e18ab363dabfdae2724291ea0587b642cadb3d"
|
||||||
|
dependencies = [
|
||||||
|
"gix-error",
|
||||||
|
"gix-fs",
|
||||||
|
"gix-tempfile",
|
||||||
|
"gix-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-macros"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f11f5429ca73cc3758c9f53af56a9fba100a8701c5b4bc30e29b8b0b15288991"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-negotiate"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ddfb0d6da849bd938d929336e07c1f26970d9f6ec59621df74ec3f79c128ea"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.2",
|
||||||
|
"gix-commitgraph",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-object",
|
||||||
|
"gix-revwalk",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-object"
|
||||||
|
version = "0.66.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "beaf9086dd00b9d2a177ca3ae83210ce926cee7c0faa112e053851221cd8f94d"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-actor",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-hashtable",
|
||||||
|
"gix-utils",
|
||||||
|
"gix-validate",
|
||||||
|
"itoa",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-packetline"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ebb59ef7aff9d435946a5e5c3d9cfb673be7665839fd72961c08c733a934fb7"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"faster-hex",
|
||||||
|
"futures-io",
|
||||||
|
"futures-lite",
|
||||||
|
"gix-error",
|
||||||
|
"gix-trace",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-parallel"
|
||||||
|
version = "0.50.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "58e7e10f8343e05f6ad8651f97dffa1caca1531bb274bfc8e3050e80e3ed5946"
|
||||||
|
dependencies = [
|
||||||
|
"gix-trace",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-path"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83976e926a485e6fb4b8d9a0d7a30c53c1f607b81b5d310f06f92fd8385bf16a"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-trace",
|
||||||
|
"gix-validate",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-prompt"
|
||||||
|
version = "0.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d9650eedebb85e55577831db217403333416573356de722a040415c416f1cec"
|
||||||
|
dependencies = [
|
||||||
|
"gix-command",
|
||||||
|
"gix-config-value",
|
||||||
|
"gix-error",
|
||||||
|
"parking_lot",
|
||||||
|
"rustix",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-protocol"
|
||||||
|
version = "0.67.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "832b5dc46a3c0a6f6fa8f8e571c11074add4b545c6789799ae6d6c36ae1a294e"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bstr",
|
||||||
|
"futures-io",
|
||||||
|
"futures-lite",
|
||||||
|
"gix-credentials",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-lock",
|
||||||
|
"gix-macros",
|
||||||
|
"gix-negotiate",
|
||||||
|
"gix-object",
|
||||||
|
"gix-ref",
|
||||||
|
"gix-refspec",
|
||||||
|
"gix-revwalk",
|
||||||
|
"gix-shallow",
|
||||||
|
"gix-trace",
|
||||||
|
"gix-transport",
|
||||||
|
"gix-utils",
|
||||||
|
"nonempty",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-quote"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2413e65271303e9b674ec4785d469df4c3c36e888dbd165e3035de0405c6d9d1"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-ref"
|
||||||
|
version = "0.69.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68686e4697b9cd15d1b152ef51df870513210ed22938eacc13b3672b76035f13"
|
||||||
|
dependencies = [
|
||||||
|
"gix-actor",
|
||||||
|
"gix-error",
|
||||||
|
"gix-fs",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-lock",
|
||||||
|
"gix-object",
|
||||||
|
"gix-parallel",
|
||||||
|
"gix-path",
|
||||||
|
"gix-tempfile",
|
||||||
|
"gix-utils",
|
||||||
|
"gix-validate",
|
||||||
|
"memmap2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-refspec"
|
||||||
|
version = "0.47.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2569309da6fdc230973cf5b846508154c0e813fda60f2b2da768cc5655ed312c"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-validate",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-revwalk"
|
||||||
|
version = "0.37.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "800479fbbf1e7f94f663e07943a91add5499343e7aac611a81e6a0460fd44af6"
|
||||||
|
dependencies = [
|
||||||
|
"gix-commitgraph",
|
||||||
|
"gix-date",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-hashtable",
|
||||||
|
"gix-object",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-sec"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9598d1f35baec7038c2d278bfcc18f1d8951f41dcc3f51ab6175661dfe5a6137"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.2",
|
||||||
|
"gix-path",
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-shallow"
|
||||||
|
version = "0.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d805949578724b5164c90ec6d19567832ccaa5ba8a3fe26f7befc52007e2407"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-hash",
|
||||||
|
"gix-lock",
|
||||||
|
"nonempty",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-tempfile"
|
||||||
|
version = "26.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8fdb135a043d6106b59bc58d59a326b277e495ec26fb9e02a1e2b6354bf4b5a"
|
||||||
|
dependencies = [
|
||||||
|
"gix-fs",
|
||||||
|
"libc",
|
||||||
|
"parking_lot",
|
||||||
|
"tempfile",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-trace"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c477c029518d3f235c26db21ff7cccc1fa13c0c31b05c005a55b7affd4ffbd81"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-transport"
|
||||||
|
version = "0.61.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e43d6b0097ea9f2f266d5d6c43b8f615ed3da7c686ec8771cd17c1cb33cb0de"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bstr",
|
||||||
|
"futures-io",
|
||||||
|
"futures-lite",
|
||||||
|
"gix-command",
|
||||||
|
"gix-error",
|
||||||
|
"gix-packetline",
|
||||||
|
"gix-path",
|
||||||
|
"gix-quote",
|
||||||
|
"gix-sec",
|
||||||
|
"gix-trace",
|
||||||
|
"gix-url",
|
||||||
|
"gix-utils",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-url"
|
||||||
|
version = "0.40.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "def12e1016b872f1094442882f627905c59bd73480435291a4958cf373a8f28d"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
"gix-path",
|
||||||
|
"gix-utils",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-utils"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11a9446060447e9ec58f5d333b98bed53389dfa10de5d8dd46fc76d01dfc2954"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"fastrand",
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"prodash",
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gix-validate"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b617c17754bf37ee7a9b48e33ffb806abecbbed779ba415199ac1480acf699"
|
||||||
|
dependencies = [
|
||||||
|
"bstr",
|
||||||
|
"gix-error",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "group"
|
name = "group"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
@@ -975,6 +1544,15 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
@@ -986,6 +1564,22 @@ dependencies = [
|
|||||||
"foldhash",
|
"foldhash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
|
dependencies = [
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex"
|
name = "hex"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -1190,6 +1784,60 @@ version = "1.0.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff"
|
||||||
|
version = "0.2.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2b005715dcbeb0089a3c0dab99f2ff1cc3b2525323552703d648585d342a383"
|
||||||
|
dependencies = [
|
||||||
|
"defmt 1.2.0",
|
||||||
|
"jiff-core",
|
||||||
|
"jiff-static",
|
||||||
|
"jiff-tzdb-platform",
|
||||||
|
"log",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"serde_core",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-core"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c"
|
||||||
|
dependencies = [
|
||||||
|
"defmt 1.2.0",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-static"
|
||||||
|
version = "0.2.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2cc9817253cf7c7ee4684451bd327e88d6f3658014e54a29198625590650695c"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-core",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa8377070c6bae868759445e5a77f66d84f0b72f3a054bfb00e6d038b8282da7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb-platform"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-tzdb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.35"
|
version = "0.1.35"
|
||||||
@@ -1279,6 +1927,12 @@ version = "0.2.191"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
@@ -1312,6 +1966,15 @@ version = "2.8.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memmap2"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b0ca1155a9ecc25aa12e8313a119f32edf0255fea2f44839c4ac0a12b2ac157"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "micromap"
|
name = "micromap"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -1361,12 +2024,18 @@ version = "0.31.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nonempty"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@@ -1530,6 +2199,12 @@ dependencies = [
|
|||||||
"windows-strings",
|
"windows-strings",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.5"
|
version = "0.12.5"
|
||||||
@@ -1661,6 +2336,21 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@@ -1715,6 +2405,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prodash"
|
||||||
|
version = "31.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf52d87428247c5aa3760ac8e7d8b13ec7b3579b955a8c3f311668b6860acba5"
|
||||||
|
dependencies = [
|
||||||
|
"parking_lot",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.47"
|
version = "1.0.47"
|
||||||
@@ -1789,7 +2488,7 @@ version = "0.5.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1821,7 +2520,7 @@ dependencies = [
|
|||||||
"ahash",
|
"ahash",
|
||||||
"fluent-uri",
|
"fluent-uri",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
"hashbrown",
|
"hashbrown 0.16.1",
|
||||||
"itoa",
|
"itoa",
|
||||||
"micromap",
|
"micromap",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
@@ -1876,7 +2575,7 @@ checksum = "3bb77a4b259312b2abbc541bca1c13cb4e9b61c560a7fd894068c3b92e0c9dc3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"bitflags",
|
"bitflags 2.13.2",
|
||||||
"block-padding",
|
"block-padding",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1969,6 +2668,19 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "1.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5e76742e5294153d4dde1207dbec5bdd81eef6fabdc0d2118babadabfd858aa"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.2",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.23"
|
version = "1.0.23"
|
||||||
@@ -1985,6 +2697,15 @@ dependencies = [
|
|||||||
"cipher",
|
"cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@@ -2087,6 +2808,12 @@ dependencies = [
|
|||||||
"digest 0.11.3",
|
"digest 0.11.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1dc"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5b0ebf6537e3e8db8bb7d21ecb6d7399738c953c757945c6b95e46c4e95df7b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.9"
|
version = "0.10.9"
|
||||||
@@ -2297,6 +3024,19 @@ dependencies = [
|
|||||||
"syn 3.0.9",
|
"syn 3.0.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand",
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"once_cell",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.21"
|
version = "2.0.21"
|
||||||
@@ -2361,6 +3101,31 @@ dependencies = [
|
|||||||
"syn 3.0.9",
|
"syn 3.0.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@@ -2484,6 +3249,16 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
|
checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
@@ -2555,6 +3330,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.62.2"
|
version = "0.62.2"
|
||||||
|
|||||||
+21
-5
@@ -26,12 +26,16 @@ name = "alkssh"
|
|||||||
[features]
|
[features]
|
||||||
# ADR-003: flat and independent — no feature implies another; `default = []`
|
# ADR-003: flat and independent — no feature implies another; `default = []`
|
||||||
# by design (a default build has no capabilities; every unfeatured open
|
# by design (a default build has no capabilities; every unfeatured open
|
||||||
# declines fail-closed). Features gate nothing yet — the wave-2 decline core
|
# declines fail-closed). The wave-2 decline core is the first `cfg`
|
||||||
# is their first consumer; the per-feature sibling deps land with their
|
# consumer; the wave-3 seam-config handles are the second (each optional
|
||||||
# first consuming wave.
|
# 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; alktunnels still lands with its first
|
||||||
|
# consuming code, w3-tunnel-direct).
|
||||||
default = []
|
default = []
|
||||||
session = []
|
session = ["dep:alktty"]
|
||||||
git = []
|
git = ["dep:alkgit"]
|
||||||
tunnel = []
|
tunnel = []
|
||||||
sftp = []
|
sftp = []
|
||||||
|
|
||||||
@@ -46,6 +50,14 @@ async-trait = "0.1"
|
|||||||
russh = { version = "0.65", default-features = false, features = ["aws-lc-rs"] }
|
russh = { version = "0.65", default-features = false, features = ["aws-lc-rs"] }
|
||||||
alkcall = "0.10"
|
alkcall = "0.10"
|
||||||
alkvault = "0.1"
|
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 }
|
||||||
tokio = { version = "1.54", features = ["full"] }
|
tokio = { version = "1.54", features = ["full"] }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
@@ -53,6 +65,10 @@ parking_lot = "0.12"
|
|||||||
zeroize = "1.9"
|
zeroize = "1.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[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"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "thin"
|
lto = "thin"
|
||||||
+429
-5
@@ -8,8 +8,12 @@
|
|||||||
//! - [`ServeConfig`] — the server direction's assembly-supplied serving
|
//! - [`ServeConfig`] — the server direction's assembly-supplied serving
|
||||||
//! configuration: the OQ-08 fields ([`ServeConfig::shell_argv`] /
|
//! configuration: the OQ-08 fields ([`ServeConfig::shell_argv`] /
|
||||||
//! [`ServeConfig::exec_wrapper_argv`]), the injected identity,
|
//! [`ServeConfig::exec_wrapper_argv`]), the injected identity,
|
||||||
//! host-key and tunnel handles, the OQ-09 `cwd`/`env` values, and the
|
//! host-key and tunnel handles, the per-feature family-seam handles
|
||||||
//! [`Limits`].
|
//! (the wave-3 extension — [`SessionSeam`] carries the alktty
|
||||||
|
//! backends map + backend selector + ownership provider;
|
||||||
|
//! [`GitSeam`] carries the alkgit backend quartet + the caller-owned
|
||||||
|
//! pipeline + the push-options flag), the OQ-09 `cwd`/`env` values,
|
||||||
|
//! and the [`Limits`].
|
||||||
//! - [`DialConfig`] — the client direction's dial configuration
|
//! - [`DialConfig`] — the client direction's dial configuration
|
||||||
//! (`client.md` §The dial surface): address, key source, host-key
|
//! (`client.md` §The dial surface): address, key source, host-key
|
||||||
//! policy, and the bounded-resource knobs (carried by [`Limits`]).
|
//! policy, and the bounded-resource knobs (carried by [`Limits`]).
|
||||||
@@ -22,7 +26,14 @@
|
|||||||
//! request time (wave-2/3 consumption), never a fallback, never
|
//! request time (wave-2/3 consumption), never a fallback, never
|
||||||
//! construction-time validation (`error.rs`'s no-config-error
|
//! construction-time validation (`error.rs`'s no-config-error
|
||||||
//! contract). No construction-time validation exists in this
|
//! contract). No construction-time validation exists in this
|
||||||
//! module.
|
//! module. The wave-3 seam handles extend the same rule per
|
||||||
|
//! feature: [`ServeConfig::session_seam`] unset → the session rows
|
||||||
|
//! decline even though the `session` feature is on;
|
||||||
|
//! [`ServeConfig::git_seam`] unset → the git row declines even
|
||||||
|
//! though `git` is on (the decline matrix's config-driven notes;
|
||||||
|
//! the feature alone configures nothing). The tunnel handle stays
|
||||||
|
//! the flat `Option<Arc<ChannelClient>>` as landed — a single-field
|
||||||
|
//! seam needs no struct.
|
||||||
//! - **Injected handles, never crate-resolved identity or trust**:
|
//! - **Injected handles, never crate-resolved identity or trust**:
|
||||||
//! the [`IdentityProvider`], [`HostKeySource`] and
|
//! the [`IdentityProvider`], [`HostKeySource`] and
|
||||||
//! [`HostKeyPolicy`] handles are `Arc<dyn ..>` the assembly
|
//! [`HostKeyPolicy`] handles are `Arc<dyn ..>` the assembly
|
||||||
@@ -44,12 +55,20 @@
|
|||||||
//! budget model.
|
//! budget model.
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use alkcall::channels::client::ChannelClient;
|
use alkcall::channels::client::ChannelClient;
|
||||||
use alkcall::core::auth::IdentityProvider;
|
use alkcall::core::auth::IdentityProvider;
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
use alkcall::core::ownership::OwnershipProvider;
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
use alkgit::{GitPackGen, GitPackIngest, GitRefs, GitRegistry};
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
use alktty::TtyBackend;
|
||||||
|
|
||||||
use crate::host_key::HostKeyPolicy;
|
use crate::host_key::HostKeyPolicy;
|
||||||
use crate::key_source::{HostKeySource, KeySource};
|
use crate::key_source::{HostKeySource, KeySource};
|
||||||
@@ -172,6 +191,101 @@ impl Default for Limits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `session` feature's alktty seam handle (`mapping.md` §The
|
||||||
|
/// seams): what `drive_session[_pre_negotiated]` takes that the
|
||||||
|
/// assembly composes (alktty 0.8.1's `adapter.rs:205-241` signature).
|
||||||
|
/// **Shape decision** (recorded at `w3-seam-config`): a whole-`Option`
|
||||||
|
/// struct per seam, not flat `Option` fields — each seam is consumed
|
||||||
|
/// atomically by exactly one seam call, so a struct admits no
|
||||||
|
/// half-supplied seam states and the unset-declines contract reads as
|
||||||
|
/// one `Option`: **`ServeConfig::session_seam` unset → the session
|
||||||
|
/// rows decline even though the `session` feature is on** (the
|
||||||
|
/// decline matrix's config-driven note), checked at request time by
|
||||||
|
/// the mappings — no construction-time validation. Cloned into each
|
||||||
|
/// spawned serving task (all payload types `Arc` or plain data).
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SessionSeam {
|
||||||
|
/// The alktty backends map — the `TtyAdapter`-style registry keyed
|
||||||
|
/// by the `NegotiateRequest.backend` selector string. **Assembled
|
||||||
|
/// by the assembly**: alkssh never touches a real backend, and the
|
||||||
|
/// `local` backend shapes stay alktty-side (this dep's `local`
|
||||||
|
/// feature is not enabled — the map holds assembly-supplied
|
||||||
|
/// implementations of alktty's [`TtyBackend`] only).
|
||||||
|
pub backends: Arc<HashMap<String, Arc<dyn TtyBackend>>>,
|
||||||
|
/// The backend **selector** — the `NegotiateRequest.backend`
|
||||||
|
/// string alkssh writes into the locally-constructed negotiation
|
||||||
|
/// (`w3-tty-session`'s negotiation rows; the wire command/args
|
||||||
|
/// never reach it). Assembly-supplied, never wire-derived.
|
||||||
|
pub backend: String,
|
||||||
|
/// The ADR-050 ownership provider — passed through
|
||||||
|
/// `drive_session[_pre_negotiated]` verbatim (the family ACL
|
||||||
|
/// layer riding alongside; an alkcall type, no new dep).
|
||||||
|
pub ownership: Option<Arc<dyn OwnershipProvider>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
impl std::fmt::Debug for SessionSeam {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let mut keys: Vec<&String> = self.backends.keys().collect();
|
||||||
|
keys.sort();
|
||||||
|
f.debug_struct("SessionSeam")
|
||||||
|
.field("backend_keys", &keys)
|
||||||
|
.field("backend", &self.backend)
|
||||||
|
.field("ownership_set", &self.ownership.is_some())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The `git` feature's alkgit seam handle (`mapping.md` §The seams):
|
||||||
|
/// what `serve_duplex_resolved` takes that the assembly composes
|
||||||
|
/// (alkgit 0.1.0's `duplex.rs:1412-1426` signature — the four backend
|
||||||
|
/// traits, the caller-owned pipeline, the push-options gate). Same
|
||||||
|
/// whole-`Option`-struct decision as [`SessionSeam`]:
|
||||||
|
/// **`ServeConfig::git_seam` unset → the git row declines even though
|
||||||
|
/// the `git` feature is on**, checked at request time by the
|
||||||
|
/// mappings — no construction-time validation.
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct GitSeam {
|
||||||
|
/// The repo-id resolution trait (`GitRegistry::resolve`) — the
|
||||||
|
/// ADR-007 pre-protocol gate's other half; alkssh never resolves
|
||||||
|
/// (the collapsed-generic-denial posture lives in alkgit).
|
||||||
|
pub registry: Arc<dyn GitRegistry>,
|
||||||
|
/// The ref listing + CAS transaction trait
|
||||||
|
/// (`list_refs`/`apply_updates`).
|
||||||
|
pub refs: Arc<dyn GitRefs>,
|
||||||
|
/// The pack generation + negotiation-ack trait
|
||||||
|
/// (`generate`/`common_haves`).
|
||||||
|
pub packgen: Arc<dyn GitPackGen>,
|
||||||
|
/// The pack-preparation trait (`prepare` — never applies; the
|
||||||
|
/// `GitRefs::apply_updates` CAS stays the single ingestion home).
|
||||||
|
pub ingest: Arc<dyn GitPackIngest>,
|
||||||
|
/// The assembler's push-options flag (alkgit's ADR-013 §11 gate,
|
||||||
|
/// passed through verbatim) — `false` in the v1 default.
|
||||||
|
pub push_options_negotiated: bool,
|
||||||
|
/// The caller-owned, server-wide pipeline permit — alkgit's
|
||||||
|
/// pack-pipeline concurrency bound, *shared across every session
|
||||||
|
/// the serving direction takes* (the caller keeps its own handle;
|
||||||
|
/// `Arc` for the share). One per `DialConfig`-independent serve
|
||||||
|
/// direction, never per channel.
|
||||||
|
pub pipeline: Arc<tokio::sync::Semaphore>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
impl std::fmt::Debug for GitSeam {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("GitSeam")
|
||||||
|
.field("registry", &"<dyn GitRegistry>")
|
||||||
|
.field("refs", &"<dyn GitRefs>")
|
||||||
|
.field("packgen", &"<dyn GitPackGen>")
|
||||||
|
.field("ingest", &"<dyn GitPackIngest>")
|
||||||
|
.field("push_options_negotiated", &self.push_options_negotiated)
|
||||||
|
.field("pipeline_permits", &self.pipeline.available_permits())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The server direction's assembly-supplied serving configuration
|
/// The server direction's assembly-supplied serving configuration
|
||||||
/// (`overview.md` §Server stack): everything wave-2's serving loop
|
/// (`overview.md` §Server stack): everything wave-2's serving loop
|
||||||
/// takes at construction. Pure data + injected handles — no russh
|
/// takes at construction. Pure data + injected handles — no russh
|
||||||
@@ -215,6 +329,22 @@ pub struct ServeConfig {
|
|||||||
/// `NegotiateRequest.env` — **never wire-derived**. Empty by
|
/// `NegotiateRequest.env` — **never wire-derived**. Empty by
|
||||||
/// default.
|
/// default.
|
||||||
pub session_env: BTreeMap<String, String>,
|
pub session_env: BTreeMap<String, String>,
|
||||||
|
/// The `session` feature's alktty seam handle ([`SessionSeam`] —
|
||||||
|
/// the backends map + backend selector + ownership provider the
|
||||||
|
/// `drive_session[_pre_negotiated]` rows take). **Unset → the
|
||||||
|
/// session rows decline even though the `session` feature is on**
|
||||||
|
/// (the decline matrix's config-driven note; the feature alone
|
||||||
|
/// configures nothing). Wave-3 extension of the wave-1 config
|
||||||
|
/// surface — shape decision recorded on [`SessionSeam`].
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
pub session_seam: Option<SessionSeam>,
|
||||||
|
/// The `git` feature's alkgit seam handle ([`GitSeam`] — the four
|
||||||
|
/// backend traits + the caller-owned pipeline + the push-options
|
||||||
|
/// flag the `serve_duplex_resolved` row takes). **Unset → the git
|
||||||
|
/// row declines even though the `git` feature is on** (same
|
||||||
|
/// postures as [`ServeConfig::session_seam`]).
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
pub git_seam: Option<GitSeam>,
|
||||||
/// The injected identity provider (alkcall's
|
/// The injected identity provider (alkcall's
|
||||||
/// `IdentityProvider::resolve_from_fingerprint`) — the assembly
|
/// `IdentityProvider::resolve_from_fingerprint`) — the assembly
|
||||||
/// supplies it; the crate never resolves identities itself and
|
/// supplies it; the crate never resolves identities itself and
|
||||||
@@ -255,6 +385,10 @@ impl ServeConfig {
|
|||||||
exec_wrapper_argv: None,
|
exec_wrapper_argv: None,
|
||||||
session_cwd: None,
|
session_cwd: None,
|
||||||
session_env: BTreeMap::new(),
|
session_env: BTreeMap::new(),
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
session_seam: None,
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
git_seam: None,
|
||||||
identity_provider,
|
identity_provider,
|
||||||
host_key_source,
|
host_key_source,
|
||||||
channel_client: None,
|
channel_client: None,
|
||||||
@@ -284,17 +418,47 @@ impl ServeConfig {
|
|||||||
pub fn tunnel_configured(&self) -> bool {
|
pub fn tunnel_configured(&self) -> bool {
|
||||||
self.channel_client.is_some()
|
self.channel_client.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the session rows' family seam is configured in this
|
||||||
|
/// configuration ([`SessionSeam`] present; the `session` feature
|
||||||
|
/// gate applies at the dispatch on top): `false` means the rows
|
||||||
|
/// decline — the unset-declines contract, checked at request time
|
||||||
|
/// by the wave-3 mappings, never here.
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
pub fn session_seam_configured(&self) -> bool {
|
||||||
|
self.session_seam.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the git row's family seam is configured in this
|
||||||
|
/// configuration ([`GitSeam`] present; the `git` feature gate
|
||||||
|
/// applies at the dispatch on top): `false` means the row declines
|
||||||
|
/// — the unset-declines contract, checked at request time by the
|
||||||
|
/// wave-3 mappings, never here.
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
pub fn git_seam_configured(&self) -> bool {
|
||||||
|
self.git_seam.is_some()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for ServeConfig {
|
impl std::fmt::Debug for ServeConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("ServeConfig")
|
let mut debug = f.debug_struct("ServeConfig");
|
||||||
|
debug
|
||||||
.field("shell_argv", &self.shell_argv)
|
.field("shell_argv", &self.shell_argv)
|
||||||
.field("exec_wrapper_argv", &self.exec_wrapper_argv)
|
.field("exec_wrapper_argv", &self.exec_wrapper_argv)
|
||||||
.field("session_cwd", &self.session_cwd)
|
.field("session_cwd", &self.session_cwd)
|
||||||
.field("session_env", &self.session_env)
|
.field("session_env", &self.session_env)
|
||||||
.field("identity_provider", &"<dyn IdentityProvider>")
|
.field("identity_provider", &"<dyn IdentityProvider>")
|
||||||
.field("host_key_source", &"<dyn HostKeySource>")
|
.field("host_key_source", &"<dyn HostKeySource>");
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
{
|
||||||
|
debug.field("session_seam", &self.session_seam.is_some());
|
||||||
|
}
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
{
|
||||||
|
debug.field("git_seam", &self.git_seam.is_some());
|
||||||
|
}
|
||||||
|
debug
|
||||||
.field("channel_client", &self.channel_client.as_ref().is_some())
|
.field("channel_client", &self.channel_client.as_ref().is_some())
|
||||||
.field("limits", &self.limits)
|
.field("limits", &self.limits)
|
||||||
.finish()
|
.finish()
|
||||||
@@ -503,6 +667,169 @@ mod tests {
|
|||||||
assert_eq!(serve.session_env.len(), 1);
|
assert_eq!(serve.session_env.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
mod git_seam {
|
||||||
|
use alkgit::{
|
||||||
|
GitPackGen, GitPackIngest, GitRefs, GitRegistry, PreparedPush, PushOptions, RefLine,
|
||||||
|
RefOutcome, RefUpdate, RegistryError, RepoRecord, StorageError,
|
||||||
|
};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use gix_hash::ObjectId;
|
||||||
|
|
||||||
|
use super::super::{GitSeam, ServeConfig};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct NoopRegistry;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl GitRegistry for NoopRegistry {
|
||||||
|
async fn resolve(&self, _repo_id: &str) -> Result<RepoRecord, RegistryError> {
|
||||||
|
Err(RegistryError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoopRefs;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl GitRefs for NoopRefs {
|
||||||
|
async fn list_refs(&self, _repo: &RepoRecord) -> Result<Vec<RefLine>, StorageError> {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn apply_updates(
|
||||||
|
&self,
|
||||||
|
_repo: &RepoRecord,
|
||||||
|
_updates: Vec<RefUpdate>,
|
||||||
|
_atomic: bool,
|
||||||
|
) -> Result<Vec<RefOutcome>, StorageError> {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoopPackGen;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl GitPackGen for NoopPackGen {
|
||||||
|
async fn generate(
|
||||||
|
&self,
|
||||||
|
_repo: &RepoRecord,
|
||||||
|
_wants: Vec<ObjectId>,
|
||||||
|
_boundary_haves: Vec<ObjectId>,
|
||||||
|
_limits: alkgit::Limits,
|
||||||
|
_sink: Box<dyn std::io::Write + Send>,
|
||||||
|
) -> Result<(), StorageError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn common_haves(
|
||||||
|
&self,
|
||||||
|
_repo: &RepoRecord,
|
||||||
|
_haves: Vec<ObjectId>,
|
||||||
|
) -> Result<Vec<ObjectId>, StorageError> {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoopPackIngest;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl GitPackIngest for NoopPackIngest {
|
||||||
|
async fn prepare(
|
||||||
|
&self,
|
||||||
|
_repo: &RepoRecord,
|
||||||
|
_updates: Vec<RefUpdate>,
|
||||||
|
_pack: Box<dyn std::io::Read + Send>,
|
||||||
|
_push_options: Option<PushOptions>,
|
||||||
|
_limits: alkgit::Limits,
|
||||||
|
) -> Result<PreparedPush, StorageError> {
|
||||||
|
Ok(PreparedPush {
|
||||||
|
unpack: Ok(()),
|
||||||
|
updates: Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assembled_seam() -> GitSeam {
|
||||||
|
GitSeam {
|
||||||
|
registry: Arc::new(NoopRegistry),
|
||||||
|
refs: Arc::new(NoopRefs),
|
||||||
|
packgen: Arc::new(NoopPackGen),
|
||||||
|
ingest: Arc::new(NoopPackIngest),
|
||||||
|
push_options_negotiated: false,
|
||||||
|
pipeline: Arc::new(tokio::sync::Semaphore::new(2)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serve_config_git_seam_unset_declines_though_the_feature_is_on() {
|
||||||
|
let serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
|
||||||
|
assert!(serve.git_seam.is_none());
|
||||||
|
assert!(!serve.git_seam_configured());
|
||||||
|
|
||||||
|
let debug = format!("{serve:?}");
|
||||||
|
assert!(debug.contains("git_seam: false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serve_config_holds_the_git_seam_whole_and_cloneable() {
|
||||||
|
let mut serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
let seam = assembled_seam();
|
||||||
|
let registry = Arc::clone(&seam.registry);
|
||||||
|
|
||||||
|
serve.git_seam = Some(seam);
|
||||||
|
|
||||||
|
assert!(serve.git_seam_configured());
|
||||||
|
let held = serve.git_seam.as_ref().expect("the seam holds");
|
||||||
|
assert!(Arc::ptr_eq(®istry, &held.registry));
|
||||||
|
assert!(!held.push_options_negotiated);
|
||||||
|
assert_eq!(held.pipeline.available_permits(), 2);
|
||||||
|
|
||||||
|
let cloned = held.clone();
|
||||||
|
assert!(Arc::ptr_eq(&cloned.registry, ®istry));
|
||||||
|
assert!(!cloned.push_options_negotiated);
|
||||||
|
assert_eq!(cloned.pipeline.available_permits(), 2);
|
||||||
|
|
||||||
|
let debug = format!("{serve:?}");
|
||||||
|
assert!(debug.contains("git_seam: true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn git_seam_pipeline_is_the_single_server_wide_share() {
|
||||||
|
let mut serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
let pipeline = Arc::new(tokio::sync::Semaphore::new(2));
|
||||||
|
|
||||||
|
let mut seam = assembled_seam();
|
||||||
|
seam.pipeline = Arc::clone(&pipeline);
|
||||||
|
serve.git_seam = Some(seam);
|
||||||
|
let held = serve.git_seam.as_ref().expect("the seam holds");
|
||||||
|
let cloned = held.clone();
|
||||||
|
|
||||||
|
assert!(Arc::ptr_eq(&pipeline, &held.pipeline));
|
||||||
|
assert!(Arc::ptr_eq(&pipeline, &cloned.pipeline));
|
||||||
|
|
||||||
|
let _permit = cloned
|
||||||
|
.pipeline
|
||||||
|
.try_acquire()
|
||||||
|
.expect("a permit is available");
|
||||||
|
assert_eq!(held.pipeline.available_permits(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn git_seam_debug_shapes_itself_not_the_backends() {
|
||||||
|
let seam = assembled_seam();
|
||||||
|
let debug = format!("{seam:?}");
|
||||||
|
|
||||||
|
assert!(debug.contains("GitSeam"));
|
||||||
|
assert!(debug.contains("<dyn GitRegistry>"));
|
||||||
|
assert!(debug.contains("<dyn GitRefs>"));
|
||||||
|
assert!(debug.contains("<dyn GitPackGen>"));
|
||||||
|
assert!(debug.contains("<dyn GitPackIngest>"));
|
||||||
|
assert!(debug.contains("push_options_negotiated: false"));
|
||||||
|
assert!(debug.contains("pipeline_permits: 2"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dial_config_defaults_carry_the_keepalive_posture() {
|
fn dial_config_defaults_carry_the_keepalive_posture() {
|
||||||
let dial = DialConfig::new("runner.example:22", key_source(), Arc::new(RejectAll));
|
let dial = DialConfig::new("runner.example:22", key_source(), Arc::new(RejectAll));
|
||||||
@@ -528,6 +855,103 @@ mod tests {
|
|||||||
assert!(Arc::ptr_eq(&policy, &dial.host_key_policy));
|
assert!(Arc::ptr_eq(&policy, &dial.host_key_policy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The wave-3 per-feature seam handles: the construction shapes, the
|
||||||
|
// unset-declines-preserved rows and the Debug posture — each block
|
||||||
|
// only runs in the build that carries its feature (compile-time
|
||||||
|
// feature isolation: no git build ever touches alktty types,
|
||||||
|
// no session build ever touches alkgit types).
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
mod session_seam {
|
||||||
|
use alktty::{TtyBackend, TtyError, TtyHandle, TtyParams};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use super::super::{ServeConfig, SessionSeam};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct StubBackend;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl TtyBackend for StubBackend {
|
||||||
|
async fn allocate(&self, _params: &TtyParams) -> Result<TtyHandle, TtyError> {
|
||||||
|
Err(TtyError::AllocFailed {
|
||||||
|
message: "stub".into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assembled_seam() -> SessionSeam {
|
||||||
|
let mut backends = std::collections::HashMap::new();
|
||||||
|
backends.insert("stub".to_string(), Arc::new(StubBackend) as _);
|
||||||
|
SessionSeam {
|
||||||
|
backends: Arc::new(backends),
|
||||||
|
backend: "stub".to_string(),
|
||||||
|
ownership: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serve_config_session_seam_unset_declines_though_the_feature_is_on() {
|
||||||
|
let serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
|
||||||
|
assert!(serve.session_seam.is_none());
|
||||||
|
assert!(!serve.session_seam_configured());
|
||||||
|
|
||||||
|
let debug = format!("{serve:?}");
|
||||||
|
assert!(debug.contains("session_seam: false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serve_config_holds_the_session_seam_whole_and_cloneable() {
|
||||||
|
let mut serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
let seam = assembled_seam();
|
||||||
|
let backends = Arc::clone(&seam.backends);
|
||||||
|
|
||||||
|
serve.session_seam = Some(seam);
|
||||||
|
|
||||||
|
assert!(serve.session_seam_configured());
|
||||||
|
let held = serve.session_seam.as_ref().expect("the seam holds");
|
||||||
|
assert!(Arc::ptr_eq(&backends, &held.backends));
|
||||||
|
assert_eq!(held.backend, "stub");
|
||||||
|
assert!(held.ownership.is_none());
|
||||||
|
|
||||||
|
let cloned = held.clone();
|
||||||
|
assert!(Arc::ptr_eq(&cloned.backends, &backends));
|
||||||
|
assert_eq!(cloned.backend, "stub");
|
||||||
|
|
||||||
|
let debug = format!("{serve:?}");
|
||||||
|
assert!(debug.contains("session_seam: true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_seam_configure_is_one_option_independent_of_the_oq08_fields() {
|
||||||
|
let mut serve = ServeConfig::new(Arc::new(NoopIdentityProvider), host_key_source());
|
||||||
|
serve.session_seam = Some(assembled_seam());
|
||||||
|
|
||||||
|
assert!(serve.session_seam_configured());
|
||||||
|
assert!(!serve.shell_configured());
|
||||||
|
assert!(!serve.exec_wrapper_configured());
|
||||||
|
|
||||||
|
serve.shell_argv = Some(vec!["/bin/sh".to_string(), "-l".to_string()]);
|
||||||
|
assert!(serve.shell_configured());
|
||||||
|
assert!(serve.session_seam_configured());
|
||||||
|
|
||||||
|
serve.session_seam = None;
|
||||||
|
assert!(serve.shell_configured());
|
||||||
|
assert!(!serve.session_seam_configured());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn session_seam_debug_shapes_itself_not_the_backends() {
|
||||||
|
let seam = assembled_seam();
|
||||||
|
let debug = format!("{seam:?}");
|
||||||
|
|
||||||
|
assert!(debug.contains("SessionSeam"));
|
||||||
|
assert!(debug.contains(r#"backend_keys: ["stub"]"#));
|
||||||
|
assert!(debug.contains(r#"backend: "stub""#));
|
||||||
|
assert!(debug.contains("ownership_set: false"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn dial_config_key_source_stays_fail_closed_through_the_config() {
|
async fn dial_config_key_source_stays_fail_closed_through_the_config() {
|
||||||
let dial = DialConfig::new("fleet.example:22", key_source(), Arc::new(RejectAll));
|
let dial = DialConfig::new("fleet.example:22", key_source(), Arc::new(RejectAll));
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ mod key_source;
|
|||||||
mod serve;
|
mod serve;
|
||||||
|
|
||||||
pub use adapter::SshAdapter;
|
pub use adapter::SshAdapter;
|
||||||
|
#[cfg(feature = "git")]
|
||||||
|
pub use config::GitSeam;
|
||||||
|
#[cfg(feature = "session")]
|
||||||
|
pub use config::SessionSeam;
|
||||||
pub use config::{DialConfig, Limits, ServeConfig};
|
pub use config::{DialConfig, Limits, ServeConfig};
|
||||||
pub use error::{AdapterError, KeySourceError};
|
pub use error::{AdapterError, KeySourceError};
|
||||||
pub use fingerprint::fingerprint;
|
pub use fingerprint::fingerprint;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: w3-seam-config
|
id: w3-seam-config
|
||||||
name: Wave 3 — serve-config seam handles (alktty/alkgit per-feature)
|
name: Wave 3 — serve-config seam handles (alktty/alkgit per-feature)
|
||||||
status: pending
|
status: completed
|
||||||
depends_on: [review-wave-2, w1-config]
|
depends_on: [review-wave-2, w1-config]
|
||||||
scope: narrow
|
scope: narrow
|
||||||
risk: low
|
risk: low
|
||||||
@@ -65,17 +65,17 @@ each seam handle carries).
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] `ServeConfig` gains the feature-gated seam handles (the final
|
- [x] `ServeConfig` gains the feature-gated seam handles (the final
|
||||||
shape decided and recorded); unset → the owned rows decline,
|
shape decided and recorded); unset → the owned rows decline,
|
||||||
structurally carried, no construction-time validation
|
structurally carried, no construction-time validation
|
||||||
- [ ] The optional deps + `dep:` feature wiring land with crates.io
|
- [x] The optional deps + `dep:` feature wiring land with crates.io
|
||||||
pins verified; a git-build never compiles alktty and vice versa
|
pins verified; a git-build never compiles alktty and vice versa
|
||||||
(no code path outside the cfg gate touches the types)
|
(no code path outside the cfg gate touches the types)
|
||||||
- [ ] The none-build's `ServeConfig::new` shape is unchanged;
|
- [x] The none-build's `ServeConfig::new` shape is unchanged;
|
||||||
feature-gated fields absent from featureless builds
|
feature-gated fields absent from featureless builds
|
||||||
- [ ] Tests: the per-feature construction shapes, the
|
- [x] Tests: the per-feature construction shapes, the
|
||||||
unset-declines-preserved rows, the `Debug` posture
|
unset-declines-preserved rows, the `Debug` posture
|
||||||
- [ ] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
- [x] `cargo test`, `cargo clippy --all-targets -- -D warnings`,
|
||||||
`cargo clippy --all-features --all-targets -- -D warnings`,
|
`cargo clippy --all-features --all-targets -- -D warnings`,
|
||||||
`cargo fmt --check`, `cargo doc --no-deps` pass
|
`cargo fmt --check`, `cargo doc --no-deps` pass
|
||||||
|
|
||||||
@@ -93,4 +93,106 @@ each seam handle carries).
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
> To be filled at implementation time.
|
### What landed (2026-10-28)
|
||||||
|
|
||||||
|
- `Cargo.toml`: optional `alktty = "0.8.1"` /
|
||||||
|
`alkgit = "0.1.0"` (both `default-features = false`), wired
|
||||||
|
`session = ["dep:alktty"]`, `git = ["dep:alkgit"]`. alktty's `local`
|
||||||
|
feature stays off — alkssh never touches a real backend; the `local`
|
||||||
|
shapes stay alktty-side. Feature-graph comment updated (wave-3
|
||||||
|
seam-config is the deps' first consumer; alktunnels still lands with
|
||||||
|
`w3-tunnel-direct`).
|
||||||
|
- `src/config.rs` (re-exported through `lib.rs`): the two seam-handle
|
||||||
|
types + the two cfg-gated `ServeConfig` fields + the cfg-gated
|
||||||
|
`session_seam_configured()` / `git_seam_configured()` accessors +
|
||||||
|
config-module docs updated (the direction list and the
|
||||||
|
unset-declines rule both state the seam handles now).
|
||||||
|
|
||||||
|
### Shape decision (the task's decide-and-record item): whole-`Option` struct per seam
|
||||||
|
|
||||||
|
`SessionSeam{backends, backend, ownership}` and
|
||||||
|
`GitSeam{registry, refs, packgen, ingest, push_options_negotiated,
|
||||||
|
pipeline}` held as `cfg`-gated `Option` fields
|
||||||
|
(`session_seam` / `git_seam`), each `Clone` (all payload types `Arc`
|
||||||
|
or plain data — the spawned serving tasks clone the seam), each with a
|
||||||
|
hand-rolled `Debug`. **Flat `Option` fields were rejected**: each seam
|
||||||
|
is consumed atomically by exactly one seam call
|
||||||
|
(`drive_session[_pre_negotiated]` / `serve_duplex_resolved`), so a
|
||||||
|
struct admits no half-supplied seam states (backends without a
|
||||||
|
selector; three traits without the fourth) that would all map to the
|
||||||
|
same all-or-nothing decline — the unset-declines contract reads as one
|
||||||
|
`Option` per seam, "unset → the owned rows decline even though the
|
||||||
|
feature is on" (the decline matrix's config-driven note), checked at
|
||||||
|
request time by the mappings, never at construction. The already-landed
|
||||||
|
tunnel handle stays the flat
|
||||||
|
`Option<Arc<ChannelClient>>` — a single-field seam needs no struct.
|
||||||
|
Naming: struct names carry the crate (the consuming mappings will see
|
||||||
|
it in the field docs); the fields carry the row vocabulary
|
||||||
|
(`session_seam` / `git_seam`, matching the decline matrix's row names).
|
||||||
|
|
||||||
|
### Pins verified against crates.io (2026-10-28, this task re-verified)
|
||||||
|
|
||||||
|
- `alktty 0.8.1`: published 2026-10-22, not yanked,
|
||||||
|
`MIT OR Apache-2.0`, `rust_version = "1.88"` ≤ our 1.89;
|
||||||
|
`alkcall ^0.10.1` — shares our `alkcall = "0.10"` resolution
|
||||||
|
(0.10.1), so no alkcall fork in the lockfile.
|
||||||
|
- `alkgit 0.1.0`: `MIT OR Apache-2.0`, `rust_version = "1.88"`;
|
||||||
|
`alkcall ^0.10` — same shared resolution.
|
||||||
|
- Signatures confirmed against the published crates (the registry
|
||||||
|
sources under `~/.cargo/registry/src/`): alktty's
|
||||||
|
`drive_session[_pre_negotiated]` (adapter.rs:205-241) takes
|
||||||
|
`(writer, reader, [req,] backends: Arc<HashMap<String, Arc<dyn
|
||||||
|
TtyBackend>>>, ownership: Option<Arc<dyn OwnershipProvider>>,
|
||||||
|
identity: Option<Identity>)` — the identity is the per-connection
|
||||||
|
resolved one, not config; alkgit's `serve_duplex_resolved`
|
||||||
|
(duplex.rs:1412) takes the four traits +
|
||||||
|
`push_options_negotiated: bool` + `pipeline: Arc<Semaphore>`.
|
||||||
|
`TtyBackend` / `NegotiateRequest` / `TerminalParamsWire` and
|
||||||
|
`GitRegistry/GitRefs/GitPackGen/GitPackIngest` are all re-exported
|
||||||
|
from the two lib roots.
|
||||||
|
|
||||||
|
### One course correction absorbed: `ObjectId` is not re-exported by alkgit
|
||||||
|
|
||||||
|
`GitPackGen::generate`/`common_haves` name `Vec<gix_hash::ObjectId>`
|
||||||
|
and alkgit's lib root does not re-export `ObjectId` — a backend-trait
|
||||||
|
doubled in tests has to name the type, so `gix-hash = "0.28"` (matching
|
||||||
|
alkgit's `^0.28` req; the same crate already in the lockfile) lands as
|
||||||
|
a **`[dev-dependencies]` entry only**, exercised exclusively by the
|
||||||
|
cfg-gated git test module. The lib dependency graph keeps the
|
||||||
|
feature-to-dep isolation below; the dev graph is universal by design
|
||||||
|
(tokio and friends are too). Flagged for `w3-git-mapping`: the
|
||||||
|
hand-rolled in-mem quartet will lean on this dev-dep for `ObjectId`
|
||||||
|
(same as this task's noop doubles, modeled on alkgit's own
|
||||||
|
`backend.rs:164-254` noop shapes — own code, not copied).
|
||||||
|
|
||||||
|
### Dependency isolation — verified structurally, not by assertion
|
||||||
|
|
||||||
|
`cargo tree -e features --features git`: zero `alktty` occurrences;
|
||||||
|
`cargo tree -e features --features session`: zero `alkgit`
|
||||||
|
occurrences; `--all-features`: both present. Combined with the cfg
|
||||||
|
gates (all `alktty`/`alkgit` type references live inside
|
||||||
|
`#[cfg(feature = "session")]` / `#[cfg(feature = "git")]` blocks —
|
||||||
|
imports, fields, accessors, Debug, constructor, tests), the "a
|
||||||
|
git-build never compiles alktty and vice versa" invariant is
|
||||||
|
compile-proven for both consumption sides.
|
||||||
|
|
||||||
|
### The unset-declines wire-level rows stay the mappings' consumption
|
||||||
|
|
||||||
|
The wave-3 mappings own the request-time decline checks; this task
|
||||||
|
lands the config-level contract rows (constructor posture, `Option`
|
||||||
|
configured() semantics, seam-vs-OQ-08-field independence, Debug
|
||||||
|
posture — 8 unit rows across the two feature modules) and leaves the
|
||||||
|
wave-2 harness rows untouched (featured-but-unset already declines at
|
||||||
|
the row the stubs own; the real serving paths make those rows
|
||||||
|
meaningful in `w3-git-mapping` / `w3-tty-session`, whose seam
|
||||||
|
consumption reads exactly these fields).
|
||||||
|
|
||||||
|
### Verification (all green)
|
||||||
|
|
||||||
|
`cargo test` (none build, 9 binaries + doctests) ·
|
||||||
|
`cargo test --features session` / `--features git` /
|
||||||
|
`--all-features` (67 unit rows under all-features) ·
|
||||||
|
`cargo clippy --all-targets -- -D warnings` ✓ ·
|
||||||
|
`cargo clippy --all-features --all-targets -- -D warnings` ✓ ·
|
||||||
|
`cargo fmt --check` ✓ · `cargo doc --no-deps` 0 warnings ·
|
||||||
|
`taskgraph validate` ✓.
|
||||||
Reference in new issue
Block a user