about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2024-01-05T13·53+0200
committerflokli <flokli@flokli.de>2024-01-06T15·33+0000
commit986e9b73c3c1e694fa0cbc4d29440ad8b8938269 (patch)
tree52be68fb5beb2aea347207d5e03f84f42f982d61 /tvix
parentc9c95f4ef3b2d4a99723a2779744f5f4def65660 (diff)
feat(tvix/build): add BuildRequest validation r/7356
Change-Id: I8182e4c4a7e5694c1e6f1f56ce092751c22adf4c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10538
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix')
-rw-r--r--tvix/Cargo.lock163
-rw-r--r--tvix/Cargo.nix186
-rw-r--r--tvix/build/Cargo.toml5
-rw-r--r--tvix/build/src/proto/mod.rs260
-rw-r--r--tvix/glue/src/tvix_build.rs12
5 files changed, 458 insertions, 168 deletions
diff --git a/tvix/Cargo.lock b/tvix/Cargo.lock
index 3b17d59f3f..9c334df251 100644
--- a/tvix/Cargo.lock
+++ b/tvix/Cargo.lock
@@ -111,9 +111,9 @@ version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -133,9 +133,9 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -154,9 +154,9 @@ version = "0.1.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -423,9 +423,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
 dependencies = [
  "heck",
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -638,9 +638,9 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -937,9 +937,9 @@ version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1843,9 +1843,9 @@ version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1932,8 +1932,8 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282"
 dependencies = [
- "proc-macro2 1.0.67",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -1947,9 +1947,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.67"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
+checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
 dependencies = [
  "unicode-ident",
 ]
@@ -2011,7 +2011,7 @@ dependencies = [
  "prost 0.12.1",
  "prost-types",
  "regex",
- "syn 2.0.39",
+ "syn 2.0.48",
  "tempfile",
  "which",
 ]
@@ -2024,8 +2024,8 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "syn 1.0.109",
 ]
 
@@ -2037,9 +2037,9 @@ checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -2068,11 +2068,11 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.33"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
 dependencies = [
- "proc-macro2 1.0.67",
+ "proc-macro2 1.0.75",
 ]
 
 [[package]]
@@ -2511,9 +2511,9 @@ version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -2686,8 +2686,8 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "104842d6278bf64aa9d2f182ba4bde31e8aec7a131d29b7f444bb9b344a09e2a"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "structmeta-derive",
  "syn 1.0.109",
 ]
@@ -2698,8 +2698,8 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24420be405b590e2d746d83b01f09af673270cf80e9b003a5fa7b651c58c7d93"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "syn 1.0.109",
 ]
 
@@ -2726,19 +2726,19 @@ version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "unicode-ident",
 ]
 
 [[package]]
 name = "syn"
-version = "2.0.39"
+version = "2.0.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "unicode-ident",
 ]
 
@@ -2816,9 +2816,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
 dependencies = [
  "cfg-if",
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -2827,9 +2827,9 @@ version = "3.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
  "test-case-core",
 ]
 
@@ -2850,8 +2850,8 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62d6408d1406657be2f9d1701fbae379331d30d2f6e92050710edb0d34eeb480"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "structmeta",
  "syn 1.0.109",
 ]
@@ -2864,22 +2864,22 @@ checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
 
 [[package]]
 name = "thiserror"
-version = "1.0.40"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -2968,9 +2968,9 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -3120,10 +3120,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d021fc044c18582b9a2408cd0dd05b1596e3ecdb5c4df822bb0183545683889"
 dependencies = [
  "prettyplease",
- "proc-macro2 1.0.67",
+ "proc-macro2 1.0.75",
  "prost-build",
- "quote 1.0.33",
- "syn 2.0.39",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -3190,9 +3190,9 @@ version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
 ]
 
 [[package]]
@@ -3283,8 +3283,11 @@ name = "tvix-build"
 version = "0.1.0"
 dependencies = [
  "bytes",
+ "itertools 0.12.0",
  "prost 0.12.1",
  "prost-build",
+ "test-case",
+ "thiserror",
  "tonic 0.10.2",
  "tonic-build",
  "tonic-reflection",
@@ -3389,8 +3392,8 @@ dependencies = [
 name = "tvix-eval-builtin-macros"
 version = "0.0.1"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
  "syn 1.0.109",
  "tvix-eval",
 ]
@@ -3697,9 +3700,9 @@ dependencies = [
  "bumpalo",
  "log",
  "once_cell",
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
  "wasm-bindgen-shared",
 ]
 
@@ -3721,7 +3724,7 @@ version = "0.2.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
 dependencies = [
- "quote 1.0.33",
+ "quote 1.0.35",
  "wasm-bindgen-macro-support",
 ]
 
@@ -3731,9 +3734,9 @@ version = "0.2.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
 dependencies = [
- "proc-macro2 1.0.67",
- "quote 1.0.33",
- "syn 2.0.39",
+ "proc-macro2 1.0.75",
+ "quote 1.0.35",
+ "syn 2.0.48",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix
index 1e95c09f1a..79c2c55ef2 100644
--- a/tvix/Cargo.nix
+++ b/tvix/Cargo.nix
@@ -403,17 +403,17 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
             usesDefaultFeatures = false;
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
             usesDefaultFeatures = false;
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             usesDefaultFeatures = false;
             features = [ "full" "parsing" "printing" "proc-macro" "clone-impls" ];
           }
@@ -456,15 +456,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" "visit-mut" ];
           }
         ];
@@ -516,15 +516,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" "visit-mut" ];
           }
         ];
@@ -1311,15 +1311,15 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" ];
           }
         ];
@@ -1896,15 +1896,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" ];
           }
         ];
@@ -2755,15 +2755,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" ];
           }
         ];
@@ -5514,15 +5514,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" "visit-mut" ];
           }
         ];
@@ -5741,12 +5741,12 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
             usesDefaultFeatures = false;
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             usesDefaultFeatures = false;
             features = [ "full" ];
           }
@@ -5754,7 +5754,7 @@ rec {
         devDependencies = [
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             usesDefaultFeatures = false;
             features = [ "parsing" ];
           }
@@ -5782,11 +5782,11 @@ rec {
         };
         resolvedDefaultFeatures = [ "default" "proc-macro" ];
       };
-      "proc-macro2 1.0.67" = rec {
+      "proc-macro2 1.0.75" = rec {
         crateName = "proc-macro2";
-        version = "1.0.67";
+        version = "1.0.75";
         edition = "2021";
-        sha256 = "0a0k7adv0yswsgzsqkd7r6ng8rpcdyqrhra5v5ii531y3agkshrx";
+        sha256 = "021pn6vxs5l4y08819q4ynijcr0p0m6w67fgs6fg5hk41yyn2ylh";
         authors = [
           "David Tolnay <dtolnay@gmail.com>"
           "Alex Crichton <alex@alexcrichton.com>"
@@ -6011,7 +6011,7 @@ rec {
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             optional = true;
             features = [ "full" ];
           }
@@ -6059,11 +6059,11 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
@@ -6097,15 +6097,15 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "extra-traits" ];
           }
         ];
@@ -6167,18 +6167,18 @@ rec {
         };
         resolvedDefaultFeatures = [ "default" "proc-macro" ];
       };
-      "quote 1.0.33" = rec {
+      "quote 1.0.35" = rec {
         crateName = "quote";
-        version = "1.0.33";
+        version = "1.0.35";
         edition = "2018";
-        sha256 = "1biw54hbbr12wdwjac55z1m2x2rylciw83qnjn564a3096jgqrsj";
+        sha256 = "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9";
         authors = [
           "David Tolnay <dtolnay@gmail.com>"
         ];
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
             usesDefaultFeatures = false;
           }
         ];
@@ -7725,15 +7725,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
           }
         ];
         features = { };
@@ -8187,11 +8187,11 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "structmeta-derive";
@@ -8223,11 +8223,11 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
@@ -8300,12 +8300,12 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
             usesDefaultFeatures = false;
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
             optional = true;
             usesDefaultFeatures = false;
           }
@@ -8323,23 +8323,23 @@ rec {
         };
         resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ];
       };
-      "syn 2.0.39" = rec {
+      "syn 2.0.48" = rec {
         crateName = "syn";
-        version = "2.0.39";
+        version = "2.0.48";
         edition = "2021";
-        sha256 = "0ymyhxnk1yi4pzf72qk3lrdm9lgjwcrcwci0hhz5vx7wya88prr3";
+        sha256 = "0gqgfygmrxmp8q32lia9p294kdd501ybn6kn2h4gqza0irik2d8g";
         authors = [
           "David Tolnay <dtolnay@gmail.com>"
         ];
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
             usesDefaultFeatures = false;
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
             optional = true;
             usesDefaultFeatures = false;
           }
@@ -8531,15 +8531,15 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" "extra-traits" ];
           }
         ];
@@ -8559,15 +8559,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" "extra-traits" "parsing" ];
           }
           {
@@ -8627,11 +8627,11 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "structmeta";
@@ -8660,9 +8660,9 @@ rec {
       };
       "thiserror" = rec {
         crateName = "thiserror";
-        version = "1.0.40";
-        edition = "2018";
-        sha256 = "1b7bdhriasdsr99y39d50jz995xaz9sw3hsbb6z9kp6q9cqrm34p";
+        version = "1.0.56";
+        edition = "2021";
+        sha256 = "1b9hnzngjan4d89zjs16i01bcpcnvdwklyh73lj16xk28p37hhym";
         authors = [
           "David Tolnay <dtolnay@gmail.com>"
         ];
@@ -8676,9 +8676,9 @@ rec {
       };
       "thiserror-impl" = rec {
         crateName = "thiserror-impl";
-        version = "1.0.40";
-        edition = "2018";
-        sha256 = "17sn41kyimc6s983aypkk6a45pcyrkbkvrw6rp407n5hqm16ligr";
+        version = "1.0.56";
+        edition = "2021";
+        sha256 = "0w9ldp8fa574ilz4dn7y7scpcq66vdjy59qal8qdpwsh7faal3zs";
         procMacro = true;
         authors = [
           "David Tolnay <dtolnay@gmail.com>"
@@ -8686,15 +8686,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
           }
         ];
 
@@ -9007,15 +9007,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" ];
           }
         ];
@@ -9595,7 +9595,7 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "prost-build";
@@ -9604,11 +9604,11 @@ rec {
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
           }
         ];
         features = {
@@ -9870,15 +9870,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             usesDefaultFeatures = false;
             features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ];
           }
@@ -10220,10 +10220,18 @@ rec {
             packageId = "bytes";
           }
           {
+            name = "itertools";
+            packageId = "itertools 0.12.0";
+          }
+          {
             name = "prost";
             packageId = "prost 0.12.1";
           }
           {
+            name = "thiserror";
+            packageId = "thiserror";
+          }
+          {
             name = "tonic";
             packageId = "tonic 0.10.2";
           }
@@ -10247,6 +10255,12 @@ rec {
             packageId = "tonic-build";
           }
         ];
+        devDependencies = [
+          {
+            name = "test-case";
+            packageId = "test-case";
+          }
+        ];
         features = {
           "tonic-reflection" = [ "dep:tonic-reflection" ];
         };
@@ -10667,11 +10681,11 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
@@ -11578,15 +11592,15 @@ rec {
           }
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "full" ];
           }
           {
@@ -11644,7 +11658,7 @@ rec {
         dependencies = [
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "wasm-bindgen-macro-support";
@@ -11668,15 +11682,15 @@ rec {
         dependencies = [
           {
             name = "proc-macro2";
-            packageId = "proc-macro2 1.0.67";
+            packageId = "proc-macro2 1.0.75";
           }
           {
             name = "quote";
-            packageId = "quote 1.0.33";
+            packageId = "quote 1.0.35";
           }
           {
             name = "syn";
-            packageId = "syn 2.0.39";
+            packageId = "syn 2.0.48";
             features = [ "visit" "full" ];
           }
           {
diff --git a/tvix/build/Cargo.toml b/tvix/build/Cargo.toml
index 99802fcc99..7b1594abc3 100644
--- a/tvix/build/Cargo.toml
+++ b/tvix/build/Cargo.toml
@@ -5,7 +5,9 @@ edition = "2021"
 
 [dependencies]
 bytes = "1.4.0"
+itertools = "0.12.0"
 prost = "0.12.1"
+thiserror = "1.0.56"
 tonic = "0.10.2"
 tvix-castore = { path = "../castore" }
 
@@ -20,3 +22,6 @@ tonic-build = "0.10.2"
 [features]
 default = []
 tonic-reflection = ["dep:tonic-reflection"]
+
+[dev-dependencies]
+test-case = "3.3.1"
diff --git a/tvix/build/src/proto/mod.rs b/tvix/build/src/proto/mod.rs
index b0360dcd4f..a9e620ecdd 100644
--- a/tvix/build/src/proto/mod.rs
+++ b/tvix/build/src/proto/mod.rs
@@ -1 +1,261 @@
+use std::path::{Path, PathBuf};
+
+use itertools::Itertools;
+use tvix_castore::proto::{NamedNode, ValidateNodeError};
+
 tonic::include_proto!("tvix.build.v1");
+
+#[cfg(feature = "tonic-reflection")]
+/// Compiled file descriptors for implementing [gRPC
+/// reflection](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) with e.g.
+/// [`tonic_reflection`](https://docs.rs/tonic-reflection).
+pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("tvix.build.v1");
+
+/// Errors that occur during the validation of [BuildRequest] messages.
+#[derive(Debug, thiserror::Error)]
+pub enum ValidateBuildRequestError {
+    #[error("invalid input node at position {0}: {1}")]
+    InvalidInputNode(usize, ValidateNodeError),
+
+    #[error("input nodes are not sorted by name")]
+    InputNodesNotSorted,
+
+    #[error("invalid working_dir")]
+    InvalidWorkingDir,
+
+    #[error("scratch_paths not sorted")]
+    ScratchPathsNotSorted,
+
+    #[error("invalid scratch path at position {0}")]
+    InvalidScratchPath(usize),
+
+    #[error("invalid inputs_dir")]
+    InvalidInputsDir,
+
+    #[error("invalid output path at position {0}")]
+    InvalidOutputPath(usize),
+
+    #[error("outputs not sorted")]
+    OutputsNotSorted,
+
+    #[error("invalid environment variable at position {0}")]
+    InvalidEnvVar(usize),
+
+    #[error("EnvVar not sorted by their keys")]
+    EnvVarNotSorted,
+
+    #[error("invalid build constraints: {0}")]
+    InvalidBuildConstraints(ValidateBuildConstraintsError),
+
+    #[error("invalid additional file path at position: {0}")]
+    InvalidAdditionalFilePath(usize),
+
+    #[error("additional_files not sorted")]
+    AdditionalFilesNotSorted,
+}
+
+/// Checks a path to be without any '..' components, and clean (no superfluous
+/// slashes).
+fn is_clean_path<P: AsRef<Path>>(p: P) -> bool {
+    let p = p.as_ref();
+
+    // Look at all components, bail in case of ".", ".." and empty normal
+    // segments (superfluous slashes)
+    // We still need to assemble a cleaned PathBuf, and compare the OsString
+    // later, as .components() already does do some normalization before
+    // yielding.
+    let mut cleaned_p = PathBuf::new();
+    for component in p.components() {
+        match component {
+            std::path::Component::Prefix(_) => {}
+            std::path::Component::RootDir => {}
+            std::path::Component::CurDir => return false,
+            std::path::Component::ParentDir => return false,
+            std::path::Component::Normal(a) => {
+                if a.is_empty() {
+                    return false;
+                }
+            }
+        }
+        cleaned_p.push(component);
+    }
+
+    // if cleaned_p looks like p, we're good.
+    if cleaned_p.as_os_str() != p.as_os_str() {
+        return false;
+    }
+
+    true
+}
+
+fn is_clean_relative_path<P: AsRef<Path>>(p: P) -> bool {
+    if p.as_ref().is_absolute() {
+        return false;
+    }
+
+    is_clean_path(p)
+}
+
+fn is_clean_absolute_path<P: AsRef<Path>>(p: P) -> bool {
+    if !p.as_ref().is_absolute() {
+        return false;
+    }
+
+    is_clean_path(p)
+}
+
+/// Checks if a given list is sorted.
+fn is_sorted<I>(data: I) -> bool
+where
+    I: Iterator,
+    I::Item: Ord + Clone,
+{
+    data.tuple_windows().all(|(a, b)| a <= b)
+}
+
+impl BuildRequest {
+    /// Ensures the build request is valid.
+    /// This means, all input nodes need to be valid, paths in lists need to be sorted,
+    /// and all restrictions around paths themselves (relative, clean, …) need
+    // to be fulfilled.
+    pub fn validate(&self) -> Result<(), ValidateBuildRequestError> {
+        // validate all input nodes
+        for (i, n) in self.inputs.iter().enumerate() {
+            // ensure the input node itself is valid
+            n.validate()
+                .map_err(|e| ValidateBuildRequestError::InvalidInputNode(i, e))?;
+        }
+
+        // now we can look at the names, and make sure they're sorted.
+        if !is_sorted(
+            self.inputs
+                .iter()
+                .map(|e| e.node.as_ref().unwrap().get_name()),
+        ) {
+            Err(ValidateBuildRequestError::InputNodesNotSorted)?
+        }
+
+        // validate working_dir
+        if !is_clean_relative_path(&self.working_dir) {
+            Err(ValidateBuildRequestError::InvalidWorkingDir)?;
+        }
+
+        // validate scratch paths
+        for (i, p) in self.scratch_paths.iter().enumerate() {
+            if !is_clean_relative_path(p) {
+                Err(ValidateBuildRequestError::InvalidScratchPath(i))?
+            }
+        }
+        if !is_sorted(self.scratch_paths.iter().map(|e| e.as_bytes())) {
+            Err(ValidateBuildRequestError::ScratchPathsNotSorted)?;
+        }
+
+        // validate inputs_dir
+        if !is_clean_relative_path(&self.inputs_dir) {
+            Err(ValidateBuildRequestError::InvalidInputsDir)?;
+        }
+
+        // validate outputs
+        for (i, p) in self.outputs.iter().enumerate() {
+            if !is_clean_relative_path(p) {
+                Err(ValidateBuildRequestError::InvalidOutputPath(i))?
+            }
+        }
+        if !is_sorted(self.outputs.iter().map(|e| e.as_bytes())) {
+            Err(ValidateBuildRequestError::OutputsNotSorted)?;
+        }
+
+        // validate environment_vars.
+        for (i, e) in self.environment_vars.iter().enumerate() {
+            if e.key.is_empty() || e.key.contains('=') {
+                Err(ValidateBuildRequestError::InvalidEnvVar(i))?
+            }
+        }
+        if !is_sorted(self.environment_vars.iter().map(|e| e.key.as_bytes())) {
+            Err(ValidateBuildRequestError::EnvVarNotSorted)?;
+        }
+
+        // validate build constraints
+        if let Some(constraints) = self.constraints.as_ref() {
+            constraints
+                .validate()
+                .map_err(ValidateBuildRequestError::InvalidBuildConstraints)?;
+        }
+
+        // validate additional_files
+        for (i, additional_file) in self.additional_files.iter().enumerate() {
+            if !is_clean_relative_path(&additional_file.path) {
+                Err(ValidateBuildRequestError::InvalidAdditionalFilePath(i))?
+            }
+        }
+        if !is_sorted(self.additional_files.iter().map(|e| e.path.as_bytes())) {
+            Err(ValidateBuildRequestError::AdditionalFilesNotSorted)?;
+        }
+
+        Ok(())
+    }
+}
+
+/// Errors that occur during the validation of
+/// [build_request::BuildConstraints] messages.
+#[derive(Debug, thiserror::Error)]
+pub enum ValidateBuildConstraintsError {
+    #[error("invalid system")]
+    InvalidSystem,
+
+    #[error("invalid available_ro_paths at position {0}")]
+    InvalidAvailableRoPaths(usize),
+
+    #[error("available_ro_paths not sorted")]
+    AvailableRoPathsNotSorted,
+}
+
+impl build_request::BuildConstraints {
+    pub fn validate(&self) -> Result<(), ValidateBuildConstraintsError> {
+        // validate system
+        if self.system.is_empty() {
+            Err(ValidateBuildConstraintsError::InvalidSystem)?;
+        }
+        // validate available_ro_paths
+        for (i, p) in self.available_ro_paths.iter().enumerate() {
+            if !is_clean_absolute_path(p) {
+                Err(ValidateBuildConstraintsError::InvalidAvailableRoPaths(i))?
+            }
+        }
+        if !is_sorted(self.available_ro_paths.iter().map(|e| e.as_bytes())) {
+            Err(ValidateBuildConstraintsError::AvailableRoPathsNotSorted)?;
+        }
+
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use test_case::test_case;
+
+    use crate::proto::is_clean_relative_path;
+
+    use super::is_clean_path;
+
+    #[test_case("foo/bar/", false; "fail trailing slash")]
+    #[test_case("foo/../bar", false; "fail dotdot")]
+    #[test_case("foo/./bar", false; "fail singledot")]
+    #[test_case("foo//bar", false; "fail unnecessary slashes")]
+    #[test_case("//foo/bar", false; "fail absolute unnecessary slashes")]
+    #[test_case("", true; "ok empty")]
+    #[test_case("foo/bar", true; "ok relative")]
+    #[test_case("/", true; "ok absolute")]
+    #[test_case("/foo/bar", true; "ok absolute2")]
+    fn test_is_clean_path(s: &str, expected: bool) {
+        assert_eq!(is_clean_path(s), expected);
+    }
+
+    #[test_case("/", false; "fail absolute")]
+    #[test_case("foo/bar", true; "ok relative")]
+    fn test_is_clean_relative_path(s: &str, expected: bool) {
+        assert_eq!(is_clean_relative_path(s), expected);
+    }
+
+    // TODO: add tests for BuildRequest validation itself
+}
diff --git a/tvix/glue/src/tvix_build.rs b/tvix/glue/src/tvix_build.rs
index b75191fe39..7ac351e9b6 100644
--- a/tvix/glue/src/tvix_build.rs
+++ b/tvix/glue/src/tvix_build.rs
@@ -141,7 +141,7 @@ where
         provide_bin_sh: true,
     });
 
-    Ok(BuildRequest {
+    let build_request = BuildRequest {
         command_args,
         outputs: output_paths,
 
@@ -161,7 +161,15 @@ where
                 .into_iter()
                 .map(|(path, contents)| AdditionalFile { path, contents }),
         ),
-    })
+    };
+
+    debug_assert!(
+        build_request.validate().is_ok(),
+        "invalid BuildRequest: {}",
+        build_request.validate().unwrap_err()
+    );
+
+    Ok(build_request)
 }
 
 /// handle passAsFile, if set.