Skip to content

fix(secretspec): supply a default activation reason so require_reason never blocks shell entry (RIG-2822) - #5

Merged
mattwilkinsonn merged 1 commit into
mainfrom
infra/2822-devenv-secretspec-default-reason
Aug 28, 2026
Merged

fix(secretspec): supply a default activation reason so require_reason never blocks shell entry (RIG-2822)#5
mattwilkinsonn merged 1 commit into
mainfrom
infra/2822-devenv-secretspec-default-reason

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Aug 27, 2026

Copy link
Copy Markdown

secretspec 0.19+ added a require_reason policy defaulting to "agents": when the caller is detected as a coding agent (detect-coding-agent) and no reason is supplied (SECRETSPEC_REASON unset / no with_reason()), every secret-access op fails with SecretSpecError::ReasonRequired, independent of required = false.

devenv's use devenv shell activation resolves secrets in resolve_secretspec_into (devenv/src/devenv/mod.rs) 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 — devenv.nix/.lock/.yaml/.envrc/toolchain pins) 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 single activation resolve site (mod.rs:3703). 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 (mod.rs:313), so it needs no reason and is untouched. Upstream devenv already does the analogous thing there for its own Cachix manifest — this applies the same remedy at the project-activation point.

Verification

  • nix build .#devenv — exit 0 (edited crate compiles against secretspec-0.19.1, the pinned rev b90afe38).
  • Gate mechanics confirmed against the built secretspec binary on a minimal require_reason-default manifest:
    • as-agent (CLAUDECODE=1) + no reason → ReasonRequired, exit 1 (the bare-validate() pre-fix path)
    • as-agent + --reason → exit 0
    • non-agent + no reason → exit 0 (gate only fires for agents)
  • End-to-end acceptance: CLAUDECODE=1 SECRETSPEC_REASON= devenv print-dev-env on that project → exit 0, no ReasonRequired, full dev env emitted. Pre-fix this exits 1.

Follow-through

  • Once merged: devenv update devenv bump of orion's devenv.lock, then revert the RIG-2550 stopgap (require_reason = false in orion's secretspec.toml) so the fleet runs the reason gate again with activation self-describing.
  • Upstreamable to cachix/devenv — the gate affects any agent using devenv + secretspec 0.19+, not just the fork.

RIG-2822.

Co-authored-by: Matt Wilkinson matt@rigel.build

… never blocks shell entry (RIG-2822)

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 <matt@rigel.build>
@linear-code

linear-code Bot commented Aug 27, 2026

Copy link
Copy Markdown

RIG-2822

@rigel-mintaka
rigel-mintaka marked this pull request as ready for review August 27, 2026 03:10
@mattwilkinsonn
mattwilkinsonn merged commit 984a4a4 into main Aug 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants