approval

package
v0.1.21 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2025 License: Apache-2.0 Imports: 4 Imported by: 4

Documentation

Overview

Package approval implements the optional human-in-the-loop approval layer. It allows selected tasks to be paused until an explicit approval or reject decision is recorded.

Index

Constants

View Source
const (
	TopicRequestCreated  = "request.created"
	TopicRequestUpdated  = "request.updated"
	TopicRequestExpired  = "request.expired"
	TopicDecisionCreated = "decision.created"

	// legacy – used only for backward compatibility
	LegacyTopicRequestNew  = "request.new"
	LegacyTopicDecisionNew = "decision.new"
)

Standard event topics – keep old names for one transition cycle.

Variables

This section is empty.

Functions

func AutoApprove

func AutoApprove(ctx context.Context,
	svc Service,
	interval time.Duration) func()

AutoApprove automatically approves all pending requests

func AutoDecider

func AutoDecider(ctx context.Context,
	svc Service,
	fn DecisionFunc,
	interval time.Duration) (stop func())

AutoDecider starts a goroutine that polls ListPending and applies fn to every request. It returns stop() – call it (or cancel ctx) to exit.

func AutoExpire added in v0.1.2

func AutoExpire(ctx context.Context,
	svc Service,
	reason string,
	interval time.Duration) (stop func())

AutoExpire periodically checks pending requests and auto-rejects those whose ExpiresAt deadline has passed. It publishes a request.expired event before recording the rejection decision.

stop := approval.AutoExpire(ctx, svc, "expired", 1*time.Second)

Passing interval <= 0 defaults to 30 s. Empty reason defaults to "expired".

func AutoReject

func AutoReject(ctx context.Context,
	svc Service,
	reason string,
	interval time.Duration) func()

AutoReject automatically rejects all pending requests with the given reason

Types

type Decision

type Decision struct {
	ID        string    `json:"id"` // same as request.ID
	Approved  bool      `json:"approved"`
	Reason    string    `json:"reason,omitempty"`
	DecidedAt time.Time `json:"decidedAt"`
}

Decision represents approval decision

func WaitForDecision added in v0.1.2

func WaitForDecision(ctx context.Context, svc Service, id string, timeout time.Duration) (*Decision, error)

WaitForDecision blocks until an approval decision for the given request ID appears on the Service event queue, or the context / timeout expires. It consumes messages from the queue and acknowledges them once processed. If timeout <= 0 the call relies solely on the lifetime of ctx.

type DecisionFunc

type DecisionFunc func(r *Request) (approved bool, reason string)

DecisionFunc decides what to do with a pending request. Return (true, "") to approve

(false, "…") to reject with reason.

type Event

type Event struct {
	Topic   string            // see topic constants below
	Data    interface{}       // *Request | *Decision
	Headers map[string]string `json:"headers,omitempty"` // optional – tenant, correlation-id etc.
}

Event envelope reused from the previous sketch.

type PendingFilter added in v0.1.2

type PendingFilter func(*Request) bool

PendingFilter is a predicate applied to *Request when filtering the list of pending approval requests. All supplied filters must return true for a request to be included in the output slice.

func WithAction added in v0.1.2

func WithAction(action string) PendingFilter

WithAction returns a PendingFilter that keeps requests whose Action matches the supplied value (empty string disables the filter).

func WithProcessID added in v0.1.2

func WithProcessID(id string) PendingFilter

WithProcessID returns a PendingFilter that keeps requests whose ProcessID matches the supplied id (empty id disables the filter and passes everything).

type Request

type Request struct {
	ID          string                 `json:"id"`                  // Globally unique, primary key
	ProcessID   string                 `json:"processId"`           // Refers to process.ID
	ExecutionID string                 `json:"executionId"`         // Refers to execution.ID
	Action      string                 `json:"action"`              // "service.method"
	Args        json.RawMessage        `json:"args,omitempty"`      // JSON-encoded expanded input, may be null
	CreatedAt   time.Time              `json:"createdAt"`           // RFC-3339 timestamp
	ExpiresAt   *time.Time             `json:"expiresAt,omitempty"` // Optional deadline
	Meta        map[string]interface{} `json:"meta,omitempty"`      // Free-form map: tenant, user, environment, etc.
}

Request represents a request for approval

func ListPending added in v0.1.2

func ListPending(ctx context.Context, svc Service, filters ...PendingFilter) ([]*Request, error)

ListPending returns pending requests that satisfy all provided filters. It delegates the retrieval to Service.ListPending and then applies the filters client-side, avoiding changes to the underlying Service interface.

Example:

reqs, _ := approval.ListPending(ctx, svc, approval.WithProcessID(pid))

type Service

type Service interface {
	RequestApproval(ctx context.Context, r *Request) error
	ListPending(ctx context.Context) ([]*Request, error)
	Decide(ctx context.Context, id string, approved bool, reason string) (*Decision, error)
	Queue() messaging.Queue[Event]
}

Service defines the approval service interface.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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