From 178775bd68b1d4dc966d631b7d67279c49d85ce4 Mon Sep 17 00:00:00 2001 From: mintaka Date: Wed, 26 Aug 2026 22:48:12 -0400 Subject: [PATCH] fix(secretspec): supply a default activation reason so require_reason never blocks shell entry (RIG-2822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit secretspec 0.19+ added a `require_reason` policy defaulting to `"agents"`: when the caller is detected as a coding agent and no reason is supplied, every secret-access op fails with `SecretSpecError::ReasonRequired`, independent of `required = false`. devenv's `use devenv` shell activation resolves secrets in `resolve_secretspec_into` via a bare `secrets.validate()?`, so any coding agent entering a devenv shell on a cold direnv cache (fresh clone, or an edit to any watched file) is blocked outright — no toolchain. This hit every repo on the fork (orion, compass, forge, infra). Fix: chain `with_default_reason("devenv shell activation")` before `validate()` at the activation resolve site. `with_default_reason` (secretspec 0.19+, already bundled) fills a reason only when the caller set none, so an explicit `SECRETSPEC_REASON` / `with_reason()` still wins and is what gets audited — the reason gate is preserved for genuine interactive `secretspec get`/`export`, while automatic shell activation self-describes and no longer blocks. The other resolve path, `resolve_builtin_cachix_auth_token`, loads a manifest that hardcodes `require_reason = false`, so it needs no reason and is untouched. This is the fleet-wide fix that reverts the orion-side stopgap (`require_reason = false` in orion's secretspec.toml, RIG-2550) once the lock bump lands. Co-authored-by: Matt Wilkinson --- devenv/src/devenv/mod.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/devenv/src/devenv/mod.rs b/devenv/src/devenv/mod.rs index 1f88ffb171..18846b6c9a 100644 --- a/devenv/src/devenv/mod.rs +++ b/devenv/src/devenv/mod.rs @@ -3700,7 +3700,19 @@ fn resolve_secretspec_into( secrets.set_profile(profile_str); } - let validated_secrets = match secrets.validate()? { + // secretspec 0.19+ gates every access behind a `require_reason` policy that + // defaults to `"agents"`: when the caller is detected as a coding agent and no + // reason is supplied, validate() fails with ReasonRequired regardless of + // `required=false`. Shell activation is automatic (no interactive `secretspec + // get`), so supply a default reason describing it. with_default_reason only + // fills an ABSENT reason — an explicit SECRETSPEC_REASON / with_reason still + // wins and is what gets audited. (The other resolve path, + // resolve_builtin_cachix_auth_token, uses a manifest with require_reason=false + // and so needs no reason.) + let validated_secrets = match secrets + .with_default_reason("devenv shell activation") + .validate()? + { Ok(validated) => validated, Err(e) => { return Err(SecretsNeedPrompting {