permissions

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 5, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

cmd/celeste/permissions/checker.go

cmd/celeste/permissions/config.go

cmd/celeste/permissions/denial.go

cmd/celeste/permissions/permission.go

cmd/celeste/permissions/rules.go

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultConfigPath

func DefaultConfigPath() string

DefaultConfigPath returns the default path for the permissions config file.

func ExtractFirstStringArg

func ExtractFirstStringArg(input map[string]any) string

ExtractFirstStringArg extracts the primary string argument from a tool input map. It checks keys in priority order: "command", "path", then returns the first string value found by iterating the map.

func MatchRule

func MatchRule(rule Rule, toolName string, input map[string]any) bool

MatchRule returns true if the given tool invocation matches the rule's patterns.

The matching process:

  1. Parse ToolPattern into tool name and optional argument glob.
  2. Match tool name: exact match or "*" wildcard.
  3. If argument glob is present, extract the first string argument from input (checking "command", then "path", then first string value found) and match using filepath.Match semantics.
  4. If InputPattern is set, JSON-serialize the input and match against it using filepath.Match.
  5. All applicable patterns must match for the rule to match.

func ParseToolPattern

func ParseToolPattern(pattern string) (toolName string, argGlob string)

ParseToolPattern splits a tool pattern into the tool name and an optional argument glob. For example:

"bash(git *)" -> ("bash", "git *")
"read_file"   -> ("read_file", "")
"*"           -> ("*", "")

func SaveConfig

func SaveConfig(path string, config *PermissionConfig) error

SaveConfig writes a PermissionConfig to disk as formatted JSON. Parent directories are created if they don't exist.

Types

type CheckResult

type CheckResult struct {
	// Decision is the final permission decision.
	Decision Decision

	// MatchedRule is the rule that produced this decision, if any.
	// Nil when the decision comes from mode fallthrough.
	MatchedRule *Rule

	// Reason is a human-readable explanation of why this decision was made.
	Reason string
}

CheckResult is the outcome of running an input through the permission checker.

func (CheckResult) IsAllowed

func (cr CheckResult) IsAllowed() bool

IsAllowed returns true if the tool execution is permitted.

func (CheckResult) IsDenied

func (cr CheckResult) IsDenied() bool

IsDenied returns true if the tool execution is blocked.

func (CheckResult) NeedsPrompt

func (cr CheckResult) NeedsPrompt() bool

NeedsPrompt returns true if the user must be prompted for approval.

type Checker

type Checker struct {
	// contains filtered or unexported fields
}

Checker evaluates whether a tool execution should be allowed, denied, or requires user approval. It implements a 5-step evaluation chain:

  1. alwaysDeny rules — if any match, return Deny immediately
  2. alwaysAllow rules — if any match, return Allow immediately
  3. IsReadOnly check — in default mode, read-only tools are auto-allowed
  4. patternRules — if any match, return the rule's decision
  5. Mode fallthrough — default asks for writes, strict asks for all, trust allows all

func NewChecker

func NewChecker(config PermissionConfig) *Checker

NewChecker creates a Checker from a PermissionConfig.

func (*Checker) AddPersistentAllow added in v1.10.0

func (c *Checker) AddPersistentAllow(rule Rule) error

AddPersistentAllow appends an always-allow rule and, if a config path is set, saves the updated config to disk. The in-memory mutation happens under the lock; disk I/O happens after releasing it so that concurrent Check() calls are not blocked.

func (*Checker) AddPersistentDeny added in v1.10.0

func (c *Checker) AddPersistentDeny(rule Rule) error

AddPersistentDeny appends an always-deny rule and, if a config path is set, saves the updated config to disk. The in-memory mutation happens under the lock; disk I/O happens after releasing it so that concurrent Check() calls are not blocked.

func (*Checker) Check

func (c *Checker) Check(tool ToolInfo, input map[string]any) CheckResult

Check evaluates whether the given tool invocation is permitted.

The tool parameter provides tool metadata (name, read-only status). The input parameter contains the tool's input arguments.

If tool is nil, it is treated as a non-read-only tool with an empty name.

func (*Checker) Mode

func (c *Checker) Mode() PermissionMode

Mode returns the current permission mode.

func (*Checker) SetConfigPath added in v1.10.0

func (c *Checker) SetConfigPath(path string)

SetConfigPath sets the file path used to persist rule additions from interactive prompts (always_allow / always_deny decisions). If unset, AddPersistentAllow and AddPersistentDeny still update the in-memory rule lists but skip disk writes.

type Decision

type Decision int

Decision represents the outcome of a permission check.

const (
	// Allow means the tool execution is permitted without user interaction.
	Allow Decision = iota
	// Deny means the tool execution is blocked.
	Deny
	// Ask means the user must be prompted for approval.
	Ask
)

func (Decision) String

func (d Decision) String() string

String returns the human-readable name of the decision.

type DenialTracker

type DenialTracker struct {
	// contains filtered or unexported fields
}

DenialTracker tracks tool execution denials within a session. It is safe for concurrent use.

func NewDenialTracker

func NewDenialTracker() *DenialTracker

NewDenialTracker creates a new DenialTracker.

func (*DenialTracker) GetDenialCount

func (dt *DenialTracker) GetDenialCount(toolName string) int

GetDenialCount returns the number of denials recorded for a specific tool.

func (*DenialTracker) GetTotalDenials

func (dt *DenialTracker) GetTotalDenials() int

GetTotalDenials returns the total number of denials across all tools.

func (*DenialTracker) RecordDenial

func (dt *DenialTracker) RecordDenial(toolName string)

RecordDenial records a denial for the given tool.

func (*DenialTracker) Reset

func (dt *DenialTracker) Reset()

Reset clears all denial tracking data.

func (*DenialTracker) ResetTool

func (dt *DenialTracker) ResetTool(toolName string)

ResetTool clears denial tracking data for a specific tool.

func (*DenialTracker) ShouldSuggestRule

func (dt *DenialTracker) ShouldSuggestRule(toolName string) bool

ShouldSuggestRule returns true if the user has denied the given tool enough times (3+) that the system should suggest adding a permanent deny rule to their config.

func (*DenialTracker) ShouldSuggestStrictMode

func (dt *DenialTracker) ShouldSuggestStrictMode() bool

ShouldSuggestStrictMode returns true if the total denials across all tools have reached the threshold (5+) where suggesting strict mode would be appropriate.

type PermissionConfig

type PermissionConfig struct {
	// Mode is the default permission mode (default, strict, trust).
	Mode PermissionMode `json:"mode"`

	// AlwaysAllow is a list of rules that are always permitted regardless of mode.
	AlwaysAllow []Rule `json:"always_allow,omitempty"`

	// AlwaysDeny is a list of rules that are always blocked regardless of mode.
	AlwaysDeny []Rule `json:"always_deny,omitempty"`

	// PatternRules are evaluated after alwaysDeny and alwaysAllow but before
	// mode fallthrough. They allow fine-grained control over specific tool/input
	// combinations.
	PatternRules []Rule `json:"pattern_rules,omitempty"`
}

PermissionConfig holds the persistent permission configuration. Stored at ~/.celeste/permissions.json.

func DefaultConfig

func DefaultConfig() PermissionConfig

DefaultConfig returns a PermissionConfig with sensible defaults:

  • Mode: default (auto-allow reads, ask for writes)
  • AlwaysDeny: sudo and su commands
  • AlwaysAllow: read_file, list_files, search_files

func LoadConfig

func LoadConfig(path string) (*PermissionConfig, error)

LoadConfig reads a PermissionConfig from disk. If the file does not exist, it returns DefaultConfig() without error. If the file exists but contains invalid JSON or an unrecognized mode, it returns an error.

type PermissionMode

type PermissionMode string

PermissionMode controls the default behavior when no explicit rule matches.

const (
	// ModeDefault auto-allows read-only tools, asks for writes.
	ModeDefault PermissionMode = "default"
	// ModeStrict asks the user for every tool invocation.
	ModeStrict PermissionMode = "strict"
	// ModeTrust auto-allows everything (current behavior pre-v1.7).
	ModeTrust PermissionMode = "trust"
)

func ParsePermissionMode

func ParsePermissionMode(s string) (PermissionMode, error)

ParsePermissionMode parses a string into a PermissionMode. Matching is case-insensitive.

func (PermissionMode) String

func (m PermissionMode) String() string

String returns the mode as a string.

func (PermissionMode) Valid

func (m PermissionMode) Valid() bool

Valid returns true if the mode is one of the recognized values.

type Rule

type Rule struct {
	// ToolPattern is the pattern to match against tool name and optionally its input.
	ToolPattern string `json:"tool_pattern"`

	// InputPattern is an optional glob matched against JSON-serialized input.
	InputPattern string `json:"input_pattern,omitempty"`

	// Decision is the action to take when this rule matches.
	Decision Decision `json:"decision"`
}

Rule defines a permission rule that matches a tool invocation pattern.

ToolPattern supports:

  • Exact tool name match: "read_file"
  • Tool name with argument glob: "bash(git *)" — matches tool "bash" when the first string argument (typically "command") matches the glob "git *"
  • Wildcard tool: "*" — matches any tool

InputPattern is an optional secondary pattern that matches against the JSON-serialized input. When empty, only ToolPattern is evaluated.

type ToolInfo

type ToolInfo interface {
	ToolName() string
	IsReadOnly() bool
}

ToolInfo is the minimal interface the Checker needs from a tool. This avoids importing the tools package (preventing circular dependencies). The tools.Tool interface satisfies this via its Name() and IsReadOnly() methods.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL