approval

package
v0.2.4 Latest Latest
Warning

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

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

Documentation

Overview

Package approval is the Human-In-The-Loop gate for AI-proposed actions. A proposed action is auto-approved (per the engagement's ApprovalMode + the action's RiskClass), or enqueued for a human, or – if undecided past the timeout – failed CLOSED (denied). Every decision is recorded on the append-only audit log, attributed to the deciding human (or the system on a timeout). It does NOT execute anything: it only produces an ApprovalDecision the safety gate consumes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ResumeFunc

type ResumeFunc func(ctx context.Context, sessionID, actionID shared.ID) error

ResumeFunc re-drives a suspended session after its pending action was decided (here: timed out). The composition root supplies it (enqueue an orchestrator resume job) so the approval package does NOT import the orchestrator – avoiding the orchestrator→safety→approval cycle.

type Service

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

Service runs the approval policy over a durable ApprovalStore.

func NewService

func NewService(store ports.ApprovalStore, audit ports.AuditLogger, clock ports.Clock, mode agent.ApprovalMode, timeout time.Duration) (*Service, error)

NewService validates its deps and returns the approval service. An unknown mode is left as-is (AutoApproves fails safe to manual); a non-positive timeout disables auto-expiry.

func (*Service) Decide

func (s *Service) Decide(ctx context.Context, human string, actionID shared.ID, approve bool, reason string) (agent.ApprovalDecision, error)

Decide records a human's approve/deny (idempotent – a 2nd decision returns ErrConflict), audited under the HUMAN actor.

func (*Service) Get added in v0.2.0

Get returns the immutable proposal and current decision for an existing approval request.

func (*Service) Request

Request returns the current decision for a proposed action. If it was already decided (resume path), that decision is returned. Otherwise: auto-approvable → approved + audited; else enqueued and returned PENDING (the orchestrator suspends; a human Decides).

func (*Service) RunSweeper

func (s *Service) RunSweeper(ctx context.Context, interval time.Duration)

RunSweeper periodically sweeps expired approvals until ctx is cancelled (a running binary must call this – fail-closed timeout is otherwise never enforced in prod).

func (*Service) SetResumeEnqueuer

func (s *Service) SetResumeEnqueuer(f ResumeFunc)

SetResumeEnqueuer installs the callback used to re-drive a session after a timeout deny, so the suspended session resumes, sees the denial via the idempotent gate, and fails fast instead of hanging in awaiting_approval forever.

func (*Service) SetTransactionRunner added in v0.2.0

func (s *Service) SetTransactionRunner(transactions ports.TenantTransactionRunner)

SetTransactionRunner makes Decide atomic. Without it the decision commits first and the audit append is a separate transaction, so an audit failure returns an error to an operator whose approval has already taken effect: the interface reports failure, the agent proceeds, and the retry answers "already decided".

func (*Service) SweepAllExpired

func (s *Service) SweepAllExpired(ctx context.Context) (int, error)

SweepAllExpired sweeps every engagement that currently has a pending approval (the prod timeout sweeper's fan-out). Returns the total expired.

The sweeper runs on a background context with no tenant, so each scope's tenant is bound before its engagement is swept. Everything downstream of that binding (Pending, Decide, the record audit and the resume enqueue) then runs inside one tenant, which is what lets the durable store reach the RLS-protected approval queue at all.

func (*Service) SweepExpired

func (s *Service) SweepExpired(ctx context.Context, engagementID shared.ID) (int, error)

SweepExpired flips pending actions for an engagement that have outlived the timeout to a fail-closed timeout-deny. Returns how many were expired. A worker calls this periodically.

Jump to

Keyboard shortcuts

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