policy

package
v0.8.19 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package policy evaluates immutable, side-effect-free automation rules for semantic agent events. It deliberately does not encode or deliver a decision: callers must fall back to a human whenever an adapter cannot represent the proposed action or a delivery fails.

Package policy evaluates immutable, side-effect-free automation rules for semantic agent events. It deliberately does not encode or deliver a decision: callers must fall back to a human whenever an adapter cannot represent the proposed action or a delivery fails.

Index

Constants

View Source
const (
	ReasonSensitivePath    = "sensitive_path_blocked"
	ReasonOutsideWorkspace = "outside_workspace_blocked"
)
View Source
const (
	ReasonDefault          = "default_action"
	ReasonRule             = "rule_match"
	ReasonInvalidEvent     = "invalid_event"
	ReasonNonActionable    = "non_actionable"
	ReasonSensitive        = "sensitive_event"
	ReasonRisk             = "risk_not_low"
	ReasonDryRun           = "dry_run"
	ReasonNoEngine         = "engine_unavailable"
	ReasonConsecutiveLimit = "consecutive_auto_limit"
	ReasonRateLimit        = "rate_limit_exceeded"
	ReasonDestructive      = "destructive_command_blocked"
	ReasonExfiltration     = "exfiltration_attempt_blocked"
	ReasonGuardrailBlocked = "guardrail_pattern_blocked"
)

Static evaluation reasons are safe to expose in logs. They never contain event text, regex matches, metadata, or other terminal output.

Variables

This section is empty.

Functions

func ContainsSensitivePathReference added in v0.3.0

func ContainsSensitivePathReference(text string) bool

ContainsSensitivePathReference returns true if the raw text contains explicit references to known sensitive filenames or paths.

func ExtractPaths added in v0.3.0

func ExtractPaths(text string) []string

ExtractPaths extracts candidate file or directory paths from a shell command line or text.

func IsPathInsideWorkspace added in v0.3.0

func IsPathInsideWorkspace(candidatePath string, workspaceRoot string) bool

IsPathInsideWorkspace determines whether candidatePath resides within workspaceRoot. Returns false if candidatePath attempts to escape workspaceRoot (via ../ or outside absolute paths).

func IsReadOnlyCommand added in v0.3.0

func IsReadOnlyCommand(command string) bool

IsReadOnlyCommand determines if a shell command line is guaranteed to be a read-only query or test execution that does not modify the filesystem or execute arbitrary code.

func IsRootedPath added in v0.8.6

func IsRootedPath(p string) bool

IsRootedPath reports whether p is absolute, or rooted without a volume (\dir on Windows), and so must not be resolved against another directory.

func IsSensitivePath added in v0.3.0

func IsSensitivePath(path string) bool

IsSensitivePath returns true if the specified file or directory path matches known sensitive security credentials, private keys, environment secrets, or critical system files.

func PresetSettings added in v0.8.6

func PresetSettings() map[string]Settings

PresetSettings returns what an editor should fill in when the user picks each preset. They come from ProfileConfig, so the form and the loader agree on what "strict" means. WorkspaceRoot is left empty: picking a preset does not move the workspace.

Types

type Action

type Action string

Action is the outcome selected by the policy engine.

const (
	ActionAllow Action = "allow"
	ActionAsk   Action = "ask"
	ActionDeny  Action = "deny"
)

type Config

type Config struct {
	DefaultAction               Action
	DryRun                      bool
	MaxConsecutiveAutoDecisions int
	RateLimitPerMinute          int
	Guardrails                  GuardrailsConfig
	Rules                       []Rule
}

Config describes the ordered rules evaluated by an Engine.

func ApplySettings added in v0.8.6

func ApplySettings(existing Config, settings Settings, configDir string) (Config, error)

ApplySettings returns existing with an editor's settings applied.

It always starts from existing, so rules and blocked patterns survive a save that did not touch them; v0.8.5 started from a preset and dropped both. The preset's rules replace the existing ones only when the editor explicitly switched to a different preset. Blocked patterns are kept even then: they only ever block more.

The limits are taken as given, zero included, which means unlimited; v0.8.5 ignored zero, so a limit could never be removed and saving the default configuration raised it to 10 and 1. A workspace root is filled in only when the outside-workspace guardrail needs one, and is always made absolute against configDir: a relative root never matched an absolute path.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig preserves Relayer's human-in-the-loop behavior.

func ProfileConfig added in v0.3.0

func ProfileConfig(profile Profile, workspaceRoot string) Config

ProfileConfig generates the base policy configuration for the chosen profile. The caller may override or append individual settings afterwards.

type Engine

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

Engine is immutable after construction and safe for concurrent evaluation.

func New

func New(config Config) (*Engine, error)

New validates and defensively copies a policy configuration. Regexes are compiled once so Evaluate remains deterministic and allocation-light.

func (*Engine) Config

func (e *Engine) Config() Config

Config returns a deep copy that cannot mutate the engine.

func (*Engine) Evaluate

func (e *Engine) Evaluate(event adapters.Event) Evaluation

Evaluate applies the first matching rule without mutating either the engine or event. Invalid and non-actionable events can never become automatic.

type Evaluation

type Evaluation struct {
	Action         Action
	ProposedAction Action
	RuleName       string
	Reason         string
	EventID        string
	Automatic      bool
	DryRun         bool
}

Evaluation separates the configured proposal from the effective action. Sensitive events and dry-run configurations retain ProposedAction for a safe audit record while forcing ActionAsk and disabling automation.

type GuardrailsConfig

type GuardrailsConfig struct {
	BlockDestructive      bool
	BlockExfiltration     bool
	BlockSensitivePaths   bool
	BlockOutsideWorkspace bool
	WorkspaceRoot         string
	BlockedPatterns       []string
}

GuardrailsConfig defines safety boundaries that prevent autonomous execution of high-risk actions even when a policy rule would otherwise allow them.

type Match

type Match struct {
	EventTypes   []adapters.EventType
	TextRegex    string
	AgentIDs     []string
	RiskLevels   []adapters.RiskLevel
	Sensitive    *bool
	CommandRegex string
	PathRegex    string
	ReadOnly     *bool
}

Match combines fields with AND semantics. Values inside each list use OR semantics. TextRegex is evaluated against Summary + "\n" + Match but that text is never retained by Engine or copied into Evaluation.

type Profile added in v0.3.0

type Profile string

Profile identifies a predefined security and automation stance.

const (
	ProfileStrict            Profile = "strict"
	ProfileDeveloperFriendly Profile = "developer-friendly"
	ProfilePermissive        Profile = "permissive"
	ProfileCustom            Profile = "custom"
)

func ParseProfile added in v0.3.0

func ParseProfile(name string) (Profile, error)

ParseProfile parses a profile name string into a validated Profile constant. It accepts common aliases (e.g. dev-friendly, developer).

type Rule

type Rule struct {
	Name   string
	Match  Match
	Action Action
}

Rule applies Action when every populated Match field accepts an event. Rules are evaluated in order and the first match wins.

type Settings added in v0.8.6

type Settings struct {
	Profile                     string
	DefaultAction               string
	DryRun                      bool
	BlockDestructive            bool
	BlockExfiltration           bool
	BlockSensitivePaths         bool
	BlockOutsideWorkspace       bool
	WorkspaceRoot               string
	RateLimitPerMinute          int
	MaxConsecutiveAutoDecisions int
}

Settings is the part of a Config the settings editors show and change. The web gateway and the Desktop GUI both convert to and from it, so the two cannot drift into different ideas of what saving a form does.

Everything a Config holds that is not listed here — the rules and the guardrail blocked_patterns — is carried through a save unchanged.

func SettingsFrom added in v0.8.6

func SettingsFrom(cfg Config) Settings

SettingsFrom describes cfg for an editor.

Profile names a preset only when cfg is exactly that preset, apart from the dry-run toggle, the workspace path and any blocked patterns, none of which a preset sets. Anything else is "custom". Earlier releases guessed: any "ask" configuration without rules was called strict — the built-in default, with every guardrail off and no limits, included — and a save then rebuilt the configuration from the guessed preset.

type Tracker

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

Tracker manages session-level execution history for policy guardrails, including consecutive automatic decisions and sliding-window rate limits. It is thread-safe and safe for concurrent calls across different sessions.

func NewTracker

func NewTracker() *Tracker

NewTracker creates a Tracker using the system clock.

func NewTrackerWithClock

func NewTrackerWithClock(clock func() time.Time) *Tracker

NewTrackerWithClock creates a Tracker with a custom clock function, primarily for deterministic unit testing.

func (*Tracker) CheckLimits

func (t *Tracker) CheckLimits(sessionID string, config Config) (Action, string, bool)

CheckLimits checks whether an automatic decision is allowed for the given sessionID against the configured MaxConsecutiveAutoDecisions and RateLimitPerMinute. If a limit is exceeded, it returns (ActionAsk, reason, false). If limits are respected, it returns (ActionAllow, "", true).

func (*Tracker) Consecutive

func (t *Tracker) Consecutive(sessionID string) int

Consecutive returns the current consecutive automatic decision count for the session.

func (*Tracker) RecordAutoDecision

func (t *Tracker) RecordAutoDecision(sessionID string)

RecordAutoDecision registers that an automatic decision was delivered for the session. It increments the consecutive counter and appends the current timestamp to the history window.

func (*Tracker) RecordHumanDecision

func (t *Tracker) RecordHumanDecision(sessionID string)

RecordHumanDecision registers that an operator intervened for the session. It resets the consecutive counter to 0. Rate limiting timestamps remain intact.

func (*Tracker) Reset

func (t *Tracker) Reset(sessionID string)

Reset clears all consecutive counters and history for the specified session.

Jump to

Keyboard shortcuts

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