From adbed5f3c0745a5b215d4ceb527dd08c15bb24a3 Mon Sep 17 00:00:00 2001 From: Alexander Miroshnichenko Date: Mon, 19 Oct 2026 09:52:45 +0300 Subject: [PATCH] chore(marmel): bump to b08923ea (main), drop obsolete patches Upstream fixed both reasons for the local patches, so neither is needed: - 62cb75634c6e (#16) reports a missing TLS trust store instead of panicking through reqwest::Client::default(); the env-cleared test child now stays reachable without SSL_CERT_FILE, which is what session-boot-trust-store.patch existed to work around. - b08923eaef60 (#17) adds /nix/store and /gnu/store to BUILTIN_READONLY_PATHS; the checkPhase rebuild confirms the store rule works on a Nix host: test_internal_sandbox_cross_directory_rename and test_internal_sandbox_extra_readonly_paths_never_grant_write run for real, no SKIP line is printed, and only the /etc/resolv.conf DNS test stays filtered. Lib suite: 1055 passed, 1 filtered; all integration suites green. passthru.updateScript now passes the bare attribute name: nix-update rejects ".#marmel" with AttributePathError, so the documented bump path was broken. Verify with `nix-update --flake marmel --use-update-script`. --- packages/marmel/landlock-nix-store.patch | 29 ---------- packages/marmel/package.nix | 53 ++++++++++--------- .../marmel/session-boot-trust-store.patch | 43 --------------- 3 files changed, 29 insertions(+), 96 deletions(-) delete mode 100644 packages/marmel/landlock-nix-store.patch delete mode 100644 packages/marmel/session-boot-trust-store.patch diff --git a/packages/marmel/landlock-nix-store.patch b/packages/marmel/landlock-nix-store.patch deleted file mode 100644 index 5ca62e1..0000000 --- a/packages/marmel/landlock-nix-store.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/src/harness/sandbox.rs -+++ b/src/harness/sandbox.rs -@@ -414,8 +414,25 @@ - } - - // 5. System toolchains, device nodes, runtime files (DNS /run/systemd/resolve), and binaries (Read-Only + Execute) -+ // -+ // On NixOS and Guix /bin, /usr/bin and /lib are symlink farms: every executable -+ // resolves below the package store, and Landlock matches the resolved target rather -+ // than the symlinked view, so the store has to be listed here or nothing can be exec'd -+ // at all. Store paths are world-readable by design, so read+execute there adds no -+ // reach that a local user does not already have. - let ro_paths = [ -- "/usr", "/bin", "/lib", "/lib64", "/opt", "/etc", "/dev", "/proc", "/sys", "/run", "/var", -+ "/usr", -+ "/bin", -+ "/lib", -+ "/lib64", -+ "/opt", -+ "/etc", -+ "/dev", -+ "/proc", -+ "/sys", -+ "/run", -+ "/var", -+ "/nix/store", - ]; - for p in ro_paths { - if Path::new(p).exists() diff --git a/packages/marmel/package.nix b/packages/marmel/package.nix index 601a2c3..628a726 100644 --- a/packages/marmel/package.nix +++ b/packages/marmel/package.nix @@ -11,35 +11,33 @@ rustPlatform.buildRustPackage rec { # says 1.0.0, so the version is meaningless and the source is tracked by # branch head, dated by nix-update's 0-unstable-* scheme. Bump with # nix-update (see passthru.updateScript). - version = "0-unstable-2026-10-17"; + version = "0-unstable-2026-10-19"; src = fetchFromGitHub { owner = "Na1w"; repo = "marmel"; - rev = "981b35b0d356e56de429ab4198e427ccfbe7d85f"; - hash = "sha256-Z72o5LsjwTIk1EsiTYfNO+WIFzOSOEmCzzfyJKksYF4="; + rev = "b08923eaef6057410140d80f5dad37b6b511c5af"; + hash = "sha256-GkGjhsVCWNqaa6a5kwSSgiI69ZabkFLPWmnI9RfWXuQ="; }; cargoHash = "sha256-etqW3xcxkiNfkiPxl/Emt5pQCkNnoIhHFkX0Zqfs4rc="; nativeCheckInputs = [ cacert ]; - patches = [ - ./session-boot-trust-store.patch - # Temporary downstream fix, upstream has no NixOS-aware allow-list yet. - # Adds "/nix/store" to the read-only+execute list of the Landlock ruleset, so the - # sandbox re-entry can exec `sh` on a Nix host at all. Drop when upstream lands it - # (nix-overlay-5ml). - ./landlock-nix-store.patch - ]; + # Both downstream patches are gone as of b08923eaef60 ("Landlock improvements", + # Na1w/marmel#17) and 62cb75634c6e ("report missing TLS trust store instead of + # panicking", #16): upstream now lists /nix/store and /gnu/store in + # BUILTIN_READONLY_PATHS, and the HTTP client reports a missing trust store + # instead of panicking through reqwest::Client::default(). - # The test suite builds `reqwest::Client`s, and rustls rejects construction - # outright when no system trust store is found ("No CA certificates were - # loaded from the system"). rustls-native-certs probes only SSL_CERT_FILE, - # SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl, /etc/pki/tls, ...), - # none of which exist in the build sandbox, so point the tests at nixpkgs' - # bundle. Build-time only; the installed binary still uses the host's trust - # store at runtime. + # The test suite exercises real HTTP round-trips against loopback servers and + # builds its `reqwest::Client`s through rustls-native-certs, which probes only + # SSL_CERT_FILE, SSL_CERT_DIR and a fixed list of /etc dirs (/etc/ssl, + # /etc/pki/tls, ...), none of which exist in the build sandbox. Without a CA + # bundle the client build fails ("No CA certificates were loaded from the + # system") and every request fails terminally with ChatError::TrustStore, so + # point the tests at nixpkgs' bundle. Build-time only; the installed binary + # still uses the host's trust store at runtime. preCheck = '' export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt ''; @@ -52,12 +50,15 @@ rustPlatform.buildRustPackage rec { # then 1 failure, then 0 with serial threads. Drop this flag once upstream # makes that state per-instance. # - # Only the DNS sandbox-exec test is skipped now. It re-execs `sh` through + # Only the DNS sandbox-exec test is skipped. It re-execs `sh` through # `marmel --internal-sandbox-exec` and then reads /etc/resolv.conf, which the - # no-network build sandbox does not provide. landlock-nix-store.patch fixed the - # exec half for both sandbox-exec tests: with it, the cross-directory rename - # test runs for real (no SKIP printed by `integration_host`) and the lib suite - # passes at 1030 tests with that single filter. + # no-network build sandbox does not provide (upstream's own decision note in + # src/harness/sandbox.rs says the same: the exec half works on a store host, + # the resolv.conf half is a fixture question). Upstream now lists + # /nix/store and /gnu/store in BUILTIN_READONLY_PATHS, so the cross-directory + # rename test and test_internal_sandbox_extra_readonly_paths_never_grant_write + # run for real here: no SKIP line is printed and the lib suite passes at 1055 + # tests with that single filter. cargoTestFlags = [ "--" "--test-threads=1" @@ -75,10 +76,14 @@ rustPlatform.buildRustPackage rec { passthru = { category = "AI Coding Agents"; + # nix-update rejects a leading dot in the attribute path (".#marmel" → + # AttributePathError), so the bare attribute name is what the bare + # `nix-update --flake` invocation takes. Verify with + # `nix-update --flake marmel --use-update-script`. updateScript = [ "nix-update" "--flake" - ".#marmel" + "marmel" "--version=branch=main" ]; }; diff --git a/packages/marmel/session-boot-trust-store.patch b/packages/marmel/session-boot-trust-store.patch deleted file mode 100644 index 2ba4965..0000000 --- a/packages/marmel/session-boot-trust-store.patch +++ /dev/null @@ -1,43 +0,0 @@ -Give the env-cleared child process a trust store. - -run_marmel() wipes the child environment so the binary under test cannot -inherit the runner's MARMEL_* variables or its terminal. reqwest's TLS stack -is rustls-native-certs, which reads SSL_CERT_FILE / SSL_CERT_DIR and then the -well-known /etc paths, so where no system trust store exists at all the child -dies inside reqwest::Client::new() ("No CA certificates were loaded from the -system") before it ever reads the bundle. Four cases in this file assert the -CLI's exit codes and stderr, and they then observe the panic's 101 instead. - -Forward the test runner's SSL_CERT_FILE when it has one. On a normal Linux -host the child picks the trust store up from /etc as before, so the assertions -themselves are unchanged. - -This is a workaround, not the real fix. The panic should not happen at all: -src/llm/client.rs builds the client with unwrap_or_default() on a -Result, and reqwest's Client::default() is -Client::new(), which repeats the same build and .expect()s it, so the fallback -can never recover. Upstream was told; drop this patch once the error is -propagated instead of discarded. - ---- a/tests/test_session_boot.rs -+++ b/tests/test_session_boot.rs -@@ -221,8 +221,17 @@ - let err_file = std::fs::File::create(&err_path).expect("stderr file"); - - let mut cmd = Command::new(env!("CARGO_BIN_EXE_marmel")); -- cmd.current_dir(dir) -- .env_clear() -+ cmd.current_dir(dir).env_clear(); -+ // rustls-native-certs reads SSL_CERT_FILE / SSL_CERT_DIR, both of which the -+ // env_clear() above drops, so when no system trust store can be probed -+ // either the child dies inside reqwest::Client::new() ("No CA certificates -+ // were loaded from the system") before it ever reaches the bundle, and the -+ // exit-code assertions below then see the panic's 101. Forward the runner's -+ // value when it has one; the assertions themselves are untouched. -+ if let Some(trust_store) = std::env::var("SSL_CERT_FILE").ok().filter(|p| !p.is_empty()) { -+ cmd.env("SSL_CERT_FILE", trust_store); -+ } -+ cmd - // A minimal, deterministic environment: the binary must not inherit the - // test runner's `MARMEL_*` variables or its terminal. - .env("PATH", "/usr/bin:/bin")