Files
pi-extensions/docs/adr/0001-recover-full-bash-command-from-session.md
T
SikongJueluo 24153412c9 feat(pi-permission-inner-cmd): authorize inner commands behind timeout wrappers
- recover the full bash command from the session by tool-call id
- add recognizer for the strict timeout wrapper grammar
- add authorizer mapping inner allow/ask/deny and forwarding agent name
- defer fail-closed on session mismatch, nested wrappers, and errors
- add unit tests for recovery, recognizer, authorizer, and lifecycle
- document the decision in ADR 0001
2026-08-11 16:33:08 +08:00

2.8 KiB

status
status
accepted

Recover the full Bash command from the Pi session

pi-permission-inner-cmd needs the complete Bash input before it may allow a transparent wrapper. @gotgenes/pi-permission-system exposes only the winning command unit as details.command; for timeout 60s pnpm test && git push, that may be timeout 60s pnpm test. An Authorizer allow approves the whole tool call, so unwrapping that unit alone could hide a sibling command.

Decision

For direct calls to Pi's native bash tool, capture the session manager at session_start. During authorization, use details.toolCallId to find exactly one matching assistant toolCall block in the current session and read its structured arguments.command value.

Proceed only when all evidence agrees:

  • the request and recovered tool call both identify the native bash tool;
  • the tool-call ID has exactly one match;
  • arguments.command is a string;
  • the complete input matches the strict wrapper grammar;
  • the inner command is not another recognized wrapper.

V0.1 recognizes only:

^timeout[ \t]+([1-9][0-9]*[smhd])[ \t]+(.+)$

The complete inner command is re-evaluated through the Deterministic Permission Policy. Map allow to allow, deny to deny, and ask to defer. Missing or ambiguous session evidence, forwarded requests, shell aliases, unsupported timeout options, nested wrappers, parse failures, and exceptions all produce defer.

Consequences

This avoids changing permission-system and avoids parsing authorization evidence from the human-facing details.message. It deliberately supports fewer contexts: forwarded and non-native shell calls continue through the existing authority chain.

The implementation must retain regression tests for:

  • inner allow, ask, and deny mapping;
  • compound input such as timeout 60s pnpm test && git push;
  • unsupported and nested wrapper syntax;
  • missing, duplicate, malformed, and forwarded session evidence;
  • Authorizer registration and disposal.

The end-to-end experiment confirmed that permission-system checks every Bash command unit but invokes the Authorizer once for the aggregated ask; an Authorizer allow then releases the complete tool call. See context ownership and minimal Bash judgment evidence for the underlying permission and evidence boundaries.

Rejected alternatives

  • Treat details.command as the full input: unsafe for compound Bash programs.
  • Parse details.message: fail-closed parsing is possible but couples authorization to UI prose.
  • Add a permission-system API: structurally clean, but would make this package depend on an unavailable upstream change.
  • Maintain a safe-command allowlist: duplicates policy and violates the re-evaluation invariant.