Documentation
¶
Overview ¶
cmd/celeste/permissions/checker.go
cmd/celeste/permissions/config.go
cmd/celeste/permissions/permission.go
cmd/celeste/permissions/rules.go
Index ¶
- func ExtractFirstStringArg(input map[string]any) string
- func MatchRule(rule Rule, toolName string, input map[string]any) bool
- func ParseToolPattern(pattern string) (toolName string, argGlob string)
- func SaveConfig(path string, config *PermissionConfig) error
- type CheckResult
- type Checker
- func (c *Checker) AddPersistentAllow(rule Rule) error
- func (c *Checker) AddPersistentDeny(rule Rule) error
- func (c *Checker) Check(tool ToolInfo, input map[string]any) CheckResult
- func (c *Checker) Mode() PermissionMode
- func (c *Checker) SetConfigPath(path string)
- func (c *Checker) SetPersistWarn(warn func(error))
- func (c *Checker) SetWorkspace(dir string)
- type Decision
- type PermissionConfig
- type PermissionMode
- type PrimaryArger
- type Rule
- type ToolInfo
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractFirstStringArg ¶
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 ¶
MatchRule returns true if the given tool invocation matches the rule's patterns.
The matching process:
- Parse ToolPattern into tool name and optional argument glob.
- Match tool name: exact match or "*" wildcard.
- 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.
- If InputPattern is set, JSON-serialize the input and match against it using filepath.Match.
- All applicable patterns must match for the rule to match.
func ParseToolPattern ¶
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:
- protected hook/trust files — best-effort Deny for shell commands
- alwaysDeny rules — if any match, return Deny immediately
- alwaysAllow rules — if any match, return Allow immediately, unless the rule is a bare tool name and an argument-scoped pattern deny or ask matches the call (the more specific rule wins)
- patternRules — if any match, return the rule's decision
- Mode fallthrough — default allows read-only tools and asks for the rest, strict asks for all, trust allows all
(Step 3, an early read-only allow, is gone: it ran before the pattern rules, so a pattern deny never applied to a read-only tool.)
func NewChecker ¶
func NewChecker(config PermissionConfig) *Checker
NewChecker creates a Checker from a PermissionConfig.
func (*Checker) AddPersistentAllow ¶
AddPersistentAllow appends an always-allow rule and, if a config path is set, adds it to the config on disk (see persistRule). 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 ¶
AddPersistentDeny appends an always-deny rule and, if a config path is set, adds it to the config on disk (see persistRule).
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 ¶
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.
func (*Checker) SetPersistWarn ¶
SetPersistWarn sets a function told when an always-allow or always-deny rule could not be saved to disk (the rule still applies in memory).
func (*Checker) SetWorkspace ¶
SetWorkspace sets the workspace a call's paths are relative to, so a path rule also matches a path spelled absolutely or through a symlink inside it (argMatches). Empty clears it.
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
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 PrimaryArger ¶
type PrimaryArger interface {
PrimaryArg() string
}
PrimaryArger is implemented by a ToolInfo that names the input field an argument-scoped rule ("write_file(src/*)") is matched against: the field the tool acts on (bash: command, the file tools: path).
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.