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
- Variables
- type Authorizer
- type Dialect
- type Option
- type Request
- type SQLStore
- func (s *SQLStore) Close() error
- func (s *SQLStore) Create(ctx context.Context, req *Request) error
- func (s *SQLStore) Get(ctx context.Context, id string) (*Request, error)
- func (s *SQLStore) List(ctx context.Context) ([]*Request, error)
- func (s *SQLStore) Migrate(ctx context.Context) error
- func (s *SQLStore) Resolve(ctx context.Context, id string, approved bool, now time.Time) (*Request, error)
- type Service
- func (s *Service) HandlePending(w http.ResponseWriter, r *http.Request)
- func (s *Service) HandleRespond(w http.ResponseWriter, r *http.Request)
- func (s *Service) Migrate(ctx context.Context) error
- func (s *Service) RequestApproval(ctx context.Context, toolName string, args map[string]any) (bool, error)
- type Store
Constants ¶
const ( StatusPending = "pending" StatusApproved = "approved" StatusDenied = "denied" )
Request states.
Variables ¶
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
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.
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
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.
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
NewSQLStore constructs a store over an already-open *sql.DB. The caller owns the DB lifecycle unless Close is used.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service manages pending approval requests.
func NewService ¶
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) 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.