approval

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 4, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package approval implements the human-in-the-loop gate (CLAUDE.md headline feature). A side-effecting tool call that policy gates pauses until a human approves or denies it. Policy evaluation is deterministic — no LLM decides whether something needs approval.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Decision

type Decision struct {
	Approved bool
	Reason   string
	By       string
}

Decision is the outcome of an approval request.

type Gate

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

Gate is the human-in-the-loop approval queue. It persists pending approvals, notifies push channels, and blocks the calling (tool) goroutine until a human resolves the request via the API/CLI/web — or the run's context is cancelled.

func NewGate

func NewGate(store storage.Store, policy Policy, notifier Notifier, log *slog.Logger) *Gate

NewGate constructs a Gate. notifier may be nil (no push channel).

func (*Gate) Create

func (g *Gate) Create(ctx context.Context, req Request) (storage.ApprovalRecord, bool, error)

Create evaluates policy and, if approval is required, persists a pending approval and notifies push channels, returning the record (required=true). Unlike Request, it does NOT block — the caller (e.g. the SDK over HTTP) polls the approval's status instead. Returns required=false when policy allows the call outright.

func (*Gate) Get

func (g *Gate) Get(ctx context.Context, id string) (storage.ApprovalRecord, error)

Get returns a single approval by id.

func (*Gate) Pending

func (g *Gate) Pending(ctx context.Context) ([]storage.ApprovalRecord, error)

Pending returns the currently-pending approvals.

func (*Gate) Request

func (g *Gate) Request(ctx context.Context, req Request) (Decision, string, error)

Request gates a side-effecting call. If approval is not required it returns an approved Decision immediately. Otherwise it persists a pending approval, notifies push channels, and BLOCKS until the request is resolved or ctx is done (run cancel / time budget). This is how a side-effecting call "pauses".

func (*Gate) Required

func (g *Gate) Required(tool, sideEffect string) bool

Required reports whether a call needs approval under the gate's policy.

func (*Gate) Resolve

func (g *Gate) Resolve(ctx context.Context, id string, approved bool, reason, by string) error

Resolve records a human decision and wakes any blocked waiter. Returns storage.ErrNotFound if the approval is unknown or already resolved.

type Notifier

type Notifier interface {
	Notify(ctx context.Context, a storage.ApprovalRecord)
}

Notifier pushes a newly-pending approval to a channel (e.g. a webhook). The CLI and web page are pull channels and do not implement this.

type Policy

type Policy struct {
	// RequireFor lists match rules; a call needs approval if it matches ANY rule.
	RequireFor []Rule
	// DefaultSafe, when true, requires approval for ANY call with a non-empty side
	// effect even if no rule matched — fail closed on side effects.
	DefaultSafe bool
}

Policy is the deterministic rule set deciding which calls need approval. It mirrors the api/v1 ApprovalPolicy schema.

func (Policy) Requires

func (p Policy) Requires(tool, sideEffect string) bool

Requires reports whether a tool call needs human approval.

type Request

type Request struct {
	RunID      string
	StepIndex  int32
	Tool       string
	SideEffect string
	Arguments  map[string]any
}

Request describes a side-effecting tool call seeking approval.

type Rule

type Rule struct {
	Tool       string
	SideEffect string
}

Rule matches a tool call by exact tool name or by a side-effect glob (e.g. "*write*"). A rule with both set matches if EITHER matches.

type WebhookNotifier

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

WebhookNotifier POSTs a JSON notification to a user-configured URL when an approval becomes pending. This is user-configured outbound network (like the OTLP endpoint) — RiskKernel calls it only because the user set the URL. It does NOT include any provider keys or secrets. See SECURITY.md.

func NewWebhookNotifier

func NewWebhookNotifier(url string, log *slog.Logger) *WebhookNotifier

NewWebhookNotifier returns a notifier, or nil if url is empty (no push channel).

func (*WebhookNotifier) Notify

Notify fires the webhook asynchronously (best-effort; failures are logged, never fatal — a flaky webhook must not wedge a governed run).

Jump to

Keyboard shortcuts

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