policy

package
v0.0.1-alpha.2 Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package policy implements the PolicyGate port (ADR-0007). Local mode uses allow/ask/deny rules; server mode verifies an ES256 claim from a control plane. Rules support glob matching on tool name and path argument, with last-match-wins ordering. Ask decisions are resolved by an injected Prompter (with the caller's context deadline acting as the forced-ask timeout); when no Prompter is wired, Ask safely degrades to Deny.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AllowAll

type AllowAll struct{}

AllowAll is a scaffold gate that permits everything. Equivalent to --dangerously-skip-permissions with no rules layered on top — use only in tests and local scaffolding, never as a shipped default.

func (AllowAll) Permit

func (AllowAll) Permit(ctx context.Context, call ports.ToolCall) (Decision, error)

type Decision

type Decision int
const (
	Allow Decision = iota
	Ask
	Deny
)

func ParseDecision

func ParseDecision(s string) (Decision, error)

ParseDecision parses an allow/ask/deny string (case-insensitive).

type DenyList

type DenyList struct {
	Denied map[string]bool
}

DenyList denies any tool call whose name is in Denied, allows everything else. A minimal, illustrative precursor to the full rule engine.

func (DenyList) Permit

func (d DenyList) Permit(ctx context.Context, call ports.ToolCall) (Decision, error)

type Gate

type Gate interface {
	Permit(ctx context.Context, call ports.ToolCall) (Decision, error)
}

Gate is the port the agent loop calls before executing any tool call.

type Prompter

type Prompter interface {
	Ask(ctx context.Context, call ports.ToolCall) (bool, error)
}

Prompter asks an operator to approve an Ask decision. The context carries the forced-ask timeout (deadline). Implementations are UI seams (T-031 TUI).

type Prompting

type Prompting struct {
	Rules    *Rules
	Prompter Prompter // optional; nil → Ask becomes Deny
}

Prompting wraps a Rules engine with a Prompter, resolving Ask decisions interactively. It implements Gate. When Prompter is nil, Ask safely degrades to Deny (never silently allow).

func (Prompting) Permit

func (p Prompting) Permit(ctx context.Context, call ports.ToolCall) (Decision, error)

Permit delegates to Rules; on Ask it calls Prompter (if present) within ctx. A prompter denial or a ctx timeout yields Deny + the wrapped error.

type Rule

type Rule struct {
	ToolGlob string // glob against the tool name; "" matches any
	PathGlob string // glob against a path argument; "" matches any/no path
	Decision Decision
}

Rule is one permission rule. A call matches if the tool name matches ToolGlob (empty = any tool) AND a path argument, if the rule specifies one, matches PathGlob (empty = any/no path). Rules are evaluated in list order; the last matching rule wins.

type Rules

type Rules struct {
	Default Decision // decision when no rule matches
	List    []Rule
}

Rules is the rule engine. It implements Gate.

func NewRules

func NewRules(def Decision, toolRules, pathRules map[string]string) (*Rules, error)

NewRules builds a deterministic Rules from decision maps: tool rules first (sorted by key), then path rules (sorted by key) — so path rules win over tool rules when both apply, via last-match-wins. Returns an error if any decision string is unrecognized.

func (Rules) Permit

func (r Rules) Permit(ctx context.Context, call ports.ToolCall) (Decision, error)

Permit evaluates List against the call, last-match-wins, falling back to Default. It never returns an error for the rule match itself; Prompting (below) layers prompt resolution on top.

type Skip

type Skip struct {
	Rules *Rules
}

Skip implements --dangerously-skip-permissions (T-024): an allow-all base where explicit rules still win, and prompts are skipped (Ask becomes Allow). It wraps a Rules engine whose Default is forced to Allow. Explicit Deny rules still deny; explicit Ask rules do not block. Use only for local/trusted runs.

func NewSkip

func NewSkip(toolRules, pathRules map[string]string) (*Skip, error)

NewSkip builds a Skip gate from explicit rules over an allow-all base. Tool rules are evaluated first, then path rules (last-match-wins), so an explicit path deny still overrides the base. Returns an error on unknown decisions.

func (Skip) Permit

func (s Skip) Permit(ctx context.Context, call ports.ToolCall) (Decision, error)

Permit returns the rule decision with Ask promoted to Allow, over an allow-all base.

Jump to

Keyboard shortcuts

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