Skip to content

[Critical] Implement Permission Rules System #17

@marklicata

Description

@marklicata

Summary

Implement a comprehensive permission rules system that controls what tools can do, with pattern-based allow/deny rules and permission modes.

Current State

Amplifier CLI has basic approval hooks but lacks:

  • Granular rule-based permissions
  • Pattern matching for paths/commands
  • Permission modes (plan, acceptEdits, full bypass)
  • Persistent permission decisions

Proposed Implementation

1. Permission Rules Configuration

Add to profile YAML:

permissions:
  # Path-based rules
  allow:
    - "Read:~/**"                    # Read anything in home
    - "Write:~/projects/current/**"  # Write to current project
    - "Bash(git *)"                  # Git commands allowed
    
  deny:
    - "Write:~/.ssh/**"             # Never touch SSH keys
    - "Write:**/.env*"              # Never modify env files
    - "Bash(rm -rf *)"              # No recursive force delete
    - "Bash(curl * | bash)"         # No pipe to bash

2. Permission Modes

permissions:
  mode: "prompt"  # Options: "plan", "prompt", "acceptEdits", "bypass"
Mode Behavior
plan AI can only describe changes, never execute
prompt Ask user for each action (default)
acceptEdits Auto-approve file edits, prompt for bash
bypass Trust all (for CI/automation with --dangerously-skip-permissions)

3. New Module: src/amplifier_app_cli/permissions/

permissions/
├── __init__.py
├── rules.py          # Rule parsing and matching
├── matcher.py        # Glob/regex pattern matching
├── modes.py          # Permission mode logic
├── evaluator.py      # Main permission evaluation
└── persistent.py     # Remember decisions for session

4. Core Interfaces

@dataclass
class PermissionRule:
    action: Literal["allow", "deny"]
    tool: str                    # Tool name or "*"
    pattern: str | None          # Glob pattern for args
    reason: str | None           # Why this rule exists

@dataclass  
class PermissionDecision:
    allowed: bool
    rule_matched: PermissionRule | None
    requires_prompt: bool
    cached: bool                 # From previous decision

class PermissionEvaluator(Protocol):
    def evaluate(
        self, 
        tool_name: str, 
        tool_args: dict[str, Any],
        context: PermissionContext
    ) -> PermissionDecision: ...

5. Integration Points

  1. Hook into approval system: Replace or augment ApprovalSystem protocol
  2. Config loading: Extend amplifier-config schema for permissions
  3. CLI flags: Add --permission-mode, --allow, --deny, --dangerously-skip-permissions

6. CLI Flags to Add

amplifier run -p "task" \
  --permission-mode acceptEdits \
  --allow "Bash(npm *)" \
  --deny "Write:**/package-lock.json"

# Dangerous mode for CI (requires explicit flag)
amplifier run -p "task" --dangerously-skip-permissions

Acceptance Criteria

  • Permission rules can be defined in profile YAML
  • Glob patterns work for paths (**/*.py, ~/projects/**)
  • Regex patterns work for bash commands
  • Four permission modes implemented (plan, prompt, acceptEdits, bypass)
  • Deny rules take precedence over allow rules
  • Session can remember "allow for this session" decisions
  • CLI flags override profile settings
  • --dangerously-skip-permissions requires explicit opt-in
  • Unit tests for pattern matching
  • Integration tests for permission flow

Related

  • Depends on: None (foundational)
  • Blocks: Enhanced Hooks System (hooks need permission checks)

Estimated Effort

High - 2-3 weeks

Files to Create/Modify

  • src/amplifier_app_cli/permissions/ (new module)
  • src/amplifier_app_cli/lib/paths.py (factory function)
  • src/amplifier_app_cli/commands/run.py (CLI flags)
  • src/amplifier_app_cli/ui/approval.py (integration)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions