git.delta.rocks / jrsonnet / refs/commits / 4b3d3e3f5e1b

difftreelog

feat prettier secret list

yklwvxmuYaroslav Bolyukin2026-04-19parent: #a23b326.patch.diff
in: trunk

2 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -117,12 +117,6 @@
 ]
 
 [[package]]
-name = "allocator-api2"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
-
-[[package]]
 name = "android_system_properties"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -201,36 +195,6 @@
 version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
-
-[[package]]
-name = "async-channel"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
-dependencies = [
- "concurrent-queue",
- "event-listener-strategy",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-io"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
-dependencies = [
- "autocfg",
- "cfg-if",
- "concurrent-queue",
- "futures-io",
- "futures-lite",
- "parking",
- "polling",
- "rustix 1.1.4",
- "slab",
- "windows-sys 0.61.2",
-]
 
 [[package]]
 name = "async-stream"
@@ -458,15 +422,6 @@
 checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
 
 [[package]]
-name = "castaway"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
-dependencies = [
- "rustversion",
-]
-
-[[package]]
 name = "cbc"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -647,29 +602,6 @@
 checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
 
 [[package]]
-name = "compact_str"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a"
-dependencies = [
- "castaway",
- "cfg-if",
- "itoa",
- "rustversion",
- "ryu",
- "static_assertions",
-]
-
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
 name = "console"
 version = "0.16.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -701,15 +633,6 @@
 checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
 
 [[package]]
-name = "convert_case"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "cookie-factory"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -749,58 +672,9 @@
 checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
 dependencies = [
  "cfg-if",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
-
-[[package]]
-name = "crossterm"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
-dependencies = [
- "bitflags",
- "crossterm_winapi",
- "derive_more",
- "document-features",
- "futures-core",
- "mio",
- "parking_lot",
- "rustix 1.1.4",
- "signal-hook",
- "signal-hook-mio",
- "winapi",
-]
-
-[[package]]
-name = "crossterm_winapi"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
-dependencies = [
- "winapi",
 ]
 
 [[package]]
-name = "crosstermion"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6ae462f0b868614980d59df41e217a77648de7ad7cf8b2a407155659896d889"
-dependencies = [
- "async-channel",
- "crossterm",
- "futures-channel",
- "futures-core",
- "futures-lite",
- "ratatui",
- "tui-react",
-]
-
-[[package]]
 name = "crypto-common"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -910,41 +784,7 @@
 checksum = "e6acc6b5822b9526adfb4fc377b67128fdd60aac757cc4a741a6278603f763cf"
 dependencies = [
  "indexmap 2.13.0",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "darling"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
-dependencies = [
- "ident_case",
  "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
-dependencies = [
- "darling_core",
  "quote",
  "syn",
 ]
@@ -967,31 +807,9 @@
 dependencies = [
  "powerfmt",
  "serde_core",
-]
-
-[[package]]
-name = "derive_more"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
-dependencies = [
- "derive_more-impl",
 ]
 
 [[package]]
-name = "derive_more-impl"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
-dependencies = [
- "convert_case",
- "proc-macro2",
- "quote",
- "rustc_version",
- "syn",
-]
-
-[[package]]
 name = "digest"
 version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1012,15 +830,6 @@
  "proc-macro2",
  "quote",
  "syn",
-]
-
-[[package]]
-name = "document-features"
-version = "0.2.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
-dependencies = [
- "litrs",
 ]
 
 [[package]]
@@ -1094,27 +903,6 @@
 dependencies = [
  "libc",
  "windows-sys 0.61.2",
-]
-
-[[package]]
-name = "event-listener"
-version = "5.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "event-listener-strategy"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
-dependencies = [
- "event-listener",
- "pin-project-lite",
 ]
 
 [[package]]
@@ -1395,19 +1183,6 @@
 checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
 
 [[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]]
 name = "futures-macro"
 version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1549,11 +1324,6 @@
 version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
-dependencies = [
- "allocator-api2",
- "equivalent",
- "foldhash 0.2.0",
-]
 
 [[package]]
 name = "heck"
@@ -1562,12 +1332,6 @@
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
-name = "hermit-abi"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
-
-[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1899,12 +1663,6 @@
 checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
 
 [[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
 name = "idna"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1978,19 +1736,6 @@
 dependencies = [
  "block-padding",
  "generic-array",
-]
-
-[[package]]
-name = "instability"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971"
-dependencies = [
- "darling",
- "indoc",
- "proc-macro2",
- "quote",
- "syn",
 ]
 
 [[package]]
@@ -2063,47 +1808,6 @@
 version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
-
-[[package]]
-name = "jiff"
-version = "0.2.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359"
-dependencies = [
- "jiff-static",
- "jiff-tzdb-platform",
- "log",
- "portable-atomic",
- "portable-atomic-util",
- "serde_core",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "jiff-static"
-version = "0.2.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jiff-tzdb"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076"
-
-[[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]]
 name = "js-sys"
@@ -2113,17 +1817,6 @@
 dependencies = [
  "once_cell",
  "wasm-bindgen",
-]
-
-[[package]]
-name = "kasuari"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899"
-dependencies = [
- "hashbrown 0.16.1",
- "portable-atomic",
- "thiserror 2.0.18",
 ]
 
 [[package]]
@@ -2162,15 +1855,6 @@
 version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
-
-[[package]]
-name = "line-clipping"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a"
-dependencies = [
- "bitflags",
-]
 
 [[package]]
 name = "link-cplusplus"
@@ -2206,12 +1890,6 @@
 checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
 
 [[package]]
-name = "litrs"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
-
-[[package]]
 name = "lock_api"
 version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2225,15 +1903,6 @@
 version = "0.4.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
-
-[[package]]
-name = "lru"
-version = "0.16.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593"
-dependencies = [
- "hashbrown 0.16.1",
-]
 
 [[package]]
 name = "matchers"
@@ -2285,7 +1954,6 @@
 checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
 dependencies = [
  "libc",
- "log",
  "wasi",
  "windows-sys 0.61.2",
 ]
@@ -2423,15 +2091,6 @@
 ]
 
 [[package]]
-name = "num_threads"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
-dependencies = [
- "libc",
-]
-
-[[package]]
 name = "once_cell"
 version = "1.21.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2563,12 +2222,6 @@
 ]
 
 [[package]]
-name = "parking"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
-
-[[package]]
 name = "parking_lot"
 version = "0.12.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2714,20 +2367,6 @@
 checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
 
 [[package]]
-name = "polling"
-version = "3.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
-dependencies = [
- "cfg-if",
- "concurrent-queue",
- "hermit-abi",
- "pin-project-lite",
- "rustix 1.1.4",
- "windows-sys 0.61.2",
-]
-
-[[package]]
 name = "poly1305"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2755,15 +2394,6 @@
 version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
-
-[[package]]
-name = "portable-atomic-util"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3"
-dependencies = [
- "portable-atomic",
-]
 
 [[package]]
 name = "potential_utf"
@@ -2828,39 +2458,9 @@
 checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
 dependencies = [
  "unicode-ident",
-]
-
-[[package]]
-name = "prodash"
-version = "31.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c"
-dependencies = [
- "async-io",
- "crosstermion",
- "futures-core",
- "futures-lite",
- "jiff",
- "parking_lot",
- "ratatui",
- "tui-react",
- "unicode-segmentation",
- "unicode-width",
 ]
 
 [[package]]
-name = "prodash-layer"
-version = "0.1.0"
-dependencies = [
- "futures",
- "futures-core",
- "prodash",
- "tokio",
- "tracing",
- "tracing-subscriber",
-]
-
-[[package]]
 name = "proptest"
 version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3054,72 +2654,9 @@
 checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
 dependencies = [
  "rand_core 0.9.5",
-]
-
-[[package]]
-name = "ratatui"
-version = "0.30.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc"
-dependencies = [
- "instability",
- "ratatui-core",
- "ratatui-crossterm",
- "ratatui-widgets",
-]
-
-[[package]]
-name = "ratatui-core"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293"
-dependencies = [
- "bitflags",
- "compact_str",
- "hashbrown 0.16.1",
- "indoc",
- "itertools 0.14.0",
- "kasuari",
- "lru",
- "strum",
- "thiserror 2.0.18",
- "unicode-segmentation",
- "unicode-truncate",
- "unicode-width",
-]
-
-[[package]]
-name = "ratatui-crossterm"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3"
-dependencies = [
- "cfg-if",
- "crossterm",
- "instability",
- "ratatui-core",
 ]
 
 [[package]]
-name = "ratatui-widgets"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db"
-dependencies = [
- "bitflags",
- "hashbrown 0.16.1",
- "indoc",
- "instability",
- "itertools 0.14.0",
- "line-clipping",
- "ratatui-core",
- "strum",
- "time",
- "unicode-segmentation",
- "unicode-width",
-]
-
-[[package]]
 name = "rcgen"
 version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3577,29 +3114,8 @@
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "signal-hook"
-version = "0.3.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
-dependencies = [
- "libc",
- "signal-hook-registry",
-]
 
 [[package]]
-name = "signal-hook-mio"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
-dependencies = [
- "libc",
- "mio",
- "signal-hook",
-]
-
-[[package]]
 name = "signal-hook-registry"
 version = "1.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3680,39 +3196,12 @@
 checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
 
 [[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
 name = "strsim"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
-name = "strum"
-version = "0.27.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
-dependencies = [
- "strum_macros",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.27.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "subtle"
 version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3931,9 +3420,7 @@
 checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
 dependencies = [
  "deranged",
- "libc",
  "num-conv",
- "num_threads",
  "powerfmt",
  "serde_core",
  "time-core",
@@ -4354,18 +3841,6 @@
 checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
 [[package]]
-name = "tui-react"
-version = "0.24.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c07031f0f4eb182785a8621967da6c75b9b21cfc7dfaaac78400b9a12492e66"
-dependencies = [
- "log",
- "ratatui",
- "unicode-segmentation",
- "unicode-width",
-]
-
-[[package]]
 name = "type-map"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4416,23 +3891,6 @@
 version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
-
-[[package]]
-name = "unicode-truncate"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5"
-dependencies = [
- "itertools 0.14.0",
- "unicode-segmentation",
- "unicode-width",
-]
 
 [[package]]
 name = "unicode-width"
@@ -4703,22 +4161,6 @@
 ]
 
 [[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
 name = "winapi-util"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4726,12 +4168,6 @@
 dependencies = [
  "windows-sys 0.61.2",
 ]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-core"
modifiedcmds/fleet/src/cmds/secrets.rsdiffbeforeafterboth
before · cmds/fleet/src/cmds/secrets.rs
1use std::collections::BTreeSet;2use std::io::{Write as _, stdout};34use anyhow::{Context as _, Result, anyhow, bail};5use clap::Parser;6use fleet_base::{fleetdata::SecretOwner, host::Config, opts::FleetOpts};7use itertools::Itertools as _;8use nix_eval::nix_go;9use tracing::{info, warn};1011#[derive(Parser)]12pub enum Secret {13	/// Force load host keys for all defined hosts14	ForceKeys,15	/// Read secret from remote host, requires sudo on one of the owning hosts16	Read {17		/// Secret name to read18		name: String,1920		/// Distribution with what machine to read21		/// If not shared between multiple - defaults to single owner22		#[clap(short = 'm', long)]23		machine: Option<String>,2425		/// Which private secret part to read26		/// If not specified - only one existing part is read27		#[clap(short = 'p', long)]28		part: Option<String>,29	},30	/// Prune (remove, mark for regeneration) secrets31	Prune {32		/// Secret to prune33		name: String,3435		/// Machines to prune - if specified, only the choosen machines will be pruned36		#[clap(short = 'm', long)]37		machine: Vec<String>,3839		/// If set - distributions containing the specified machines will be pruned fully40		#[clap(long)]41		whole_dist: bool,42	},43	/// Ensure secret is generated and not expired44	Ensure {45		/// Secret to ensure generated46		name: String,4748		/// Machines to force secret for49		#[clap(short = 'm', long)]50		machine: Vec<String>,51	},52	/// Regenerate secret (prune then ensure)53	Regenerate {54		/// Secret to regenerate55		name: String,5657		/// Machines to regenerate for - if specified, only those machines58		#[clap(short = 'm', long)]59		machine: Vec<String>,60	},61	List {},62}6364impl Secret {65	pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {66		match self {67			Secret::ForceKeys => {68				for host in config.list_hosts()? {69					if opts.should_skip(&host)? {70						continue;71					}72					config.host_key(&host.name).await?;73				}74			}75			Secret::Read {76				name,77				machine,78				part: part_name,79			} => {80				let (owners, secret_data) = {81					let secret = config.data.secrets.read().expect("not poisoned");8283					let Some(dist) = secret.get(&name) else {84						bail!("secret doesn't exists");85					};8687					let dist = if let Some(machine) = &machine {88						dist.get(&SecretOwner::host(machine))89							.ok_or_else(|| anyhow!("machine {machine} has no secret generated"))?90					} else {91						dist.distributions()92							.exactly_one()93							.map_err(|e| anyhow!("{e}"))94							.context(95								"with no machine specified, there should be exactly one distribution",96							)?97					};9899					let part = if let Some(part_name) = &part_name {100						dist.secret.parts.get(part_name).ok_or_else(|| {101							anyhow!("secret {name} does not have part named {part_name}")102						})?103					} else {104						dist.secret105							.parts106							.iter()107							.exactly_one()108							.map_err(|e| anyhow!("{e}"))109							.context("with no part specified, there should be exactly one part")?110							.1111					};112					let owners = dist.owners().cloned().collect::<Vec<_>>();113					let secret_data = part.raw.clone();114					(owners, secret_data)115				};116117				for host in config118					.preferred_hosts(|h| owners.iter().any(|o| o.as_host() == Some(h)))119					.context("failed to list hosts")?120				{121					let host = match host {122						Ok(h) => h,123						Err(e) => {124							warn!("failed to use host: {e}");125							continue;126						}127					};128					match host.decrypt(secret_data.clone()).await {129						Ok(data) => {130							let mut w = stdout();131							w.write_all(&data)?;132							return Ok(());133						}134						Err(e) => warn!("failed to decrypt on {}: {e}", host.name),135					};136				}137				bail!("failed to find suitable decrypting host");138			}139			Secret::List {} => {140				let secrets = config.data.secrets.read().expect("not poisoned");141142				#[derive(tabled::Tabled)]143				struct Row {144					#[tabled(rename = "Name")]145					name: String,146					#[tabled(rename = "Dist")]147					dist: String,148					#[tabled(rename = "Owners")]149					owners: String,150				}151152				let mut rows = Vec::new();153				for name in secrets.keys() {154					let dists = secrets.get(name).unwrap();155					for (idx, dist) in dists.all_distributions().enumerate() {156						let active: Vec<_> = dist157							.owners()158							.filter_map(|o| o.as_host())159							.map(str::to_owned)160							.collect();161						let pruned: Vec<_> = dist162							.owners_pending_prune()163							.filter_map(|o| o.as_host())164							.map(|h| format!("{h} (pruned)"))165							.collect();166						let mut all_owners = active;167						all_owners.extend(pruned);168169						let dist_label = if dist.is_pending_prune() {170							format!("{idx} (pruned)")171						} else {172							idx.to_string()173						};174175						rows.push(Row {176							name: if idx == 0 {177								name.clone()178							} else {179								String::new()180							},181							dist: dist_label,182							owners: all_owners.join("\n"),183						});184					}185				}186187				use tabled::settings::{Style, width::Width};188				let mut table = tabled::Table::new(rows);189				table.with(Width::wrap(80));190				println!("{table}");191			}192			Secret::Prune {193				name,194				machine,195				whole_dist,196			} => {197				Self::prune(config, &name, &machine, whole_dist)?;198			}199			Secret::Ensure { name, machine } => {200				Self::ensure(config, opts, &name, &machine)?;201			}202			Secret::Regenerate { name, machine } => {203				let pruned = Self::prune(config, &name, &machine, true)?;204				// In general, this is not correct - already evaluated secret would still be cached after pruning205				// But as a dedicated CLI subcommand it is safe to assume it was not evaluated yet206				Self::ensure(config, opts, &name, &pruned)?;207			}208		}209		Ok(())210	}211212	fn prune(213		config: &Config,214		name: &str,215		machine: &[String],216		whole_dist: bool,217	) -> Result<Vec<String>> {218		let mut secrets = config.data.secrets.write().expect("not poisoned");219		let Some(dists) = secrets.get_mut(name) else {220			bail!("secret {name} not found");221		};222		let owners_before: BTreeSet<String> = dists223			.owners()224			.filter_map(|o| o.as_host().map(str::to_owned))225			.collect();226227		if machine.is_empty() && whole_dist {228			for dist in dists.distributions_mut() {229				dist.prune("manual prune".to_owned());230			}231		} else if machine.is_empty() {232			let dist = dists233				.distributions_mut()234				.exactly_one()235				.map_err(|e| anyhow!("{e}"))236				.context("with no machine specified, there should be exactly one distribution")?;237			dist.prune("manual prune".to_owned());238		} else if whole_dist {239			for dist in dists.distributions_mut() {240				if machine241					.iter()242					.any(|m| dist.owners().any(|o| o.as_host() == Some(m.as_str())))243				{244					dist.prune(format!(245						"manual prune of distribution containing {}",246						machine.join(", ")247					));248				}249			}250		} else {251			let owners: BTreeSet<SecretOwner> = machine.iter().map(SecretOwner::host).collect();252			for dist in dists.distributions_mut() {253				dist.prune_owners(&owners, "manual prune".to_owned());254			}255		}256257		let owners_after: BTreeSet<String> = dists258			.owners()259			.filter_map(|o| o.as_host().map(str::to_owned))260			.collect();261		Ok(owners_before.difference(&owners_after).cloned().collect())262	}263264	fn ensure(config: &Config, opts: &FleetOpts, name: &str, machine: &[String]) -> Result<()> {265		let hosts: Vec<String> = if machine.is_empty() {266			config267				.list_hosts()?268				.into_iter()269				.filter(|h| opts.should_skip(h).ok() != Some(true))270				.map(|h| h.name)271				.collect()272		} else {273			machine.to_vec()274		};275276		for hostname in &hosts {277			let nixos_cfg = config.system_config(hostname)?;278			let secrets = nix_go!(nixos_cfg.secrets);279			if secrets.has_field(name)? {280				info!("ensuring secret {name} for {hostname}");281				// Force evaluation of secret parts, triggering __fleetEnsureHostSecret282				nix_go!(secrets[{ name }].definition.parts);283			}284		}285		Ok(())286	}287}
after · cmds/fleet/src/cmds/secrets.rs
1use std::collections::BTreeSet;2use std::io::{Write as _, stdout};34use anyhow::{Context as _, Result, anyhow, bail};5use clap::Parser;6use fleet_base::{fleetdata::SecretOwner, host::Config, opts::FleetOpts};7use itertools::Itertools as _;8use nix_eval::nix_go;9use tabled::settings::{Style, width::Width};10use tabled::{Table, Tabled};11use tracing::{info, warn};1213#[derive(Parser)]14pub enum Secret {15	/// Force load host keys for all defined hosts16	ForceKeys,17	/// Read secret from remote host, requires sudo on one of the owning hosts18	Read {19		/// Secret name to read20		name: String,2122		/// Distribution with what machine to read23		/// If not shared between multiple - defaults to single owner24		#[clap(short = 'm', long)]25		machine: Option<String>,2627		/// Which private secret part to read28		/// If not specified - only one existing part is read29		#[clap(short = 'p', long)]30		part: Option<String>,31	},32	/// Prune (remove, mark for regeneration) secrets33	Prune {34		/// Secret to prune35		name: String,3637		/// Machines to prune - if specified, only the choosen machines will be pruned38		#[clap(short = 'm', long)]39		machine: Vec<String>,4041		/// If set - distributions containing the specified machines will be pruned fully42		#[clap(long)]43		whole_dist: bool,44	},45	/// Ensure secret is generated and not expired46	Ensure {47		/// Secret to ensure generated48		name: String,4950		/// Machines to force secret for51		#[clap(short = 'm', long)]52		machine: Vec<String>,53	},54	/// Regenerate secret (prune then ensure)55	Regenerate {56		/// Secret to regenerate57		name: String,5859		/// Machines to regenerate for - if specified, only those machines60		#[clap(short = 'm', long)]61		machine: Vec<String>,62	},63	List {},64}6566impl Secret {67	pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {68		match self {69			Secret::ForceKeys => {70				for host in config.list_hosts()? {71					if opts.should_skip(&host)? {72						continue;73					}74					config.host_key(&host.name).await?;75				}76			}77			Secret::Read {78				name,79				machine,80				part: part_name,81			} => {82				let (owners, secret_data) = {83					let secret = config.data.secrets.read().expect("not poisoned");8485					let Some(dist) = secret.get(&name) else {86						bail!("secret doesn't exists");87					};8889					let dist = if let Some(machine) = &machine {90						dist.get(&SecretOwner::host(machine))91							.ok_or_else(|| anyhow!("machine {machine} has no secret generated"))?92					} else {93						dist.distributions()94							.exactly_one()95							.map_err(|e| anyhow!("{e}"))96							.context(97								"with no machine specified, there should be exactly one distribution",98							)?99					};100101					let part = if let Some(part_name) = &part_name {102						dist.secret.parts.get(part_name).ok_or_else(|| {103							anyhow!("secret {name} does not have part named {part_name}")104						})?105					} else {106						dist.secret107							.parts108							.iter()109							.exactly_one()110							.map_err(|e| anyhow!("{e}"))111							.context("with no part specified, there should be exactly one part")?112							.1113					};114					let owners = dist.owners().cloned().collect::<Vec<_>>();115					let secret_data = part.raw.clone();116					(owners, secret_data)117				};118119				for host in config120					.preferred_hosts(|h| owners.iter().any(|o| o.as_host() == Some(h)))121					.context("failed to list hosts")?122				{123					let host = match host {124						Ok(h) => h,125						Err(e) => {126							warn!("failed to use host: {e}");127							continue;128						}129					};130					match host.decrypt(secret_data.clone()).await {131						Ok(data) => {132							let mut w = stdout();133							w.write_all(&data)?;134							return Ok(());135						}136						Err(e) => warn!("failed to decrypt on {}: {e}", host.name),137					};138				}139				bail!("failed to find suitable decrypting host");140			}141			Secret::List {} => {142				let secrets = config.data.secrets.read().expect("not poisoned");143144				#[derive(Tabled)]145				struct Row {146					#[tabled(rename = "Name")]147					name: String,148					#[tabled(rename = "Dist")]149					dist: String,150					#[tabled(rename = "Owners")]151					owners: String,152				}153154				let mut rows = Vec::new();155				for name in secrets.keys() {156					let dists = secrets.get(name).unwrap();157					for (idx, dist) in dists.all_distributions().enumerate() {158						let active: Vec<_> = dist159							.owners()160							.filter_map(|o| o.as_host())161							.map(str::to_owned)162							.collect();163						let pruned: Vec<_> = dist164							.owners_pending_prune()165							.filter_map(|o| o.as_host())166							.map(|h| format!("{h} (pruned)"))167							.collect();168						let mut all_owners = active;169						all_owners.extend(pruned);170171						let dist_label = if dist.is_pending_prune() {172							format!("{idx} (pruned)")173						} else {174							idx.to_string()175						};176177						rows.push(Row {178							name: if idx == 0 {179								name.clone()180							} else {181								String::new()182							},183							dist: dist_label,184							owners: all_owners.join("\n"),185						});186					}187				}188189				let mut table = Table::new(rows);190				table.with(Style::rounded());191				table.with(Width::wrap(80));192				println!("{table}");193			}194			Secret::Prune {195				name,196				machine,197				whole_dist,198			} => {199				Self::prune(config, &name, &machine, whole_dist)?;200			}201			Secret::Ensure { name, machine } => {202				Self::ensure(config, opts, &name, &machine)?;203			}204			Secret::Regenerate { name, machine } => {205				let pruned = Self::prune(config, &name, &machine, true)?;206				// In general, this is not correct - already evaluated secret would still be cached after pruning207				// But as a dedicated CLI subcommand it is safe to assume it was not evaluated yet208				Self::ensure(config, opts, &name, &pruned)?;209			}210		}211		Ok(())212	}213214	fn prune(215		config: &Config,216		name: &str,217		machine: &[String],218		whole_dist: bool,219	) -> Result<Vec<String>> {220		let mut secrets = config.data.secrets.write().expect("not poisoned");221		let Some(dists) = secrets.get_mut(name) else {222			bail!("secret {name} not found");223		};224		let owners_before: BTreeSet<String> = dists225			.owners()226			.filter_map(|o| o.as_host().map(str::to_owned))227			.collect();228229		if machine.is_empty() && whole_dist {230			for dist in dists.distributions_mut() {231				dist.prune("manual prune".to_owned());232			}233		} else if machine.is_empty() {234			let dist = dists235				.distributions_mut()236				.exactly_one()237				.map_err(|e| anyhow!("{e}"))238				.context("with no machine specified, there should be exactly one distribution")?;239			dist.prune("manual prune".to_owned());240		} else if whole_dist {241			for dist in dists.distributions_mut() {242				if machine243					.iter()244					.any(|m| dist.owners().any(|o| o.as_host() == Some(m.as_str())))245				{246					dist.prune(format!(247						"manual prune of distribution containing {}",248						machine.join(", ")249					));250				}251			}252		} else {253			let owners: BTreeSet<SecretOwner> = machine.iter().map(SecretOwner::host).collect();254			for dist in dists.distributions_mut() {255				dist.prune_owners(&owners, "manual prune".to_owned());256			}257		}258259		let owners_after: BTreeSet<String> = dists260			.owners()261			.filter_map(|o| o.as_host().map(str::to_owned))262			.collect();263		Ok(owners_before.difference(&owners_after).cloned().collect())264	}265266	fn ensure(config: &Config, opts: &FleetOpts, name: &str, machine: &[String]) -> Result<()> {267		let hosts: Vec<String> = if machine.is_empty() {268			config269				.list_hosts()?270				.into_iter()271				.filter(|h| opts.should_skip(h).ok() != Some(true))272				.map(|h| h.name)273				.collect()274		} else {275			machine.to_vec()276		};277278		for hostname in &hosts {279			let nixos_cfg = config.system_config(hostname)?;280			let secrets = nix_go!(nixos_cfg.secrets);281			if secrets.has_field(name)? {282				info!("ensuring secret {name} for {hostname}");283				// Force evaluation of secret parts, triggering __fleetEnsureHostSecret284				nix_go!(secrets[{ name }].definition.parts);285			}286		}287		Ok(())288	}289}