gate

package
v0.5.3 Latest Latest
Warning

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

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

Documentation

Overview

Package gate is the pre-execution and pre-edit policy engine (RFC-001 §5.5): commands are parsed with a real shell parser (never regex), classified against the effect catalogue, and evaluated against CEL rules over the declared environment. Every decision is appended to an audit log.

Index

Constants

View Source
const (
	VerdictAllow    = "allow"
	VerdictApproval = "require_approval"
	VerdictDeny     = "deny"
)

Decision severities, weakest to strongest.

Variables

View Source
var ErrBlocked = errors.New("blocked by policy")

ErrBlocked marks decisions that must stop the caller (enforce mode); the CLI maps it to a distinct exit code for hooks and CI.

Functions

func Audit

func Audit(root, kind, input string, p *Policy, d *Decision) error

Audit appends the decision to <root>/.seamark/audit.jsonl (0600, rotated by size and age). The default entry stores the normalized command names, a SHA-256 of the input, the verdict and the policy hash — never the raw input, which frequently carries tokens, passwords and connection strings. Opting in via policy.yaml (`audit:` → `raw: true`) persists the input line with best-effort secret redaction.

func ChangedPaths added in v0.2.0

func ChangedPaths(diffText string) []string

ChangedPaths lists the repo-relative files a unified diff touches, in first-appearance order — the same header parsing EvalDiff trusts, so an advisory surface (lessons on `check`) can never disagree with the verdict about which files changed.

Types

type Decision

type Decision struct {
	Verdict string   `json:"verdict"` // strongest of the matches
	Mode    string   `json:"mode"`    // warn | enforce
	Effects []string `json:"effects"`
	Matches []Match  `json:"matches,omitempty"`
	// Commands are the normalized command names found in the input
	// (wrappers unwrapped, interpreter payloads included) — what the
	// audit log stores instead of the raw command line.
	Commands []string `json:"commands,omitempty"`
	// PolicySHA identifies the exact policy text that produced this
	// decision.
	PolicySHA string `json:"policy_sha256,omitempty"`
	// Notes carry uncertainty the verdict alone would hide — e.g.
	// changed files the index has no symbols for. A note never changes
	// the verdict; it changes how much the verdict may be trusted.
	Notes []string `json:"notes,omitempty"`
}

Decision is the gate's answer for one input.

func EvalCommand

func EvalCommand(p *Policy, catalog *effects.Catalog, root, commandLine string) (*Decision, error)

EvalCommand parses a shell command line, classifies every command in it (pipelines, &&-chains, substitutions, and interpreter payloads like `bash -c "…"` included) against the catalogue, and evaluates the policy. Parse failures fail closed with an error — a gate that shrugs at unparseable input is a bypass.

func EvalDiff

func EvalDiff(p *Policy, st *store.Store, diffText string) (*Decision, error)

EvalDiff computes a unified diff's blast radius and evaluates policy over it: changed lines map to symbols, and symbols already carry the transitively-propagated effect tags — their union is what this change can ultimately reach (RFC-001 §5.5, pre-edit enforcement).

func (*Decision) Blocking

func (d *Decision) Blocking() bool

Blocking reports whether this decision should stop execution: only enforce mode blocks; warn mode always lets the command through.

type Match

type Match struct {
	RuleID  string `json:"rule"`
	Verdict string `json:"verdict"`
	Message string `json:"message"`
}

Match is one rule that fired.

type Policy

type Policy struct {
	// Mode "warn" reports verdicts without blocking; "enforce" makes deny
	// and require_approval binding. Warn is the default (§10: a policy
	// layer that cries wolf gets disabled).
	Mode        string `yaml:"mode"`
	Environment struct {
		Detect      []string `yaml:"detect"`
		ProdMarkers []string `yaml:"prod_markers"`
	} `yaml:"environment"`
	// Audit configures decision logging. Raw opts into persisting the
	// input line (secret patterns redacted best-effort); the default
	// entry carries only a SHA-256 of the input, because command lines
	// frequently embed tokens, passwords and connection strings.
	Audit struct {
		Raw bool `yaml:"raw"`
	} `yaml:"audit"`
	Deny            []Rule `yaml:"deny"`
	RequireApproval []Rule `yaml:"require_approval"`

	// Hash is the SHA-256 of the policy source that produced this rule
	// set: audit entries carry it so a decision can be correlated with
	// the exact policy text that made it.
	Hash string `yaml:"-"`
}

Policy is the loaded rule set.

func LoadPolicy

func LoadPolicy(root string) (*Policy, error)

LoadPolicy returns the workspace policy at .seamark/policy.yaml, or the embedded warn-mode default when absent. The workspace file REPLACES the default rule set (policy is a whole, not a patch — partial merges would make the effective rules unreviewable). All CEL expressions compile at load time so a broken rule fails loudly, not at decision time.

func (*Policy) DetectEnv

func (p *Policy) DetectEnv(environ []string) map[string]any

DetectEnv inspects the process environment per policy: which declared variables are set, and whether any value carries a production marker.

type Rule

type Rule struct {
	ID      string `yaml:"id"`
	When    string `yaml:"when"`
	Message string `yaml:"message"`
	// contains filtered or unexported fields
}

Rule is one policy predicate.

Jump to

Keyboard shortcuts

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