approval

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package approval provides human-in-the-loop approval workflows for the ChronosOS control plane.

The Service is:

  • ctx-aware: RequestApproval honors caller cancellation/deadline instead of blocking forever;
  • persisted (optionally): with a Store, pending requests and their decisions survive a process restart and are visible across replicas, so a decision recorded on one node resolves a waiter on another;
  • authorized (optionally): an Authorizer gates who may resolve a request.

The Service satisfies engine/tool.Approver (RequestApproval has the matching signature), so it can be wired into the tool execution path via Registry.SetApprover for tools whose Permission is PermRequireApproval.

Index

Constants

View Source
const (
	StatusPending  = "pending"
	StatusApproved = "approved"
	StatusDenied   = "denied"
)

Request states.

Variables

View Source
var ErrNotFound = errors.New("approval: request not found")

ErrNotFound is returned when an approval request does not exist.

Functions

This section is empty.

Types

type Authorizer added in v0.4.0

type Authorizer interface {
	Authorize(r *http.Request, req *Request) error
}

Authorizer decides whether the HTTP caller responding to an approval request is permitted to resolve it. Returning a non-nil error rejects the response with 403. A nil Authorizer (the default) permits all responders.

type Dialect added in v0.4.0

type Dialect string

Dialect selects SQL syntax for the target database.

const (
	// DialectSQLite targets SQLite (dev/test).
	DialectSQLite Dialect = "sqlite"
	// DialectPostgres targets PostgreSQL (production).
	DialectPostgres Dialect = "postgres"
)

type Option added in v0.4.0

type Option func(*Service)

Option configures a Service.

func WithAuthorizer added in v0.4.0

func WithAuthorizer(a Authorizer) Option

WithAuthorizer installs an Authorizer that gates approval responses.

func WithPollInterval added in v0.4.0

func WithPollInterval(d time.Duration) Option

WithPollInterval sets how often a store-backed waiter polls for a decision recorded elsewhere (another replica or after a restart). Ignored without a Store. Default is 1s.

func WithStore added in v0.4.0

func WithStore(s Store) Option

WithStore backs the Service with a persistent Store. Pending requests and decisions then survive restarts and are shared across replicas.

type Request

type Request struct {
	ID        string         `json:"id"`
	ToolName  string         `json:"tool_name"`
	Args      map[string]any `json:"args"`
	Status    string         `json:"status"`
	CreatedAt time.Time      `json:"created_at"`
	// Response is the in-process wakeup channel for a live waiter. It is never
	// persisted or serialized.
	Response chan bool `json:"-"`
}

Request represents an approval request for a tool call.

type SQLStore added in v0.4.0

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

SQLStore implements Store over any database/sql database (SQLite or PostgreSQL, selected by Dialect). It owns the approval schema and never touches the shared storage package's tables.

func NewSQLStore added in v0.4.0

func NewSQLStore(db *sql.DB, dialect Dialect) *SQLStore

NewSQLStore constructs a store over an already-open *sql.DB. The caller owns the DB lifecycle unless Close is used.

func (*SQLStore) Close added in v0.4.0

func (s *SQLStore) Close() error

Close closes the underlying database.

func (*SQLStore) Create added in v0.4.0

func (s *SQLStore) Create(ctx context.Context, req *Request) error

Create records a new pending request.

func (*SQLStore) Get added in v0.4.0

func (s *SQLStore) Get(ctx context.Context, id string) (*Request, error)

Get returns a request by ID.

func (*SQLStore) List added in v0.4.0

func (s *SQLStore) List(ctx context.Context) ([]*Request, error)

List returns all pending requests.

func (*SQLStore) Migrate added in v0.4.0

func (s *SQLStore) Migrate(ctx context.Context) error

Migrate creates the approval schema.

func (*SQLStore) Resolve added in v0.4.0

func (s *SQLStore) Resolve(ctx context.Context, id string, approved bool, now time.Time) (*Request, error)

Resolve transitions a pending request to approved/denied.

type Service

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

Service manages pending approval requests.

func NewService

func NewService(opts ...Option) *Service

NewService creates an approval Service. With no options it is a ctx-aware, in-memory service.

func (*Service) HandlePending

func (s *Service) HandlePending(w http.ResponseWriter, r *http.Request)

HandlePending returns all pending approval requests.

func (*Service) HandleRespond

func (s *Service) HandleRespond(w http.ResponseWriter, r *http.Request)

HandleRespond processes an approval response. It authorizes the responder (if an Authorizer is configured) and resolves the request.

func (*Service) Migrate added in v0.4.0

func (s *Service) Migrate(ctx context.Context) error

Migrate initializes the backing store schema, if any.

func (*Service) RequestApproval

func (s *Service) RequestApproval(ctx context.Context, toolName string, args map[string]any) (bool, error)

RequestApproval submits a tool call for human approval and blocks until it is resolved or ctx is done. It returns whether the call was approved. The signature matches engine/tool.Approver so the Service can be wired into the tool path via Registry.SetApprover.

type Store added in v0.4.0

type Store interface {
	// Migrate creates the approval schema (idempotent).
	Migrate(ctx context.Context) error
	// Create records a new pending request.
	Create(ctx context.Context, req *Request) error
	// Resolve transitions a pending request to approved/denied and returns the
	// updated request. It returns ErrNotFound if the request does not exist.
	Resolve(ctx context.Context, id string, approved bool, now time.Time) (*Request, error)
	// Get returns a request by ID (ErrNotFound if absent).
	Get(ctx context.Context, id string) (*Request, error)
	// List returns all pending requests.
	List(ctx context.Context) ([]*Request, error)
	// Close releases resources owned by the store.
	Close() error
}

Store persists approval requests so they survive restarts and are shared across replicas. All timestamps are passed explicitly for deterministic tests.

Jump to

Keyboard shortcuts

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