The access policy never reaches a custom argument formatter
- Status: Todo
- Kind: Bug
- Authors: jp
- Date: 2026-09-04
- Implements: 076
- Label: package=jp_cli
- Label: package=jp_tool
- Label: type=bug
A local tool with style.parameters = "<command>" runs that command with a Context whose access field is absent, so it deserializes as None — indistinguishable from "this tool has no access grants".
format_args_custom builds the context JSON by hand (crates/jp_cli/src/render/tool.rs:812-823) with action, root, workspace_id, and conversation_id, and nothing else. The Run path does plumb the compiled policy (execute_local takes access: Option<&jp_tool::AccessPolicy>, crates/jp_llm/src/tool.rs:832), so the same tool binary sees its grants for one action and not the other.
RFD 076 Phase 3 covers both halves and only one shipped:
Include access policy in the JSON context passed to tool commands in
execute_local()and theFormatArgumentspath.
What this is not
Enforcement is cooperative. run_tool_command never clears the environment (crates/jp_llm/src/tool.rs:461), so a local tool binary can read any variable with std::env::var on either path, policy or no policy. Passing the policy to the formatter does not create a boundary that isn't there on the Run path.
The defect is narrower and worth fixing on its own terms: a tool author who wants their formatter to honour the grants it was given has no way to read them. A formatter that renders a preview of what a call will touch cannot say "this variable is denied" without them.
Scope
- Compile the policy once and pass it into both context constructions, rather than compiling it twice with two chances to diverge.
- A test covering both
Action::RunandAction::FormatArgumentson one tool with one policy, asserting theaccessfield is present and equal in both.
Predates access.env: access.fs has had the same gap since ab94ec0a (#727).