Skip to content

Add global-level permissions from user config#2230

Draft
trungutt wants to merge 1 commit intodocker:mainfrom
trungutt:feat/global-permissions
Draft

Add global-level permissions from user config#2230
trungutt wants to merge 1 commit intodocker:mainfrom
trungutt:feat/global-permissions

Conversation

@trungutt
Copy link
Contributor

@trungutt trungutt commented Mar 24, 2026

Summary

Closes #52

Adds a permissions field to the user config (~/.config/cagent/config.yaml) so users can define permission patterns that apply across all sessions and agents as user-wide defaults, without having to reconfigure each session.

Configuration

Add a permissions block under settings in your user config:

# ~/.config/cagent/config.yaml
version: v1
settings:
  permissions:
    allow:
      - "read_*"
      - "list_directory"
      - "shell:cmd=git*"
      - "shell:cmd=ls*"
      - "mcp:github:*"
    deny:
      - "shell:cmd=rm*"
      - "shell:cmd=sudo*"
    ask:
      - "shell:cmd=docker*"

This uses the same pattern syntax as agent-level permissions — globs, argument matching (shell:cmd=git*), and MCP-qualified names (mcp:server:tool) all work.

How it works

Global patterns are merged into the team's permission checker before the runtime is created (run.go), using permissions.Merge(). The runtime receives a single pre-merged checker and has no concept of "global" — it just sees team permissions as before.

The merged checker evaluates all deny patterns first (from both team and global), then all allow patterns, then all ask patterns. This means:

  • A deny from either source blocks the tool (most secure)
  • An allow from either source auto-approves the tool
  • Session permissions still override everything (evaluated separately by the runtime)

Changes

  • pkg/userconfig/userconfig.go — add Permissions *latest.PermissionsConfig to Settings
  • pkg/permissions/permissions.go — add Merge() function to combine multiple checkers
  • pkg/team/team.go — add SetPermissions() to allow post-construction updates
  • cmd/root/run.go — load global permissions, merge into team, pass to runtime
  • pkg/permissions/permissions_test.go — tests for Merge()
  • pkg/userconfig/userconfig_test.go — YAML round-trip test

@trungutt trungutt changed the title feat: add global-level permissions from user config Add global-level permissions from user config Mar 24, 2026
@trungutt
Copy link
Contributor Author

/review

// WithGlobalPermissions sets user-level permission patterns loaded from the
// user config (~/.config/cagent/config.yaml). These are evaluated after session
// and team permissions in the approval cascade, acting as user-wide defaults.
func WithGlobalPermissions(checker *permissions.Checker) Opt {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the runtime needs to know that global permissions exist, the runtime should just get a permissions checker that is already merged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — reworked. Global patterns are now merged into the team's checker in run.go before the runtime is created (permissions.Merge() + team.SetPermissions()). The runtime has no concept of "global" and receives a single pre-merged checker.

Copy link

@docker-agent docker-agent bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: 🟢 APPROVE

This PR correctly implements global-level permissions from user config. The code is well-structured with proper nil checks and comprehensive test coverage.

Key strengths:

  • Proper permission cascade: Session → Team → Global → ReadOnlyHint → Ask
  • Safe nil handling throughout (checks before creating options, checks before accessing fields)
  • Comprehensive test coverage (7 new tests covering deny, allow, cascade priority, YOLO override, and merging)
  • Clear documentation in comments

Verified:

  • No nil pointer dereferences (all accesses properly guarded)
  • Permission cascade logic is correct and matches documentation
  • Global permissions are properly integrated into the runtime via options pattern
  • Tests validate all priority scenarios

The implementation follows Go best practices and the project's existing patterns.

@trungutt trungutt force-pushed the feat/global-permissions branch from 733673b to f7d632b Compare March 24, 2026 19:50
Allow users to define permission patterns in ~/.config/cagent/config.yaml
that apply across all sessions and agents as user-wide defaults.

Global patterns are merged into the team's permission checker before the
runtime is created, so the runtime receives a single pre-merged set.
@trungutt trungutt force-pushed the feat/global-permissions branch from f7d632b to 1fe3f42 Compare March 24, 2026 20:01
@trungutt
Copy link
Contributor Author

/review

@docker-agent
Copy link

docker-agent bot commented Mar 24, 2026

Assessment: 🟢 APPROVE

No bugs found in the changed code. The implementation correctly:

  • Loads global permissions from user config
  • Merges them with team permissions using the new Merge() function
  • Handles nil checkers appropriately
  • Creates fresh team instances for each runtime/session

The permission merge logic is sound and follows Go best practices.

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.

[FEAT] - Add abort (or skip) option to the tool execution confirmation

2 participants