workflow

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Jun 20, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package workflow provides a Validate-step middleware that enforces permitted state transitions on a model. Use it for status-driven workflows where only certain transitions are legal — e.g. invoices that flow draft → submitted → approved → paid.

Rules are checked against the *current* stored value of the chosen status field on update, so every PATCH that touches the field issues one extra `ctx.GetModel(...).Read(id)`. Reads are routed through `ctx.Tx` when one is active, so the cost is bounded by the request's existing transaction.

On rejection the middleware aborts with `422 INVALID_TRANSITION`. Guard errors (e.g. role checks) use the same code; the guard's error string becomes the response message.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Guard

type Guard interface {
	Check(ctx *maniflex.ServerContext, from, to string) error
}

Guard gates a state transition on something beyond the from/to pair — typically the caller's roles, but it may inspect any aspect of the request. Returning a non-nil error rejects the transition with the error's message as the 422 detail.

func RequireRole

func RequireRole(roles ...string) Guard

RequireRole accepts the transition only if the caller holds any one of the listed roles (OR-semantics, matching maniflex.HasRole). With no roles passed, the guard always rejects — that protects against accidentally declaring an unguarded "require" rule.

type GuardFunc

type GuardFunc func(ctx *maniflex.ServerContext, from, to string) error

GuardFunc adapts a plain function to the Guard interface.

func (GuardFunc) Check

func (f GuardFunc) Check(ctx *maniflex.ServerContext, from, to string) error

Check implements Guard.

type Machine

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

Machine is a compiled set of allowed transitions on a single status field. Build one with New and pass Middleware() to the Validate step.

func New

func New(field string, opts ...Option) *Machine

New compiles a state-machine for the named status field.

sm := workflow.New("status",
    workflow.Allow("draft",     "submitted"),
    workflow.Allow("submitted", "approved", workflow.RequireRole("manager")),
    workflow.AllowAny(workflow.RequireRole("admin")),
)

`field` is the JSON field name as it appears in `ctx.ParsedBody`.

func (*Machine) Middleware

func (m *Machine) Middleware() maniflex.MiddlewareFunc

Middleware returns the Validate-step MiddlewareFunc for this Machine.

type Option

type Option func(*Machine)

Option mutates a Machine during construction. Returned by Allow, AllowAny, and AllowInitial.

func Allow

func Allow(from, to string, guards ...Guard) Option

Allow permits the transition from -> to. `from` may be "*" to match any prior state; `to` may be "*" to match any new state. Guards run in order after a rule matches; the first guard error rejects the transition.

func AllowAny

func AllowAny(guards ...Guard) Option

AllowAny is shorthand for Allow("*", "*", guards...). Typical use is an admin escape hatch: AllowAny(RequireRole("admin")).

func AllowInitial

func AllowInitial(states ...string) Option

AllowInitial declares the set of states a Create may seed the record with. When set, OpCreate is allowed only if the body's field value is in the set. When not set, any initial state passes.

Jump to

Keyboard shortcuts

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