operation

package
v1.0.11 Latest Latest
Warning

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

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

Documentation

Overview

Package operation defines the durable state machine for device-changing operations.

Index

Constants

View Source
const (
	TerminalClaimNotProven  = "not_proven"
	DefaultReceiptRetention = 30 * 24 * time.Hour
)
View Source
const (
	EffectInput = domain.EffectInput
	EffectPower = domain.EffectPower
	EffectMedia = domain.EffectMedia
	EffectAdmin = domain.EffectAdmin
)

Variables

View Source
var (
	ErrConflict          = errors.New("operation ID is already bound to a different request")
	ErrNotFound          = errors.New("operation was not found")
	ErrInvalidDigestKey  = errors.New("operation digest key must contain at least 32 bytes")
	ErrInvalidRequest    = errors.New("invalid operation request")
	ErrInvalidTransition = errors.New("invalid operation state transition")
)

Functions

func ValidatePatch

func ValidatePatch(from, to Stage, patch Patch) error

ValidatePatch enforces delivery and retry semantics for a destination stage.

func ValidateTransition

func ValidateTransition(from, to Stage) error

ValidateTransition enforces the sole operation state-transition authority.

Types

type Clock

type Clock interface {
	Now() time.Time
}

Clock supplies deterministic timestamps to the operation service.

type Delivery

type Delivery string

Delivery describes only transport delivery, not the physical outcome.

const (
	DeliveryNotSent           Delivery = "not_sent"
	DeliveryPossiblySent      Delivery = "possibly_sent"
	DeliveryTransportAccepted Delivery = "transport_accepted"
)

type Digester

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

Digester creates keyed request digests so low-entropy input such as typed text cannot be recovered from the durable ledger by offline guessing.

func NewDigester

func NewDigester(key []byte) (Digester, error)

NewDigester constructs a request digester from a stable application secret.

func (Digester) NewRequest

func (d Digester) NewRequest(id uuid.UUID, deviceID domain.DeviceID, generation uint64, effect EffectClass, action, policyRevision string, canonicalArguments []byte) (Request, error)

NewRequest creates a keyed request digest without retaining the canonical arguments. Callers must use a deterministic, versioned canonical encoding.

type EffectClass

type EffectClass = domain.EffectClass

EffectClass aliases the domain's single effect classification authority.

type Patch

type Patch struct {
	Delivery      Delivery
	Verification  Verification
	TerminalClaim string
	RetrySafe     bool
	ErrorKind     string
	Warnings      []string
}

Patch contains the state owned by one transition. Zero values deliberately clear optional fields so callers provide the complete resulting receipt state.

type Receipt

type Receipt struct {
	Request
	Stage         Stage
	Delivery      Delivery
	Verification  Verification
	TerminalClaim string
	RetrySafe     bool
	ErrorKind     string
	Warnings      []string
	CreatedAt     time.Time
	UpdatedAt     time.Time
	SendStartedAt time.Time
	TerminalAt    time.Time
}

Receipt is the durable, redacted record returned for an operation.

func (Receipt) IsTerminal

func (r Receipt) IsTerminal() bool

IsTerminal reports whether no further state transition is permitted.

type Repository

type Repository interface {
	Begin(ctx context.Context, request Request, now time.Time) (Receipt, bool, error)
	Get(ctx context.Context, id uuid.UUID) (Receipt, error)
	Transition(ctx context.Context, id uuid.UUID, to Stage, patch Patch, now time.Time) (Receipt, error)
	RecoverInterrupted(ctx context.Context, now time.Time) (int64, error)
	PurgeTerminalBefore(ctx context.Context, cutoff time.Time) (int64, error)
}

Repository atomically owns operation deduplication and state persistence.

type Request

type Request struct {
	ID                uuid.UUID
	Digest            [sha256.Size]byte
	DeviceID          domain.DeviceID
	ControlGeneration uint64
	Effect            EffectClass
	Action            string
	PolicyRevision    string
}

Request is the immutable identity of a state-changing operation. Digest must cover the canonicalized complete arguments and the other request fields.

func (Request) Validate

func (r Request) Validate() error

Validate checks the immutable request identity before it enters the ledger.

type Service

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

Service is the application-facing operation ledger API.

func NewService

func NewService(repository Repository) *Service

NewService creates an operation service using the system clock.

func NewServiceWithClock

func NewServiceWithClock(repository Repository, clock Clock) *Service

NewServiceWithClock creates an operation service with an injectable clock.

func (*Service) Begin

func (s *Service) Begin(ctx context.Context, request Request) (receipt Receipt, existing bool, err error)

Begin atomically registers a request. Existing is true only when the exact same operation ID and digest were already registered.

func (*Service) Get

func (s *Service) Get(ctx context.Context, id uuid.UUID) (Receipt, error)

Get returns the current durable receipt.

func (*Service) MarkSendStarted

func (s *Service) MarkSendStarted(ctx context.Context, id uuid.UUID) (Receipt, error)

MarkSendStarted crosses the no-replay boundary before any device bytes are sent.

func (*Service) PurgeRetainedReceipts

func (s *Service) PurgeRetainedReceipts(ctx context.Context, retention time.Duration) (int64, error)

PurgeRetainedReceipts removes terminal receipts older than retention.

func (*Service) RecoverInterrupted

func (s *Service) RecoverInterrupted(ctx context.Context) (int64, error)

RecoverInterrupted converts every interrupted send into a terminal ambiguous receipt.

func (*Service) Transition

func (s *Service) Transition(ctx context.Context, id uuid.UUID, to Stage, patch Patch) (Receipt, error)

Transition persists one legal state transition.

type Stage

type Stage string

Stage records how far execution progressed. SendStarted is the durable point after which an interrupted non-idempotent operation must never be replayed.

const (
	StageNotSent            Stage = "not_sent"
	StageSendStarted        Stage = "send_started"
	StageTransportAccepted  Stage = "transport_accepted"
	StageObservationStarted Stage = "observation_started"
	StageStateObserved      Stage = "state_observed"
	StageCompleted          Stage = "completed"
	StageFailed             Stage = "failed"
	StageAmbiguous          Stage = "ambiguous"
	StageCancelled          Stage = "cancelled"
)

func (Stage) IsTerminal

func (s Stage) IsTerminal() bool

IsTerminal reports whether no further state transition is permitted.

type Verification

type Verification struct {
	Status        VerificationStatus
	Signals       []string
	ObservationID string
}

Verification records independent evidence without claiming a physical outcome.

type VerificationStatus

type VerificationStatus string

VerificationStatus describes independently observed state after delivery.

const (
	VerificationNotRequested VerificationStatus = "not_requested"
	VerificationPending      VerificationStatus = "pending"
	VerificationObserved     VerificationStatus = "observed"
	VerificationNotObserved  VerificationStatus = "not_observed"
)

Jump to

Keyboard shortcuts

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