Skip to content

Commit 95f765b

Browse files
Remove concept of tool permissions
1 parent 9b07059 commit 95f765b

File tree

3 files changed

+38
-407
lines changed

3 files changed

+38
-407
lines changed

pkg/runtime/runtime.go

Lines changed: 36 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,39 +1335,18 @@ func (r *LocalRuntime) processToolCalls(ctx context.Context, sess *session.Sessi
13351335
//
13361336
// The approval flow considers (in order):
13371337
//
1338-
// 1. Session-level permissions (if configured) - checked first
1339-
// a. Per-tool settings (Tools map) - most specific, checked first
1340-
// b. Pattern-based Allow/Deny - broader rules, checked as fallback
1338+
// 1. Session-level permissions (if configured) - pattern-based Allow/Deny rules
13411339
// 2. Team-level permissions config - checked second
13421340
// 3. sess.ToolsApproved (--yolo flag) - auto-approve all
13431341
// 4. tool.Annotations.ReadOnlyHint - auto-approve read-only tools
13441342
// 5. Default: ask for user confirmation
13451343
//
1346-
// Example session permissions configurations:
1344+
// Example session permissions configuration:
13471345
//
1348-
// // Per-tool settings - granular control per tool
1349-
// sess.Permissions = &session.PermissionsConfig{
1350-
// Tools: map[string]session.ToolPermission{
1351-
// "shell": {Enabled: ptr(true), Mode: "ask"}, // require confirmation
1352-
// "filesystem": {Enabled: ptr(true), Mode: "always_allow"}, // auto-approve
1353-
// "dangerous": {Enabled: ptr(false)}, // disabled
1354-
// },
1355-
// }
1356-
//
1357-
// // Pattern-based rules - apply to multiple tools at once
13581346
// sess.Permissions = &session.PermissionsConfig{
13591347
// Allow: []string{"read_*", "think"}, // auto-approve matching tools
13601348
// Deny: []string{"shell", "exec_*"}, // block matching tools
13611349
// }
1362-
//
1363-
// // Mixed: per-tool settings take priority over patterns
1364-
// sess.Permissions = &session.PermissionsConfig{
1365-
// Tools: map[string]session.ToolPermission{
1366-
// "shell": {Enabled: ptr(true), Mode: "ask"}, // overrides Deny pattern
1367-
// },
1368-
// Allow: []string{"*"}, // applies to tools not in Tools map
1369-
// Deny: []string{"shell"}, // ignored for shell since it's in Tools map
1370-
// }
13711350
func (r *LocalRuntime) executeWithApproval(
13721351
ctx context.Context,
13731352
sess *session.Session,
@@ -1389,81 +1368,50 @@ func (r *LocalRuntime) executeWithApproval(
13891368
}
13901369
}
13911370

1392-
// requiresConfirmation tracks if per-tool settings require user confirmation
1393-
// (skipping pattern-based rules and other auto-approve checks)
1394-
requiresConfirmation := false
1395-
13961371
// 1. Check session-level permissions first (if configured)
13971372
if sess.Permissions != nil {
1398-
// 1a. Check Tools map first (new per-tool settings)
1399-
if perm := sess.Permissions.GetToolPermission(toolName); perm != nil {
1400-
// Check if tool is disabled
1401-
if !sess.Permissions.IsToolEnabled(toolName) {
1402-
slog.Debug("Tool disabled by session permissions", "tool", toolName, "session_id", sess.ID)
1403-
r.addToolErrorResponse(ctx, sess, toolCall, tool, events, a, fmt.Sprintf("Tool '%s' is disabled by session permissions.", toolName))
1404-
return false
1405-
}
1406-
// Check permission mode
1407-
mode := sess.Permissions.GetToolMode(toolName)
1408-
switch mode {
1409-
case session.PermissionModeAlwaysAllow:
1410-
slog.Debug("Tool auto-approved by session per-tool permissions", "tool", toolName, "mode", mode, "session_id", sess.ID)
1411-
runTool()
1412-
return false
1413-
case session.PermissionModeAsk:
1414-
default:
1415-
slog.Debug("Tool requires confirmation by session per-tool permissions ", "tool", toolName, "mode", mode, "session_id", sess.ID)
1416-
requiresConfirmation = true
1417-
}
1418-
}
1419-
1420-
// 1b. Fall back to pattern-based Allow/Deny rules (only if not already handled by Tools map)
1421-
if !requiresConfirmation {
1422-
sessionChecker := permissions.NewChecker(&latest.PermissionsConfig{
1423-
Allow: sess.Permissions.Allow,
1424-
Deny: sess.Permissions.Deny,
1425-
})
1426-
decision := sessionChecker.CheckWithArgs(toolName, toolArgs)
1427-
switch decision {
1428-
case permissions.Deny:
1429-
slog.Debug("Tool denied by session permissions", "tool", toolName, "session_id", sess.ID)
1430-
r.addToolErrorResponse(ctx, sess, toolCall, tool, events, a, fmt.Sprintf("Tool '%s' is denied by session permissions.", toolName))
1431-
return false
1432-
case permissions.Allow:
1433-
slog.Debug("Tool auto-approved by session permissions", "tool", toolName, "session_id", sess.ID)
1434-
runTool()
1435-
return false
1436-
case permissions.Ask:
1437-
// Fall through to team permissions
1438-
}
1373+
sessionChecker := permissions.NewChecker(&latest.PermissionsConfig{
1374+
Allow: sess.Permissions.Allow,
1375+
Deny: sess.Permissions.Deny,
1376+
})
1377+
decision := sessionChecker.CheckWithArgs(toolName, toolArgs)
1378+
switch decision {
1379+
case permissions.Deny:
1380+
slog.Debug("Tool denied by session permissions", "tool", toolName, "session_id", sess.ID)
1381+
r.addToolErrorResponse(ctx, sess, toolCall, tool, events, a, fmt.Sprintf("Tool '%s' is denied by session permissions.", toolName))
1382+
return false
1383+
case permissions.Allow:
1384+
slog.Debug("Tool auto-approved by session permissions", "tool", toolName, "session_id", sess.ID)
1385+
runTool()
1386+
return false
1387+
case permissions.Ask:
1388+
// Fall through to team permissions
14391389
}
14401390
}
14411391

1442-
// 2. Check team-level permissions config (skip if per-tool ask mode is set)
1443-
if !requiresConfirmation {
1444-
if permChecker := r.team.Permissions(); permChecker != nil {
1445-
decision := permChecker.CheckWithArgs(toolName, toolArgs)
1446-
switch decision {
1447-
case permissions.Deny:
1448-
slog.Debug("Tool denied by team permissions config", "tool", toolName, "session_id", sess.ID)
1449-
r.addToolErrorResponse(ctx, sess, toolCall, tool, events, a, fmt.Sprintf("Tool '%s' is denied by permissions configuration.", toolName))
1450-
return false
1451-
case permissions.Allow:
1452-
slog.Debug("Tool auto-approved by team permissions config", "tool", toolName, "session_id", sess.ID)
1453-
runTool()
1454-
return false
1455-
case permissions.Ask:
1456-
// Fall through to normal approval flow
1457-
}
1458-
}
1459-
1460-
// Check --yolo flag or read-only hint (skip if per-tool ask mode is set)
1461-
if sess.ToolsApproved || tool.Annotations.ReadOnlyHint {
1392+
// 2. Check team-level permissions config
1393+
if permChecker := r.team.Permissions(); permChecker != nil {
1394+
decision := permChecker.CheckWithArgs(toolName, toolArgs)
1395+
switch decision {
1396+
case permissions.Deny:
1397+
slog.Debug("Tool denied by team permissions config", "tool", toolName, "session_id", sess.ID)
1398+
r.addToolErrorResponse(ctx, sess, toolCall, tool, events, a, fmt.Sprintf("Tool '%s' is denied by permissions configuration.", toolName))
1399+
return false
1400+
case permissions.Allow:
1401+
slog.Debug("Tool auto-approved by team permissions config", "tool", toolName, "session_id", sess.ID)
14621402
runTool()
14631403
return false
1404+
case permissions.Ask:
1405+
// Fall through to normal approval flow
14641406
}
14651407
}
14661408

1409+
// 3. Check --yolo flag or read-only hint
1410+
if sess.ToolsApproved || tool.Annotations.ReadOnlyHint {
1411+
runTool()
1412+
return false
1413+
}
1414+
14671415
// Ask user for confirmation
14681416
slog.Debug("Tools not approved, waiting for resume", "tool", toolCall.Function.Name, "session_id", sess.ID)
14691417
events <- ToolCallConfirmation(toolCall, tool, a.Name())

0 commit comments

Comments
 (0)