git.delta.rocks / jrsonnet / refs/commits / 521a65806d80

difftreelog

refactor use nix bindings instead of REPL

lzxxowxyYaroslav Bolyukin2025-09-01parent: #757475f.patch.diff
in: trunk

33 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -22,9 +22,9 @@
 
 [[package]]
 name = "adler2"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
 
 [[package]]
 name = "aead"
@@ -63,9 +63,9 @@
 
 [[package]]
 name = "age"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2020562e68d7a02c2743707b262c62484b340a296924a5e4146d5a0a96ca8103"
+checksum = "57fc171f4874fa10887e47088f81a55fcf030cd421aa31ec2b370cafebcc608a"
 dependencies = [
  "aes",
  "aes-gcm",
@@ -127,12 +127,13 @@
 
 [[package]]
 name = "alejandra"
-version = "3.1.0"
-source = "git+https://github.com/kamadorueda/alejandra#264e23546663a5676a77174cab31340a81aa2cc0"
+version = "4.0.0"
+source = "git+https://github.com/kamadorueda/alejandra#c68bef57c1db3add865493d9cb741a14618bdc28"
 dependencies = [
  "mimalloc",
  "rnix",
  "rowan",
+ "serde",
 ]
 
 [[package]]
@@ -152,9 +153,9 @@
 
 [[package]]
 name = "anstream"
-version = "0.6.18"
+version = "0.6.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -167,43 +168,44 @@
 
 [[package]]
 name = "anstyle"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.1.2"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
 dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.6"
+version = "3.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
 dependencies = [
  "anstyle",
- "windows-sys 0.59.0",
+ "once_cell_polyfill",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.93"
+version = "1.0.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
 
 [[package]]
 name = "arc-swap"
@@ -241,9 +243,9 @@
 
 [[package]]
 name = "async-trait"
-version = "0.1.88"
+version = "0.1.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -258,9 +260,9 @@
 
 [[package]]
 name = "autocfg"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
 
 [[package]]
 name = "axum"
@@ -283,8 +285,8 @@
  "pin-project-lite",
  "rustversion",
  "serde",
- "sync_wrapper 1.0.1",
- "tower 0.5.1",
+ "sync_wrapper",
+ "tower 0.5.2",
  "tower-layer",
  "tower-service",
 ]
@@ -304,16 +306,16 @@
  "mime",
  "pin-project-lite",
  "rustversion",
- "sync_wrapper 1.0.1",
+ "sync_wrapper",
  "tower-layer",
  "tower-service",
 ]
 
 [[package]]
 name = "backtrace"
-version = "0.3.74"
+version = "0.3.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
 dependencies = [
  "addr2line",
  "cfg-if",
@@ -321,7 +323,7 @@
  "miniz_oxide",
  "object",
  "rustc-demangle",
- "windows-targets",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -338,15 +340,15 @@
 
 [[package]]
 name = "base64ct"
-version = "1.6.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
 
 [[package]]
 name = "basic-toml"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8"
+checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
 dependencies = [
  "serde",
 ]
@@ -380,10 +382,30 @@
 ]
 
 [[package]]
+name = "bindgen"
+version = "0.72.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "itertools 0.13.0",
+ "log",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash 2.1.1",
+ "shlex",
+ "syn",
+]
+
+[[package]]
 name = "bitflags"
-version = "2.9.1"
+version = "2.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
 dependencies = [
  "serde",
 ]
@@ -418,15 +440,15 @@
 
 [[package]]
 name = "bumpalo"
-version = "3.16.0"
+version = "3.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
 
 [[package]]
 name = "bytecount"
-version = "0.6.8"
+version = "0.6.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
+checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
 
 [[package]]
 name = "byteorder"
@@ -436,9 +458,9 @@
 
 [[package]]
 name = "bytes"
-version = "1.8.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
+checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
 
 [[package]]
 name = "cbc"
@@ -450,28 +472,28 @@
 ]
 
 [[package]]
-name = "cbitset"
-version = "0.2.0"
+name = "cc"
+version = "1.2.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
+checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
 dependencies = [
- "num-traits",
+ "shlex",
 ]
 
 [[package]]
-name = "cc"
-version = "1.2.1"
+name = "cexpr"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
 dependencies = [
- "shlex",
+ "nom 7.1.3",
 ]
 
 [[package]]
 name = "cfg-if"
-version = "1.0.0"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
 
 [[package]]
 name = "cfg_aliases"
@@ -530,10 +552,21 @@
 ]
 
 [[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
 name = "clap"
-version = "4.5.21"
+version = "4.5.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
+checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -541,9 +574,9 @@
 
 [[package]]
 name = "clap_builder"
-version = "4.5.21"
+version = "4.5.46"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
+checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
 dependencies = [
  "anstream",
  "anstyle",
@@ -551,23 +584,23 @@
  "strsim",
  "terminal_size",
  "unicase",
- "unicode-width 0.2.0",
+ "unicode-width 0.2.1",
 ]
 
 [[package]]
 name = "clap_complete"
-version = "4.5.38"
+version = "4.5.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01"
+checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.18"
+version = "4.5.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -577,27 +610,38 @@
 
 [[package]]
 name = "clap_lex"
-version = "0.7.3"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
+checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+[[package]]
+name = "codespan-reporting"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
+dependencies = [
+ "serde",
+ "termcolor",
+ "unicode-width 0.2.1",
+]
 
 [[package]]
 name = "colorchoice"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
 
 [[package]]
 name = "console"
-version = "0.15.8"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d"
 dependencies = [
  "encode_unicode",
- "lazy_static",
  "libc",
- "unicode-width 0.1.11",
- "windows-sys 0.52.0",
+ "once_cell",
+ "unicode-width 0.2.1",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -632,26 +676,20 @@
 
 [[package]]
 name = "countme"
-version = "2.0.4"
+version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58"
+checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.15"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
 dependencies = [
  "libc",
 ]
 
 [[package]]
-name = "crossbeam-utils"
-version = "0.8.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
-
-[[package]]
 name = "crossterm"
 version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -664,7 +702,7 @@
  "filedescriptor",
  "mio",
  "parking_lot",
- "rustix 1.0.7",
+ "rustix 1.0.8",
  "signal-hook",
  "signal-hook-mio",
  "winapi",
@@ -691,6 +729,22 @@
 ]
 
 [[package]]
+name = "ctor"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb"
+dependencies = [
+ "ctor-proc-macro",
+ "dtor",
+]
+
+[[package]]
+name = "ctor-proc-macro"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2"
+
+[[package]]
 name = "ctr"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -727,24 +781,72 @@
 ]
 
 [[package]]
-name = "dashmap"
-version = "6.1.0"
+name = "cxx"
+version = "1.0.173"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c64ed3da1c337cbaae7223cdcff8b4dddf698d188cd3eaddd1116f6b0295950"
+dependencies = [
+ "cc",
+ "cxxbridge-cmd",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "foldhash",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.173"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
+checksum = "ae0a26a75a05551f5ae3d75b3557543d06682284eaa7419113162d602cb45766"
 dependencies = [
- "cfg-if",
- "crossbeam-utils",
- "hashbrown 0.14.5",
- "lock_api",
- "once_cell",
- "parking_lot_core",
+ "cc",
+ "codespan-reporting",
+ "indexmap 2.11.0",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
 ]
 
 [[package]]
+name = "cxxbridge-cmd"
+version = "1.0.173"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "952d408b6002b7db4b36da07c682a9cbb34f2db0efa03e976ae50a388414e16c"
+dependencies = [
+ "clap",
+ "codespan-reporting",
+ "indexmap 2.11.0",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.173"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccbd201b471c75c6abb6321cace706d1982d270e308b891c11a3262d320f5265"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.173"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bea8b915bbc4cb4288f242aa7ca18b23ecc6965e4d6e7c1b07905e3fe2e0c41"
+dependencies = [
+ "indexmap 2.11.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
 name = "der"
-version = "0.7.9"
+version = "0.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
 dependencies = [
  "const-oid",
  "zeroize",
@@ -752,9 +854,9 @@
 
 [[package]]
 name = "deranged"
-version = "0.4.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
+checksum = "75d7cc94194b4dd0fa12845ef8c911101b7f37633cda14997a6e82099aa0b693"
 dependencies = [
  "powerfmt",
  "serde",
@@ -814,6 +916,21 @@
 ]
 
 [[package]]
+name = "dtor"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934"
+dependencies = [
+ "dtor-proc-macro",
+]
+
+[[package]]
+name = "dtor-proc-macro"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
+
+[[package]]
 name = "ed25519"
 version = "2.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -825,9 +942,9 @@
 
 [[package]]
 name = "ed25519-dalek"
-version = "2.1.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
+checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
 dependencies = [
  "curve25519-dalek",
  "ed25519",
@@ -839,37 +956,58 @@
 
 [[package]]
 name = "either"
-version = "1.13.0"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
 
 [[package]]
 name = "encode_unicode"
-version = "0.3.6"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
+name = "env_filter"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "log",
+]
 
 [[package]]
 name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
 [[package]]
 name = "errno"
-version = "0.3.12"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
 dependencies = [
  "libc",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
 name = "fastrand"
-version = "2.2.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
 name = "fiat-crypto"
@@ -879,9 +1017,9 @@
 
 [[package]]
 name = "filedescriptor"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e"
+checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d"
 dependencies = [
  "libc",
  "thiserror 1.0.69",
@@ -899,9 +1037,9 @@
 
 [[package]]
 name = "fixedbitset"
-version = "0.4.2"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
 
 [[package]]
 name = "fleet"
@@ -963,7 +1101,7 @@
  "nixlike",
  "nom 8.0.0",
  "openssh",
- "rand 0.9.1",
+ "rand 0.9.2",
  "serde",
  "serde_json",
  "tabled",
@@ -985,7 +1123,7 @@
  "ed25519-dalek",
  "fleet-shared",
  "hex",
- "rand 0.9.1",
+ "rand 0.9.2",
  "x25519-dalek",
 ]
 
@@ -1035,7 +1173,7 @@
  "fluent-syntax",
  "intl-memoizer",
  "intl_pluralrules",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "self_cell 0.10.3",
  "smallvec",
  "unic-langid",
@@ -1066,6 +1204,12 @@
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
+[[package]]
 name = "futures"
 version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1166,13 +1310,13 @@
 
 [[package]]
 name = "getrandom"
-version = "0.2.15"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi 0.11.1+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -1184,7 +1328,7 @@
  "cfg-if",
  "libc",
  "r-efi",
- "wasi 0.14.2+wasi-0.2.4",
+ "wasi 0.14.3+wasi-0.2.4",
 ]
 
 [[package]]
@@ -1204,10 +1348,16 @@
 checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
+name = "glob"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
+
+[[package]]
 name = "h2"
-version = "0.4.6"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
+checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
 dependencies = [
  "atomic-waker",
  "bytes",
@@ -1215,7 +1365,7 @@
  "futures-core",
  "futures-sink",
  "http",
- "indexmap 2.6.0",
+ "indexmap 2.11.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -1224,12 +1374,6 @@
 
 [[package]]
 name = "hashbrown"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
-
-[[package]]
-name = "hashbrown"
 version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
@@ -1242,9 +1386,9 @@
 
 [[package]]
 name = "hashbrown"
-version = "0.15.1"
+version = "0.15.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
 
 [[package]]
 name = "heck"
@@ -1254,15 +1398,9 @@
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
-[[package]]
-name = "hermit-abi"
-version = "0.4.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
 
 [[package]]
 name = "hex"
@@ -1310,9 +1448,9 @@
 
 [[package]]
 name = "http"
-version = "1.1.0"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
 dependencies = [
  "bytes",
  "fnv",
@@ -1331,12 +1469,12 @@
 
 [[package]]
 name = "http-body-util"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
 dependencies = [
  "bytes",
- "futures-util",
+ "futures-core",
  "http",
  "http-body",
  "pin-project-lite",
@@ -1344,9 +1482,9 @@
 
 [[package]]
 name = "httparse"
-version = "1.9.5"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
 
 [[package]]
 name = "httpdate"
@@ -1362,13 +1500,14 @@
 
 [[package]]
 name = "hyper"
-version = "1.5.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
+checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
 dependencies = [
+ "atomic-waker",
  "bytes",
  "futures-channel",
- "futures-util",
+ "futures-core",
  "h2",
  "http",
  "http-body",
@@ -1376,6 +1515,7 @@
  "httpdate",
  "itoa",
  "pin-project-lite",
+ "pin-utils",
  "smallvec",
  "tokio",
  "want",
@@ -1396,18 +1536,20 @@
 
 [[package]]
 name = "hyper-util"
-version = "0.1.10"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
+checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
 dependencies = [
  "bytes",
  "futures-channel",
+ "futures-core",
  "futures-util",
  "http",
  "http-body",
  "hyper",
+ "libc",
  "pin-project-lite",
- "socket2",
+ "socket2 0.6.0",
  "tokio",
  "tower-service",
  "tracing",
@@ -1415,9 +1557,9 @@
 
 [[package]]
 name = "i18n-config"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e88074831c0be5b89181b05e6748c4915f77769ecc9a4c372f88b169a8509c9"
+checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef"
 dependencies = [
  "basic-toml",
  "log",
@@ -1429,9 +1571,9 @@
 
 [[package]]
 name = "i18n-embed"
-version = "0.15.2"
+version = "0.15.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7839d8c7bb8da7bd58c1112d3a1aeb7f178ff3df4ae87783e758ca3bfb750b7"
+checksum = "669ffc2c93f97e6ddf06ddbe999fcd6782e3342978bb85f7d3c087c7978404c4"
 dependencies = [
  "arc-swap",
  "fluent",
@@ -1439,7 +1581,6 @@
  "fluent-syntax",
  "i18n-embed-impl",
  "intl-memoizer",
- "lazy_static",
  "log",
  "parking_lot",
  "rust-embed",
@@ -1450,17 +1591,15 @@
 
 [[package]]
 name = "i18n-embed-fl"
-version = "0.9.2"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6e9571c3cba9eba538eaa5ee40031b26debe76f0c7e17bafc97ea57a76cd82e"
+checksum = "04b2969d0b3fc6143776c535184c19722032b43e6a642d710fa3f88faec53c2d"
 dependencies = [
- "dashmap",
  "find-crate",
  "fluent",
  "fluent-syntax",
  "i18n-config",
  "i18n-embed",
- "lazy_static",
  "proc-macro-error2",
  "proc-macro2",
  "quote",
@@ -1484,14 +1623,15 @@
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.61"
+version = "0.1.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
  "iana-time-zone-haiku",
  "js-sys",
+ "log",
  "wasm-bindgen",
  "windows-core",
 ]
@@ -1517,24 +1657,24 @@
 
 [[package]]
 name = "indexmap"
-version = "2.6.0"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
 dependencies = [
  "equivalent",
- "hashbrown 0.15.1",
+ "hashbrown 0.15.5",
 ]
 
 [[package]]
 name = "indicatif"
-version = "0.17.9"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281"
+checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd"
 dependencies = [
  "console",
- "number_prefix",
  "portable-atomic",
- "unicode-width 0.2.0",
+ "unicode-width 0.2.1",
+ "unit-prefix",
  "vt100",
  "web-time",
 ]
@@ -1547,9 +1687,9 @@
 
 [[package]]
 name = "inout"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
 dependencies = [
  "block-padding",
  "generic-array",
@@ -1557,9 +1697,9 @@
 
 [[package]]
 name = "intl-memoizer"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda"
+checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f"
 dependencies = [
  "type-map",
  "unic-langid",
@@ -1575,6 +1715,17 @@
 ]
 
 [[package]]
+name = "io-uring"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+]
+
+[[package]]
 name = "io_tee"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1582,13 +1733,13 @@
 
 [[package]]
 name = "is-terminal"
-version = "0.4.13"
+version = "0.4.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
 dependencies = [
- "hermit-abi 0.4.0",
+ "hermit-abi",
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -1623,16 +1774,17 @@
 
 [[package]]
 name = "itoa"
-version = "1.0.11"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
 [[package]]
 name = "js-sys"
-version = "0.3.72"
+version = "0.3.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
 dependencies = [
+ "once_cell",
  "wasm-bindgen",
 ]
 
@@ -1647,27 +1799,46 @@
 
 [[package]]
 name = "libc"
-version = "0.2.174"
+version = "0.2.175"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
 
 [[package]]
+name = "libloading"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
+dependencies = [
+ "cfg-if",
+ "windows-targets 0.53.3",
+]
+
+[[package]]
 name = "libm"
-version = "0.2.11"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
+checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
 
 [[package]]
 name = "libmimalloc-sys"
-version = "0.1.39"
+version = "0.1.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44"
+checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870"
 dependencies = [
  "cc",
  "libc",
 ]
 
 [[package]]
+name = "link-cplusplus"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212"
+dependencies = [
+ "cc",
+]
+
+[[package]]
 name = "linked-hash-map"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1675,9 +1846,9 @@
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.14"
+version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
 
 [[package]]
 name = "linux-raw-sys"
@@ -1687,15 +1858,15 @@
 
 [[package]]
 name = "litrs"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
 
 [[package]]
 name = "lock_api"
-version = "0.4.12"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -1703,17 +1874,17 @@
 
 [[package]]
 name = "log"
-version = "0.4.22"
+version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 
 [[package]]
 name = "matchers"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
 dependencies = [
- "regex-automata 0.1.10",
+ "regex-automata",
 ]
 
 [[package]]
@@ -1724,24 +1895,24 @@
 
 [[package]]
 name = "memchr"
-version = "2.7.4"
+version = "2.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
 
 [[package]]
 name = "memoffset"
-version = "0.6.5"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
 dependencies = [
  "autocfg",
 ]
 
 [[package]]
 name = "mimalloc"
-version = "0.1.43"
+version = "0.1.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633"
+checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8"
 dependencies = [
  "libmimalloc-sys",
 ]
@@ -1760,31 +1931,30 @@
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.0"
+version = "0.8.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
 dependencies = [
  "adler2",
 ]
 
 [[package]]
 name = "mio"
-version = "1.0.2"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
 dependencies = [
- "hermit-abi 0.3.9",
  "libc",
  "log",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.52.0",
+ "wasi 0.11.1+wasi-snapshot-preview1",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "multimap"
-version = "0.10.0"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
+checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
 
 [[package]]
 name = "nix"
@@ -1804,17 +1974,24 @@
 dependencies = [
  "anyhow",
  "better-command",
+ "bindgen",
+ "ctor",
+ "cxx",
+ "cxx-build",
  "futures",
  "itertools 0.14.0",
  "nixlike",
+ "pkg-config",
  "r2d2",
  "regex",
  "serde",
  "serde_json",
- "thiserror 2.0.12",
+ "test-log",
+ "thiserror 2.0.16",
  "tokio",
  "tokio-util",
  "tracing",
+ "tracing-indicatif",
  "unindent",
 ]
 
@@ -1829,7 +2006,7 @@
  "serde",
  "serde-transcode",
  "serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
 ]
 
 [[package]]
@@ -1853,12 +2030,11 @@
 
 [[package]]
 name = "nu-ansi-term"
-version = "0.46.0"
+version = "0.50.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
 dependencies = [
- "overload",
- "winapi",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1915,25 +2091,25 @@
 ]
 
 [[package]]
-name = "number_prefix"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
-
-[[package]]
 name = "object"
-version = "0.36.5"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.20.2"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
 
 [[package]]
 name = "opaque-debug"
@@ -1951,24 +2127,18 @@
  "once_cell",
  "shell-escape",
  "tempfile",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
  "tokio",
 ]
 
 [[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
-[[package]]
 name = "owo-colors"
-version = "4.2.1"
+version = "4.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec"
+checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e"
 dependencies = [
  "supports-color 2.1.0",
- "supports-color 3.0.1",
+ "supports-color 3.0.2",
 ]
 
 [[package]]
@@ -1979,14 +2149,14 @@
 dependencies = [
  "bytecount",
  "fnv",
- "unicode-width 0.2.0",
+ "unicode-width 0.2.1",
 ]
 
 [[package]]
 name = "parking_lot"
-version = "0.12.3"
+version = "0.12.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -1994,15 +2164,15 @@
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.10"
+version = "0.9.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -2050,9 +2220,9 @@
 
 [[package]]
 name = "pem"
-version = "3.0.4"
+version = "3.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae"
+checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3"
 dependencies = [
  "base64 0.22.1",
  "serde",
@@ -2060,34 +2230,34 @@
 
 [[package]]
 name = "percent-encoding"
-version = "2.3.1"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
 
 [[package]]
 name = "petgraph"
-version = "0.6.5"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
+checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
 dependencies = [
  "fixedbitset",
- "indexmap 2.6.0",
+ "indexmap 2.11.0",
 ]
 
 [[package]]
 name = "pin-project"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.7"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2096,9 +2266,9 @@
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.15"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
 
 [[package]]
 name = "pin-utils"
@@ -2128,6 +2298,12 @@
 ]
 
 [[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
 name = "poly1305"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2152,9 +2328,9 @@
 
 [[package]]
 name = "portable-atomic"
-version = "1.9.0"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
+checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
 
 [[package]]
 name = "powerfmt"
@@ -2164,18 +2340,18 @@
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.20"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
 dependencies = [
  "zerocopy",
 ]
 
 [[package]]
 name = "prettyplease"
-version = "0.2.25"
+version = "0.2.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
 dependencies = [
  "proc-macro2",
  "syn",
@@ -2205,18 +2381,18 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.89"
+version = "1.0.101"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.13.3"
+version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f"
+checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2224,13 +2400,12 @@
 
 [[package]]
 name = "prost-build"
-version = "0.13.3"
+version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15"
+checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
 dependencies = [
- "bytes",
  "heck",
- "itertools 0.13.0",
+ "itertools 0.14.0",
  "log",
  "multimap",
  "once_cell",
@@ -2245,12 +2420,12 @@
 
 [[package]]
 name = "prost-derive"
-version = "0.13.3"
+version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5"
+checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
 dependencies = [
  "anyhow",
- "itertools 0.13.0",
+ "itertools 0.14.0",
  "proc-macro2",
  "quote",
  "syn",
@@ -2258,18 +2433,18 @@
 
 [[package]]
 name = "prost-types"
-version = "0.13.3"
+version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670"
+checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
 dependencies = [
  "prost",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 dependencies = [
  "proc-macro2",
 ]
@@ -2304,9 +2479,9 @@
 
 [[package]]
 name = "rand"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
 dependencies = [
  "rand_chacha 0.9.0",
  "rand_core 0.9.3",
@@ -2338,7 +2513,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom 0.2.15",
+ "getrandom 0.2.16",
 ]
 
 [[package]]
@@ -2352,9 +2527,9 @@
 
 [[package]]
 name = "rcgen"
-version = "0.13.1"
+version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779"
+checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
 dependencies = [
  "pem",
  "ring",
@@ -2365,68 +2540,52 @@
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.7"
+version = "0.5.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
+checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "regex"
-version = "1.11.1"
+version = "1.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata 0.4.9",
- "regex-syntax 0.8.5",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-dependencies = [
- "regex-syntax 0.6.29",
+ "regex-automata",
+ "regex-syntax",
 ]
 
 [[package]]
 name = "regex-automata"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax 0.8.5",
+ "regex-syntax",
 ]
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
 
 [[package]]
 name = "ring"
-version = "0.17.8"
+version = "0.17.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
 dependencies = [
  "cc",
  "cfg-if",
- "getrandom 0.2.15",
+ "getrandom 0.2.16",
  "libc",
- "spin",
  "untrusted",
  "windows-sys 0.52.0",
 ]
@@ -2455,20 +2614,18 @@
 
 [[package]]
 name = "rnix"
-version = "0.10.2"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8024a523e8836f1a5d051203dc00d833357fee94e351b51348dfaeca5364daa9"
+checksum = "6f15e00b0ab43abd70d50b6f8cd021290028f9b7fdd7cdfa6c35997173bc1ba9"
 dependencies = [
- "cbitset",
  "rowan",
- "smol_str",
 ]
 
 [[package]]
 name = "ron"
-version = "0.10.1"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "beceb6f7bf81c73e73aeef6dd1356d9a1b2b4909e1f0fc3e59b034f9572d7b7f"
+checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468"
 dependencies = [
  "base64 0.22.1",
  "bitflags",
@@ -2479,22 +2636,22 @@
 
 [[package]]
 name = "rowan"
-version = "0.12.6"
+version = "0.15.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043"
+checksum = "d4f1e4a001f863f41ea8d0e6a0c34b356d5b733db50dadab3efef640bafb779b"
 dependencies = [
  "countme",
- "hashbrown 0.9.1",
+ "hashbrown 0.14.5",
  "memoffset",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "text-size",
 ]
 
 [[package]]
 name = "rsa"
-version = "0.9.6"
+version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
+checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
 dependencies = [
  "const-oid",
  "digest",
@@ -2512,9 +2669,9 @@
 
 [[package]]
 name = "rust-embed"
-version = "8.5.0"
+version = "8.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0"
+checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a"
 dependencies = [
  "rust-embed-impl",
  "rust-embed-utils",
@@ -2523,9 +2680,9 @@
 
 [[package]]
 name = "rust-embed-impl"
-version = "8.5.0"
+version = "8.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478"
+checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2536,9 +2693,9 @@
 
 [[package]]
 name = "rust-embed-utils"
-version = "8.5.0"
+version = "8.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d"
+checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594"
 dependencies = [
  "sha2",
  "walkdir",
@@ -2546,9 +2703,9 @@
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.24"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
 
 [[package]]
 name = "rustc-hash"
@@ -2557,6 +2714,12 @@
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
+name = "rustc-hash"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
+
+[[package]]
 name = "rustc_version"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2567,35 +2730,35 @@
 
 [[package]]
 name = "rustix"
-version = "0.38.40"
+version = "0.38.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
 dependencies = [
  "bitflags",
  "errno",
  "libc",
- "linux-raw-sys 0.4.14",
- "windows-sys 0.52.0",
+ "linux-raw-sys 0.4.15",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "rustix"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
 dependencies = [
  "bitflags",
  "errno",
  "libc",
  "linux-raw-sys 0.9.4",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
 name = "rustls"
-version = "0.23.17"
+version = "0.23.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e"
+checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
 dependencies = [
  "log",
  "once_cell",
@@ -2617,15 +2780,18 @@
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.10.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
+checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
+dependencies = [
+ "zeroize",
+]
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.8"
+version = "0.103.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
 dependencies = [
  "ring",
  "rustls-pki-types",
@@ -2634,15 +2800,15 @@
 
 [[package]]
 name = "rustversion"
-version = "1.0.18"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
 
 [[package]]
 name = "ryu"
-version = "1.0.18"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "salsa20"
@@ -2678,6 +2844,12 @@
 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
+name = "scratch"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2"
+
+[[package]]
 name = "scrypt"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2703,20 +2875,20 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
 dependencies = [
- "self_cell 1.0.4",
+ "self_cell 1.2.0",
 ]
 
 [[package]]
 name = "self_cell"
-version = "1.0.4"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a"
+checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
 
 [[package]]
 name = "semver"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
 
 [[package]]
 name = "serde"
@@ -2738,9 +2910,9 @@
 
 [[package]]
 name = "serde_bytes"
-version = "0.11.15"
+version = "0.11.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a"
+checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96"
 dependencies = [
  "serde",
 ]
@@ -2758,9 +2930,9 @@
 
 [[package]]
 name = "serde_json"
-version = "1.0.140"
+version = "1.0.143"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
 dependencies = [
  "itoa",
  "memchr",
@@ -2770,9 +2942,9 @@
 
 [[package]]
 name = "sha2"
-version = "0.10.8"
+version = "0.10.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -2802,9 +2974,9 @@
 
 [[package]]
 name = "signal-hook"
-version = "0.3.17"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
+checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
 dependencies = [
  "libc",
  "signal-hook-registry",
@@ -2823,9 +2995,9 @@
 
 [[package]]
 name = "signal-hook-registry"
-version = "1.4.2"
+version = "1.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
 dependencies = [
  "libc",
 ]
@@ -2842,36 +3014,34 @@
 
 [[package]]
 name = "slab"
-version = "0.4.9"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
 
 [[package]]
 name = "smallvec"
-version = "1.13.2"
+version = "1.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
 
 [[package]]
-name = "smol_str"
-version = "0.1.24"
+name = "socket2"
+version = "0.5.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9"
+checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
 dependencies = [
- "serde",
+ "libc",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "socket2"
-version = "0.5.7"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -2914,18 +3084,18 @@
 
 [[package]]
 name = "supports-color"
-version = "3.0.1"
+version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77"
+checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
 dependencies = [
  "is_ci",
 ]
 
 [[package]]
 name = "syn"
-version = "2.0.87"
+version = "2.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2934,15 +3104,9 @@
 
 [[package]]
 name = "sync_wrapper"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
-
-[[package]]
-name = "sync_wrapper"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
 
 [[package]]
 name = "tabled"
@@ -2970,25 +3134,34 @@
 
 [[package]]
 name = "tempfile"
-version = "3.20.0"
+version = "3.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
+checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
 dependencies = [
  "fastrand",
  "getrandom 0.3.3",
  "once_cell",
- "rustix 1.0.7",
- "windows-sys 0.59.0",
+ "rustix 1.0.8",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
+name = "termcolor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
 name = "terminal_size"
-version = "0.4.0"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
+checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
 dependencies = [
- "rustix 0.38.40",
- "windows-sys 0.59.0",
+ "rustix 1.0.8",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -3003,12 +3176,34 @@
 ]
 
 [[package]]
+name = "test-log"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b"
+dependencies = [
+ "env_logger",
+ "test-log-macros",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "test-log-macros"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "testing_table"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc"
 dependencies = [
- "unicode-width 0.2.0",
+ "unicode-width 0.2.1",
 ]
 
 [[package]]
@@ -3056,11 +3251,11 @@
 
 [[package]]
 name = "thiserror"
-version = "2.0.12"
+version = "2.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
 dependencies = [
- "thiserror-impl 2.0.12",
+ "thiserror-impl 2.0.16",
 ]
 
 [[package]]
@@ -3076,9 +3271,9 @@
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3087,19 +3282,18 @@
 
 [[package]]
 name = "thread_local"
-version = "1.1.8"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
 dependencies = [
  "cfg-if",
- "once_cell",
 ]
 
 [[package]]
 name = "time"
-version = "0.3.41"
+version = "0.3.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
+checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3"
 dependencies = [
  "deranged",
  "num-conv",
@@ -3111,15 +3305,15 @@
 
 [[package]]
 name = "time-core"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
+checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68"
 
 [[package]]
 name = "time-macros"
-version = "0.2.22"
+version = "0.2.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
+checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c"
 dependencies = [
  "num-conv",
  "time-core",
@@ -3127,28 +3321,31 @@
 
 [[package]]
 name = "tinystr"
-version = "0.7.6"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
 dependencies = [
  "displaydoc",
+ "zerovec",
 ]
 
 [[package]]
 name = "tokio"
-version = "1.45.1"
+version = "1.47.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
+checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
 dependencies = [
  "backtrace",
  "bytes",
+ "io-uring",
  "libc",
  "mio",
  "pin-project-lite",
  "signal-hook-registry",
- "socket2",
+ "slab",
+ "socket2 0.6.0",
  "tokio-macros",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -3164,20 +3361,19 @@
 
 [[package]]
 name = "tokio-rustls"
-version = "0.26.0"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
+checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
 dependencies = [
  "rustls",
- "rustls-pki-types",
  "tokio",
 ]
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.16"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1"
+checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -3187,9 +3383,9 @@
 
 [[package]]
 name = "tokio-util"
-version = "0.7.15"
+version = "0.7.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
 dependencies = [
  "bytes",
  "futures-core",
@@ -3229,7 +3425,7 @@
  "pin-project",
  "prost",
  "rustls-pemfile",
- "socket2",
+ "socket2 0.5.10",
  "tokio",
  "tokio-rustls",
  "tokio-stream",
@@ -3275,14 +3471,14 @@
 
 [[package]]
 name = "tower"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
 dependencies = [
  "futures-core",
  "futures-util",
  "pin-project-lite",
- "sync_wrapper 0.1.2",
+ "sync_wrapper",
  "tower-layer",
  "tower-service",
 ]
@@ -3318,9 +3514,9 @@
 
 [[package]]
 name = "tracing"
-version = "0.1.40"
+version = "0.1.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
 dependencies = [
  "pin-project-lite",
  "tracing-attributes",
@@ -3329,9 +3525,9 @@
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.27"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3340,9 +3536,9 @@
 
 [[package]]
 name = "tracing-core"
-version = "0.1.32"
+version = "0.1.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
 dependencies = [
  "once_cell",
  "valuable",
@@ -3350,9 +3546,9 @@
 
 [[package]]
 name = "tracing-indicatif"
-version = "0.3.6"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d"
+checksum = "04d4e11e0e27acef25a47f27e9435355fecdc488867fa2bc90e75b0700d2823d"
 dependencies = [
  "indicatif",
  "tracing",
@@ -3373,9 +3569,9 @@
 
 [[package]]
 name = "tracing-serde"
-version = "0.1.3"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1"
+checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
 dependencies = [
  "serde",
  "tracing-core",
@@ -3383,14 +3579,14 @@
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.18"
+version = "0.3.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
 dependencies = [
  "matchers",
  "nu-ansi-term",
  "once_cell",
- "regex",
+ "regex-automata",
  "serde",
  "serde_json",
  "sharded-slab",
@@ -3410,33 +3606,33 @@
 
 [[package]]
 name = "type-map"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f"
+checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
 dependencies = [
- "rustc-hash",
+ "rustc-hash 2.1.1",
 ]
 
 [[package]]
 name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 
 [[package]]
 name = "unic-langid"
-version = "0.9.5"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44"
+checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05"
 dependencies = [
  "unic-langid-impl",
 ]
 
 [[package]]
 name = "unic-langid-impl"
-version = "0.9.5"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5"
+checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
 dependencies = [
  "serde",
  "tinystr",
@@ -3444,15 +3640,15 @@
 
 [[package]]
 name = "unicase"
-version = "2.8.0"
+version = "2.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
+checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.13"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 
 [[package]]
 name = "unicode-segmentation"
@@ -3462,15 +3658,15 @@
 
 [[package]]
 name = "unicode-width"
-version = "0.1.11"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
 [[package]]
 name = "unicode-width"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
 
 [[package]]
 name = "unicode_categories"
@@ -3485,6 +3681,12 @@
 checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
 
 [[package]]
+name = "unit-prefix"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817"
+
+[[package]]
 name = "universal-hash"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3508,9 +3710,9 @@
 
 [[package]]
 name = "valuable"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
 
 [[package]]
 name = "version_check"
@@ -3526,7 +3728,7 @@
 dependencies = [
  "itoa",
  "log",
- "unicode-width 0.1.11",
+ "unicode-width 0.1.14",
  "vte",
 ]
 
@@ -3572,39 +3774,39 @@
 
 [[package]]
 name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
+version = "0.11.1+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
 
 [[package]]
 name = "wasi"
-version = "0.14.2+wasi-0.2.4"
+version = "0.14.3+wasi-0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95"
 dependencies = [
- "wit-bindgen-rt",
+ "wit-bindgen",
 ]
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.95"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
 dependencies = [
  "cfg-if",
  "once_cell",
+ "rustversion",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.95"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
 dependencies = [
  "bumpalo",
  "log",
- "once_cell",
  "proc-macro2",
  "quote",
  "syn",
@@ -3613,9 +3815,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.95"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -3623,9 +3825,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.95"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3636,9 +3838,12 @@
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.95"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
 
 [[package]]
 name = "web-time"
@@ -3659,7 +3864,7 @@
  "either",
  "home",
  "once_cell",
- "rustix 0.38.40",
+ "rustix 0.38.44",
 ]
 
 [[package]]
@@ -3680,11 +3885,11 @@
 
 [[package]]
 name = "winapi-util"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
 dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -3695,11 +3900,37 @@
 
 [[package]]
 name = "windows-core"
-version = "0.52.0"
+version = "0.61.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
 dependencies = [
- "windows-targets",
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -3709,12 +3940,30 @@
 checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
 
 [[package]]
+name = "windows-result"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
 name = "windows-sys"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -3723,23 +3972,49 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.3",
+]
+
+[[package]]
 name = "windows-targets"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
 ]
 
 [[package]]
@@ -3749,55 +4024,100 @@
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[package]]
 name = "windows_i686_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
+name = "windows_x86_64_msvc"
+version = "0.53.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
-dependencies = [
- "bitflags",
-]
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
+[[package]]
+name = "wit-bindgen"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
 
 [[package]]
 name = "wsl"
@@ -3834,19 +4154,18 @@
 
 [[package]]
 name = "zerocopy"
-version = "0.7.35"
+version = "0.8.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
 dependencies = [
- "byteorder",
  "zerocopy-derive",
 ]
 
 [[package]]
 name = "zerocopy-derive"
-version = "0.7.35"
+version = "0.8.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3854,6 +4173,12 @@
 ]
 
 [[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+
+[[package]]
 name = "zeroize"
 version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3872,3 +4197,12 @@
  "quote",
  "syn",
 ]
+
+[[package]]
+name = "zerovec"
+version = "0.11.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
+dependencies = [
+ "zerofrom",
+]
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,7 +11,7 @@
 nix-eval = { path = "./crates/nix-eval" }
 nixlike = { path = "./crates/nixlike" }
 
-age = { version = "0.11", features = ["ssh", "plugin"] }
+age = { version = "0.11", features = ["plugin", "ssh"] }
 anyhow = "1.0"
 clap = { version = "4.5", features = ["derive", "env", "unicode", "wrap_help"] }
 clap_complete = "4.5"
modifiedcmds/fleet/Cargo.tomldiffbeforeafterboth
--- a/cmds/fleet/Cargo.toml
+++ b/cmds/fleet/Cargo.toml
@@ -43,7 +43,7 @@
 
 fleet-base = { version = "0.1.0", path = "../../crates/fleet-base" }
 human-repr = { version = "1.1", optional = true }
-indicatif = { version = "0.17", optional = true }
+indicatif = { version = "0.18", optional = true }
 nom = "8.0.0"
 tracing-indicatif = { version = "0.3", optional = true }
 
modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/build_systems.rs
+++ b/cmds/fleet/src/cmds/build_systems.rs
@@ -1,13 +1,13 @@
 use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf};
 
-use anyhow::{Result, anyhow};
+use anyhow::Result;
 use clap::Parser;
 use fleet_base::{
 	deploy::{DeployAction, deploy_task, upload_task},
 	host::{Config, DeployKind, GenerationStorage},
 	opts::FleetOpts,
 };
-use nix_eval::{NixBuildBatch, nix_go};
+use nix_eval::nix_go;
 use tokio::task::LocalSet;
 use tracing::{Instrument, error, field, info, info_span, warn};
 
@@ -32,17 +32,15 @@
 	config: Config,
 	hostname: String,
 	build_attr: &str,
-	batch: Option<NixBuildBatch>,
+	// batch: Option<NixBuildBatch>,
 ) -> Result<PathBuf> {
 	info!("building");
 	let host = config.host(&hostname).await?;
 	// let action = Action::from(self.subcommand.clone());
 	let nixos = host.nixos_config().await?;
 	let drv = nix_go!(nixos.system.build[{ build_attr }]);
-	let outputs = drv.build_maybe_batch(batch).await?;
-	let out_output = outputs
-		.get("out")
-		.ok_or_else(|| anyhow!("system build should produce \"out\" output"))?;
+	// let outputs = drv.build_maybe_batch(batch).await?;
+	let out_output = drv.build("out").await?;
 
 	// We already have system profiles for backups.
 	if !host.local {
@@ -56,11 +54,11 @@
 					config.data().gc_root_prefix
 				),
 			)
-			.arg(out_output);
+			.arg(&out_output);
 		cmd.sudo().run_nix().await?;
 	}
 
-	Ok(out_output.clone())
+	Ok(out_output)
 }
 
 impl BuildSystems {
@@ -68,21 +66,20 @@
 		let hosts = opts.filter_skipped(config.list_hosts().await?).await?;
 		let set = LocalSet::new();
 		let build_attr = self.build_attr.clone();
-		let batch = (hosts.len() > 1).then(|| {
-			config
-				.nix_session
-				.new_build_batch("build-hosts".to_string())
-		});
+		// let batch = (hosts.len() > 1).then(|| {
+		// 	config
+		// 		.nix_session
+		// 		.new_build_batch("build-hosts".to_string())
+		// });
 		for host in hosts {
 			let config = config.clone();
 			let span = info_span!("build", host = field::display(&host.name));
 			let hostname = host.name;
 			let build_attr = build_attr.clone();
-			let batch = batch.clone();
+			// let batch = batch.clone();
 			set.spawn_local(
 				(async move {
-					let built = match build_task(config, hostname.clone(), &build_attr, batch).await
-					{
+					let built = match build_task(config, hostname.clone(), &build_attr).await {
 						Ok(path) => path,
 						Err(e) => {
 							error!("failed to deploy host: {}", e);
@@ -91,7 +88,7 @@
 					};
 					// TODO: Handle error
 					let mut out = current_dir().expect("cwd exists");
-					out.push(format!("built-{}", hostname));
+					out.push(format!("built-{hostname}"));
 
 					info!("linking iso image to {:?}", out);
 					if let Err(e) = symlink(built, out) {
@@ -101,7 +98,6 @@
 				.instrument(span),
 			);
 		}
-		drop(batch);
 		set.await;
 		Ok(())
 	}
@@ -111,17 +107,16 @@
 	pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> {
 		let hosts = opts.filter_skipped(config.list_hosts().await?).await?;
 		let set = LocalSet::new();
-		let batch = (hosts.len() > 1).then(|| {
-			config
-				.nix_session
-				.new_build_batch("deploy-hosts".to_string())
-		});
+		// let batch = (hosts.len() > 1).then(|| {
+		// 	config
+		// 		.nix_session
+		// 		.new_build_batch("deploy-hosts".to_string())
+		// });
 		for host in hosts.into_iter() {
 			let config = config.clone();
 			let span = info_span!("deploy", host = field::display(&host.name));
 			let hostname = host.name.clone();
 			let opts = opts.clone();
-			let batch = batch.clone();
 			if let Some(deploy_kind) = opts.action_attr::<DeployKind>(&host, "deploy_kind").await? {
 				host.set_deploy_kind(deploy_kind);
 			};
@@ -131,15 +126,14 @@
 
 			set.spawn_local(
 				(async move {
-					let built =
-						match build_task(config.clone(), hostname.clone(), "toplevel", batch).await
-						{
-							Ok(path) => path,
-							Err(e) => {
-								error!("failed to build host system closure: {}", e);
-								return;
-							}
-						};
+					let built = match build_task(config.clone(), hostname.clone(), "toplevel").await
+					{
+						Ok(path) => path,
+						Err(e) => {
+							error!("failed to build host system closure: {:#}", e);
+							return;
+						}
+					};
 
 					let deploy_kind = match host.deploy_kind().await {
 						Ok(v) => v,
@@ -187,7 +181,6 @@
 				.instrument(span),
 			);
 		}
-		drop(batch);
 		set.await;
 		Ok(())
 	}
modifiedcmds/fleet/src/cmds/info.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/info.rs
+++ b/cmds/fleet/src/cmds/info.rs
@@ -38,7 +38,8 @@
 				'host: for host in config.list_hosts().await? {
 					if !tagged.is_empty() {
 						let config = &config.config_field;
-						let tags: Vec<String> = nix_go_json!(config.hosts[{ host.name }].tags);
+						let host_name = &host.name;
+						let tags: Vec<String> = nix_go_json!(config.hosts[host_name].tags);
 						for tag in tagged {
 							if !tags.contains(tag) {
 								continue 'host;
modifiedcmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -2,6 +2,7 @@
 	collections::{BTreeMap, BTreeSet, HashSet},
 	io::{self, Read, Write, stdin, stdout},
 	path::PathBuf,
+	slice,
 };
 
 use age::Recipient;
@@ -14,7 +15,7 @@
 	opts::FleetOpts,
 };
 use fleet_shared::SecretData;
-use nix_eval::{NixBuildBatch, Value, nix_go, nix_go_json};
+use nix_eval::{NixType, Value, nix_go, nix_go_json};
 use owo_colors::OwoColorize;
 use serde::Deserialize;
 use tabled::{Table, Tabled};
@@ -159,7 +160,7 @@
 }
 
 #[allow(clippy::too_many_arguments)]
-#[tracing::instrument(skip(config, secret, field, prefer_identities, batch))]
+#[tracing::instrument(skip(config, secret, field, prefer_identities))]
 async fn maybe_regenerate_shared_secret(
 	secret_name: &str,
 	config: &Config,
@@ -168,7 +169,7 @@
 	expected_owners: &[String],
 	expected_generation_data: serde_json::Value,
 	prefer_identities: &[String],
-	batch: Option<NixBuildBatch>,
+	// batch: Option<NixBuildBatch>,
 ) -> Result<FleetSharedSecret> {
 	let original_set = secret.owners.clone();
 
@@ -206,12 +207,12 @@
 			field,
 			expected_owners.to_vec(),
 			expected_generation_data,
-			batch,
+			// batch,
 		)
 		.await?;
 		Ok(generated)
 	} else {
-		drop(batch);
+		// drop(batch);
 		let identity_holder = if !prefer_identities.is_empty() {
 			prefer_identities
 				.iter()
@@ -263,7 +264,7 @@
 	default_generator: Value,
 	expected_owners: &[String],
 	expected_generation_data: serde_json::Value,
-	batch: Option<NixBuildBatch>,
+	// batch: Option<NixBuildBatch>,
 ) -> Result<FleetSecret> {
 	let generator = nix_go!(secret.generator);
 	let on: Option<String> = nix_go_json!(default_generator.impureOn);
@@ -284,17 +285,16 @@
 		recipients.push(key);
 	}
 	let generators = nix_go!(mk_secret_generators(Obj { recipients }));
-	let pkgs_and_generators = nix_go!(on_pkgs + generators);
+	// FIXME: Apparently, // operator is slow in nix
+	let pkgs_and_generators = on_pkgs.attrs_update(generators)?;
 
 	let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators));
 
 	let generator = nix_go!(call_package(generator)(Obj {}));
 
-	let generator = generator.build_maybe_batch(batch).await?;
-	let generator = generator
-		.get("out")
-		.ok_or_else(|| anyhow!("missing generateImpure out"))?;
-	let generator = host.remote_derivation(generator).await?;
+	// let generator = generator.build_maybe_batch(batch).await?;
+	let generator = generator.build("out").await?;
+	let generator = host.remote_derivation(&generator).await?;
 
 	let out_parent = host.mktemp_dir().await?;
 	let out = format!("{out_parent}/out");
@@ -347,21 +347,21 @@
 	secret: Value,
 	expected_owners: &[String],
 	expected_generation_data: serde_json::Value,
-	batch: Option<NixBuildBatch>,
+	// batch: Option<NixBuildBatch>,
 ) -> Result<FleetSecret> {
 	let generator = nix_go!(secret.generator);
 	// Can't properly check on nix module system level
 	{
-		let gen_ty = generator.type_of().await?;
-		if gen_ty == "null" {
+		let gen_ty = generator.type_of()?;
+		if matches!(gen_ty, NixType::Null) {
 			bail!("secret has no generator defined, can't automatically generate it.");
 		}
-		if gen_ty == "set" {
-			if !generator.has_field("__functor").await? {
-				bail!("generator should be functor, got {gen_ty}");
+		if matches!(gen_ty, NixType::Attrs) {
+			if !generator.has_field("__functor")? {
+				bail!("generator should be functor, got {gen_ty:?}");
 			}
-		} else if gen_ty != "lambda" {
-			bail!("generator should be functor, got {gen_ty}");
+		} else if matches!(gen_ty, NixType::Function) {
+			bail!("generator should be functor, got {gen_ty:?}");
 		}
 	}
 	let nixpkgs = &config.nixpkgs;
@@ -378,7 +378,7 @@
 	let generators = nix_go!(default_mk_secret_generators(Obj {
 		recipients: <Vec<String>>::new(),
 	}));
-	let pkgs_and_generators = nix_go!(default_pkgs + generators);
+	let pkgs_and_generators = default_pkgs.clone().attrs_update(generators)?;
 
 	let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators));
 	let default_generator = nix_go!(call_package(generator)(Obj {}));
@@ -394,7 +394,7 @@
 				default_generator,
 				expected_owners,
 				expected_generation_data,
-				batch,
+				// batch,
 			)
 			.await
 		}
@@ -416,7 +416,7 @@
 	secret: Value,
 	expected_owners: Vec<String>,
 	expected_generation_data: serde_json::Value,
-	batch: Option<NixBuildBatch>,
+	// batch: Option<NixBuildBatch>,
 ) -> Result<FleetSharedSecret> {
 	// let owners: Vec<String> = nix_go_json!(secret.expectedOwners);
 	Ok(FleetSharedSecret {
@@ -426,7 +426,7 @@
 			secret,
 			&expected_owners,
 			expected_generation_data,
-			batch,
+			// batch,
 		)
 		.await?,
 		owners: expected_owners,
@@ -722,7 +722,8 @@
 				}
 
 				let config_field = &config.config_field;
-				let field = nix_go!(config_field.sharedSecrets[{ name }]);
+				let name_clone = name.clone();
+				let field = nix_go!(config_field.sharedSecrets[name_clone]);
 				let expected_generation_data = nix_go_json!(field.expectedGenerationData);
 
 				let updated = maybe_regenerate_shared_secret(
@@ -733,7 +734,7 @@
 					&target_machines,
 					expected_generation_data,
 					&prefer_identities,
-					None,
+					// None,
 				)
 				.await?;
 				config.replace_shared(name, updated);
@@ -746,7 +747,7 @@
 				let stored_shared_set = config.list_shared().into_iter().collect::<HashSet<_>>();
 				{
 					// Generate missing shared
-					let shared_batch = None;
+					// let shared_batch = None;
 					let _span = info_span!("shared").entered();
 					let expected_shared_set = config
 						.list_configured_shared()
@@ -771,7 +772,7 @@
 							secret,
 							expected_owners,
 							expected_generation_data,
-							shared_batch.clone(),
+							// shared_batch.clone(),
 						)
 						.in_current_span()
 						.await?;
@@ -779,7 +780,7 @@
 					}
 				}
 				if !skip_hosts {
-					let hosts_batch = None;
+					// let hosts_batch = None;
 					for host in config.list_hosts().await? {
 						if opts.should_skip(&host).await? {
 							continue;
@@ -805,9 +806,9 @@
 								config,
 								missing,
 								secret,
-								&[host.name.clone()],
+								slice::from_ref(&host.name),
 								expected_generation_data,
-								hosts_batch.clone(),
+								// hosts_batch.clone(),
 							)
 							.in_current_span()
 							.await
@@ -831,9 +832,9 @@
 									config,
 									&name,
 									secret,
-									&[host.name.clone()],
+									slice::from_ref(&host.name),
 									expected_generation_data,
-									hosts_batch.clone(),
+									// hosts_batch.clone(),
 								)
 								.in_current_span()
 								.await
@@ -874,7 +875,7 @@
 							&expected_owners,
 							expected_generation_data,
 							&prefer_identities,
-							None,
+							// None,
 						)
 						.await?,
 					);
modifiedcmds/fleet/src/cmds/tf.rsdiffbeforeafterboth
--- a/cmds/fleet/src/cmds/tf.rs
+++ b/cmds/fleet/src/cmds/tf.rs
@@ -42,8 +42,7 @@
 			debug!("generating terraform configs");
 			let system = &config.local_system;
 			let config = &config.config_field;
-			let data: HashMap<String, PathBuf> = nix_go!(config.tf({ system })).build().await?;
-			let data = &data["out"];
+			let data: PathBuf = nix_go!(config.tf({ system })).build("out").await?;
 			let data = fs::read(&data).await?;
 
 			create_dir_all(&dir).await?;
modifiedcmds/fleet/src/main.rsdiffbeforeafterboth
--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -23,6 +23,7 @@
 use human_repr::HumanCount;
 #[cfg(feature = "indicatif")]
 use indicatif::{ProgressState, ProgressStyle};
+use nix_eval::{gc_register_my_thread, gc_unregister_my_thread, init_libraries};
 use tracing::{Instrument, error, info, info_span};
 #[cfg(feature = "indicatif")]
 use tracing_indicatif::IndicatifLayer;
@@ -183,21 +184,31 @@
 	}
 
 	setup_logging();
-	async_main(opts)
-}
 
-#[tokio::main]
-async fn async_main(opts: RootOpts) -> ExitCode {
-	if let Err(e) = main_real(opts).await {
-		error!("{e:#}");
-		return ExitCode::FAILURE;
-	}
-	ExitCode::SUCCESS
+	init_libraries();
+
+	tokio::runtime::Builder::new_multi_thread()
+		.enable_all()
+		.on_thread_start(|| {
+			gc_register_my_thread();
+		})
+		.on_thread_stop(|| {
+			gc_unregister_my_thread();
+		})
+		.build()
+		.expect("failed to build runtime")
+		.block_on(async {
+			if let Err(e) = main_real(opts).await {
+				error!("{e:#}");
+				ExitCode::FAILURE
+			} else {
+				ExitCode::SUCCESS
+			}
+		})
+	// async_main(opts)
 }
 
 async fn main_real(opts: RootOpts) -> Result<()> {
-	nix_eval::init_tokio();
-
 	let nix_args = std::env::var_os("NIX_ARGS")
 		.map(|a| extra_args::parse_os(&a))
 		.transpose()?
modifiedcrates/fleet-base/src/host.rsdiffbeforeafterboth
--- a/crates/fleet-base/src/host.rs
+++ b/crates/fleet-base/src/host.rs
@@ -12,7 +12,7 @@
 
 use anyhow::{Context, Result, anyhow, bail, ensure};
 use fleet_shared::SecretData;
-use nix_eval::{NixSession, Value, nix_go, nix_go_json, util::assert_warn};
+use nix_eval::{Value, nix_go, nix_go_json, util::assert_warn};
 use openssh::SessionBuilder;
 use serde::de::DeserializeOwned;
 use tabled::Tabled;
@@ -41,8 +41,6 @@
 	pub default_pkgs: Value,
 	/// inputs.nixpkgs
 	pub nixpkgs: Value,
-
-	pub nix_session: NixSession,
 }
 
 // TODO: Make field not pub
@@ -232,14 +230,17 @@
 			}
 		};
 		if !is_fleet_managed {
-			bail!(indoc::indoc! {"
+			bail!(
+				"{}",
+				indoc::indoc! {"
 				host is not marked as managed by fleet
 				if you're not trying to lustrate/install system from scratch,
 				you should either
 					1. manually create /etc/FLEET_HOST file on the target host,
 					2. use ?deploy_kind=fleet host argument if you're upgrading from older version of fleet
 					3. use ?deploy_kind=upgrade_to_fleet if you're upgrading from plain nixos to fleet-managed nixos
-			"});
+			"}
+			);
 		}
 		// TOCTOU is possible
 		let _ = self.deploy_kind.set(DeployKind::Fleet);
@@ -503,8 +504,8 @@
 		let nixos = self.nixos_unchecked_config().await?;
 		let secrets = nix_go!(nixos.secrets);
 		let mut out = Vec::new();
-		for name in secrets.list_fields().await? {
-			let secret = nix_go!(secrets[{ name }]);
+		for name in secrets.list_fields()? {
+			let secret = secrets.get_field(&name)?;
 			let is_shared: bool = nix_go_json!(secret.shared);
 			if is_shared {
 				continue;
@@ -592,7 +593,7 @@
 	}
 	pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {
 		let config = &self.config_field;
-		let names = nix_go!(config.hosts).list_fields().await?;
+		let names = nix_go!(config.hosts).list_fields()?;
 		let mut out = vec![];
 		for name in names {
 			out.push(self.host(&name).await?);
@@ -608,7 +609,7 @@
 	/// Shared secrets configured in fleet.nix or in flake
 	pub async fn list_configured_shared(&self) -> Result<Vec<String>> {
 		let config_field = &self.config_field;
-		Ok(nix_go!(config_field.sharedSecrets).list_fields().await?)
+		nix_go!(config_field.sharedSecrets).list_fields()
 	}
 	/// Shared secrets configured in fleet.nix
 	pub fn list_shared(&self) -> Vec<String> {
@@ -680,10 +681,10 @@
 	// maybe it can be a .nix file for persistence, but accessible only
 	// thru some shared state controller? Might it be stored in terraform
 	// state provider?
-	pub fn data(&self) -> MutexGuard<FleetData> {
+	pub fn data(&'_ self) -> MutexGuard<'_, FleetData> {
 		self.data.lock().unwrap()
 	}
-	pub fn data_mut(&self) -> MutexGuard<FleetData> {
+	pub fn data_mut(&'_ self) -> MutexGuard<'_, FleetData> {
 		self.data.lock().unwrap()
 	}
 	pub fn save(&self) -> Result<()> {
@@ -691,8 +692,7 @@
 		let data = nixlike::serialize(&self.data() as &FleetData)?;
 		tempfile.write_all(
 			format!(
-				"# This file contains fleet state and shouldn't be edited by hand\n\n{}\n\n# vim: ts=2 et nowrap\n",
-				data
+				"# This file contains fleet state and shouldn't be edited by hand\n\n{data}\n\n# vim: ts=2 et nowrap\n"
 			)
 			.as_bytes(),
 		)?;
modifiedcrates/fleet-base/src/opts.rsdiffbeforeafterboth
--- a/crates/fleet-base/src/opts.rs
+++ b/crates/fleet-base/src/opts.rs
@@ -7,7 +7,7 @@
 };
 
 use anyhow::{Context, Result, bail};
-use nix_eval::{NixSessionPool, Value, nix_go, util::assert_warn};
+use nix_eval::{FetchSettings, FlakeReference, FlakeSettings, Value, nix_go, util::assert_warn};
 use nom::{
 	Parser,
 	bytes::complete::take_while1,
@@ -210,30 +210,39 @@
 			std::fs::read_to_string(&fleet_data_path).context("reading fleet state (fleet.nix)")?;
 		let data: Mutex<FleetData> = nixlike::parse_str(&bytes)?;
 
-		let pool = NixSessionPool::new(
-			directory.as_os_str().to_owned(),
-			nix_args.clone(),
-			self.local_system.clone(),
-			self.fail_fast,
-		)
-		.await?;
-		let nix_session = pool.get().await?;
+		let mut fetch_settings = FetchSettings::new();
+		fetch_settings.set(c"warn-dirty", c"false");
+
+		// TODO: use correct directory, not cwd
+		let (mut flake, _) = FlakeReference::new(
+			directory
+				.to_str()
+				.ok_or_else(|| anyhow::anyhow!("fleet dir should have utf-8 path"))?,
+			&fetch_settings,
+		)?;
+		let flake = flake.lock(&fetch_settings)?;
+
+		let mut flake_settings = FlakeSettings::new()?;
+		let flake = flake.get_attrs(&mut flake_settings)?;
 
-		let builtins_field = Value::binding(nix_session.clone(), "builtins").await?;
+		let builtins_field = Value::eval("builtins")?;
 
-		let fleet_root = Value::binding(nix_session.clone(), "fleetConfigurations").await?;
-		let fleet_field = nix_go!(fleet_root.default({ data }));
+		let fleet_root = flake.get_field("fleetConfigurations")?;
+		let data_val = Value::serialized(&data)?;
+		let fleet_field = nix_go!(fleet_root.default(data_val));
 
 		let config_field = nix_go!(fleet_field.config);
 
 		if assert {
-			assert_warn("fleet config evaluation", &config_field).await?;
+			assert_warn("fleet config evaluation", &config_field)
+				.await
+				.context("failed to verify assertions")?;
 		}
 
 		let import = nix_go!(builtins_field.import);
 		let overlays = nix_go!(config_field.nixpkgs.overlays);
 		let nixpkgs = nix_go!(config_field.nixpkgs.buildUsing);
-		let nixpkgs_imported = nix_go!(nixpkgs | import);
+		let nixpkgs_imported = nix_go!(import(nixpkgs));
 
 		let default_pkgs = nix_go!(nixpkgs_imported(Obj {
 			overlays,
@@ -241,7 +250,6 @@
 		}));
 
 		Ok(Config(Arc::new(FleetConfigInternals {
-			nix_session,
 			directory,
 			data,
 			local_system: self.local_system.clone(),
modifiedcrates/nix-eval/Cargo.tomldiffbeforeafterboth
--- a/crates/nix-eval/Cargo.toml
+++ b/crates/nix-eval/Cargo.toml
@@ -16,12 +16,17 @@
 tokio-util.workspace = true
 tracing.workspace = true
 
+cxx = "1.0.168"
 futures = "0.3.31"
 itertools = "0.14.0"
 r2d2 = "0.8.10"
 regex = "1.11.1"
+test-log = { version = "0.2.18", features = ["trace"] }
 unindent = "0.2.4"
+tracing-indicatif = "0.3.13"
+ctor = "0.5.0"
 
-# [build-dependencies]
-# bindgen = "0.69.4"
-# pkg-config = "0.3.30"
+[build-dependencies]
+bindgen = "0.72.0"
+cxx-build = "1.0.168"
+pkg-config = "0.3.30"
modifiedcrates/nix-eval/build.rsdiffbeforeafterboth
--- a/crates/nix-eval/build.rs
+++ b/crates/nix-eval/build.rs
@@ -1,30 +1,101 @@
-// use bindgen::callbacks::ParseCallbacks;
-// use std::path::PathBuf;
-//
-// #[derive(Debug)]
-// struct StripPrefix;
-// impl ParseCallbacks for StripPrefix {
-//     fn item_name(&self, name: &str) -> Option<String> {
-//         name.strip_prefix("nix_").map(ToOwned::to_owned)
-//     }
-// }
+use bindgen::{
+	RustEdition,
+	callbacks::{ItemInfo, ParseCallbacks},
+};
+use std::path::PathBuf;
 
+#[derive(Debug)]
+struct StripPrefix;
+impl ParseCallbacks for StripPrefix {
+	fn item_name(&self, name: ItemInfo<'_>) -> Option<String> {
+		name.name.strip_prefix("nix_").map(ToOwned::to_owned)
+	}
+}
+
 fn main() {
-	//
-	// let mut libnix = bindgen::builder().header_contents("nix.h", "
-	// 	#define GC_THREADS
-	// 	#include <gc/gc.h>
-	// 	#include <nix_api_expr.h>
-	// 	#include <nix_api_store.h>
-	// 	#include <nix_api_util.h>
-	// 	#include <nix_api_value.h>
-	// ").parse_callbacks(Box::new(StripPrefix));
-	//
-	// for header in pkg_config::probe_library("nix-expr-c").expect("nix-expr-c").include_paths.into_iter().chain(pkg_config::probe_library("bdw-gc").expect("bdw-gc").include_paths.into_iter()) {
-	// 	libnix = libnix.clang_arg(format!("-I{}", header.to_str().expect("path is utf-8")));
-	// }
+	// Link nix C++ libraries for cxx
+	for lib in &[
+		"nix-util",
+		"nix-store",
+		"nix-expr",
+		"nix-flake",
+		"nix-fetchers",
+		"bdw-gc",
+	] {
+		if let Ok(library) = pkg_config::probe_library(lib) {
+			for lib_path in library.libs {
+				println!("cargo:rustc-link-lib={lib_path}");
+			}
+			for search_path in library.link_paths {
+				println!("cargo:rustc-link-search=native={}", search_path.display());
+			}
+		}
+	}
+
+	cxx_build::bridge("src/logging.rs")
+		.file("src/logging.cc")
+		.std("c++20")
+		.shared_flag(true)
+		.compile("nix-eval-logging");
+	cxx_build::bridge("src/lib.rs")
+		.file("src/lib.cc")
+		.std("c++20")
+		.shared_flag(true)
+		.compile("nix-eval");
+
+	println!("cargo:rerun-if-changed=src/lib.cc");
+	println!("cargo:rerun-if-changed=src/lib.hh");
+	println!("cargo:rerun-if-changed=src/logging.cc");
+	println!("cargo:rerun-if-changed=src/logging.hh");
+
 	//
-	// let mut out = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is set by cargo"));
-	// out.push("bindings.rs");
-	// libnix.generate().expect("generate bindings").write_to_file(out).expect("write bindings");
+	let mut libnix = bindgen::builder()
+		.rust_edition(RustEdition::Edition2024)
+		.header_contents(
+			"nix.h",
+			"
+				#define GC_THREADS
+				#include <gc/gc.h>
+				#include <nix_api_expr.h>
+				#include <nix_api_store.h>
+				#include <nix_api_flake.h>
+				#include <nix_api_fetchers.h>
+				#include <nix_api_util.h>
+				#include <nix_api_value.h>
+			",
+		)
+		.parse_callbacks(Box::new(StripPrefix));
+
+	for header in pkg_config::probe_library("nix-expr-c")
+		.expect("nix-expr-c")
+		.include_paths
+		.into_iter()
+		.chain(
+			pkg_config::probe_library("nix-flake-c")
+				.expect("nix-flake-c")
+				.include_paths
+				.into_iter(),
+		)
+		.chain(
+			pkg_config::probe_library("nix-fetchers-c")
+				.expect("nix-fetchers-c")
+				.include_paths
+				.into_iter(),
+		)
+		.chain(
+			pkg_config::probe_library("bdw-gc")
+				.expect("bdw-gc")
+				.include_paths
+				.into_iter(),
+		) {
+		libnix = libnix.clang_arg(format!("-I{}", header.to_str().expect("path is utf-8")));
+	}
+
+	let mut out = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is set by cargo"));
+	out.push("bindings.rs");
+	libnix
+		.generate()
+		.expect("generate bindings")
+		.write_to_file(out)
+		.expect("write bindings");
 }
addedcrates/nix-eval/src/lib.ccdiffbeforeafterboth
--- /dev/null
+++ b/crates/nix-eval/src/lib.cc
@@ -0,0 +1,17 @@
+#include "nix-eval/src/lib.rs"
+#include "lib.hh"
+#include <nix/fetchers/fetch-settings.hh>
+#include <nix/util/ref.hh>
+#include <nix_api_fetchers.h>
+
+struct nix_fetchers_settings {
+  nix::ref<nix::fetchers::Settings> settings;
+};
+
+extern "C" {
+void set_fetcher_setting(nix_fetchers_settings *settings_struct,
+                         const char *setting, const char *value) {
+  auto &settings_ref = settings_struct->settings;
+  bool result = settings_ref->set(setting, value);
+}
+}
addedcrates/nix-eval/src/lib.hhdiffbeforeafterboth

no changes

modifiedcrates/nix-eval/src/lib.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/lib.rs
+++ b/crates/nix-eval/src/lib.rs
@@ -3,120 +3,892 @@
 //!
 //! Current api is awful, little effort was put into this implementation.
 
-use std::{collections::HashMap, path::PathBuf, sync::Arc};
+use std::borrow::Cow;
+use std::cell::RefCell;
+use std::ffi::{CStr, CString, c_char, c_int, c_uint, c_void};
+use std::fmt;
+use std::ptr::null_mut;
+use std::sync::LazyLock;
+use std::{collections::HashMap, path::PathBuf};
 
-pub use pool::NixSessionPool;
-use pool::NixSessionPoolInner;
-use r2d2::PooledConnection;
-pub use session::{Error, Result};
-use tokio::sync::{mpsc, oneshot};
-use tracing::instrument;
-pub use value::{Index, Value};
+use anyhow::{Context, bail};
+use serde::Serialize;
+use serde::de::DeserializeOwned;
+
+pub use anyhow::Result;
+
+use self::logging::nix_logging_cxx;
+use self::nix_cxx::set_fetcher_setting;
+use self::nix_raw::{
+	alloc_value, c_context, c_context_create, err_code, err_info_msg, eval_state_build,
+	eval_state_builder_new, expr_eval_from_string, fetchers_settings, fetchers_settings_free,
+	fetchers_settings_new, flake_lock, flake_lock_flags, flake_lock_flags_free,
+	flake_lock_flags_new, flake_reference_parse_flags, flake_reference_parse_flags_free,
+	flake_reference_parse_flags_new, flake_reference_parse_flags_set_base_directory,
+	flake_settings, flake_settings_free, flake_settings_new, init_bool, init_int, init_string,
+	locked_flake_free, locked_flake_get_output_attrs, set_err_msg, setting_set, state_free,
+	value_decref, value_force, value_incref,
+};
 
-mod pool;
-mod session;
 mod value;
 // Contains macros helpers
+pub mod logging;
 #[doc(hidden)]
 pub mod macros;
 pub mod util;
-// #[allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
-// mod nix_raw {
-// 	include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
-// }
 
-// fn init() {
-// 	nix_raw::libutil_init();
-// }
+#[allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
+mod nix_raw {
+	include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
+}
+#[cxx::bridge]
+pub mod nix_cxx {
+	unsafe extern "C++" {
+		type nix_fetchers_settings;
+		include!("nix-eval/src/lib.hh");
+
+		unsafe fn set_fetcher_setting(
+			settings: *mut nix_fetchers_settings,
+			setting: *const c_char,
+			value: *const c_char,
+		);
+	}
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum NixType {
+	Thunk,
+	Int,
+	Float,
+	Bool,
+	String,
+	Path,
+	Null,
+	Attrs,
+	List,
+	Function,
+	External,
+}
+impl NixType {
+	fn from_int(c: c_uint) -> Self {
+		match c {
+			0 => Self::Thunk,
+			1 => Self::Int,
+			2 => Self::Float,
+			3 => Self::Bool,
+			4 => Self::String,
+			5 => Self::Path,
+			6 => Self::Null,
+			7 => Self::Attrs,
+			8 => Self::List,
+			9 => Self::Function,
+			10 => Self::External,
+			_ => unreachable!("unknown nix type: {c}"),
+		}
+	}
+}
+
+#[derive(Debug)]
+#[repr(i32)]
+enum NixErrorKind {
+	Unknown = 1,
+	Overflow = 2,
+	Key = 3,
+	Generic = 4,
+}
+impl NixErrorKind {
+	fn from_int(v: c_int) -> Option<Self> {
+		Some(match v {
+			0 => return None,
+			-1 => Self::Unknown,
+			-2 => Self::Overflow,
+			-3 => Self::Key,
+			-4 => Self::Generic,
+			_ => {
+				debug_assert!(false, "unexpected nix error kind: {v}");
+				Self::Unknown
+			}
+		})
+	}
+}
+
+pub fn gc_register_my_thread() {
+	assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 0);
+
+	let mut sb = nix_raw::GC_stack_base {
+		mem_base: null_mut(),
+	};
+	let r = unsafe { nix_raw::GC_get_stack_base(&mut sb) };
+	if r as u32 != nix_raw::GC_SUCCESS {
+		panic!("failed to get thread stack base");
+	}
+	unsafe { nix_raw::GC_register_my_thread(&sb) };
+}
+pub fn gc_unregister_my_thread() {
+	assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 1);
+
+	unsafe { nix_raw::GC_unregister_my_thread() };
+}
+
+struct ThreadRegisterGuard {}
+impl ThreadRegisterGuard {
+	fn new() -> Self {
+		gc_register_my_thread();
+		Self {}
+	}
+}
+impl Drop for ThreadRegisterGuard {
+	fn drop(&mut self) {
+		gc_unregister_my_thread();
+	}
+}
+
+struct NixContext(*mut c_context);
+impl NixContext {
+	fn set_err(&mut self, err: NixErrorKind, msg: &CStr) {
+		unsafe { set_err_msg(self.0, err as c_int, msg.as_ptr()) };
+	}
+	fn new() -> Self {
+		let ctx = unsafe { c_context_create() };
+		Self(ctx)
+	}
+	fn error_kind(&self) -> Option<NixErrorKind> {
+		let code = unsafe { err_code(self.0) };
+		NixErrorKind::from_int(code)
+	}
+	fn error<'t>(&self) -> Option<Cow<'t, str>> {
+		if let NixErrorKind::Generic = self.error_kind()? {
+			let mut err_out = String::new();
+			unsafe {
+				err_info_msg(
+					null_mut(),
+					self.0,
+					Some(copy_nix_str),
+					(&raw mut err_out).cast(),
+				)
+			};
+			return Some(Cow::Owned(err_out));
+		};
+
+		// TODO: Can throw error (resulting in panic) if unable to retrieve error. Should be able to resolve by passing context as a first argument,
+		// but it looks ugly
+		let str = unsafe { nix_raw::err_msg(null_mut(), self.0, null_mut()) };
+		Some(unsafe { CStr::from_ptr(str) }.to_string_lossy())
+
+		// TODO: There is also nix_err_info_msg, but I don't understand when it should be used
+		// Some(match self.error_kind()? {
+		// 	NixErrorKind::Generic => {
+		// 	}
+		// })
+	}
+	fn clean_err(&mut self) {
+		unsafe {
+			nix_raw::clear_err(self.0);
+		}
+	}
+
+	fn bail_if_error(&self) -> Result<()> {
+		if let Some(err) = self.error() {
+			bail!("{err}");
+		};
+		Ok(())
+	}
+
+	fn run_in_context<T>(&mut self, f: impl FnOnce(*mut c_context) -> T) -> Result<T> {
+		self.clean_err();
+		let o = f(self.0);
+		self.bail_if_error()?;
+		self.clean_err();
+		Ok(o)
+	}
+}
+impl Drop for NixContext {
+	fn drop(&mut self) {
+		unsafe {
+			nix_raw::c_context_free(self.0);
+		}
+	}
+}
+struct GlobalState {
+	store: Store,
+	state: EvalState,
+}
+impl GlobalState {
+	fn new() -> Result<Self> {
+		let mut ctx = NixContext::new();
+		let store = ctx
+			.run_in_context(|c| unsafe { nix_raw::store_open(c, c"daemon".as_ptr(), null_mut()) })
+			.map(Store)?;
+
+		let builder = ctx.run_in_context(|c| unsafe { eval_state_builder_new(c, store.0) })?;
+		ctx.run_in_context(|c| {
+			unsafe {
+				nix_raw::eval_state_builder_set_eval_setting(
+					c,
+					builder,
+					c"lazy-trees".as_ptr(),
+					c"true".as_ptr(),
+				)
+			}
+			// eval_s
+		})?;
+		let state = ctx
+			.run_in_context(|c| unsafe { eval_state_build(c, builder) })
+			.map(EvalState)?;
+
+		Ok(Self { store, state })
+	}
+}
+
+struct ThreadState {
+	ctx: NixContext,
+}
+impl ThreadState {
+	fn new() -> Result<Self> {
+		let ctx = NixContext::new();
+
+		Ok(Self { ctx })
+	}
+}
+
+static GLOBAL_STATE: LazyLock<GlobalState> =
+	LazyLock::new(|| GlobalState::new().expect("global state init shouldn't fail"));
+
+thread_local! {
+	static THREAD_STATE: RefCell<ThreadState> = RefCell::new(ThreadState::new().expect("thread state init shouldn't fail"));
+}
+fn with_default_context<T>(
+	f: impl FnOnce(*mut c_context, *mut nix_raw::EvalState) -> T,
+) -> Result<T> {
+	let global = &GLOBAL_STATE.state;
+	let (ctx, state) = THREAD_STATE.with_borrow_mut(|w| (w.ctx.0, global.0));
+	let mut ctx = NixContext(ctx);
+	let v = ctx.run_in_context(|c| f(c, state));
+	// It is reused for thread
+	std::mem::forget(ctx);
+	v
+}
+
+fn set_setting(s: &CStr, v: &CStr) -> Result<()> {
+	with_default_context(|c, _| unsafe { setting_set(c, s.as_ptr(), v.as_ptr()) }).map(|_| ())
+}
+
+pub struct FetchSettings(*mut fetchers_settings);
+impl FetchSettings {
+	pub fn new() -> Self {
+		Self::try_new().expect("allocation should not fail")
+	}
+	fn try_new() -> Result<Self> {
+		with_default_context(|c, _| unsafe { fetchers_settings_new(c) }).map(Self)
+	}
+	pub fn set(&mut self, setting: &CStr, value: &CStr) {
+		unsafe {
+			set_fetcher_setting(self.0.cast(), setting.as_ptr(), value.as_ptr());
+		};
+	}
+}
+unsafe impl Send for FetchSettings {}
+unsafe impl Sync for FetchSettings {}
+impl Drop for FetchSettings {
+	fn drop(&mut self) {
+		unsafe { fetchers_settings_free(self.0) };
+	}
+}
+pub struct FlakeSettings(*mut flake_settings);
+impl FlakeSettings {
+	pub fn new() -> Result<Self> {
+		with_default_context(|c, _| unsafe { flake_settings_new(c) }).map(Self)
+	}
+}
+unsafe impl Send for FlakeSettings {}
+unsafe impl Sync for FlakeSettings {}
+impl Drop for FlakeSettings {
+	fn drop(&mut self) {
+		unsafe {
+			flake_settings_free(self.0);
+		}
+	}
+}
+
+struct FlakeReferenceParseFlags(*mut flake_reference_parse_flags);
+impl FlakeReferenceParseFlags {
+	fn new(settings: &mut FlakeSettings) -> Result<Self> {
+		with_default_context(|c, _| unsafe { flake_reference_parse_flags_new(c, settings.0) })
+			.map(Self)
+	}
+	fn set_base_dir(&mut self, dir: &str) -> Result<()> {
+		with_default_context(|c, _| {
+			unsafe {
+				flake_reference_parse_flags_set_base_directory(
+					c,
+					self.0,
+					dir.as_ptr().cast(),
+					dir.len(),
+				)
+			};
+		})
+	}
+}
+impl Drop for FlakeReferenceParseFlags {
+	fn drop(&mut self) {
+		unsafe {
+			flake_reference_parse_flags_free(self.0);
+		}
+	}
+}
+struct FlakeLockFlags(*mut flake_lock_flags);
+impl FlakeLockFlags {
+	fn new(settings: &mut FlakeSettings) -> Result<Self> {
+		with_default_context(|c, _| unsafe { flake_lock_flags_new(c, settings.0) }).map(Self)
+	}
+}
+impl Drop for FlakeLockFlags {
+	fn drop(&mut self) {
+		unsafe {
+			flake_lock_flags_free(self.0);
+		}
+	}
+}
+
+unsafe extern "C" fn copy_nix_str(start: *const c_char, n: c_uint, user_data: *mut c_void) {
+	let s = unsafe { std::slice::from_raw_parts(start.cast::<u8>(), n as usize) };
+	let s = std::str::from_utf8(s).expect("c string has invalid utf-8");
+	unsafe { *user_data.cast::<String>() = s.to_owned() };
+}
+
+struct Store(*mut nix_raw::Store);
+unsafe impl Send for Store {}
+unsafe impl Sync for Store {}
+
+struct EvalState(*mut nix_raw::EvalState);
+impl EvalState {
+	// TODO: store ownership
+	fn new_raw(store: *mut nix_raw::Store) -> Result<Self> {
+		let builder =
+			with_default_context(|c, _| unsafe { nix_raw::eval_state_builder_new(c, store) })?;
+
+		with_default_context(|c, _| unsafe { eval_state_build(c, builder) }).map(Self)
+
+		// with_default_context(|c| state_create(c))
+	}
+}
+unsafe impl Send for EvalState {}
+unsafe impl Sync for EvalState {}
+impl Drop for EvalState {
+	fn drop(&mut self) {
+		unsafe {
+			state_free(self.0);
+		}
+	}
+}
+
+pub struct FlakeReference(*mut nix_raw::flake_reference);
+impl FlakeReference {
+	pub fn new(s: &str, fetch: &FetchSettings) -> Result<(Self, String)> {
+		let mut flake_settings = FlakeSettings::new()?;
+		let mut parse_flags = FlakeReferenceParseFlags::new(&mut flake_settings)?;
+
+		// parse_flags.set_base_dir("/home/lach/build/fleet")?;
+
+		let mut out = null_mut();
+		let mut fragment = String::new();
+		// let fetch_settings = fetcher_settings;
+		with_default_context(|c, _| unsafe {
+			nix_raw::flake_reference_and_fragment_from_string(
+				c,
+				fetch.0,
+				flake_settings.0,
+				parse_flags.0,
+				s.as_ptr().cast(),
+				s.len(),
+				&mut out,
+				Some(copy_nix_str),
+				(&raw mut fragment).cast(),
+			)
+		})?;
+		assert!(!out.is_null());
+
+		Ok((Self(out), fragment))
+	}
+	pub fn lock(&mut self, fetch: &FetchSettings) -> Result<LockedFlake> {
+		let mut settings = FlakeSettings::new()?;
+		let lock_flags = FlakeLockFlags::new(&mut settings)?;
+		with_default_context(|c, es| unsafe {
+			flake_lock(c, fetch.0, settings.0, es, lock_flags.0, self.0)
+		})
+		.map(LockedFlake)
+	}
+}
+unsafe impl Send for FlakeReference {}
+unsafe impl Sync for FlakeReference {}
+
+pub struct LockedFlake(*mut nix_raw::locked_flake);
+impl LockedFlake {
+	pub fn get_attrs(&self, settings: &mut FlakeSettings) -> Result<Value> {
+		with_default_context(|c, es| unsafe {
+			locked_flake_get_output_attrs(c, settings.0, es, self.0)
+		})
+		.map(Value)
+	}
+}
+unsafe impl Send for LockedFlake {}
+unsafe impl Sync for LockedFlake {}
+impl Drop for LockedFlake {
+	fn drop(&mut self) {
+		unsafe {
+			locked_flake_free(self.0);
+		};
+	}
+}
+
+type FieldName = [u8; 32];
+fn init_field_name(v: &str) -> FieldName {
+	let mut f = [0; 32];
+	assert!(v.len() < 32, "max field name is 31 char");
+	assert!(
+		v.bytes().all(|v| v != 0),
+		"nul bytes are unsupported in field name"
+	);
+	f[0..v.len()].copy_from_slice(v.as_bytes());
+	f
+}
+
+pub struct RealisedString(*mut nix_raw::realised_string);
+impl fmt::Debug for RealisedString {
+	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+		self.as_str().fmt(f)
+	}
+}
+
+impl RealisedString {
+	fn as_str(&self) -> &str {
+		let len = unsafe { nix_raw::realised_string_get_buffer_size(self.0) };
+		let data: *const u8 = unsafe { nix_raw::realised_string_get_buffer_start(self.0) }.cast();
+		let data = unsafe { std::slice::from_raw_parts(data, len) };
+		std::str::from_utf8(data).expect("non-utf8 strings not supported")
+	}
+	fn path_count(&self) -> usize {
+		unsafe { nix_raw::realised_string_get_store_path_count(self.0) }
+	}
+	fn path(&self, i: usize) -> String {
+		assert!(i < self.path_count());
+		let path = unsafe { nix_raw::realised_string_get_store_path(self.0, i) };
+		let mut err_out = String::new();
+		unsafe { nix_raw::store_path_name(path, Some(copy_nix_str), (&raw mut err_out).cast()) };
+		err_out
+	}
+}
+
+unsafe impl Send for RealisedString {}
+impl Drop for RealisedString {
+	fn drop(&mut self) {
+		with_default_context(|c, _| unsafe { nix_raw::realised_string_free(self.0) })
+			.expect("string free should not fail")
+	}
+}
 
-#[derive(Clone)]
-pub struct NixSession(pub(crate) Arc<tokio::sync::Mutex<PooledConnection<NixSessionPoolInner>>>);
+pub struct Value(*mut nix_raw::value);
 
-struct NixBuildTask(Value, oneshot::Sender<Result<HashMap<String, PathBuf>>>);
+unsafe impl Send for Value {}
+unsafe impl Sync for Value {}
 
-#[derive(Clone)]
-pub struct NixBuildBatch {
-	tx: mpsc::UnboundedSender<NixBuildTask>,
+pub trait AsFieldName {
+	fn as_field_name<T>(&self, v: impl FnOnce(FieldName) -> Result<T>) -> Result<T>;
+	fn to_field_name(&self) -> Result<String>;
+}
+impl AsFieldName for Value {
+	fn as_field_name<T>(&self, v: impl FnOnce(FieldName) -> Result<T>) -> Result<T> {
+		let f = self.to_string()?;
+		v(init_field_name(&f))
+	}
+	fn to_field_name(&self) -> Result<String> {
+		self.to_string()
+	}
+}
+impl<E> AsFieldName for E
+where
+	E: AsRef<str>,
+{
+	fn as_field_name<T>(&self, v: impl FnOnce(FieldName) -> Result<T>) -> Result<T> {
+		let f = self.as_ref();
+		v(init_field_name(f))
+	}
+	fn to_field_name(&self) -> Result<String> {
+		Ok(self.as_ref().to_owned())
+	}
 }
 
-#[instrument(skip(session, values))]
-async fn build_multiple(name: String, session: NixSession, values: Vec<Value>) -> Result<()> {
-	let system = session.0.lock().await.nix_system.clone();
-	let builtins = Value::binding(session, "builtins").await?;
-	let drv = nix_go!(builtins.derivation(Obj {
-		system,
-		name,
-		builder: "/bin/sh",
-		// we want nothing from this derivation, it is only used to perform multiple builds at once.
-		args: vec!["-c", "echo > $out"],
-		preferLocalBuild: true,
-		allowSubstitutes: false,
-		buildInputs: values,
-	}));
-	drv.build().await?;
-	Ok(())
+struct AttrsBuilder(*mut nix_raw::BindingsBuilder);
+impl AttrsBuilder {
+	fn new(capacity: usize) -> Self {
+		with_default_context(|c, es| unsafe { nix_raw::make_bindings_builder(c, es, capacity) })
+			.map(Self)
+			.expect("alloc should not fail")
+	}
+	fn insert(&mut self, k: &impl AsFieldName, v: Value) {
+		k.as_field_name(|name| {
+			with_default_context(|c, _| unsafe {
+				nix_raw::bindings_builder_insert(c, self.0, name.as_ptr().cast(), v.0)
+			})
+		})
+		.expect("builder insert shouldn't fail");
+	}
 }
+impl Drop for AttrsBuilder {
+	fn drop(&mut self) {
+		unsafe { nix_raw::bindings_builder_free(self.0) };
+	}
+}
+
+impl Value {
+	pub fn new_attrs(v: HashMap<&str, Value>) -> Result<Self> {
+		let out = Self::new_uninit()?;
+		let mut b = AttrsBuilder::new(v.len());
+		for (k, v) in v {
+			b.insert(&k, v);
+		}
+		with_default_context(|c, _| unsafe { nix_raw::make_attrs(c, out.0, b.0) })?;
+		Ok(out)
+	}
+	fn new_list<T: Into<Self>>(v: Vec<T>) -> Result<Self> {
+		todo!()
+	}
+	fn new_uninit() -> Result<Self> {
+		let out = with_default_context(|c, es| unsafe { alloc_value(c, es) })?;
+		Ok(Self(out))
+	}
+	fn new_str(v: &str) -> Result<Self> {
+		let s = CString::new(v).expect("string should not contain NULs");
+		let uninit = Self::new_uninit()?;
+		// String is copied, `s` is free to be dropped
+		with_default_context(|c, _| unsafe { init_string(c, uninit.0, s.as_ptr()) })?;
+		Ok(uninit)
+	}
+	fn new_int(i: i64) -> Result<Self> {
+		let uninit = Self::new_uninit()?;
+		with_default_context(|c, _| unsafe { init_int(c, uninit.0, i) })?;
+		Ok(uninit)
+	}
+	fn new_bool(v: bool) -> Result<Self> {
+		let uninit = Self::new_uninit()?;
+		with_default_context(|c, _| unsafe { init_bool(c, uninit.0, v) })?;
+		Ok(uninit)
+	}
+	fn force(&mut self, st: &mut EvalState) -> Result<()> {
+		with_default_context(|c, _| unsafe { value_force(c, st.0, self.0) })?;
+		Ok(())
+	}
+	pub fn type_of(&self) -> Result<NixType> {
+		let ty = with_default_context(|c, _| unsafe { nix_raw::get_type(c, self.0) })?;
+		Ok(NixType::from_int(ty))
+	}
+	pub fn to_string(&self) -> Result<String> {
+		Ok(self.to_realised_string()?.as_str().to_owned())
+	}
+	pub fn to_realised_string(&self) -> Result<RealisedString> {
+		with_default_context(|c, es| unsafe { nix_raw::string_realise(c, es, self.0, false) })
+			.map(RealisedString)
+
+		// let store_paths = unsafe { nix_raw::realised_string_get_store_path_count(str) };
+		// for i in 0..store_paths {
+		// 	let store_path = unsafe { nix_raw::realised_string_get_store_path(str, i) };
+		// 	nix_raw::store_path_name(store_path, callback, user_data);
+		// }
+		// dbg!(store_paths);
+		// todo!();
+	}
+
+	pub fn has_field(&self, field: &str) -> Result<bool> {
+		let f = init_field_name(field);
+		with_default_context(|c, es| unsafe {
+			nix_raw::has_attr_byname(c, self.0, es, f.as_ptr().cast())
+		})
+	}
+	// pub fn derivation_path(&self) {
+	// 	nix_raw::real
+	// }
+	pub fn list_fields(&self) -> Result<Vec<String>> {
+		if !matches!(self.type_of()?, NixType::Attrs) {
+			bail!("invalid type: expected attrs");
+		}
 
-impl NixBuildBatch {
-	fn new(name: String, session: NixSession) -> Self {
-		let (tx, mut rx) = mpsc::unbounded_channel::<NixBuildTask>();
+		let len = with_default_context(|c, _| unsafe { nix_raw::get_attrs_size(c, self.0) })?;
+		let mut out = Vec::with_capacity(len as usize);
 
-		tokio::task::spawn(async move {
-			let mut deps = vec![];
-			let mut build_data = vec![];
-			while let Some(task) = rx.recv().await {
-				build_data.push(task.0.clone());
-				deps.push(task);
+		for i in 0..len {
+			let name = with_default_context(|c, es| unsafe {
+				nix_raw::get_attr_name_byidx(c, self.0, es, i)
+			})?;
+			let c = unsafe { CStr::from_ptr(name) };
+			out.push(c.to_str().expect("nix field names are utf-8").to_owned());
+		}
+		Ok(out)
+	}
+	pub fn get_elem(&self, v: usize) -> Result<Self> {
+		if !matches!(self.type_of()?, NixType::List) {
+			bail!("invalid type: expected list");
+		}
+		let len =
+			with_default_context(|c, _| unsafe { nix_raw::get_list_size(c, self.0) })? as usize;
+		if v >= len {
+			bail!("oob list get: {v} >= {len}");
+		}
+
+		with_default_context(|c, es| unsafe { nix_raw::get_list_byidx(c, self.0, es, v as u32) })
+			.map(Self)
+	}
+	pub fn attrs_update(self, other: Value) -> Result<Self> {
+		let a_fields = self.list_fields()?;
+		let b_fields = other.list_fields()?;
+		match (a_fields.len(), b_fields.len()) {
+			(_, 0) => return Ok(self),
+			(0, _) => return Ok(other),
+			_ => {}
+		}
+		let mut out = HashMap::new();
+		for f in a_fields.iter() {
+			if b_fields.contains(f) {
+				break;
 			}
-			if deps.is_empty() {
-				return;
+			out.insert(f.as_str(), self.get_field(f)?);
+		}
+		if out.is_empty() {
+			// All fields from lhs are overriden by rhs
+			return Ok(other);
+		}
+		for f in b_fields.iter() {
+			out.insert(f.as_str(), other.get_field(f)?);
+		}
+		Self::new_attrs(out)
+	}
+	pub fn get_field(&self, name: impl AsFieldName) -> Result<Self> {
+		if !matches!(self.type_of()?, NixType::Attrs) {
+			bail!("invalid type: expected attrs");
+		}
+
+		name.as_field_name(|name| {
+			with_default_context(|c, es| unsafe {
+				nix_raw::get_attr_byname(c, self.0, es, name.as_ptr().cast())
+			})
+			.map(Self)
+		})
+		.with_context(|| format!("getting field {:?}", name.to_field_name()))
+	}
+	pub fn call(&self, v: Value) -> Result<Self> {
+		if !matches!(self.type_of()?, NixType::Function) {
+			// TODO: Functors
+			bail!("invalid type: expected function");
+		}
+
+		let out = Value::new_uninit()?;
+		with_default_context(|c, es| unsafe { nix_raw::value_call(c, es, self.0, v.0, out.0) })?;
+
+		Ok(out)
+	}
+	pub fn eval(v: &str) -> Result<Self> {
+		let s = CString::new(v).expect("expression shouldn't have internal NULs");
+		let out = Self::new_uninit()?;
+		with_default_context(|c, es| unsafe {
+			expr_eval_from_string(c, es, s.as_ptr(), c"/homeless-shelter".as_ptr(), out.0)
+		})?;
+		Ok(out)
+	}
+	pub async fn build(&self, output: &str) -> Result<PathBuf> {
+		if !self.is_derivation() {
+			bail!("expected derivation to build")
+		}
+		let output_name = self.get_field("outputName")?.to_string()?;
+		let v = if output_name != output {
+			let out = self.get_field(output)?;
+			if !out.is_derivation() {
+				bail!("unknown output: {output}");
 			}
-			match build_multiple(name, session, build_data).await {
-				Ok(_) => {
-					for NixBuildTask(v, o) in deps {
-						let _ = o.send(v.build().await);
-					}
-				}
-				Err(e) => {
-					for NixBuildTask(v, o) in deps {
-						let s = v.to_string_weak().await;
-						let s = match s {
-							Ok(s) => s,
-							Err(e) => {
-								let _ = o.send(Err(e));
-								continue;
-							}
-						};
-						if PathBuf::from(s).exists() {
-							let _ = o.send(v.build().await);
-						} else {
-							let _ = o.send(Err(e.clone()));
-						}
-					}
-				}
-			};
-		});
-		Self { tx }
+			out
+		} else {
+			self.clone()
+		};
+		// to_string here blocks until the path is built
+		let drv_path = tokio::task::spawn_blocking(move || v.get_field("outPath")?.to_string())
+			.await
+			.expect("should not fail")?;
+		Ok(PathBuf::from(drv_path))
 	}
-	pub async fn submit(self, task: Value) -> Result<HashMap<String, PathBuf>> {
-		let Self { tx: task_tx } = self;
-		let (tx, rx) = oneshot::channel();
-		let _ = task_tx.send(NixBuildTask(task, tx));
-		drop(task_tx);
-		rx.await.expect("shoudn't be cancelled here")
+	pub fn as_json<T: DeserializeOwned>(&self) -> Result<T> {
+		let to_json = Self::eval("builtins.toJSON")?;
+		let s = to_json.call(self.clone())?.to_string()?;
+		Ok(serde_json::from_str(&s)?)
+	}
+	pub fn serialized<T: Serialize>(v: &T) -> Result<Self> {
+		Self::eval(&nixlike::serialize(v)?)
+	}
+
+	// Convert to string/evaluate derivations/etc
+	fn to_string_weak(&self) -> Result<String> {
+		// TODO
+		self.to_string()
+	}
+
+	fn is_derivation(&self) -> bool {
+		if !matches!(self.type_of(), Ok(NixType::Attrs)) {
+			return false;
+		}
+		let Some(ty) = self.get_field("type").ok() else {
+			return false;
+		};
+		matches!(ty.to_string().as_deref(), Ok("derivation"))
 	}
 }
 
-impl NixSession {
-	fn ptr_eq(a: &Self, b: &Self) -> bool {
-		Arc::ptr_eq(&a.0, &b.0)
+impl From<String> for Value {
+	fn from(value: String) -> Self {
+		Value::new_str(&value).expect("todo: TryFrom")
 	}
+}
+impl From<bool> for Value {
+	fn from(value: bool) -> Self {
+		Value::new_bool(value).expect("todo: TryFrom")
+	}
+}
+impl From<&str> for Value {
+	fn from(value: &str) -> Self {
+		Value::new_str(&value).expect("todo: TryFrom")
+	}
+}
+impl<T> From<Vec<T>> for Value
+where
+	T: Into<Value>,
+{
+	fn from(value: Vec<T>) -> Self {
+		Value::new_list(value).expect("todo: TryFrom")
+	}
+}
 
-	pub fn new_build_batch(&self, name: String) -> NixBuildBatch {
-		NixBuildBatch::new(name, self.clone())
+impl Clone for Value {
+	fn clone(&self) -> Self {
+		with_default_context(|c, _| unsafe { value_incref(c, self.0) })
+			.expect("value incref should not fail");
+		Self(self.0)
 	}
 }
+impl Drop for Value {
+	fn drop(&mut self) {
+		with_default_context(|c, _| unsafe { value_decref(c, self.0) })
+			.expect("value drop should not fail");
+	}
+}
+
+pub fn init_libraries() {
+	unsafe { nix_raw::GC_allow_register_threads() };
 
-pub fn init_tokio() {
-	let _ = pool::TOKIO_RUNTIME.set(tokio::runtime::Handle::current());
+	let mut ctx = NixContext::new();
+	ctx.run_in_context(|c| unsafe { nix_raw::libutil_init(c) })
+		.expect("util init should not fail");
+	ctx.run_in_context(|c| unsafe { nix_raw::libstore_init(c) })
+		.expect("store init should not fail");
+	ctx.run_in_context(|c| unsafe { nix_raw::libexpr_init(c) })
+		.expect("expr init should not fail");
+
+	nix_logging_cxx::apply_tracing_logger();
 }
+
+#[test_log::test]
+fn test_native() -> Result<()> {
+	let mut fetch_settings = FetchSettings::new();
+	fetch_settings.set(c"warn-dirty", c"false");
+	//
+
+	let (mut r, _) = FlakeReference::new("/home/lach/build/fleet", &fetch_settings)?;
+	let locked = r.lock(&fetch_settings)?;
+	let attrs = locked.get_attrs(&mut FlakeSettings::new()?)?;
+
+	let builtins = Value::eval("builtins")?;
+	dbg!(builtins.type_of()?);
+
+	dbg!(attrs.type_of()?);
+	dbg!(attrs.list_fields()?);
+	dbg!(
+		attrs
+			.get_field("packages")?
+			.get_field("x86_64-linux")?
+			.get_field("fleet")?
+			.get_field("outPath")?
+			.to_string()
+	);
+
+	Ok(())
+}
+
+// struct NixBuildTask(Value, oneshot::Sender<Result<HashMap<String, PathBuf>>>);
+//
+// #[derive(Clone)]
+// pub struct NixBuildBatch {
+// 	tx: mpsc::UnboundedSender<NixBuildTask>,
+// }
+//
+// #[instrument(skip(values))]
+// async fn build_multiple(name: String, values: Vec<Value>) -> Result<()> {
+// 	let builtins = Value::eval("builtins")?;
+// 	let drv = nix_go!(builtins.derivation(Obj {
+// 		// FIXME: pass system from localSystem or fleet args
+// 		// system,
+// 		name,
+// 		builder: "/bin/sh",
+// 		// we want nothing from this derivation, it is only used to perform multiple builds at once.
+// 		args: vec!["-c", "echo > $out"],
+// 		preferLocalBuild: true,
+// 		allowSubstitutes: false,
+// 		buildInputs: values,
+// 	}));
+// 	drv.build()?;
+// 	Ok(())
+// }
+//
+// impl NixBuildBatch {
+// 	fn new(name: String) -> Self {
+// 		let (tx, mut rx) = mpsc::unbounded_channel::<NixBuildTask>();
+//
+// 		tokio::task::spawn(async move {
+// 			let mut deps = vec![];
+// 			let mut build_data = vec![];
+// 			while let Some(task) = rx.recv().await {
+// 				build_data.push(task.0.clone());
+// 				deps.push(task);
+// 			}
+// 			if deps.is_empty() {
+// 				return;
+// 			}
+// 			match build_multiple(name, build_data).await {
+// 				Ok(_) => {
+// 					for NixBuildTask(v, o) in deps {
+// 						let _ = o.send(v.build());
+// 					}
+// 				}
+// 				Err(e) => {
+// 					for NixBuildTask(v, o) in deps {
+// 						let s = v.to_string_weak();
+// 						let s = match s {
+// 							Ok(s) => s,
+// 							Err(e) => {
+// 								let _ = o.send(Err(e));
+// 								continue;
+// 							}
+// 						};
+// 						if PathBuf::from(s).exists() {
+// 							let _ = o.send(v.build());
+// 						} else {
+// 							let _ = o.send(Err(e.clone()));
+// 						}
+// 					}
+// 				}
+// 			};
+// 		});
+// 		Self { tx }
+// 	}
+// 	pub async fn submit(self, task: Value) -> Result<HashMap<String, PathBuf>> {
+// 		let Self { tx: task_tx } = self;
+// 		let (tx, rx) = oneshot::channel();
+// 		let _ = task_tx.send(NixBuildTask(task, tx));
+// 		drop(task_tx);
+// 		rx.await.expect("shoudn't be cancelled here")
+// 	}
+// }
addedcrates/nix-eval/src/logging.ccdiffbeforeafterboth
--- /dev/null
+++ b/crates/nix-eval/src/logging.cc
@@ -0,0 +1,75 @@
+#include "nix-eval/src/logging.rs"
+#include "logging.hh"
+#include <nix/util/logging.hh>
+
+using namespace nix;
+
+struct TracingLogger : Logger {
+  TracingLogger() {}
+
+  bool isVerbose() override { return true; }
+  // void addFields(nlohmann::json & json, const Fields & fields)
+  //    {
+  //        if (fields.empty())
+  //            return;
+  //        auto & arr = json["fields"] = nlohmann::json::array();
+  //        for (auto & f : fields)
+  //            if (f.type == Logger::Field::tInt)
+  //                arr.push_back(f.i);
+  //            else if (f.type == Logger::Field::tString)
+  //                arr.push_back(f.s);
+  //            else
+  //                unreachable();
+  //    }
+  void log(Verbosity lvl, std::string_view s) override {
+    rust::Str str(s.data(), s.size());
+    emit_log(lvl, str);
+  }
+  void logEI(const ErrorInfo &ei) override { emit_log(ei.level, ei.msg.str()); }
+
+  void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
+                     const std::string &s, const Fields &fields,
+                     ActivityId parent) override {
+    auto b = new_start_activity(act, lvl, type);
+    for (auto &f : fields) {
+      if (f.type == Logger::Field::tInt) {
+        b->add_int_field(f.i);
+      } else if (f.type == Logger::Field::tString) {
+        b->add_string_field(f.s);
+      } else {
+        unreachable();
+      }
+    }
+    b->emit(parent, s);
+  };
+
+  void stopActivity(ActivityId act) override { emit_stop(act); };
+
+  void result(ActivityId act, ResultType type, const Fields &fields) override {
+    auto b = new_start_activity(act, 0, type);
+    for (auto &f : fields) {
+      if (f.type == Logger::Field::tInt) {
+        b->add_int_field(f.i);
+      } else if (f.type == Logger::Field::tString) {
+        b->add_string_field(f.s);
+      } else {
+        unreachable();
+      }
+    }
+    b->emit_result(type);
+  };
+
+  void writeToStdout(std::string_view s) override {
+    printf("writeToStdout() called\n");
+  }
+  void warn(const std::string &msg) override { emit_warn(msg); }
+
+  virtual std::optional<char> ask(std::string_view s) {
+    printf("ask() called\n");
+    return {};
+  }
+};
+
+extern "C" {
+void apply_tracing_logger() { logger = std::make_unique<TracingLogger>(); }
+}
addedcrates/nix-eval/src/logging.hhdiffbeforeafterboth
--- /dev/null
+++ b/crates/nix-eval/src/logging.hh
@@ -0,0 +1,5 @@
+#pragma once
+
+extern "C" {
+void apply_tracing_logger();
+}
addedcrates/nix-eval/src/logging.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/nix-eval/src/logging.rs
@@ -0,0 +1,602 @@
+use std::collections::HashMap;
+use std::fmt::Arguments;
+use std::sync::{LazyLock, Mutex};
+
+use tracing::{
+	Level, Metadata, Span, debug, debug_span, error, error_span, event, info, info_span, trace,
+	trace_span, warn, warn_span,
+};
+use tracing_indicatif::span_ext::IndicatifSpanExt as _;
+
+#[derive(Debug)]
+enum ActivityType {
+	Unknown = 0,
+	CopyPath = 100,
+	FileTransfer = 101,
+	Realise = 102,
+	CopyPaths = 103,
+	Builds = 104,
+	Build = 105,
+	OptimiseStore = 106,
+	VerifyPaths = 107,
+	Substitute = 108,
+	QueryPathInfo = 109,
+	PostBuildHook = 110,
+	BuildWaiting = 111,
+	FetchTree = 112,
+}
+
+fn strip_prefix_suffix<'s, 'p>(a: &'s str, pref: &'p str, suff: &'p str) -> Option<&'s str> {
+	a.strip_prefix(pref)?.strip_suffix(suff)
+}
+
+fn parse_path(path: &str) -> &str {
+	let path = strip_prefix_suffix(path, "\x1b[35;1m", "\x1b[0m").unwrap_or(path);
+	path
+}
+
+fn parse_drv(drv: &str) -> &str {
+	let drv = parse_path(drv);
+	if let Some(pkg) = drv.strip_prefix("/nix/store/") {
+		let mut it = pkg.splitn(2, '-');
+		it.next();
+		if let Some(pkg) = it.next() {
+			return pkg;
+		}
+	}
+	drv
+}
+fn parse_host(host: &str) -> &str {
+	if host.is_empty() || host == "local" {
+		return "local";
+	}
+	// https/ssh is the default
+	host.strip_prefix("https://").unwrap_or(host)
+}
+
+impl ActivityType {
+	fn name(&self) -> &'static str {
+		match self {
+			ActivityType::Unknown => "nix",
+			ActivityType::CopyPath => "nix::copy-path",
+			ActivityType::FileTransfer => "nix::file-transfer",
+			ActivityType::Realise => "nix::realise",
+			ActivityType::CopyPaths => "nix::copy-paths",
+			ActivityType::Builds => "nix::builds",
+			ActivityType::Build => "nix::build",
+			ActivityType::OptimiseStore => "nix::optimise-store",
+			ActivityType::VerifyPaths => "nix::verify-paths",
+			ActivityType::Substitute => "nix::substitute",
+			ActivityType::QueryPathInfo => "nix::query-path-info",
+			ActivityType::PostBuildHook => "nix::post-build-hook",
+			ActivityType::BuildWaiting => "nix::build-waiting",
+			ActivityType::FetchTree => "nix::fetch-tree",
+		}
+	}
+	fn format(
+		&self,
+		values: &[FieldValue],
+		s: &str,
+		into: impl FnOnce(Arguments<'_>) -> Span,
+	) -> Span {
+		use FieldValue::*;
+		match (self, values) {
+			(ActivityType::QueryPathInfo, [Str(drv), Str(host)]) => {
+				let drv = parse_drv(drv);
+				let host = parse_host(host);
+				debug_span!(target: "nix::query-path-info", "querying", drv, host)
+			}
+			(ActivityType::Substitute, [Str(drv), Str(host)]) => {
+				let drv = parse_drv(drv);
+				let host = parse_host(host);
+				debug_span!(target: "nix::substitute", "substituting", drv, host)
+			}
+			(ActivityType::CopyPath, [Str(drv), Str(from), Str(to)]) => {
+				let drv = parse_drv(drv);
+				let from = parse_host(from);
+				let to = parse_host(to);
+				debug_span!(target: "nix::copy-path", "copying", drv, from, to)
+			}
+			(ActivityType::Build, [Str(drv), Str(host), Int(_), Int(_)]) => {
+				let drv = parse_drv(drv);
+				let host = parse_host(host);
+				info_span!(target: "nix::build", "building", drv, host)
+			}
+			(ActivityType::FileTransfer, [Str(file)]) => {
+				info_span!(target: "nix::file-transfer", "downloading", file)
+			}
+			(ActivityType::Realise, []) => {
+				debug_span!(target: "nix::realise", "realising")
+			}
+			(ActivityType::CopyPaths, []) => {
+				debug_span!(target: "nix::copy-paths", "copying paths")
+			}
+			(ActivityType::Unknown, [])
+				if s.starts_with("copying \"") && s.ends_with("\" to the store") =>
+			{
+				let tree = s
+					.trim_start_matches("copying \"")
+					.trim_end_matches("\" to the store");
+				debug_span!(target: "nix::trees", "copying", tree)
+			}
+			(ActivityType::Unknown, [])
+				if s.starts_with("copying '") && s.ends_with("' to the store") =>
+			{
+				let tree = s
+					.trim_start_matches("copying '")
+					.trim_end_matches("' to the store");
+				debug_span!(target: "nix::trees", "copying", tree)
+			}
+			(ActivityType::Unknown, []) if s.starts_with("hashing '") && s.ends_with("'") => {
+				let tree = s.trim_start_matches("hashing '").trim_end_matches("'");
+				debug_span!(target: "nix::trees", "hashing", tree)
+			}
+			(ActivityType::Unknown, []) if s.starts_with("connecting to '") && s.ends_with("'") => {
+				let host = s
+					.trim_start_matches("connecting to '")
+					.trim_end_matches("'");
+				debug_span!(target: "nix::remote", "connecting", host)
+			}
+			(ActivityType::Unknown, [])
+				if s.starts_with("copying outputs from '") && s.ends_with("'") =>
+			{
+				let host = s
+					.trim_start_matches("copying outputs from '")
+					.trim_end_matches("'");
+				debug_span!(target: "nix::remote", "copying outputs", host)
+			}
+			(ActivityType::Unknown, [])
+				if s.starts_with("copying dependencies to '") && s.ends_with("'") =>
+			{
+				let host = s
+					.trim_start_matches("copying dependencies to '")
+					.trim_end_matches("'");
+				debug_span!(target: "nix::remote", "copying dependencies", host)
+			}
+			(ActivityType::Unknown, [])
+				if s.starts_with("waiting for the upload lock to '") && s.ends_with("'") =>
+			{
+				let host = s
+					.trim_start_matches("waiting for the upload lock to '")
+					.trim_end_matches("'");
+				debug_span!(target: "nix::remote", "waiting for upload lock", host)
+			}
+			(ActivityType::BuildWaiting, [])
+				if s.starts_with("waiting for a machine to build '") && s.ends_with("'") =>
+			{
+				let drv = parse_drv(
+					s.trim_start_matches("waiting for a machine to build '")
+						.trim_end_matches("'"),
+				);
+				debug_span!(target: "nix::build-waiting", "waiting for available builder", drv)
+			}
+			(ActivityType::Unknown, []) if s == "querying info about missing paths" => {
+				debug_span!(target: "nix::remote", "querying")
+			}
+			_ => into(format_args!("{}({values:?})", self.name())),
+		}
+	}
+	fn from_int(v: u32) -> Self {
+		match v {
+			0 => Self::Unknown,
+			100 => Self::CopyPath,
+			101 => Self::FileTransfer,
+			102 => Self::Realise,
+			103 => Self::CopyPaths,
+			104 => Self::Builds,
+			105 => Self::Build,
+			106 => Self::OptimiseStore,
+			107 => Self::VerifyPaths,
+			108 => Self::Substitute,
+			109 => Self::QueryPathInfo,
+			110 => Self::PostBuildHook,
+			111 => Self::BuildWaiting,
+			112 => Self::FetchTree,
+			_ => {
+				warn!("unknown nix action: {v}");
+				Self::Unknown
+			}
+		}
+	}
+}
+
+#[derive(Debug)]
+enum ResultType {
+	FileLinked = 100,
+	BuildLogLine = 101,
+	UntrustedPath = 102,
+	CorruptedPath = 103,
+	SetPhase = 104,
+	Progress = 105,
+	SetExpected = 106,
+	PostBuildLogLine = 107,
+	FetchStatus = 108,
+
+	Unknown = 999,
+}
+impl ResultType {
+	fn from_int(v: u32) -> Self {
+		match v {
+			100 => Self::FileLinked,
+			101 => Self::BuildLogLine,
+			102 => Self::UntrustedPath,
+			103 => Self::CorruptedPath,
+			104 => Self::SetPhase,
+			105 => Self::Progress,
+			106 => Self::SetExpected,
+			107 => Self::PostBuildLogLine,
+			108 => Self::FetchStatus,
+
+			_ => {
+				warn!("unknown nix result: {v}");
+				Self::Unknown
+			}
+		}
+	}
+}
+#[derive(Clone, Copy)]
+enum Verbosity {
+	Error,
+	Warn,
+	Notice,
+	Info,
+	Talkative,
+	Chatty,
+	Debug,
+	Vomit,
+}
+impl Into<tracing::Level> for Verbosity {
+	fn into(self) -> tracing::Level {
+		match self {
+			Verbosity::Error => Level::ERROR,
+			Verbosity::Warn => Level::WARN,
+			Verbosity::Notice => Level::WARN,
+			Verbosity::Info => Level::INFO,
+			Verbosity::Talkative => Level::DEBUG,
+			Verbosity::Chatty => Level::DEBUG,
+			Verbosity::Debug => Level::DEBUG,
+			Verbosity::Vomit => Level::TRACE,
+		}
+	}
+}
+impl Verbosity {
+	fn from_int(u: u32) -> Self {
+		[
+			Self::Error,
+			Self::Warn,
+			Self::Notice,
+			Self::Info,
+			Self::Talkative,
+			Self::Chatty,
+			Self::Debug,
+			Self::Vomit,
+		]
+		.get(u as usize)
+		.cloned()
+		.unwrap_or_else(|| {
+			warn!("unknown log level: {u}");
+			Verbosity::Vomit
+		})
+	}
+}
+
+#[derive(Hash, PartialEq, Eq, Clone, Copy)]
+enum MetadataKind {
+	Span,
+	Event,
+}
+// impl MetadataKind {
+// 	fn kind(&self) -> Kind {
+// 		match self {
+// 			MetadataKind::Span => Kind::SPAN,
+// 			MetadataKind::Event => Kind::EVENT,
+// 		}
+// 	}
+// }
+
+#[derive(Hash, PartialEq, Eq)]
+struct ForeignMetadataInfo {
+	target: &'static str,
+	level: Level,
+	kind: MetadataKind,
+	name: &'static str,
+	module: Option<&'static str>,
+	file: Option<&'static str>,
+	line: Option<u32>,
+	names: &'static [&'static str],
+}
+
+struct FakeCallsite;
+impl tracing::callsite::Callsite for FakeCallsite {
+	fn set_interest(&self, interest: tracing::subscriber::Interest) {
+		unreachable!()
+	}
+
+	fn metadata(&self) -> &Metadata<'_> {
+		unreachable!()
+	}
+}
+const FAKE_CALLSITE: FakeCallsite = FakeCallsite;
+
+#[cfg(false)]
+#[derive(Default)]
+struct ForeignSpanData {
+	interned: HashSet<&'static str>,
+	metadatas: HashMap<ForeignMetadataInfo, &'static Metadata<'static>>,
+}
+#[cfg(false)]
+impl ForeignSpanData {
+	fn intern(&mut self, s: &str) -> &'static str {
+		if let Some(v) = self.interned.get(s) {
+			return *v;
+		}
+		let leaked: Box<str> = s.into();
+		let leaked = Box::leak(leaked);
+		self.interned.insert(leaked);
+		return leaked;
+	}
+	fn alloc_metadata<'t>(
+		&'t mut self,
+		target: &'static str,
+		level: Level,
+		kind: MetadataKind,
+		name: &'static str,
+		module: Option<&'static str>,
+		file: Option<&'static str>,
+		line: Option<u32>,
+		names: &'static [&'static str],
+	) -> &'static Metadata<'static> {
+		let info = ForeignMetadataInfo {
+			target,
+			level,
+			kind,
+			name,
+			module,
+			file,
+			line,
+			names,
+		};
+		if let Some(v) = self.metadatas.get(&info) {
+			return *v;
+		}
+		let fake = FakeCallsite;
+		let metadata = Box::leak::<'static>(Box::new(Metadata::new(
+			name,
+			target,
+			level,
+			file,
+			line,
+			module,
+			FieldSet::new(names, tracing::callsite::Identifier(&FAKE_CALLSITE)),
+			kind.kind(),
+		)));
+
+		let meta_raw = &raw const *metadata;
+		let fields_raw = &raw const *metadata.fields();
+
+		// SAFETY: FieldSet struct should be inside of metadata struct... Which we assume here, but do not test
+		// FIXME: Safety comment above might be invalidated at any time, this should actually be covered by unit test (or, better: runtime assertion... Somehow.)
+		let fields_offset = unsafe { fields_raw.cast::<u8>().offset_from(meta_raw.cast()) };
+		let field_set = unsafe {
+			((&raw mut *metadata).cast::<()>())
+				.byte_offset(fields_offset)
+				.cast::<FieldSet>()
+		};
+		// FIXME: metadata borrow here invalidates our &mut borrow of 'static Metadata, and 'static FieldSet so this construction should be replaced with raw pointers or idk.
+		// Something should be better done inside of tracing crate itself, someting like interior mutability.
+		let callsite = Box::leak(Box::new(tracing::callsite::DefaultCallsite::new(metadata)));
+		unsafe { *field_set = FieldSet::new(names, tracing::callsite::Identifier(callsite)) };
+
+		tracing::callsite::register(&*callsite);
+
+		self.metadatas.insert(info, metadata);
+		return metadata;
+	}
+}
+
+#[cfg(false)]
+static FOREIGN_SPAN_DATA: LazyLock<Mutex<ForeignSpanData>> =
+	LazyLock::new(|| Mutex::new(ForeignSpanData::default()));
+static NIX_SPAN_MAPPING: LazyLock<Mutex<HashMap<u64, Span>>> =
+	LazyLock::new(|| Mutex::new(HashMap::new()));
+
+#[derive(Debug)]
+enum FieldValue {
+	Int(i32),
+	Str(String),
+}
+
+struct StartActivityBuilder {
+	activity_id: u64,
+	verbosity: Verbosity,
+	typ: ActivityType,
+	fields: Vec<FieldValue>,
+}
+impl StartActivityBuilder {
+	fn add_int_field(&mut self, i: i32) {
+		self.fields.push(FieldValue::Int(i));
+	}
+	fn add_string_field(&mut self, v: &str) {
+		self.fields.push(FieldValue::Str(v.to_owned()));
+	}
+	fn emit(&mut self, parent: u64, s: &str) {
+		let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned");
+
+		let parent = mapping.get(&parent);
+
+		// let meta = spans.alloc_metadata(
+		// 	self.typ.name(),
+		// 	self.verbosity.into(),
+		// 	MetadataKind::Span,
+		// 	"nix activity start",
+		// 	None,
+		// 	None,
+		// 	None,
+		// 	self.typ.fields(),
+		// );
+		//
+		// let mut fields = meta.fields().iter();
+		// let span = if let Some(parent) = parent {
+		// 	let s = Span::new(
+		// 		meta,
+		// 		&match meta.fields().len() {
+		// 			1 => meta.fields().value_set(
+		// 				&<[_; 1]>::try_from([(
+		// 					&fields.next().expect("has field"),
+		// 					Some(&format_args!("Test") as &dyn tracing::Value),
+		// 				)])
+		// 				.expect("valid size"),
+		// 			),
+		// 			_ => unreachable!(),
+		// 		},
+		// 	);
+		// 	s.follows_from(parent);
+		// 	s
+		// } else {
+		// 	Span::new_root(
+		// 		meta,
+		// 		&match meta.fields().len() {
+		// 			1 => meta.fields().value_set(
+		// 				&<[_; 1]>::try_from([(
+		// 					&fields.next().expect("has field"),
+		// 					Some(&format_args!("Test") as &dyn tracing::Value),
+		// 				)])
+		// 				.expect("valid size"),
+		// 			),
+		// 			_ => unreachable!(),
+		// 		},
+		// 	)
+		// };
+		//
+		// let id = span.id().expect("id created");
+
+		let span = {
+			let _in_parent = parent.map(|p| p.enter());
+			let level: Level = self.verbosity.into();
+			if level == Level::ERROR {
+				self.typ
+					.format(&self.fields, s, |v| error_span!("action", v))
+			} else if level == Level::WARN {
+				self.typ
+					.format(&self.fields, s, |v| warn_span!("action", v))
+			} else if level == Level::INFO {
+				self.typ
+					.format(&self.fields, s, |v| info_span!("action", v))
+			} else if level == Level::DEBUG {
+				self.typ
+					.format(&self.fields, s, |v| debug_span!("action", v))
+			} else {
+				self.typ
+					.format(&self.fields, s, |v| trace_span!("action", v))
+			}
+		};
+		if !s.trim().is_empty() {
+			span.pb_set_message(s);
+			let _e = span.enter();
+			let level: Level = self.verbosity.into();
+			if level == Level::ERROR {
+				error!(target: "nix", "{}", s)
+			} else if level == Level::WARN {
+				warn!(target: "nix", "{}", s)
+			} else if level == Level::INFO {
+				info!(target: "nix", "{}", s)
+			} else if level == Level::DEBUG {
+				debug!(target: "nix", "{}", s)
+			} else {
+				trace!(target: "nix", "{}", s)
+			}
+		} else {
+			span.pb_start();
+		}
+		mapping.insert(self.activity_id, span);
+	}
+	fn emit_result(&mut self, ty: u32) {
+		let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned");
+
+		let Some(parent) = mapping.get(&self.activity_id) else {
+			panic!("unexpected result for dead parent");
+		};
+
+		let _in_parent = parent.enter();
+		let res = ResultType::from_int(ty);
+
+		use FieldValue::*;
+		match (&res, self.fields.as_slice()) {
+			// ResultType::FileLinked => todo!(),
+			(ResultType::BuildLogLine, [Str(s)]) => {
+				info!("{s:?}");
+			}
+			// ResultType::UntrustedPath => todo!(),
+			// ResultType::CorruptedPath => todo!(),
+			// ResultType::SetPhase => todo!(),
+			(ResultType::SetExpected, [Int(act_ty), Int(_expected)]) => {
+				let _act_ty = ActivityType::from_int(*act_ty as u32);
+			}
+			(ResultType::SetPhase, [Str(phase)]) => {
+				// parent.pb_set_message(phase);
+				debug!(target: "nix::phase", phase)
+			}
+			(ResultType::Progress, [Int(done), Int(expected), Int(_), Int(_)]) => {
+				parent.pb_set_length(*expected as u64);
+				parent.pb_set_position(*done as u64);
+			}
+			_ => warn!("unknown progress report: {:?}({:?})", &res, &self.fields),
+		}
+	}
+}
+fn new_start_activity(activity_id: u64, lvl: u32, typ: u32) -> Box<StartActivityBuilder> {
+	Box::new(StartActivityBuilder {
+		activity_id,
+		verbosity: Verbosity::from_int(lvl),
+		typ: ActivityType::from_int(typ),
+		fields: vec![],
+	})
+}
+
+fn emit_warn(v: &str) {
+	warn!(target: "nix::eval", "{v}")
+}
+fn emit_stop(v: u64) {
+	let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned");
+	mapping.remove(&v);
+}
+fn emit_log(lvl: u32, v: &str) {
+	let verbosity = Verbosity::from_int(lvl);
+	let level: Level = verbosity.into();
+	if level == Level::ERROR {
+		error!(target: "nix", "{v}")
+	} else if level == Level::WARN {
+		warn!(target: "nix", "{v}")
+	} else if level == Level::INFO {
+		info!(target: "nix", "{v}")
+	} else if level == Level::DEBUG {
+		debug!(target: "nix", "{v}")
+	} else {
+		trace!(target: "nix", "{v}")
+	}
+}
+
+// fn start_activity(act: u64, lvl: u32, act_ty: u32, s: &str, parent: u32) {
+// 	tracing::Span::new(meta, values)
+// }
+
+#[cxx::bridge]
+pub mod nix_logging_cxx {
+	extern "Rust" {
+		type StartActivityBuilder;
+		fn new_start_activity(activity_id: u64, lvl: u32, typ: u32) -> Box<StartActivityBuilder>;
+		fn add_int_field(&mut self, i: i32);
+		fn add_string_field(&mut self, v: &str);
+		fn emit(&mut self, parent: u64, s: &str);
+		fn emit_result(&mut self, ty: u32);
+
+		fn emit_warn(v: &str);
+		fn emit_stop(id: u64);
+		fn emit_log(lvl: u32, v: &str);
+	}
+	unsafe extern "C++" {
+		include!("nix-eval/src/logging.hh");
+
+		fn apply_tracing_logger();
+	}
+}
modifiedcrates/nix-eval/src/macros.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/macros.rs
+++ b/crates/nix-eval/src/macros.rs
@@ -1,171 +1,26 @@
-use serde::Serialize;
-
-use crate::{NixSession, Value};
-
-#[derive(Clone)]
-pub struct NixExprBuilder {
-	pub(crate) out: String,
-	used_fields: Vec<Value>,
-}
-pub trait AttrSetValue {
-	fn to_builder(self) -> NixExprBuilder;
-}
-trait Primitive {}
-
-macro_rules! impl_primitive {
-	($($t:ty),+) => {
-			$(
-				impl Primitive for $t {}
-			)+
-	};
-}
-impl_primitive!(String, bool, &'static str);
-
-impl<T> AttrSetValue for T
-where
-	// Limited by Primitive trait to avoid orphan rules violation with Vec<T: AttrSetValue>
-	T: Serialize + Primitive,
-{
-	fn to_builder(self) -> NixExprBuilder {
-		let serialized = nixlike::serialize(self).expect("invalid value for apply");
-		NixExprBuilder {
-			out: serialized.trim_end().to_owned(),
-			used_fields: Vec::new(),
-		}
-	}
-}
-impl AttrSetValue for Value {
-	fn to_builder(self) -> NixExprBuilder {
-		NixExprBuilder {
-			out: format!("sess_field_{}", self.session_field_id()),
-			used_fields: vec![self],
-		}
-	}
-}
-impl<T> AttrSetValue for Vec<T>
-where
-	T: AttrSetValue,
-{
-	fn to_builder(self) -> NixExprBuilder {
-		let mut builder = NixExprBuilder::list();
-		for v in self {
-			builder.list_value(NixExprBuilder::attrset_value(v));
-		}
-		builder.list_end();
-		builder
-	}
-}
-
-impl NixExprBuilder {
-	pub fn object() -> Self {
-		NixExprBuilder {
-			out: "{ ".to_owned(),
-			used_fields: Vec::new(),
-		}
-	}
-	pub fn list() -> Self {
-		NixExprBuilder {
-			out: "[".to_owned(),
-			used_fields: Vec::new(),
-		}
-	}
-	pub fn string(s: &str) -> Self {
-		NixExprBuilder {
-			out: nixlike::serialize(s)
-				.expect("no problems with serializing_string")
-				.trim_end()
-				.to_owned(),
-			used_fields: Vec::new(),
-		}
-	}
-	pub fn attrset_value(v: impl AttrSetValue) -> Self {
-		v.to_builder()
-	}
-	pub fn serialized(v: impl Serialize) -> Self {
-		let serialized = nixlike::serialize(v).expect("invalid value for apply");
-		Self {
-			out: serialized.trim_end().to_owned(),
-			used_fields: Vec::new(),
-		}
-	}
-	pub fn value(f: Value) -> Self {
-		Self {
-			out: format!("sess_field_{}", f.session_field_id()),
-			used_fields: vec![f],
-		}
-	}
-	pub fn end_obj(&mut self) {
-		self.out.push('}');
-	}
-	pub fn obj_key(&mut self, name: Self, value: Self) {
-		self.out.push_str(r#""${"#);
-		self.extend(name);
-		self.out.push_str(r#"}" = "#);
-		self.extend(value);
-		self.out.push_str("; ");
-	}
-	pub fn list_value(&mut self, value: Self) {
-		self.extend(value);
-		self.out.push(' ');
-	}
-	pub fn list_end(&mut self) {
-		self.out.push(']');
-	}
-
-	pub fn extend(&mut self, e: Self) {
-		self.out.push_str(&e.out);
-		self.used_fields.extend(e.used_fields);
-	}
-
-	#[allow(dead_code)]
-	pub fn session(&self) -> NixSession {
-		let mut session = None;
-		for ele in &self.used_fields {
-			if session.is_none() {
-				session = Some(ele.session());
-				continue;
-			}
-			let session = session.as_ref().expect("checked");
-			let ele_sess = ele.session();
-			assert!(
-				NixSession::ptr_eq(session, &ele_sess),
-				"can't mix fields from different session"
-			);
-		}
-		session.expect("expr without fields used")
-	}
-	#[allow(dead_code)]
-	pub fn index_attr(&mut self, s: &str) {
-		let escaped = nixlike::serialize(s).expect("string");
-		self.out.push('.');
-		self.out.push_str(escaped.trim_end());
-	}
-}
-
 #[macro_export]
 macro_rules! nix_expr_inner {
 	//(@munch_object FIXME: value should be arbitrary nix_expr_inner input... Time to write proc-macro?
 	(@obj($o:ident) $field:ident$(, $($tt:tt)*)?) => {{
-		$o.obj_key(
-			NixExprBuilder::string(stringify!($field)),
-			NixExprBuilder::attrset_value($field),
+		$o.insert(
+			stringify!($field),
+			$crate::Value::from($field),
 		);
 		$(nix_expr_inner!(@obj($o) $($tt)*);)?
 	}};
 	(@obj($o:ident) $field:ident: $v:expr$(, $($tt:tt)*)?) => {{
-		$o.obj_key(
-			NixExprBuilder::string(stringify!($field)),
-			NixExprBuilder::attrset_value($v),
+		$o.insert(
+			stringify!($field),
+			$crate::Value::from($v),
 		);
 		$(nix_expr_inner!(@obj($o) $($tt)*);)?
 	}};
 	(@obj($o:ident)) => {{}};
 	(Obj { $($tt:tt)* }) => {{
-		use $crate::{macros::NixExprBuilder, nix_expr_inner};
-		let mut out = NixExprBuilder::object();
+		use $crate::{nix_expr_inner};
+		let mut out = std::collections::hash_map::HashMap::new();
 		nix_expr_inner!(@obj(out) $($tt)*);
-		out.end_obj();
-		out
+		Value::new_attrs(out)?
 	}};
 	(@field($o:ident) . $var:ident $($tt:tt)*) => {{
 		$o.index_attr(stringify!($var));
@@ -185,10 +40,10 @@
 	};
 	(@field($o:ident)) => {};
 	($field:ident $($tt:tt)*) => {{
-		use $crate::{macros::NixExprBuilder, nix_expr_inner};
+		use $crate::{nix_expr_inner};
 		// might be used if indexed
 		#[allow(unused_mut)]
-		let mut out = NixExprBuilder::value($field.clone());
+		let mut out = $field.clone();
 		nix_expr_inner!(@field(out) $($tt)*);
 		out
 	}};
@@ -197,8 +52,7 @@
 		NixExprBuilder::string($v)
 	}};
 	({$v:expr}) => {{
-		use $crate::macros::NixExprBuilder;
-		NixExprBuilder::serialized(&$v)
+		$crate::Value::serialized(&$v)?
 	}}
 }
 #[macro_export]
@@ -212,40 +66,25 @@
 
 #[macro_export]
 macro_rules! nix_go {
-	(@o($o:ident) . $var:ident $($tt:tt)*) => {{
-		$o.push(Index::attr(stringify!($var)));
-		nix_go!(@o($o) $($tt)*);
-	}};
-	(@o($o:ident) [{ $v:expr }] $($tt:tt)*) => {{
-		$o.push(Index::attr(&$v));
-		nix_go!(@o($o) $($tt)*);
+	(@o($o:expr) . $var:ident $($tt:tt)*) => {{
+		nix_go!(@o($o.get_field(stringify!($var))?) $($tt)*)
 	}};
-	(@o($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{
-		$o.push(Index::Expr($crate::nix_expr_inner!($($var)+)));
-		nix_go!(@o($o) $($tt)*);
+	(@o($o:expr) [ $v:expr ] $($tt:tt)*) => {{
+		nix_go!(@o($o.get_field($v)?) $($tt)*)
 	}};
-	(@o($o:ident) ($($var:tt)*) $($tt:tt)*) => {
-		$o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));
-		nix_go!(@o($o) $($tt)*);
-	};
-	(@o($o:ident) | $($var:tt)*) => {
-		$o.push(Index::Pipe($crate::nix_expr_inner!($($var)+)));
-	};
-	(@o($o:ident) + $($var:tt)*) => {
-		$o.push(Index::Merge($crate::nix_expr_inner!($($var)+)));
+	(@o($o:expr) ($($var:tt)*) $($tt:tt)*) => {
+		nix_go!(@o($o.call($crate::nix_expr_inner!($($var)+))?) $($tt)*)
 	};
-	(@o($o:ident)) => {};
+	(@o($o:expr)) => {$o};
 	($field:ident $($tt:tt)+) => {{
-		use $crate::{nix_go, Index};
-		let field = $field.clone();
-		let mut out = vec![];
-		nix_go!(@o(out) $($tt)*);
-		field.select(out).await?
+		use $crate::nix_go;
+		let out = $field.clone();
+		nix_go!(@o(out) $($tt)*)
 	}}
 }
 #[macro_export]
 macro_rules! nix_go_json {
 	($($tt:tt)*) => {{
-		$crate::nix_go!($($tt)*).as_json().await?
+		$crate::nix_go!($($tt)*).as_json()?
 	}};
 }
deletedcrates/nix-eval/src/pool.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/pool.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-use std::{
-	ffi::OsString,
-	sync::{Arc, OnceLock},
-};
-
-use r2d2::Pool;
-
-use crate::{Error, NixSession, Result, session::NixSessionInner};
-
-pub struct NixSessionPool(Pool<NixSessionPoolInner>);
-impl NixSessionPool {
-	pub async fn new(
-		flake: OsString,
-		nix_args: Vec<OsString>,
-		nix_system: String,
-		fail_fast: bool,
-	) -> Result<Self> {
-		let inner = tokio::task::block_in_place(|| {
-			r2d2::Builder::<NixSessionPoolInner>::new()
-				.min_idle(Some(0))
-				.build(NixSessionPoolInner {
-					flake,
-					nix_args,
-					nix_system,
-					fail_fast,
-				})
-		})?;
-		Ok(Self(inner))
-	}
-	pub async fn get(&self) -> Result<NixSession> {
-		let v = tokio::task::block_in_place(|| self.0.get())?;
-		Ok(NixSession(Arc::new(tokio::sync::Mutex::new(v))))
-	}
-}
-
-pub(crate) struct NixSessionPoolInner {
-	flake: OsString,
-	nix_args: Vec<OsString>,
-	fail_fast: bool,
-	pub(crate) nix_system: String,
-}
-
-impl r2d2::ManageConnection for NixSessionPoolInner {
-	type Connection = NixSessionInner;
-	type Error = Error;
-	fn connect(&self) -> std::result::Result<Self::Connection, Self::Error> {
-		let _v = TOKIO_RUNTIME
-			.get()
-			.expect("missed tokio runtime init!")
-			.enter();
-		futures::executor::block_on(NixSessionInner::new(
-			self.flake.as_os_str(),
-			self.nix_args.iter().map(OsString::as_os_str),
-			self.nix_system.clone(),
-			self.fail_fast,
-		))
-	}
-
-	fn is_valid(&self, conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> {
-		let _v = TOKIO_RUNTIME
-			.get()
-			.expect("missed tokio runtime init!")
-			.enter();
-		let res = futures::executor::block_on(conn.execute_expression_number("2 + 2"))?;
-		if res != 4 {
-			// just in case, should fail much earlier
-			return Err(Error::SessionInit("misbehaving session"));
-		};
-		Ok(())
-	}
-
-	fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
-		false
-	}
-}
-pub static TOKIO_RUNTIME: OnceLock<tokio::runtime::Handle> = OnceLock::new();
deletedcrates/nix-eval/src/session.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/session.rs
+++ /dev/null
@@ -1,450 +0,0 @@
-use std::{ffi::OsStr, num::ParseIntError, process::Stdio, sync::Arc};
-
-use better_command::{ClonableHandler, Handler, NixHandler, NoopHandler};
-use futures::StreamExt;
-use itertools::Itertools as _;
-use serde::{Deserialize, de::DeserializeOwned};
-use thiserror::Error;
-use tokio::{
-	io::AsyncWriteExt,
-	process::{ChildStderr, ChildStdin, ChildStdout, Command},
-	select,
-	sync::{Mutex, mpsc, oneshot},
-};
-use tokio_util::codec::{FramedRead, LinesCodec};
-use tracing::{Level, debug, error, warn};
-
-#[derive(Error, Debug, Clone)]
-pub enum Error {
-	#[error("failed to create nix repl session: {0}")]
-	SessionInit(&'static str),
-	#[error("unexpected end of output, nix crashed?")]
-	MissingDelimiter,
-
-	#[error("expression did'nt produce any output")]
-	ExpectedOutput,
-	#[error("expression produced output, which is unexpected")]
-	UnexpectedOutput,
-
-	#[error("unexpected expression output type")]
-	InvalidType,
-
-	#[error("failed to build attr {attribute}:\n{error}")]
-	BuildFailed { attribute: String, error: String },
-
-	#[error("output: {0}")]
-	Json(Arc<serde_json::Error>),
-	// int outputs are too specific, and should not be used,
-	// thus error is ok to be not informative.
-	#[error("int output: {0}")]
-	Int(ParseIntError),
-	#[error("pool: {0}")]
-	Pool(Arc<r2d2::Error>),
-	#[error("io: {0}")]
-	Io(Arc<std::io::Error>),
-
-	// TODO: Should be done by wrapper/in different type.
-	#[error("at {0}: {1}")]
-	InContext(String, Box<Self>),
-
-	#[error("error: {0}")]
-	NixError(String),
-}
-impl From<r2d2::Error> for Error {
-	fn from(value: r2d2::Error) -> Self {
-		Self::Pool(Arc::new(value))
-	}
-}
-impl From<std::io::Error> for Error {
-	fn from(value: std::io::Error) -> Self {
-		Self::Io(Arc::new(value))
-	}
-}
-impl From<serde_json::Error> for Error {
-	fn from(value: serde_json::Error) -> Self {
-		Self::Json(Arc::new(value))
-	}
-}
-impl Error {
-	pub(crate) fn context(self, context: String) -> Self {
-		Self::InContext(context, Box::new(self))
-	}
-}
-pub type Result<T, E = Error> = std::result::Result<T, E>;
-
-enum OutputLine {
-	Out(String),
-	Err(String),
-}
-struct OutputHandler {
-	rx: mpsc::Receiver<OutputLine>,
-	_cancel_handle: oneshot::Receiver<()>,
-}
-impl OutputHandler {
-	fn new(out: ChildStdout, err: ChildStderr) -> Self {
-		let mut out = FramedRead::new(out, LinesCodec::new());
-		let mut err = FramedRead::new(err, LinesCodec::new());
-		let (tx, rx) = mpsc::channel(20);
-		let (mut cancelled, _cancel_handle) = oneshot::channel();
-		tokio::spawn(async move {
-			loop {
-				select! {
-					// We should receive errors earlier than synchronization
-					biased;
-					e = err.next() => {
-						let Some(Ok(e)) = e else {
-							if e.is_some() {
-								error!("bad repl stderr: {e:?}");
-							}
-							continue;
-						};
-						let _ = tx.send(OutputLine::Err(e)).await;
-					}
-					o = out.next() => {
-						let Some(Ok(o)) = o else {
-							if o.is_some() {
-								error!("bad repl stdout: {o:?}");
-							}
-							continue;
-						};
-						let _ = tx.send(OutputLine::Out(o)).await;
-					}
-					// Reader doesn't care about stdout, as this is cancelled.
-					// Error still might be useful, to process leftover span closures?
-					_ = cancelled.closed() => {
-						break;
-					}
-				}
-			}
-		});
-		Self { rx, _cancel_handle }
-	}
-	async fn next(&mut self) -> Option<OutputLine> {
-		self.rx.recv().await
-	}
-}
-
-#[must_use]
-struct ErrorCollector<'i, H> {
-	collected: Vec<String>,
-	inner: &'i mut H,
-}
-impl<'i, H> ErrorCollector<'i, H> {
-	fn new(inner: &'i mut H) -> Self {
-		Self {
-			collected: vec![],
-			inner,
-		}
-	}
-}
-impl<H> ErrorCollector<'_, H> {
-	fn handle_line_inner(&mut self, msg: &str) -> bool {
-		let Some(msg) = msg.strip_prefix("@nix ") else {
-			return false;
-		};
-		#[derive(Deserialize)]
-		struct ErrorAction {
-			action: String,
-			level: u32,
-			msg: String,
-		}
-		let Ok(act) = serde_json::from_str::<ErrorAction>(msg) else {
-			return false;
-		};
-		if act.action != "msg" || act.level != 0 {
-			return false;
-		}
-		self.collected.push(act.msg);
-		true
-	}
-	fn finish(self) -> Result<()> {
-		// fn dedent(s: String) -> String {
-		// 	s.split('\n').filter(|s| !s.trim().is_empty()).map(|v| v.)
-		// }
-		if !self.collected.is_empty() {
-			return Err(Error::NixError(
-				self.collected
-					.iter()
-					.map(|v| {
-						if let Some(f) = v.strip_prefix("\u{1b}[31;1merror:\u{1b}[0m ") {
-							let v = unindent::unindent(f.trim_start());
-							v.trim().to_owned()
-						} else {
-							v.to_owned()
-						}
-					})
-					.join("\n")
-					.to_string(),
-			));
-		}
-		Ok(())
-	}
-	fn flush(self) {
-		for line in self.collected {
-			warn!("{line}");
-		}
-	}
-}
-impl<H: Handler> Handler for ErrorCollector<'_, H> {
-	fn handle_line(&mut self, e: &str) {
-		if self.handle_line_inner(e) {
-			return;
-		}
-		self.inner.handle_line(e)
-	}
-}
-
-pub struct NixSessionInner {
-	full_delimiter: String,
-	nix_handler: ClonableHandler<NixHandler>,
-	out: OutputHandler,
-	stdin: ChildStdin,
-	string_wrapping: (String, String),
-	number_wrapping: (String, String),
-
-	executing_command: Arc<Mutex<()>>,
-
-	next_id: u32,
-	pub(crate) free_list: Vec<u32>,
-
-	pub nix_system: String,
-}
-
-/// Discover inter-message repl delimiter
-const REPL_DELIMITER: &str = "\"FLEET_MAGIC_REPL_DELIMITER\"";
-/// Discover formatting around strings
-const TRAIN_STRING: &str = "\"TRAIN_STRING\"";
-/// Discover formatting around numbers
-const TRAIN_NUMBER: &str = "13141516";
-// Other types of formatting are not discovered, because they are not used, JSON serialization is used instead
-// Techically, number training is also not required, because numbers can be converted to string too...
-// Eh, I'll remove it later.
-
-impl NixSessionInner {
-	pub(crate) async fn new(
-		flake: &OsStr,
-		extra_args: impl IntoIterator<Item = &OsStr>,
-		nix_system: String,
-		fail_fast: bool,
-	) -> Result<Self> {
-		let mut cmd = Command::new("nix");
-		cmd.arg("repl")
-			.args(["--option", "pure-eval", "true"])
-			.arg(flake)
-			.arg("--log-format")
-			.arg("internal-json");
-		if !fail_fast {
-			cmd.arg("--keep-going");
-		}
-		for arg in extra_args {
-			cmd.arg(arg);
-		}
-		cmd.stdin(Stdio::piped());
-		cmd.stdout(Stdio::piped());
-		cmd.stderr(Stdio::piped());
-		let cmd = cmd.spawn()?;
-		let stdout = cmd.stdout.unwrap();
-		let stderr = cmd.stderr.unwrap();
-		let mut out = OutputHandler::new(stdout, stderr);
-		let mut stdin = cmd.stdin.unwrap();
-		// Standard repl hello doesn't work with internal-json logger
-		stdin.write_all(REPL_DELIMITER.as_bytes()).await?;
-		stdin.write_all(b"\n").await?;
-		stdin.flush().await?;
-		let nix_handler = NixHandler::default();
-		let mut full_delimiter = None;
-		let mut errors = vec![];
-		while let Some(line) = out.next().await {
-			let line = match line {
-				OutputLine::Out(o) => o,
-				OutputLine::Err(_e) => {
-					// Handle startup errors, but skip repl hello?
-					errors.push(_e);
-					continue;
-				}
-			};
-			if line.contains(REPL_DELIMITER) {
-				debug!("discovered repl delimiter with added colors: {line}");
-				full_delimiter = Some(line.to_owned());
-				break;
-			}
-		}
-		let Some(full_delimiter) = full_delimiter else {
-			for e in errors {
-				error!("{e}");
-			}
-			return Err(Error::SessionInit("failed to discover delimiter"));
-		};
-		let mut res = Self {
-			full_delimiter,
-			nix_handler: ClonableHandler::new(nix_handler),
-			out,
-			stdin,
-			string_wrapping: Default::default(),
-			number_wrapping: Default::default(),
-
-			executing_command: Arc::new(Mutex::new(())),
-
-			next_id: 0,
-			free_list: vec![],
-
-			nix_system,
-		};
-		res.train().await?;
-		Ok(res)
-	}
-	async fn train(&mut self) -> Result<()> {
-		{
-			let full_string = self
-				.execute_expression_raw(TRAIN_STRING, &mut NoopHandler)
-				.await?;
-			let string_offset = full_string.find(TRAIN_STRING).expect("contained");
-			let string_prefix = &full_string[..string_offset];
-			let string_suffix = &full_string[string_offset + TRAIN_STRING.len()..];
-			self.string_wrapping = (string_prefix.to_owned(), string_suffix.to_owned());
-		}
-		{
-			let full_number = self
-				.execute_expression_raw(TRAIN_NUMBER, &mut NoopHandler)
-				.await?;
-			let number_offset = full_number.find(TRAIN_NUMBER).expect("contained");
-			let number_prefix = &full_number[..number_offset];
-			let number_suffix = &full_number[number_offset + TRAIN_NUMBER.len()..];
-			self.number_wrapping = (number_prefix.to_owned(), number_suffix.to_owned());
-		}
-		Ok(())
-	}
-	async fn send_command(&mut self, cmd: impl AsRef<[u8]>) -> Result<()> {
-		if tracing::enabled!(Level::DEBUG) && cmd.as_ref() != REPL_DELIMITER.as_bytes() {
-			let cmd_str = String::from_utf8_lossy(cmd.as_ref());
-			tracing::debug!("{cmd_str}");
-		};
-		self.stdin.write_all(cmd.as_ref()).await?;
-		self.stdin.write_all(b"\n").await?;
-		Ok(())
-	}
-	async fn read_until_delimiter(&mut self, err_handler: &mut dyn Handler) -> Result<String> {
-		let mut out = String::new();
-		while let Some(line) = self.out.next().await {
-			let line = match line {
-				OutputLine::Out(out) => out,
-				OutputLine::Err(err) => {
-					err_handler.handle_line(&err);
-					continue;
-				}
-			};
-			if line == self.full_delimiter {
-				return Ok(out);
-			}
-			if !out.is_empty() {
-				out.push('\n');
-			}
-			out.push_str(&line);
-		}
-		Err(Error::MissingDelimiter)
-	}
-	pub(crate) async fn execute_expression_number(
-		&mut self,
-		expr: impl AsRef<[u8]>,
-	) -> Result<u64> {
-		let num = self.number_wrapping.clone();
-		let n = self.execute_expression_wrapping(expr, &num).await?;
-		n.parse::<u64>().map_err(Error::Int)
-	}
-	async fn execute_expression_string(&mut self, expr: impl AsRef<[u8]>) -> Result<String> {
-		// builtins.toJSON escapes some thing in incorrect way, e.g escaped "$" in "\${" is being outputed as "\$",
-		// while this escape should be removed as it is intended for nix itself, not for json output.
-		//
-		// This regex only allows \$ in the beginning of the string, it is easier to implement correctly.
-		// TODO: Add peg parser for nix-produced JSON?..
-		let regex = regex::Regex::new(r#"(?<prefix>[: {,\[]\\")\\\$"#).expect("fixup json");
-
-		let num = self.string_wrapping.clone();
-		let n = self.execute_expression_wrapping(expr, &num).await?;
-		let n = regex.replace_all(&n, "$prefix$$");
-		let str: String = serde_json::from_str(&n)?;
-		Ok(str)
-	}
-	pub(crate) async fn execute_expression_to_json<V: DeserializeOwned>(
-		&mut self,
-		expr: impl AsRef<[u8]>,
-	) -> Result<V> {
-		let mut fexpr = b"builtins.toJSON (".to_vec();
-		fexpr.extend_from_slice(expr.as_ref());
-		fexpr.push(b')');
-
-		Ok(serde_json::from_str(
-			&self.execute_expression_string(fexpr).await?,
-		)?)
-	}
-	async fn execute_expression_wrapping(
-		&mut self,
-		expr: impl AsRef<[u8]>,
-		wrapping: &(String, String),
-	) -> Result<String> {
-		let mut nix_handler = self.nix_handler.clone();
-		let mut collected = ErrorCollector::new(&mut nix_handler);
-		let res = self.execute_expression_raw(expr, &mut collected).await?;
-		if res.is_empty() {
-			collected.finish()?;
-			return Err(Error::ExpectedOutput);
-		} else {
-			collected.flush()
-		};
-		let Some(res) = res.strip_prefix(&wrapping.0) else {
-			return Err(Error::InvalidType);
-		};
-		let Some(res) = res.strip_suffix(&wrapping.1) else {
-			return Err(Error::InvalidType);
-		};
-		Ok(res.to_owned())
-	}
-	async fn execute_expression_empty(&mut self, expr: impl AsRef<[u8]>) -> Result<()> {
-		let mut nix_handler = self.nix_handler.clone();
-		let mut collected = ErrorCollector::new(&mut nix_handler);
-		let v = self.execute_expression_raw(expr, &mut collected).await?;
-		collected.finish()?;
-		if !v.is_empty() {
-			return Err(Error::UnexpectedOutput);
-		}
-		Ok(())
-	}
-	pub(crate) async fn execute_expression_raw(
-		&mut self,
-		expr: impl AsRef<[u8]>,
-		err_handler: &mut dyn Handler,
-	) -> Result<String> {
-		// Prevent two commands from being executed in parallel, messing with each other.
-		let _lock = self.executing_command.clone();
-		let _guard = _lock.lock().await;
-
-		self.send_command(expr).await?;
-		// It will be echoed
-		self.send_command(REPL_DELIMITER).await?;
-		self.read_until_delimiter(err_handler).await
-	}
-	pub(crate) async fn execute_assign(&mut self, expr: impl AsRef<str>) -> Result<u32> {
-		let id = self.allocate_id();
-		self.execute_expression_empty(format!("sess_field_{id} = {}", expr.as_ref()))
-			.await?;
-		Ok(id)
-	}
-
-	/// Id should be immediately used
-	fn allocate_id(&mut self) -> u32 {
-		if let Some(free) = self.free_list.pop() {
-			free
-		} else {
-			let v = self.next_id;
-			self.next_id += 1;
-			v
-		}
-	}
-	// Nix has no way to deallocate variable, yet GC will correct everything not reachable.
-	// async fn free_id(&mut self, id: u32) -> Result<()> {
-	// 	self.execute_expression_empty(format!("sess_field_{id} = null"))
-	// 		.await?;
-	// 	self.free_list.push(id);
-	// 	Ok(())
-	// }
-}
modifiedcrates/nix-eval/src/value.rsdiffbeforeafterboth
--- a/crates/nix-eval/src/value.rs
+++ b/crates/nix-eval/src/value.rs
@@ -3,302 +3,4 @@
 use better_command::NixHandler;
 use serde::{Serialize, de::DeserializeOwned};
 
-use crate::{Error, NixBuildBatch, NixSession, Result, macros::NixExprBuilder, nix_go};
-
-#[derive(Clone)]
-pub enum Index {
-	Var(String),
-	String(String),
-	#[allow(dead_code)]
-	Apply(String),
-	#[allow(dead_code)]
-	Expr(NixExprBuilder),
-	ExprApply(NixExprBuilder),
-	Pipe(NixExprBuilder),
-	Merge(NixExprBuilder),
-}
-impl Index {
-	pub fn var(v: impl AsRef<str>) -> Self {
-		let v = v.as_ref();
-		assert!(
-			!(v.contains('.') | v.contains(' ')),
-			"bad variable name: {v}"
-		);
-		Self::Var(v.to_owned())
-	}
-	pub fn attr(v: impl AsRef<str>) -> Self {
-		Self::String(v.as_ref().to_owned())
-	}
-	#[allow(dead_code)]
-	pub fn apply(v: impl Serialize) -> Self {
-		let serialized = nixlike::serialize(v).expect("invalid value for apply");
-		Self::Apply(serialized.trim_end().to_owned())
-	}
-}
-impl fmt::Display for Index {
-	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-		match self {
-			Index::Var(v) => {
-				write!(f, "{v}")
-			}
-			Index::String(k) => {
-				let v = nixlike::format_identifier(k.as_str());
-				write!(f, ".{v}")
-			}
-			Index::Apply(_) => {
-				write!(f, "<apply>(...)")
-			}
-			Index::Expr(e) => {
-				write!(f, "[{}]", e.out)
-			}
-			Index::ExprApply(_) => {
-				write!(f, "<apply>(...)")
-			}
-			Index::Pipe(e) => {
-				write!(f, "<map>({})", e.out)
-			}
-			Index::Merge(e) => {
-				write!(f, "//({})", e.out)
-			}
-		}
-	}
-}
-impl fmt::Debug for Index {
-	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-		write!(f, "{self}")
-	}
-}
-struct PathDisplay<'i>(&'i [Index]);
-impl fmt::Display for PathDisplay<'_> {
-	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-		if !matches!(self.0.first(), Some(Index::Var(_))) {
-			write!(f, "<unknown>")?;
-		}
-		for i in self.0 {
-			write!(f, "{i}")?;
-		}
-		Ok(())
-	}
-}
-struct ValueInner {
-	full_path: Vec<Index>,
-	session: NixSession,
-	value: u32,
-}
-#[derive(Clone)]
-pub struct Value(Arc<ValueInner>);
-impl Value {
-	async fn new(session: NixSession, query: &str) -> Result<Self> {
-		let vid = session.0.lock().await.execute_assign(query).await?;
-		Ok(Self(Arc::new(ValueInner {
-			full_path: vec![],
-			session,
-			value: vid,
-		})))
-	}
-	/// Get a top-level binding.
-	///
-	/// In flake repl session, every output is exposed as top-level binding.
-	pub async fn binding(session: NixSession, query: &str) -> Result<Self> {
-		// TODO: Verify that query is a valid variable name
-		let vid = session.0.lock().await.execute_assign(query).await?;
-		Ok(Self(Arc::new(ValueInner {
-			full_path: vec![Index::Var(query.to_owned())],
-			session,
-			value: vid,
-		})))
-	}
-	pub async fn select(&self, name: impl IntoIterator<Item = Index>) -> Result<Self> {
-		let mut used_fields = Vec::new();
-		let name = name.into_iter();
-
-		let mut full_path = self.0.full_path.clone();
-		let mut query = self.sess_field_name();
-		for v in name {
-			full_path.push(v.clone());
-			match v {
-				Index::Var(_) => panic!("var item may only be first"),
-				Index::String(s) => {
-					let escaped =
-						nixlike::serialize(s).expect("strings are always serialized successfully");
-					query.push('.');
-					query.push_str(escaped.trim());
-				}
-				Index::Apply(a) => {
-					// In cases like `a {}.b` first `{}.b` will be evaluated, so `a {}` should be encased in `()`
-					query = format!("({query} {a})");
-				}
-				Index::Expr(e) => {
-					let index = Value::new(self.0.session.clone(), &e.out).await?;
-					used_fields.push(index.clone());
-					query.push('.');
-					let index = format!("${{sess_field_{}}}", index.0.value);
-					query.push_str(&index);
-				}
-				Index::ExprApply(e) => {
-					let index = Value::new(self.0.session.clone(), &e.out).await?;
-					used_fields.push(index.clone());
-					query.push(' ');
-					let index = format!("sess_field_{}", index.0.value);
-					query.push_str(&index);
-					query = format!("({query})");
-				}
-				Index::Pipe(v) => {
-					let index = Value::new(self.0.session.clone(), &v.out).await?;
-					used_fields.push(index.clone());
-					let index = format!("sess_field_{}", index.0.value);
-					query = format!("({index} {query})");
-				}
-				Index::Merge(v) => {
-					let index = Value::new(self.0.session.clone(), &v.out).await?;
-					used_fields.push(index.clone());
-					let index = format!("sess_field_{}", index.0.value);
-					query = format!("({query} // {index})");
-				}
-			}
-		}
-
-		let vid = self
-			.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_assign(&query)
-			.await
-			.map_err(|e| e.context(self.attribute()))?;
-		Ok(Self(Arc::new(ValueInner {
-			full_path,
-			session: self.0.session.clone(),
-			value: vid,
-		})))
-	}
-	pub async fn as_json<V: DeserializeOwned>(&self) -> Result<V> {
-		let query = self.sess_field_name();
-		self.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_to_json(&query)
-			.await
-			.map_err(|e| e.context(self.attribute()))
-	}
-	#[allow(dead_code)]
-	pub async fn has_field(&self, name: &str) -> Result<bool> {
-		let key = nixlike::escape_string(name);
-		let query = format!("{} ? {key}", self.sess_field_name());
-		self.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_to_json(&query)
-			.await
-			.map_err(|e| e.context(self.attribute()))
-	}
-	pub async fn list_fields(&self) -> Result<Vec<String>> {
-		let query = format!("builtins.attrNames {}", self.sess_field_name());
-		self.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_to_json(&query)
-			.await
-			.map_err(|e| e.context(self.attribute()))
-	}
-	pub async fn type_of(&self) -> Result<String> {
-		let query = format!("builtins.typeOf {}", self.sess_field_name());
-		self.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_to_json(&query)
-			.await
-			.map_err(|e| e.context(self.attribute()))
-	}
-	#[allow(dead_code)]
-	pub async fn import(&self) -> Result<Self> {
-		let import = Self::new(self.0.session.clone(), "import").await?;
-		Ok(nix_go!(self | import))
-	}
-	fn sess_field_name(&self) -> String {
-		format!("sess_field_{}", self.0.value)
-	}
-	pub async fn build_maybe_batch(
-		&self,
-		batch: Option<NixBuildBatch>,
-	) -> Result<HashMap<String, PathBuf>> {
-		if let Some(batch) = batch {
-			batch.submit(self.clone()).await
-		} else {
-			self.build().await
-		}
-	}
-	pub async fn build(&self) -> Result<HashMap<String, PathBuf>> {
-		let query = format!(":b {}", self.sess_field_name());
-		let vid = self
-			.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_raw(&query, &mut NixHandler::default())
-			.await?;
-		if vid.is_empty() {
-			return Err(Error::BuildFailed {
-				attribute: self.attribute(),
-				error: "build produced no output".to_owned(),
-			});
-		}
-		let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n")
-		else {
-			return Err(Error::BuildFailed {
-				attribute: self.attribute(),
-				error: format!("failed to parse output: {vid}"),
-			});
-		};
-		let outputs = vid
-			.split('\n')
-			.filter(|v| !v.is_empty())
-			.map(|v| v.split_once(" -> ").expect("unexpected build output"))
-			.map(|(a, b)| (a.trim_start().to_owned(), PathBuf::from(b)))
-			.collect();
-		Ok(outputs)
-	}
-	/// Weakly convert string-like types (derivation/path/string) to string
-	pub async fn to_string_weak(&self) -> Result<String> {
-		let query = format!("\"${{{}}}\"", self.sess_field_name());
-		let vid: String = self
-			.0
-			.session
-			.0
-			.lock()
-			.await
-			.execute_expression_to_json(&query)
-			.await?;
-		Ok(vid)
-	}
-
-	fn attribute(&self) -> String {
-		PathDisplay(&self.0.full_path).to_string()
-	}
-
-	pub(crate) fn session(&self) -> NixSession {
-		self.0.session.clone()
-	}
-
-	pub(crate) fn session_field_id(&self) -> u32 {
-		self.0.value
-	}
-}
-impl Drop for ValueInner {
-	fn drop(&mut self) {
-		if let Ok(mut lock) = self.session.0.try_lock() {
-			lock.free_list.push(self.value)
-		}
-		// Leaked
-	}
-}
+use crate::{Result, Value, nix_go};
modifiedcrates/nixlike/Cargo.tomldiffbeforeafterboth
--- a/crates/nixlike/Cargo.toml
+++ b/crates/nixlike/Cargo.toml
@@ -10,7 +10,7 @@
 alejandra = { git = "https://github.com/kamadorueda/alejandra" }
 linked-hash-map = "0.5.6"
 peg = "0.8.5"
-ron = "0.10.1"
+ron = "0.11.0"
 serde = "1.0.219"
 serde-transcode = "1.1.1"
 serde_json = "1.0.140"
modifiedcrates/nixlike/src/lib.rsdiffbeforeafterboth
--- a/crates/nixlike/src/lib.rs
+++ b/crates/nixlike/src/lib.rs
@@ -5,6 +5,7 @@
 //! expressions and expect it to work, only basic primitives are supported, and there is no
 //! variables/recursive records, interpolation, e.t.c.
 
+use alejandra::config::Indentation;
 use linked_hash_map::LinkedHashMap;
 use peg::str::LineCol;
 use se_impl::MySerialize;
@@ -196,7 +197,13 @@
 	assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"\n");
 }
 pub fn format_nix(value: &String) -> String {
-	let (_, out) = alejandra::format::in_memory("".to_owned(), value.to_owned());
+	let (_, out) = alejandra::format::in_memory(
+		"".to_owned(),
+		value.to_owned(),
+		alejandra::config::Config {
+			indentation: Indentation::TwoSpaces,
+		},
+	);
 	out
 }
 
modifiedcrates/nixlike/src/to_string.rsdiffbeforeafterboth
--- a/crates/nixlike/src/to_string.rs
+++ b/crates/nixlike/src/to_string.rs
@@ -1,3 +1,5 @@
+use alejandra::config::Indentation;
+
 use crate::Value;
 
 pub fn write_identifier(k: &str, out: &mut String) {
@@ -98,6 +100,12 @@
 pub fn write_nix(value: &Value) -> String {
 	let mut out = String::new();
 	write_nix_buf(value, &mut out);
-	let (_, out) = alejandra::format::in_memory("".to_owned(), out);
+	let (_, out) = alejandra::format::in_memory(
+		"".to_owned(),
+		out,
+		alejandra::config::Config {
+			indentation: Indentation::TwoSpaces,
+		},
+	);
 	out
 }
modifiedflake.lockdiffbeforeafterboth
--- a/flake.lock
+++ b/flake.lock
@@ -15,6 +15,22 @@
         "type": "github"
       }
     },
+    "flake-compat": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-parts": {
       "inputs": {
         "nixpkgs-lib": [
@@ -35,8 +51,117 @@
         "type": "github"
       }
     },
+    "flake-parts_2": {
+      "inputs": {
+        "nixpkgs-lib": [
+          "nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1748821116,
+        "narHash": "sha256-F82+gS044J1APL0n4hH50GYdPRv/5JWm34oCJYmVKdE=",
+        "rev": "49f0870db23e8c1ca0b5259734a02cd9e1e371a1",
+        "revCount": 377,
+        "type": "tarball",
+        "url": "https://api.flakehub.com/f/pinned/hercules-ci/flake-parts/0.1.377%2Brev-49f0870db23e8c1ca0b5259734a02cd9e1e371a1/01972f28-554a-73f8-91f4-d488cc502f08/source.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://flakehub.com/f/hercules-ci/flake-parts/0.1"
+      }
+    },
+    "git-hooks-nix": {
+      "inputs": {
+        "flake-compat": "flake-compat",
+        "gitignore": [
+          "nix"
+        ],
+        "nixpkgs": [
+          "nix",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1747372754,
+        "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
+        "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
+        "revCount": 1026,
+        "type": "tarball",
+        "url": "https://api.flakehub.com/f/pinned/cachix/git-hooks.nix/0.1.1026%2Brev-80479b6ec16fefd9c1db3ea13aeb038c60530f46/0196d79a-1b35-7b8e-a021-c894fb62163d/source.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://flakehub.com/f/cachix/git-hooks.nix/0.1.941"
+      }
+    },
+    "nix": {
+      "inputs": {
+        "flake-parts": "flake-parts_2",
+        "git-hooks-nix": "git-hooks-nix",
+        "nixpkgs": "nixpkgs",
+        "nixpkgs-23-11": "nixpkgs-23-11",
+        "nixpkgs-regression": "nixpkgs-regression"
+      },
+      "locked": {
+        "lastModified": 1756860322,
+        "narHash": "sha256-mT01CpWVdqSm79L270dSkjdYbdc37r+Hq9vk4GTp7Ao=",
+        "path": "/home/lach/build/nix-src",
+        "type": "path"
+      },
+      "original": {
+        "path": "/home/lach/build/nix-src",
+        "type": "path"
+      }
+    },
     "nixpkgs": {
       "locked": {
+        "lastModified": 1755922037,
+        "narHash": "sha256-wY1+2JPH0ZZC4BQefoZw/k+3+DowFyfOxv17CN/idKs=",
+        "rev": "b1b3291469652d5a2edb0becc4ef0246fff97a7c",
+        "revCount": 808723,
+        "type": "tarball",
+        "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2505.808723%2Brev-b1b3291469652d5a2edb0becc4ef0246fff97a7c/0198daf7-011a-7703-95d7-57146e794342/source.tar.gz"
+      },
+      "original": {
+        "type": "tarball",
+        "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2505"
+      }
+    },
+    "nixpkgs-23-11": {
+      "locked": {
+        "lastModified": 1717159533,
+        "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446",
+        "type": "github"
+      }
+    },
+    "nixpkgs-regression": {
+      "locked": {
+        "lastModified": 1643052045,
+        "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
+        "type": "github"
+      }
+    },
+    "nixpkgs_2": {
+      "locked": {
         "lastModified": 1753320130,
         "narHash": "sha256-KCuv6iYQ0XTVAEJvDLIsk99CJm7fuqIE0/KknyeYPtM=",
         "owner": "nixos",
@@ -55,7 +180,8 @@
       "inputs": {
         "crane": "crane",
         "flake-parts": "flake-parts",
-        "nixpkgs": "nixpkgs",
+        "nix": "nix",
+        "nixpkgs": "nixpkgs_2",
         "rust-overlay": "rust-overlay",
         "shelly": "shelly",
         "treefmt-nix": "treefmt-nix"
modifiedflake.nixdiffbeforeafterboth
--- a/flake.nix
+++ b/flake.nix
@@ -17,6 +17,9 @@
       url = "github:numtide/treefmt-nix";
       inputs.nixpkgs.follows = "nixpkgs";
     };
+    # DeterminateSystem's nix fork is controversial, but I don't mind it,
+    # and it has lazy-trees support which is useful for fleet.
+    nix.url = "/home/lach/build/nix-src";
   };
   outputs =
     inputs:
@@ -41,6 +44,11 @@
 
           fleetModules.tf = ./modules/extras/tf.nix;
 
+          testObj = {
+            v = "Hello";
+          };
+          testString = "hello";
+
           # To be used with https://github.com/NixOS/nix/pull/8892
           schemas =
             let
@@ -80,6 +88,7 @@
             system,
             pkgs,
             self,
+            inputs',
             ...
           }:
           let
@@ -108,7 +117,7 @@
             packages = lib.mkIf deployerSystem (
               let
                 packages = pkgs.callPackages ./pkgs {
-                  inherit craneLib;
+                  inherit craneLib inputs';
                 };
               in
               packages // { default = packages.fleet; }
@@ -120,6 +129,7 @@
                 nixpkgsCraneLib = inputs.crane.mkLib pkgs;
                 packages = pkgs.callPackages ./pkgs {
                   craneLib = nixpkgsCraneLib;
+                  inherit inputs;
                 };
                 prefixAttrs =
                   prefix: attrs:
@@ -150,13 +160,16 @@
                 cargo-fuzz
                 cargo-watch
                 cargo-outdated
+                gdb
 
                 pkg-config
                 openssl
                 bacon
                 nil
                 rustPlatform.bindgenHook
-                # nixVersions.nix_2_22
+                inputs'.nix.packages.nix-expr-c
+                inputs'.nix.packages.nix-flake-c
+                inputs'.nix.packages.nix-fetchers-c
               ];
               environment.PROTOC = "${pkgs.protobuf}/bin/protoc";
             };
modifiedlib/flakePart.nixdiffbeforeafterboth
--- a/lib/flakePart.nix
+++ b/lib/flakePart.nix
@@ -65,7 +65,7 @@
           normalEval = bootstrapNixpkgs.lib.evalModules {
             modules = (import ../modules/module-list.nix) ++ [
               module
-              {
+              ({inputs', ...}: {
                 config = {
                   data = if isPath data then import data else data;
                   nixpkgs.buildUsing = mkOptionDefault bootstrapNixpkgs;
@@ -74,6 +74,7 @@
                       inherit
                         (import ../pkgs {
                           inherit (prev) callPackage;
+                          inherit inputs';
                           craneLib = crane.mkLib prev;
                         })
                         fleet-install-secrets
@@ -82,7 +83,7 @@
                     })
                   ];
                 };
-              }
+              })
             ];
             specialArgs = {
               inherit inputs self;
modifiedmodules/nixos/online.nixdiffbeforeafterboth
--- a/modules/nixos/online.nix
+++ b/modules/nixos/online.nix
@@ -80,7 +80,8 @@
       '';
       supportsDryActivation = true;
     };
-  } // config.system.onlineActivationScripts;
+  }
+  // config.system.onlineActivationScripts;
 
   config.systemd.services = mkIf config.networking.networkmanager.enable {
     # If machine is managed by fleet, we should not restart NetworkManager during activation,
modifiedmodules/secrets-data.nixdiffbeforeafterboth
--- a/modules/secrets-data.nix
+++ b/modules/secrets-data.nix
@@ -105,7 +105,7 @@
         description = "Age-compatible key";
       };
     };
-    config = {};
+    config = { };
   };
 in
 {
modifiedpkgs/default.nixdiffbeforeafterboth
--- a/pkgs/default.nix
+++ b/pkgs/default.nix
@@ -1,9 +1,10 @@
 {
   callPackage,
   craneLib,
+  inputs',
 }:
 {
-  fleet = callPackage ./fleet.nix { inherit craneLib; };
+  fleet = callPackage ./fleet.nix { inherit craneLib inputs'; };
   fleet-install-secrets = callPackage ./fleet-install-secrets.nix { inherit craneLib; };
   fleet-generator-helper = callPackage ./fleet-generator-helper.nix { inherit craneLib; };
 }
modifiedpkgs/fleet.nixdiffbeforeafterboth
--- a/pkgs/fleet.nix
+++ b/pkgs/fleet.nix
@@ -1,16 +1,35 @@
 {
+  lib,
   craneLib,
   installShellFiles,
+  inputs',
+  pkg-config,
+  rustPlatform,
 }:
 craneLib.buildPackage rec {
   pname = "fleet";
-
-  src = craneLib.cleanCargoSource (craneLib.path ../.);
+  src = lib.cleanSourceWith {
+    src = ../.;
+    filter =
+      path: type:
+      (lib.hasSuffix "\.cc" path)
+      || (lib.hasSuffix "\.hh" path)
+      || (craneLib.filterCargoSources path type);
+  };
   strictDeps = true;
 
   cargoExtraArgs = "--locked -p ${pname}";
 
-  nativeBuildInputs = [ installShellFiles ];
+  buildInputs = [
+    inputs'.nix.packages.nix-expr-c
+    inputs'.nix.packages.nix-flake-c
+    inputs'.nix.packages.nix-fetchers-c
+  ];
+  nativeBuildInputs = [
+    installShellFiles
+    pkg-config
+    rustPlatform.bindgenHook
+  ];
 
   postInstall = ''
     for shell in bash fish zsh; do
modifiedtreefmt.nixdiffbeforeafterboth
--- a/treefmt.nix
+++ b/treefmt.nix
@@ -9,4 +9,5 @@
   programs.shfmt.enable = true;
   programs.rustfmt.enable = true;
   programs.taplo.enable = true;
+  programs.clang-format.enable = true;
 }