engine

package
v0.3.7 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 111 Imported by: 0

Documentation

Overview

Package engine implements the CUE recipe execution loop, decoupled from UI.

Index

Constants

View Source
const (
	StageFallbackDetect        = "fallback_detect"
	StageFallbackDetectFailed  = "fallback_detect_failed"
	StagePresignPutStart       = "presign_put_start"
	StagePresignPut            = "presign_put"
	StagePresignPutFailed      = "presign_put_failed"
	StagePresignGetStart       = "presign_get_start"
	StagePresignGet            = "presign_get"
	StagePresignGetFailed      = "presign_get_failed"
	StagePresignMultipartStart = "presign_multipart_start"
	StagePresignMultipart      = "presign_multipart"
	StagePresignMultipartAbort = "presign_multipart_aborted"
	StagePresignComplete       = "presign_complete"
	StagePresignCompleteFailed = "presign_complete_failed"
	StagePresignCleanup        = "presign_cleanup"
	StagePresignCleanupFailed  = "presign_cleanup_failed"
	StagePresignFallback       = "presign_falling_back_to_agent"
)

Fallback-path stage names. Emitted as the Stage field on AgentTransferEvent

View Source
const CueAIDefaultMaxInputChars = 200000

CueAIDefaultMaxInputChars ...

View Source
const RecipeMetaHostLimit = 200

RecipeMetaHostLimit caps how many host records are copied into a recording's RecipeMeta. Standard across all run callers.

Variables

View Source
var ErrTargetResolution = errors.New("target resolution failed")

ErrTargetResolution marks a failure to resolve a RunRequest.Target into host records (search error or empty result), so callers can distinguish a bad target (a 400-class caller error) from an execution failure. Test with errors.Is.

Functions

func AnnotateCueStepResult

func AnnotateCueStepResult(res *HostExecResult, stepIdx int, step cuetry.Step, kind string)

AnnotateCueStepResult ...

func ApplyCueRecipeResultExpressions

func ApplyCueRecipeResultExpressions(opts ExecutionOptions, step cuetry.Step, r hosts.Record, res *HostExecResult)

ApplyCueRecipeResultExpressions ...

func BuildCueRecipeTranscript

func BuildCueRecipeTranscript(history [][]HostExecResult) string

BuildCueRecipeTranscript formats prior CUE step HostExecResult groups for an AI summarizer. BuildCueRecipeTranscript ...

func CanTrueNASTunnel

func CanTrueNASTunnel(r hosts.Record) bool

CanTrueNASTunnel reports whether the Tunnel action can run for this TrueNAS row. CanTrueNASTunnel ...

func CueApplyRecipeSSHDialOptions

func CueApplyRecipeSSHDialOptions(recipe cuetry.Recipe, re *cuetry.RemoteExec, targets []hosts.Record) []hosts.Record

CueApplyRecipeSSHDialOptions ...

func CueEnvRunOpts

func CueEnvRunOpts(recipe *cuetry.Recipe, store *cuetry.StepOutputStore, capture *cuetry.RecipeOutputCapture, kv cuetry.KVReader, dryRun bool) *cuetry.EffectiveEnvForRunOpts

CueEnvRunOpts ...

func CueGetLocalIsDirectory

func CueGetLocalIsDirectory(localField, absResolved string) (bool, error)

CueGetLocalIsDirectory ...

func CueHookNotifyRemote

func CueHookNotifyRemote(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind string, phase, hostName string, notify *cuetry.RecipeNotify, body string)

CueHookNotifyRemote sends notify after a per-host hook; failures are logged only. CueHookNotifyRemote ...

func CueRecipeDisplayOutput

func CueRecipeDisplayOutput(res HostExecResult) string

CueRecipeDisplayOutput ...

func CueRecipeLoopItems

func CueRecipeLoopItems(run *CueRun, step cuetry.Step, target hosts.Record) ([]string, error)

CueRecipeLoopItems ...

func CueRecipeLoopUsesItemHost

func CueRecipeLoopUsesItemHost(step cuetry.Step) bool

CueRecipeLoopUsesItemHost ...

func CueSanitizeHostName

func CueSanitizeHostName(name string) string

CueSanitizeHostName ...

func CueStepAllTargetsTransientTransportFailed

func CueStepAllTargetsTransientTransportFailed(results []HostExecResult) bool

CueStepAllTargetsTransientTransportFailed ...

func CueStepNotifyAppendSuffix

func CueStepNotifyAppendSuffix(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind string, notify *cuetry.RecipeNotify, body string) string

CueStepNotifyAppendSuffix sends notify after a successful AI step; returns text to append on missing receivers or send errors. CueStepNotifyAppendSuffix ...

func CueStepNotifyRemote

func CueStepNotifyRemote(ctx context.Context, recipe cuetry.Recipe, stepNo int, kind string, notify *cuetry.RecipeNotify, body string)

CueStepNotifyRemote sends notify after a non-AI step; failures are logged only (no change to streamed host rows). CueStepNotifyRemote ...

func DetectTransferTargetRuntime

func DetectTransferTargetRuntime(cache *ClientCache, sshUser string, rec hosts.Record) (string, string, string, error)

DetectTransferTargetRuntime runs uname on the host to determine GOOS/GOARCH for agent binaries. DetectTransferTargetRuntime ...

func DialDockerCheck

func DialDockerCheck(user string, r hosts.Record, reg hostexec.Registry) error

DialDockerCheck verifies that a docker record can reach the Engine API (dial + close). Re-exported from dockerprovider for callers that already import ui. DialDockerCheck ...

func DialTrueNASUpstream

func DialTrueNASUpstream(ctx context.Context, _ string, r hosts.Record, address string) (net.Conn, error)

DialTrueNASUpstream provides an in-memory net.Conn proxied over the API shell. DialTrueNASUpstream ...

func DispatchHostResults added in v0.3.7

func DispatchHostResults(ctx context.Context, targets []TargetContext, maxConc, defaultConc int, fn func(TargetContext) HostExecResult, sink func(HostExecResult))

DispatchHostResults runs fn for each target, bounded by a weighted semaphore sized maxConc (falling back to defaultConc when maxConc <= 0, clamped to maxConcurrencyCap), and passes each result to sink. If ctx is cancelled before a target's turn, fn is not called for that target — sink instead receives a synthesized failure result carrying the target's identity and the acquire error.

This concentrates the per-target concurrency-dispatch shape shared by every step executor that fans work out across hosts; callers keep whatever is genuinely specific to them (retries, side-channel error tracking, post hooks) inside their own fn/sink closures.

func DockerInteractiveRunner

func DockerInteractiveRunner() dockerprovider.InteractiveRunner

DockerInteractiveRunner returns the ui-backed docker interactive session runner. DockerInteractiveRunner ...

func EnsureKVSessionForRecipe

func EnsureKVSessionForRecipe(_ cuetry.Recipe, recipeKV *RecipeKVCoordinator, execute bool) error

EnsureKVSessionForRecipe ...

func EvalAIStepWhen

func EvalAIStepWhen(ctx context.Context, recipe cuetry.Recipe, step cuetry.Step, store *cuetry.StepResultStore, secretResolver cuetry.SecretResolver, kv cuetry.KVReader, cliEnv map[string]string, execute bool) (bool, error)

EvalAIStepWhen ...

func EvalAgentTransferWhen

func EvalAgentTransferWhen(ctx context.Context, recipe cuetry.Recipe, step cuetry.Step, src, dst hosts.Record, store *cuetry.StepResultStore, secretResolver cuetry.SecretResolver, kv cuetry.KVReader, cliEnv map[string]string, execute bool) (bool, error)

EvalAgentTransferWhen ...

func EvaluateAssertions

func EvaluateAssertions(result *HostExecResult, assertions []cuetry.Assertion) error

EvaluateAssertions runs step output through the requested rules. Mutates result.Success and result.ErrMsg if an assertion fails or overrides.

func FormatCueStepHostResultsForNotify

func FormatCueStepHostResultsForNotify(stepNo int, group []HostExecResult) string

FormatCueStepHostResultsForNotify formats one step’s host results for notify bodies (non-AI steps). FormatCueStepHostResultsForNotify ...

func FormatTargetForDryRun

func FormatTargetForDryRun(r hosts.Record) string

FormatTargetForDryRun returns a string describing how the target will be connected to. FormatTargetForDryRun ...

func HostConnectableForTransfer

func HostConnectableForTransfer(r hosts.Record) bool

HostConnectableForTransfer reports whether a record can be dialed for SSH, k8s exec, or docker exec.

func HostFactsFromContext

func HostFactsFromContext(ctx context.Context) map[string]map[string]any

HostFactsFromContext ...

func HostNameFromExecResult

func HostNameFromExecResult(name string) string

HostNameFromExecResult ...

func HostsForRecipeMeta

func HostsForRecipeMeta(jobs []hosts.Record, limit int) []hosts.Record

HostsForRecipeMeta copies up to limit connectable host records for recipe-meta (web re-run). HostsForRecipeMeta ...

func InitTracer

func InitTracer(ctx context.Context) (func(context.Context) error, error)

InitTracer initializes an OpenTelemetry tracer provider. If OTEL_EXPORTER_OTLP_ENDPOINT is not set, it returns a no-op shutdown function.

func IsAgentTransferValidationError

func IsAgentTransferValidationError(err error) bool

IsAgentTransferValidationError reports whether err is an AgentTransferValidationError (HTTP 400 class input). IsAgentTransferValidationError ...

func IsSSHConnTransientError

func IsSSHConnTransientError(err error) bool

IsSSHConnTransientError reports whether err is a transport-level failure that often clears after closing the TCP/SSH session and dialing again (stale cache entry, local routing/socket glitch, reset by peer). IsSSHConnTransientError ...

func K8sInteractiveRunner

func K8sInteractiveRunner() k8sprovider.InteractiveRunner

K8sInteractiveRunner returns the ui-backed k8s interactive session runner. K8sInteractiveRunner ...

func KvReaderFromCoordinator

func KvReaderFromCoordinator(coord *RecipeKVCoordinator) cuetry.KVReader

KvReaderFromCoordinator ...

func LoadTransferConfigFromConfigPath

func LoadTransferConfigFromConfigPath(configPath string) config.TransferConfigEffective

LoadTransferConfigFromConfigPath ...

func MergeRecipeSecretRefs

func MergeRecipeSecretRefs(defaults *cuetry.RecipeDefaults, step cuetry.Step) map[string]string

MergeRecipeSecretRefs ...

func NewPostgresBridge

func NewPostgresBridge(h *plugins.HostRunContext, pools *postgres.PoolManager) plugins.PostgresBridge

NewPostgresBridge returns a PostgresBridge for one plugin host invocation. NewPostgresBridge ...

func NewRemoteBridge

func NewRemoteBridge(user string, record hosts.Record, cache *ClientCache, reg hostexec.Registry, recipeDir, runAs string, env map[string]string, allowedPaths map[string]string) plugins.RemoteBridge

NewRemoteBridge returns a RemoteBridge for one plugin host invocation. NewRemoteBridge ...

func ObserveRecipeRun

func ObserveRecipeRun(obs metrics.Observer, recipe cuetry.Recipe, execute bool, start time.Time, err error)

ObserveRecipeRun ...

func ObserveRecipeStep

func ObserveRecipeStep(obs metrics.Observer, kind string, start time.Time, rows []HostExecResult, retryAttempts int)

ObserveRecipeStep ...

func PluginExecStatus

func PluginExecStatus(success, skipped bool) string

PluginExecStatus ...

func PrintStaticTable

func PrintStaticTable(records []hosts.Record) error

PrintStaticTable prints the records as an ASCII table to stdout and exits. PrintStaticTable ...

func ReadTrueNASBridgeReady

func ReadTrueNASBridgeReady(br *bufio.Reader) (int, error)

ReadTrueNASBridgeReady scans shell output for the python bridge READY line (used in tests).

func RecipeHostMaxConc

func RecipeHostMaxConc(step cuetry.Step, defaults *cuetry.RecipeDefaults) int

RecipeHostMaxConc ...

func RecordGraphStepStdout

func RecordGraphStepStdout(recipe cuetry.Recipe, step cuetry.Step, kind string, store *cuetry.StepOutputStore, rows []HostExecResult)

RecordGraphStepStdout ...

func RecordMaxAttempts

func RecordMaxAttempts(attemptMax *atomic.Int32, attempts int)

RecordMaxAttempts ...

func RecordStepHostResults

func RecordStepHostResults(store *cuetry.StepResultStore, stepID string, rows []HostExecResult)

RecordStepHostResults ...

func RegisterStepExecutor

func RegisterStepExecutor(kind string, exec StepExecutor)

RegisterStepExecutor registers an executor for a specific step kind.

func RemoteOpts

func RemoteOpts(s cuetry.Step) *cuetry.RemoteExec

RemoteOpts returns the SSH/fan-out options for a step, or nil for local-only steps (template, ai) that do not implement cuetry.RemoteStep. The cuetry helpers that consume *RemoteExec are nil-safe.

func ResolveAgentTransferSigningHints

func ResolveAgentTransferSigningHints(configPath string, cloud AgentCloudBackend, ref *CloudBackendRef) (cloudtransfer.SigningHints, error)

ResolveAgentTransferSigningHints loads honey config when ref is set and fills AWS/GCP signing hints (same semantics as the web files API). configPath is the explicit or resolved honey YAML path. ResolveAgentTransferSigningHints ...

func ResolveAppDialer

func ResolveAppDialer(_ context.Context, user string, rec hosts.Record, _ string) (proxy.Dialer, io.Closer, error)

ResolveAppDialer returns the correct proxy.Dialer and an optional io.Closer for any hosts.Record. It hides all provider-specific connection logic (SSH, K8s exec, TrueNAS shell API, etc.). ResolveAppDialer ...

func ResolveAppDialerWithCache

func ResolveAppDialerWithCache(user string, rec hosts.Record, cache *ClientCache) (proxy.Dialer, io.Closer, error)

ResolveAppDialerWithCache returns an app proxy dialer, borrowing SSH clients from cache when available. ResolveAppDialerWithCache ...

func RewritePluginConfigTunnelStep

func RewritePluginConfigTunnelStep(config []byte, pluginID string, tunnelCoord *RecipeTunnelCoordinator, sshUser string, target hosts.Record, execute bool) ([]byte, error)

RewritePluginConfigTunnelStep sets base_url from a recipe tunnel step endpoint. When pluginID is rclone, tunnel_step or a non-empty base_url is required on execute. RewritePluginConfigTunnelStep ...

func RunCueRecipeSteps

func RunCueRecipeSteps(ctx context.Context, out io.Writer, p CueRecipeRunParams, rec *SessionRecorder) (runErr error)

RunCueRecipeSteps executes a CUE recipe over a slice of target records.

func RunCueStepHooks

func RunCueStepHooks(ctx context.Context, opts ExecutionOptions, stepIdx int, kind string, step cuetry.Step, r hosts.Record, tc TargetContext, res *HostExecResult, recipeScopedKV bool)

RunCueStepHooks ...

func RunDockerInteractiveWithRecorder

func RunDockerInteractiveWithRecorder(user string, r hosts.Record, recorder *SessionRecorder, reg hostexec.Registry) error

RunDockerInteractiveWithRecorder ...

func RunK8sInteractiveWithRecorder

func RunK8sInteractiveWithRecorder(user string, r hosts.Record, recorder *SessionRecorder) error

RunK8sInteractiveWithRecorder ...

func RunRecipe

func RunRecipe(_ context.Context, _ RunParams, events chan<- Event) error

RunRecipe executes a recipe and emits lifecycle events.

func RunSSHInteractive

func RunSSHInteractive(user string, r hosts.Record, recorder *SessionRecorder) error

RunSSHInteractive opens a login shell over crypto/ssh (respects ~/.ssh/config), or a Proxmox LXC/QEMU serial PVE console when exec_mode/token match the same policy as the web UI. RunSSHInteractive ...

func RunTerminalInteractive

func RunTerminalInteractive(user string, r hosts.Record, console string, reg hostexec.Registry) error

RunTerminalInteractive opens an interactive session (SSH, K8s, Docker, TrueNAS API shell, or Proxmox) on os.Stdin/Stdout. RunTerminalInteractive ...

func RunTrueNASShellInteractive

func RunTrueNASShellInteractive(ctx context.Context, console string, r hosts.Record, recorder *SessionRecorder) error

RunTrueNASShellInteractive ...

func RunTrueNASTunnel

func RunTrueNASTunnel(ctx context.Context, _ string, r hosts.Record, localFwd string, out io.Writer) error

RunTrueNASTunnel listens locally and forwards each connection through the TrueNAS API shell dial bridge into the guest at remoteHost:remotePort (as seen from inside the guest). RunTrueNASTunnel ...

func SSHClientCacheKey

func SSHClientCacheKey(user string, r hosts.Record) string

SSHClientCacheKey is the stable cache key for a pooled SSH client for (user, record). SSHClientCacheKey ...

func SetupRecipeWorkspace added in v0.3.7

func SetupRecipeWorkspace(env map[string]string) (string, func(), error)

SetupRecipeWorkspace creates a unique temporary directory for the recipe run and injects it into env as HONEY_WORKSPACE. It returns the path and a cleanup function. Centralized here so CLI cue-exec, API, Webhooks, and Scheduler runs all get consistent behavior.

func ShellSingleQuote

func ShellSingleQuote(s string) string

ShellSingleQuote ...

func ShellSingleQuoted

func ShellSingleQuoted(s string) string

ShellSingleQuoted ...

func StartK8sPortForward

func StartK8sPortForward(ctx context.Context, r hosts.Record, localPort, remotePort int) (host string, port int, stop func(), err error)

StartK8sPortForward starts a non-blocking k8s port-forward; returns local listen host/port after readyCh. StartK8sPortForward ...

func StartTrueNASForward

func StartTrueNASForward(ctx context.Context, user string, r hosts.Record, localFwd string) (host string, port int, stop func(), err error)

StartTrueNASForward starts a non-blocking TrueNAS API shell tunnel. StartTrueNASForward ...

func StreamCommandParallel added in v0.3.7

func StreamCommandParallel(ctx context.Context, user string, jobs []TargetContext, kvTunnel bool, remoteCmd SSHRemoteCmdFunc, out chan<- HostExecResult, opts BatchOptions) error

StreamCommandParallel runs the command on records and streams results to out channel. It does not close the channel itself. StreamCommandParallel ...

func StreamCueRecipeSteps

func StreamCueRecipeSteps(ctx context.Context, p CueRecipeRunParams, out chan<- HostExecResult) error

StreamCueRecipeSteps ...

func StreamCueRecipeStepsGraph

func StreamCueRecipeStepsGraph(ctx context.Context, run *CueRun, out chan<- HostExecResult) error

StreamCueRecipeStepsGraph ...

func StreamParallel

func StreamParallel[T any](jobs []T, maxConc int, worker func(T))

StreamParallel executes a generic job list concurrently with a bounded semaphore.

func StreamSFTPDownloadParallel

func StreamSFTPDownloadParallel(ctx context.Context, user string, jobs []SFTPDownloadJob, out chan<- HostExecResult, opts BatchOptions) error

StreamSFTPDownloadParallel downloads files from multiple hosts in parallel. StreamSFTPDownloadParallel ...

func StreamSFTPUploadParallel

func StreamSFTPUploadParallel(ctx context.Context, user string, recs []TargetContext, localAbs, remotePath string, out chan<- HostExecResult, opts BatchOptions) error

StreamSFTPUploadParallel uploads the same local file to remotePath on each record (SFTP over DialHoneyClient). Failures on one host do not cancel others. StreamSFTPUploadParallel ...

func StreamScriptContentRunParallel

func StreamScriptContentRunParallel(ctx context.Context, user string, recs []TargetContext, scriptContent, fileExtension string, scriptOpts ScriptUploadRunOptions, out chan<- HostExecResult, opts BatchOptions) error

StreamScriptContentRunParallel writes scriptContent to a local temp file, uploads it to each host, runs it using Rundeck-style script-file semantics, and removes the local temp file afterwards. StreamScriptContentRunParallel ...

func StreamScriptUploadRunParallel

func StreamScriptUploadRunParallel(ctx context.Context, user string, recs []TargetContext, localAbs, remotePath string, kvTunnel bool, remoteCmd SSHRemoteCmdFunc, out chan<- HostExecResult, opts BatchOptions) error

StreamScriptUploadRunParallel uploads a script and executes it on multiple hosts in parallel. StreamScriptUploadRunParallel ...

func StreamScriptUploadRunParallelWithOptions

func StreamScriptUploadRunParallelWithOptions(ctx context.Context, user string, recs []TargetContext, localAbs, remotePath string, kvTunnel bool, remoteCmd SSHRemoteCmdFunc, scriptOpts ScriptUploadRunOptions, out chan<- HostExecResult, opts BatchOptions) error

StreamScriptUploadRunParallelWithOptions uploads a script and executes it with optional interpreter/cleanup behavior. StreamScriptUploadRunParallelWithOptions ...

func SummarizeAgentTransferEvents

func SummarizeAgentTransferEvents(events []AgentTransferEvent) string

SummarizeAgentTransferEvents ...

func TransferConfigFromSessionHoney

func TransferConfigFromSessionHoney(path string, f *config.File) config.TransferConfigEffective

TransferConfigFromSessionHoney ...

func TransferStagingObjectKey

func TransferStagingObjectKey(cloud AgentCloudBackend, src, dst hosts.Record) string

TransferStagingObjectKey builds a unique object key when the caller leaves cloud.Object empty. TransferStagingObjectKey ...

func TruenasApplianceSSHForwardEligible

func TruenasApplianceSSHForwardEligible(r hosts.Record) bool

TruenasApplianceSSHForwardEligible ...

func TruenasTunnelRunner

func TruenasTunnelRunner() truenasprovider.TunnelRunner

TruenasTunnelRunner returns the ui-backed TrueNAS API-shell port-forward runner, injected into the truenas provider factory by the composition root. TruenasTunnelRunner ...

func TruenasUpstreamDialer

func TruenasUpstreamDialer() truenasprovider.UpstreamDialer

TruenasUpstreamDialer returns the ui-backed TrueNAS API-shell upstream dialer. TruenasUpstreamDialer ...

func TruncateCueTranscript

func TruncateCueTranscript(s string, maxChars int) string

TruncateCueTranscript limits transcript size for LLM input; keeps head and tail with a banner if truncated. TruncateCueTranscript ...

func TunnelDerivedKey

func TunnelDerivedKey(mode, provider, hostKey, spec string) string

TunnelDerivedKey ...

func TunnelLookupKeyForShare

func TunnelLookupKeyForShare(shareKey, derivedKey string) string

TunnelLookupKeyForShare returns a stable global pool key from recipe tunnel config. TunnelLookupKeyForShare ...

func WithHostFacts

func WithHostFacts(ctx context.Context, facts map[string]map[string]any) context.Context

WithHostFacts ...

func WrapRecordingReader

func WrapRecordingReader(inner io.Reader, recorder *SessionRecorder, direction string) io.Reader

WrapRecordingReader returns a Reader that tees reads into recorder when non-nil. WrapRecordingReader ...

func WrapRecordingWriter

func WrapRecordingWriter(inner io.Writer, recorder *SessionRecorder, direction string) io.Writer

WrapRecordingWriter returns a Writer that tees writes into recorder when non-nil. WrapRecordingWriter ...

func WriteCueKVTunnelDryLine

func WriteCueKVTunnelDryLine(out io.Writer, recipe cuetry.Recipe, stepIdx int, step cuetry.Step, def *cuetry.RecipeDefaults)

WriteCueKVTunnelDryLine ...

func WriteCueSSHPrivateKeyDryLine

func WriteCueSSHPrivateKeyDryLine(out io.Writer, stepIdx int, step cuetry.Step, def *cuetry.RecipeDefaults)

WriteCueSSHPrivateKeyDryLine ...

func WriteCueStepHooksDryLines

func WriteCueStepHooksDryLines(out io.Writer, stepIdx int, step cuetry.Step)

WriteCueStepHooksDryLines prints one plan line per configured hook (no secrets). WriteCueStepHooksDryLines ...

func WriteCueStepNotifyDryLine

func WriteCueStepNotifyDryLine(out io.Writer, step cuetry.Step)

WriteCueStepNotifyDryLine prints one plan line when notify is enabled (boolean only; no secrets). WriteCueStepNotifyDryLine ...

func WriteCueStepRetryDryLine

func WriteCueStepRetryDryLine(out io.Writer, stepIdx int, cfg cuetry.RecipeStepRetry)

WriteCueStepRetryDryLine prints retry settings when enabled. WriteCueStepRetryDryLine ...

func WriteWhenDryLines

func WriteWhenDryLines(out interface{ Write([]byte) (int, error) }, stepIdx int, step cuetry.Step, recipe cuetry.Recipe, targets []hosts.Record, store *cuetry.StepResultStore, cliEnv map[string]string, execute bool) error

WriteWhenDryLines ...

Types

type AIExecutor

type AIExecutor struct{}

AIExecutor executes the corresponding recipe step.

func (*AIExecutor) ExecuteDryRun

func (e *AIExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*AIExecutor) ExecuteStream

func (e *AIExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type AgentCloudBackend

type AgentCloudBackend struct {
	Provider string `json:"provider"`
	Bucket   string `json:"bucket"`
	Prefix   string `json:"prefix,omitempty"`
	Object   string `json:"object,omitempty"`
	Region   string `json:"region,omitempty"`
	Endpoint string `json:"endpoint,omitempty"`
}

AgentCloudBackend describes the cloud object target path for staging. AgentCloudBackend ...

func AgentTransferCloudFromRecipe

func AgentTransferCloudFromRecipe(c *cuetry.RecipeAgentTransferCloud) AgentCloudBackend

AgentTransferCloudFromRecipe ...

type AgentTransferEndpoint

type AgentTransferEndpoint struct {
	Record hosts.Record `json:"record"`
	Path   string       `json:"path"`
}

AgentTransferEndpoint identifies one source/destination endpoint for transfer. AgentTransferEndpoint ...

type AgentTransferEvent

type AgentTransferEvent struct {
	Stage     string    `json:"stage"`
	Host      string    `json:"host,omitempty"`
	Success   bool      `json:"success"`
	Message   string    `json:"message,omitempty"`
	Error     string    `json:"error,omitempty"`
	Attempt   int       `json:"attempt,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

AgentTransferEvent is emitted for each orchestration stage. AgentTransferEvent ...

func ExecuteAgentCloudTransfer

func ExecuteAgentCloudTransfer(job AgentTransferJob, cache *ClientCache) ([]AgentTransferEvent, error)

ExecuteAgentCloudTransfer orchestrates source upload and destination download using ephemeral transfer agents over existing HostClient connections (SSH / k8s pod exec abstraction). ExecuteAgentCloudTransfer ...

func ExecuteAgentCloudTransferWithEmit

func ExecuteAgentCloudTransferWithEmit(job AgentTransferJob, cache *ClientCache, emit func(AgentTransferEvent)) ([]AgentTransferEvent, error)

ExecuteAgentCloudTransferWithEmit runs the agent cloud transfer job with a specific emit function.

func RunAgentTransferWithFallback

func RunAgentTransferWithFallback(
	ctx context.Context,
	cache *ClientCache,
	sshUser, agentOverride, preferredAgentPath, agentBuildCacheDir, agentRemoteDir string,
	src, dst hosts.Record,
	srcPath, dstPath string,
	cloud AgentCloudBackend,
	keepObject bool,
	maxRetries int,
	hints cloudtransfer.SigningHints,
	transferCfg config.TransferConfigEffective,
	emit func(AgentTransferEvent),
) ([]AgentTransferEvent, error)

RunAgentTransferWithFallback runs Build + Execute, transparently retrying via the agent path on fallback-path failure when transferCfg.PresignedRetryWithAgent is true. Returns the combined event timeline across both attempts so the caller always sees the full record.

emit may be nil; when non-nil it receives events as they happen for both attempts (the original fallback-path attempt and the agent-path retry). RunAgentTransferWithFallback ...

type AgentTransferExecutor

type AgentTransferExecutor struct{}

AgentTransferExecutor executes the corresponding recipe step.

func (*AgentTransferExecutor) ExecuteDryRun

ExecuteDryRun executes a dry run of the step.

func (*AgentTransferExecutor) ExecuteStream

func (e *AgentTransferExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type AgentTransferJob

type AgentTransferJob struct {
	SSHUser                 string                `json:"ssh_user"`
	ResolvedSourceUser      string                `json:"resolved_source_user"`
	ResolvedDestUser        string                `json:"resolved_dest_user"`
	AgentLocalAbs           string                `json:"agent_local_path"`
	SourceAgentLocalAbs     string                `json:"source_agent_local_path,omitempty"`
	DestAgentLocalAbs       string                `json:"dest_agent_local_path,omitempty"`
	AgentRemoteDir          string                `json:"agent_remote_dir,omitempty"`
	Source                  AgentTransferEndpoint `json:"source"`
	Destination             AgentTransferEndpoint `json:"destination"`
	Cloud                   AgentCloudBackend     `json:"cloud"`
	CredentialProvider      string                `json:"credential_provider,omitempty"`
	CredentialEnv           map[string]string     `json:"credential_env,omitempty"`
	CredentialExpiresAtUnix int64                 `json:"credential_expires_at_unix,omitempty"`
	KeepObject              bool                  `json:"keep_object,omitempty"`
	MaxRetries              int                   `json:"max_retries,omitempty"`
	// FallbackPlan is non-nil when the curl-based presigned-URL transport should be
	// used instead of the staged-agent path. See docs/superpowers/specs/2026-05-12-presigned-url-transfer-path-design.md.
	FallbackPlan          *presign.Plan `json:"-"`
	FallbackCapabilitySrc string        `json:"-"`
	FallbackCapabilityDst string        `json:"-"`
	// RetryWithAgentOnCurlFailure controls whether a fallback-path failure transparently
	// retries via the agent path.
	RetryWithAgentOnCurlFailure bool `json:"retry_with_agent_on_curl_failure,omitempty"`
}

AgentTransferJob describes one A->cloud->B transfer orchestration request. AgentTransferJob ...

func BuildAgentTransferJob

func BuildAgentTransferJob(
	ctx context.Context,
	cache *ClientCache,
	sshUser, agentOverride, preferredAgentPath, agentBuildCacheDir, agentRemoteDir string,
	src, dst hosts.Record,
	srcPath, dstPath string,
	cloud AgentCloudBackend,
	keepObject bool,
	maxRetries int,
	hints cloudtransfer.SigningHints,
	transferCfg config.TransferConfigEffective,
) (AgentTransferJob, error)

BuildAgentTransferJob wires cloud credentials, per-target agent binaries, and staging object key. preferredAgentPath is used when agentOverride is empty (e.g. web server default binary); agentBuildCacheDir overrides the directory for cross-compiled agents (empty uses HONEY_TRANSFER_AGENT_CACHE or os temp).

transferCfg controls whether the fallback-path (presigned-URL) transport is attempted before falling back to staging the transfer-agent binary. When transferCfg.ForceAgentPath is true, the curl branch is bypassed. BuildAgentTransferJob ...

type AgentTransferValidationError

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

AgentTransferValidationError indicates user/input issues (HTTP 400). AgentTransferValidationError ...

func (*AgentTransferValidationError) Error

type AppDialerTransport

type AppDialerTransport string

AppDialerTransport describes the transport used to reach an app upstream. AppDialerTransport ...

const (
	// AppDialerTransportSSH means the upstream is reached through a regular SSH client.
	AppDialerTransportSSH AppDialerTransport = "ssh"
	// AppDialerTransportInMemory means the upstream is reached through a provider-native tunnel.
	AppDialerTransportInMemory AppDialerTransport = "in-memory"
)

func TransportForAppDialer

func TransportForAppDialer(rec hosts.Record) AppDialerTransport

TransportForAppDialer returns the transport family used for a record's app upstream connection. TransportForAppDialer ...

type BatchOptions

type BatchOptions struct {
	MaxConc        int
	Cache          *ClientCache
	RecipeKV       *RecipeKVCoordinator
	RecipeScopedKV bool
	Post           SSHPostHostResultFunc
	RetryCfg       cuetry.RecipeStepRetry
	Obs            metrics.Observer
	AttemptMax     *atomic.Int32
	Reg            hostexec.Registry
	// CmdTimeout bounds each per-host remote command; 0 means no timeout. On
	// expiry the SSH session is closed (best-effort kill) and the host result
	// is marked failed/timed-out.
	CmdTimeout time.Duration
	// MaxOutputBytes limits the captured output per host. 0 = default (6000), < 0 = unlimited.
	MaxOutputBytes int
}

BatchOptions groups the cross-cutting knobs shared by the parallel SSH/SFTP/script runners (previously trailing positional parameters). Zero values are valid: a nil Cache makes the runner build a short-lived one from Reg; a nil AttemptMax/Obs disables the corresponding bookkeeping. BatchOptions ...

type BiometricVerifier

type BiometricVerifier interface {
	VerifyToken(actor, token string) bool
}

BiometricVerifier verifies a biometric step-up token for an actor. Implemented by *webauthn.Manager; an interface here keeps the engine free of that import.

type CacheStats

type CacheStats struct {
	Hits         int64
	Misses       int64
	RaceHits     int64
	DialAttempts int64
	DialErrors   int64
}

CacheStats holds connection metrics from the client cache.

type ClientCache

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

ClientCache maintains a pool of open HostClient connections for reuse across steps. ClientCache ...

func NewClientCache

func NewClientCache() *ClientCache

NewClientCache creates a new uninitialized cache. You must call SetRegistry on it before it can dial properly. NewClientCache ...

func (*ClientCache) AcquireLease

func (c *ClientCache) AcquireLease(user string, r hosts.Record) (*ClientLease, error)

AcquireLease returns a cached client and tracks a lightweight borrow for app proxy sessions.

func (*ClientCache) BorrowSSH

func (c *ClientCache) BorrowSSH(user string, hop hosts.Record) (interface{}, bool)

BorrowSSH is used to wire up the ExecRegistry SSHBorrower.

func (*ClientCache) Clients

func (c *ClientCache) Clients() map[string]HostClient

Clients ...

func (*ClientCache) CloseAll

func (c *ClientCache) CloseAll()

CloseAll closes all cached connections and clears the cache.

func (*ClientCache) Evict

func (c *ClientCache) Evict(user string, r hosts.Record)

Evict removes the cached client for this host (if any) and closes it so the next GetOrDial establishes a fresh connection.

func (*ClientCache) GetOrDial

func (c *ClientCache) GetOrDial(user string, r hosts.Record) (HostClient, error)

GetOrDial returns an existing connection or dials a new one and stores it.

func (*ClientCache) Reg

func (c *ClientCache) Reg() hostexec.Registry

Reg returns the executor registry.

func (*ClientCache) Registry

func (c *ClientCache) Registry() hostexec.Registry

Registry ...

func (*ClientCache) SetRegistry

func (c *ClientCache) SetRegistry(reg hostexec.Registry)

SetRegistry configures the executor registry.

func (*ClientCache) Stats

func (c *ClientCache) Stats() CacheStats

Stats returns a snapshot of cache metrics.

type ClientLease

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

ClientLease is a borrowed cached host connection. Close releases the borrow without directly closing the shared underlying connection. ClientLease ...

func (*ClientLease) Close

func (l *ClientLease) Close() error

Close releases the lease. The cached connection remains available until eviction or CloseAll.

func (*ClientLease) HostClient

func (l *ClientLease) HostClient() HostClient

HostClient returns the borrowed client.

type CloudBackendRef

type CloudBackendRef struct {
	Kind  string `json:"kind"`
	Name  string `json:"name,omitempty"`
	Index *int   `json:"index,omitempty"`
}

CloudBackendRef selects a backend entry from honey YAML for agent-transfer signing hints. CloudBackendRef ...

func CloudBackendRefFromRecipe

func CloudBackendRefFromRecipe(r *cuetry.RecipeCloudBackendRef) *CloudBackendRef

CloudBackendRefFromRecipe ...

type CommandExecutor

type CommandExecutor struct{}

CommandExecutor executes the corresponding recipe step.

func (*CommandExecutor) ExecuteDryRun

func (e *CommandExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*CommandExecutor) ExecuteStream

func (e *CommandExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type CommandRunRequest

type CommandRunRequest struct {
	Command        string
	IsScript       bool
	FileExtension  string
	ScriptOpts     ScriptUploadRunOptions
	Target         *hostapi.SearchHostsInput
	Records        []hosts.Record // bypasses Target resolution if populated
	SSHUser        string
	ActorID        string
	AISystemPrompt string
	RecordSession  bool
	RecordLabel    string
	CmdTimeout     time.Duration
	MaxOutputBytes int
}

CommandRunRequest is the high-level input for executing ad-hoc commands or scripts.

type CommandRunner

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

CommandRunner owns the full ad-hoc remote execution lifecycle: target resolution, session recording, and streaming execution.

func NewCommandRunner

func NewCommandRunner(opts CommandRunnerOptions) *CommandRunner

NewCommandRunner builds a CommandRunner from injected dependencies.

func (*CommandRunner) Execute

func (r *CommandRunner) Execute(ctx context.Context, req CommandRunRequest) (<-chan HostExecResult, error)

Execute runs the command or script and streams the results. It manages the session recording internally if enabled.

func (*CommandRunner) ExecuteAndWait

func (r *CommandRunner) ExecuteAndWait(ctx context.Context, req CommandRunRequest) ([]HostExecResult, error)

ExecuteAndWait runs the command to completion and discards the streamed host results. For callers that only need side effects (like recording) but not the stream.

type CommandRunnerOptions

type CommandRunnerOptions struct {
	ExecRegistry   hostexec.Registry
	SearchRegistry *searchrun.Registry // required for host resolution
	Metrics        metrics.Observer
	RecordDir      string // "" disables session recording
}

CommandRunnerOptions configures a CommandRunner. All fields are injected at construction.

type CueRecipeRunParams

type CueRecipeRunParams struct {
	Recipe         cuetry.Recipe
	RecipeDir      string
	Records        []hosts.Record
	SSHUser        string
	ActorID        string // caller identity for OPA policy input; "" resolves to "api"
	CLIEnv         map[string]string
	ConfigPath     string
	AISystemPrompt string
	SecretResolver cuetry.SecretResolver
	PluginMgr      *plugins.Manager
	Execute        bool
	JSON           bool
	Reg            hostexec.Registry
	Obs            metrics.Observer
	Pools          *postgres.PoolManager
	Cache          *ClientCache     // optional shared cache; nil = create a fresh per-run cache
	Enforcer       *policy.Enforcer // optional OPA host-filter gate; nil = allow all
	Inventory      config.Inventory // config inventory; resolved per-host into OPA host_vars
	CmdTimeout     time.Duration    // per-host command timeout; 0 = none
}

CueRecipeRunParams ...

type CueRun

type CueRun struct {
	Params            CueRecipeRunParams
	Cache             *ClientCache
	RecipeKV          *RecipeKVCoordinator
	TunnelCoord       *RecipeTunnelCoordinator
	DockerPluginSess  *plugins.DockerHostSession
	OutputStore       *cuetry.StepOutputStore
	OutputCapture     *cuetry.RecipeOutputCapture
	Facts             map[string]map[string]any
	TriggeredHandlers map[string]bool
}

CueRun ...

func (*CueRun) ExecuteStep

func (run *CueRun) ExecuteStep(ctx context.Context, i int, kind string, step cuetry.Step, targets []hosts.Record, history [][]HostExecResult, ch chan<- HostExecResult, retryCfg cuetry.RecipeStepRetry, attemptMax *atomic.Int32) error

ExecuteStep dispatches execution to the appropriate step logic via StepExecutors.

func (*CueRun) GatherFacts

func (run *CueRun) GatherFacts(ctx context.Context)

GatherFacts ...

func (*CueRun) StepEnv

func (run *CueRun) StepEnv(ctx context.Context, step *cuetry.StepBase, target *hosts.Record, resolveSecrets, dryRun bool) (map[string]string, error)

StepEnv resolves the effective environment for one step on one target. All run-scoped inputs (secret resolver, recipe defaults, CLI env, prior step outputs, output capture, and live KV) come from the run; callers pass only what varies per step/target. Env cannot be pre-resolved before the run because OutputStore and KV are populated as earlier steps execute.

type DockerExecutor

type DockerExecutor struct{}

DockerExecutor executes the corresponding recipe step.

func (*DockerExecutor) ExecuteDryRun

func (e *DockerExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*DockerExecutor) ExecuteStream

func (e *DockerExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type DockerNativeClient

type DockerNativeClient = dockerprovider.DockerNativeClient

DockerNativeClient is a type alias so existing ui code can continue using the unexported name.

type ErrPendingApproval

type ErrPendingApproval struct {
	ID     string
	Reason string
}

ErrPendingApproval signals that a run is held pending human approval.

func (*ErrPendingApproval) Error

func (e *ErrPendingApproval) Error() string

type Event

type Event interface {
	Kind() EventKind
}

Event is the interface for all engine events. Event ...

type EventKind

type EventKind string

EventKind identifies the type of an Event. EventKind ...

const (
	// EventKindStepStarted is emitted when a step begins execution.
	EventKindStepStarted EventKind = "StepStarted"
	// EventKindStepStdout is emitted for stdout chunks.
	EventKindStepStdout EventKind = "StepStdout"
	// EventKindStepStderr is emitted for stderr chunks.
	EventKindStepStderr EventKind = "StepStderr"
	// EventKindStepCompleted is emitted when a step succeeds.
	EventKindStepCompleted EventKind = "StepCompleted"
	// EventKindStepFailed is emitted when a step fails.
	EventKindStepFailed EventKind = "StepFailed"
)

type EventStepCompleted

type EventStepCompleted struct {
	StepIdx int
}

EventStepCompleted indicates step success. EventStepCompleted ...

func (EventStepCompleted) Kind

func (e EventStepCompleted) Kind() EventKind

Kind implements Event.

type EventStepFailed

type EventStepFailed struct {
	StepIdx int
	Error   error
}

EventStepFailed indicates step failure. EventStepFailed ...

func (EventStepFailed) Kind

func (e EventStepFailed) Kind() EventKind

Kind implements Event.

type EventStepStarted

type EventStepStarted struct {
	StepIdx int
}

EventStepStarted indicates a step started. EventStepStarted ...

func (EventStepStarted) Kind

func (e EventStepStarted) Kind() EventKind

Kind implements Event.

type EventStepStderr

type EventStepStderr struct {
	StepIdx int
	Output  []byte
}

EventStepStderr indicates stderr output. EventStepStderr ...

func (EventStepStderr) Kind

func (e EventStepStderr) Kind() EventKind

Kind implements Event.

type EventStepStdout

type EventStepStdout struct {
	StepIdx int
	Output  []byte
}

EventStepStdout indicates stdout output. EventStepStdout ...

func (EventStepStdout) Kind

func (e EventStepStdout) Kind() EventKind

Kind implements Event.

type ExecutionOptions

type ExecutionOptions struct {
	Execute           bool
	JSON              bool
	Recipe            cuetry.Recipe
	RecipeDir         string
	SSHUser           string
	ActorID           string
	CLIEnv            map[string]string
	AISystemPrompt    string
	SecretResolver    cuetry.SecretResolver
	PluginMgr         *plugins.Manager
	Obs               metrics.Observer
	Cache             *ClientCache
	RecipeKV          *RecipeKVCoordinator
	ConfigPath        string
	Enforcer          *policy.Enforcer
	Inventory         config.Inventory
	CmdTimeout        time.Duration
	Reg               hostexec.Registry
	Pools             *postgres.PoolManager
	Records           []hosts.Record
	OutputStore       *cuetry.StepOutputStore
	OutputCapture     *cuetry.RecipeOutputCapture
	Facts             map[string]map[string]any
	TriggeredHandlers map[string]bool
	TunnelCoord       *RecipeTunnelCoordinator
	// DockerPluginSess scopes remote runtime:docker plugin containers to the
	// run (one shim-container per plugin+host, torn down at run end). nil on
	// paths that never run remote docker plugins.
	DockerPluginSess *plugins.DockerHostSession
}

ExecutionOptions provides engine-level context dependencies for specific executors (like sub-recipes or SSH commands) without forcing the executor to depend on the entire CueRun lifecycle state.

type ExecutionRequest

type ExecutionRequest struct {
	Targets    []TargetContext
	Index      int
	Step       cuetry.Step
	Kind       string
	RetryCfg   cuetry.RecipeStepRetry
	AttemptMax *atomic.Int32
	History    [][]HostExecResult
}

ExecutionRequest represents a self-contained execution payload.

type Executor

type Executor = hostexec.Executor

Executor aliases the shared executor interface. Executor ...

type GetExecutor

type GetExecutor struct{}

GetExecutor executes the corresponding recipe step.

func (*GetExecutor) ExecuteDryRun

func (e *GetExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*GetExecutor) ExecuteStream

func (e *GetExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type GlobalTunnelPool

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

GlobalTunnelPool caches active tunnels keyed by share_key or derived spec hash. GlobalTunnelPool ...

func DefaultGlobalTunnelPool

func DefaultGlobalTunnelPool() *GlobalTunnelPool

DefaultGlobalTunnelPool returns the process-wide tunnel pool. DefaultGlobalTunnelPool ...

func NewGlobalTunnelPool

func NewGlobalTunnelPool(ttl time.Duration) *GlobalTunnelPool

NewGlobalTunnelPool creates a pool with the given idle TTL (0 = default 30m). NewGlobalTunnelPool ...

func (*GlobalTunnelPool) Acquire

func (p *GlobalTunnelPool) Acquire(ctx context.Context, key string, factory func(context.Context) (TunnelEndpoint, func(), error)) (TunnelEndpoint, func(), error)

Acquire returns an endpoint, creating via factory on miss. release() decrements refcount.

func (*GlobalTunnelPool) Close

func (p *GlobalTunnelPool) Close()

Close stops all entries and the sweeper.

type HostClient

type HostClient = hostexec.HostClient

HostClient aliases the shared execution interface (see internal/hostexec). HostClient ...

type HostClientTransferNode

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

HostClientTransferNode implements TransferNode by wrapping a generic HostClient.

func NewHostClientTransferNode

func NewHostClientTransferNode(record hosts.Record, client HostClient) *HostClientTransferNode

NewHostClientTransferNode creates a new TransferNode around a HostClient.

func (*HostClientTransferNode) CleanupAgent

func (n *HostClientTransferNode) CleanupAgent(_ context.Context, agentPath string) error

CleanupAgent removes the ephemeral agent binary.

func (*HostClientTransferNode) HostLabel

func (n *HostClientTransferNode) HostLabel() string

HostLabel returns the label.

func (*HostClientTransferNode) Record

func (n *HostClientTransferNode) Record() hosts.Record

Record returns the record.

func (*HostClientTransferNode) RunAgentSession

func (n *HostClientTransferNode) RunAgentSession(_ context.Context, agentPath string, mintJWE func(string) (string, error), postBootstrap []agentSessionHostMsg) (string, error)

RunAgentSession runs the agent session.

func (*HostClientTransferNode) RunScript

func (n *HostClientTransferNode) RunScript(_ context.Context, script string) (string, error)

RunScript executes a script.

func (*HostClientTransferNode) StageAgent

func (n *HostClientTransferNode) StageAgent(_ context.Context, localPath, remotePath string) (bool, string, error)

StageAgent stages the agent binary onto the node.

type HostExecResult

type HostExecResult struct {
	Name     string
	IP       string
	Provider string
	Success  bool
	Skipped  bool
	Changed  bool
	ExitCode int
	Output   string
	// Stdout is the step's raw stdout only, with no stderr mixed in — unlike
	// Output, which concatenates stdout+stderr for human display. Only
	// populated by executors that keep the two streams genuinely separate
	// internally (currently: plugin steps, via apiv1.ExecuteStepOutput);
	// empty otherwise (e.g. command/script steps, whose HostClient.Run
	// returns one already-merged stream from the SSH session — there is no
	// separate stdout to recover there). env_from/stepStdout consumers
	// should prefer this over Output when non-empty, since a step whose
	// process logs diagnostics to stderr (common, not a bug in the process)
	// would otherwise corrupt output_format: "json" parsing downstream.
	Stdout        string
	OutputCapture string
	// KVCaptureKey is set when a step wrote its output to the recipe KV store
	// (e.g. plugin.kv_key) instead of a named output capture. Unlike
	// OutputCapture, run.go's graph dispatch never overwrites this field, so
	// it survives to CueRecipeDisplayOutput to suppress the raw dump.
	KVCaptureKey string
	ErrMsg       string
	IsTransient  bool

	StepIndex int    `json:",omitempty"`
	StepID    string `json:",omitempty"`
	StepKind  string `json:",omitempty"`

	HookPhase  string
	HookOutput string
	HookFailed bool
}

HostExecResult is the outcome of one host execution step. HostExecResult ...

func ExecuteSFTPDownloadParallel

func ExecuteSFTPDownloadParallel(user string, jobs []SFTPDownloadJob, maxConc int) ([]HostExecResult, error)

ExecuteSFTPDownloadParallel runs each download job (possibly different local paths per host) in parallel. ExecuteSFTPDownloadParallel ...

func ExecuteSFTPUploadParallel

func ExecuteSFTPUploadParallel(user string, recs []TargetContext, localAbs, remotePath string, maxConc int) ([]HostExecResult, error)

ExecuteSFTPUploadParallel executes an SFTP upload in parallel across multiple hosts and returns results synchronously. ExecuteSFTPUploadParallel ...

func ExecuteSSHParallel

func ExecuteSSHParallel(user string, recs []TargetContext, remoteCmdFunc func(hosts.Record) string, maxConc int, reg hostexec.Registry) ([]HostExecResult, error)

ExecuteSSHParallel runs the same remote shell command on every record that has PrimaryIP set. Failures on individual hosts do not cancel others. It uses DialHoneyClient (golang.org/x/crypto/ssh + ~/.ssh/config) with known_hosts verification. ExecuteSSHParallel ...

func ExecuteScriptContentRunParallel

func ExecuteScriptContentRunParallel(user string, recs []TargetContext, scriptContent, fileExtension string, opts ScriptUploadRunOptions, maxConc int, reg hostexec.Registry) ([]HostExecResult, error)

ExecuteScriptContentRunParallel writes scriptContent to a local temp file, uploads it to each host, runs it using Rundeck-style script-file semantics in parallel, and returns results synchronously. ExecuteScriptContentRunParallel ...

func ExecuteScriptUploadRunParallel

func ExecuteScriptUploadRunParallel(user string, recs []TargetContext, localAbs, remotePath, remoteCmd string, maxConc int) ([]HostExecResult, error)

ExecuteScriptUploadRunParallel uploads localAbs to remotePath on each host over SFTP, then runs remoteCmd on the same SSH connection (one session per host per step). ExecuteScriptUploadRunParallel ...

func FilterTargetsByWhen

func FilterTargetsByWhen(
	ctx context.Context,
	recipe cuetry.Recipe,
	step cuetry.Step,
	targets []hosts.Record,
	store *cuetry.StepResultStore,
	secretResolver cuetry.SecretResolver,
	kv cuetry.KVReader,
	cliEnv map[string]string,
	execute bool,
) ([]hosts.Record, []HostExecResult, error)

FilterTargetsByWhen ...

func RunCueStepSummarizeExecute added in v0.3.7

func RunCueStepSummarizeExecute(ctx context.Context, recipe cuetry.Recipe, stepIdx int, step cuetry.Step, history [][]HostExecResult, aiSystemPromptFromCfg string) HostExecResult

RunCueStepSummarizeExecute performs the actual AI model completion based on recipe context.

func RunOneRemoteSSH

func RunOneRemoteSSH(ctx context.Context, user string, tc TargetContext, cache *ClientCache, kvTunnel bool, cmd SSHRemoteCmdFunc, recipeKV *RecipeKVCoordinator, recipeScopedKV bool, cmdTimeout time.Duration, maxOutputBytes int) HostExecResult

RunOneRemoteSSH executes a single remote command on a host with transient retry support.

func RunOneSFTPUploadWithProgress

func RunOneSFTPUploadWithProgress(user string, r hosts.Record, localAbs, remotePath string, cache *ClientCache, onProgress func(written, total int64)) HostExecResult

RunOneSFTPUploadWithProgress uploads one local file to remotePath on r, like runOneSFTPUpload. onProgress is optional; it receives cumulative bytes written toward the remote and the local file size. Live updates are emitted for *sshclient.HoneyClient (SFTP); other executors only report start/end. RunOneSFTPUploadWithProgress ...

func SortHostExecForUI

func SortHostExecForUI(s []HostExecResult) []HostExecResult

SortHostExecForUI orders failures first, then host name (case-insensitive). SortHostExecForUI ...

func StreamCueLoopStep

func StreamCueLoopStep(ctx context.Context, run *CueRun, i int, step cuetry.Step, targets []hosts.Record, history [][]HostExecResult, out chan<- HostExecResult) ([]HostExecResult, error)

StreamCueLoopStep ...

func StreamCueRecipeStep

func StreamCueRecipeStep(ctx context.Context, run *CueRun, i int, step cuetry.Step, history [][]HostExecResult, out chan<- HostExecResult) (stepResults []HostExecResult, err error)

StreamCueRecipeStep ...

func WhenSkippedResult

func WhenSkippedResult(r hosts.Record) HostExecResult

WhenSkippedResult ...

type HostExecRetryOutcome

type HostExecRetryOutcome struct {
	Result              HostExecResult
	Attempts            int
	LastAttemptDuration time.Duration
}

HostExecRetryOutcome is the result of RunHostExecWithRetry. HostExecRetryOutcome ...

func RunHostExecWithRetry

func RunHostExecWithRetry(ctx context.Context, cfg cuetry.RecipeStepRetry, run func() HostExecResult) HostExecRetryOutcome

RunHostExecWithRetry ...

type HostTransport added in v0.3.7

type HostTransport interface {
	RunCommand(ctx context.Context, user string, tc TargetContext, cache *ClientCache, kvTunnel bool, cmd SSHRemoteCmdFunc, opts BatchOptions) HostExecResult
}

HostTransport defines the seam for executing a shell command on a target record. Implementations map to specific execution environments (SSH, TrueNAS, Local OS).

type K8sExecutor

type K8sExecutor struct{}

K8sExecutor executes the corresponding recipe step.

func (*K8sExecutor) ExecuteDryRun

ExecuteDryRun executes a dry run of the step.

func (*K8sExecutor) ExecuteStream

func (e *K8sExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type K8sNativeClient

type K8sNativeClient = k8sprovider.K8sNativeClient

K8sNativeClient is a type alias so existing ui code can continue using the unexported name.

type K8sPodExecutor

type K8sPodExecutor = k8sprovider.K8sPodExecutor

K8sPodExecutor is a type alias so existing ui code can continue using the unexported name.

type KVTunnelProvider

type KVTunnelProvider interface {
	SupportsKVTunnel() bool
}

KVTunnelProvider is an optional interface that HostClients can implement if they natively support or explicitly reject bootstrapping KV tunnels. KVTunnelProvider ...

type OPAExecutor

type OPAExecutor struct{}

OPAExecutor evaluates an inline rego policy step. It runs locally and emits a single result; a deny fails the step so later steps can gate on it.

func (*OPAExecutor) ExecuteDryRun

func (e *OPAExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, _ ExecutionOptions, out io.Writer) error

ExecuteDryRun writes the step plan line without compiling or evaluating.

func (*OPAExecutor) ExecuteStream

func (e *OPAExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream compiles and evaluates the policy, emitting one result.

type OpensearchExecutor

type OpensearchExecutor struct{}

OpensearchExecutor executes the corresponding recipe step.

func (*OpensearchExecutor) ExecuteDryRun

ExecuteDryRun executes a dry run of the step.

func (*OpensearchExecutor) ExecuteStream

func (e *OpensearchExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type PackageExecutor added in v0.3.7

type PackageExecutor struct{}

PackageExecutor executes the corresponding recipe step.

func (*PackageExecutor) ExecuteDryRun added in v0.3.7

ExecuteDryRun performs a dry run of the step.

func (*PackageExecutor) ExecuteStream added in v0.3.7

func (e *PackageExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type PluginExecutor

type PluginExecutor struct{}

PluginExecutor executes the corresponding recipe step.

func (*PluginExecutor) ExecuteDryRun

func (e *PluginExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*PluginExecutor) ExecuteStream

func (e *PluginExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type PluginLifecycle

type PluginLifecycle string

PluginLifecycle defines how the plugin manager is managed during a run. PluginLifecycle defines how the plugin manager is handled for a run.

const (
	// LifecycleShared uses a shared plugin cache.
	LifecycleShared PluginLifecycle = "shared"
	// LifecycleFresh creates a fresh plugin manager for the run.
	LifecycleFresh PluginLifecycle = "fresh"
)

type PostgresExecutor

type PostgresExecutor struct{}

PostgresExecutor executes the corresponding recipe step.

func (*PostgresExecutor) ExecuteDryRun

ExecuteDryRun executes a dry run of the step.

func (*PostgresExecutor) ExecuteStream

func (e *PostgresExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type PutExecutor

type PutExecutor struct{}

PutExecutor executes the corresponding recipe step.

func (*PutExecutor) ExecuteDryRun

func (e *PutExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*PutExecutor) ExecuteStream

func (e *PutExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type RecipeExecutor

type RecipeExecutor struct{}

RecipeExecutor executes the corresponding recipe step.

func (*RecipeExecutor) ExecuteDryRun

func (e *RecipeExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*RecipeExecutor) ExecuteStream

func (e *RecipeExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type RecipeKVCoordinator

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

RecipeKVCoordinator owns one operator-side stepkv session for a cue-exec run and one forward (SSH remote-forward or k8s exec bridge) per cached client key. The mutex is only held while the per-key placeholder is reserved; the slow handshake runs outside the lock so parallel hosts don't serialize. RecipeKVCoordinator ...

func NewRecipeKVCoordinator

func NewRecipeKVCoordinator(ttl time.Duration) *RecipeKVCoordinator

NewRecipeKVCoordinator constructs a coordinator; ttl defaults to stepKVTunnelTTL when <= 0. NewRecipeKVCoordinator ...

func (*RecipeKVCoordinator) Close

func (c *RecipeKVCoordinator) Close()

Close stops all remote listeners / k8s bridges and closes the stepkv session.

func (*RecipeKVCoordinator) EnsureK8sExecBridgeEnv

func (c *RecipeKVCoordinator) EnsureK8sExecBridgeEnv(user string, r hosts.Record, k8c *K8sNativeClient) (map[string]string, error)

EnsureK8sExecBridgeEnv returns HONEY_KV_* for this pod by multiplexing pod loopback HTTP to the shared stepkv session over a long-lived kubectl exec.

func (*RecipeKVCoordinator) EnsureKVTunnelEnv

func (c *RecipeKVCoordinator) EnsureKVTunnelEnv(user string, r hosts.Record, hc *sshclient.HoneyClient) (map[string]string, error)

EnsureKVTunnelEnv returns HONEY_KV_* for this host's remote-forward into the shared session.

func (*RecipeKVCoordinator) EnsureSession

func (c *RecipeKVCoordinator) EnsureSession() (*stepkv.Session, error)

EnsureSession returns the shared stepkv session, creating it if needed (no SSH forward).

func (*RecipeKVCoordinator) EnsureTrueNASAPIShellBridgeEnv

func (c *RecipeKVCoordinator) EnsureTrueNASAPIShellBridgeEnv(ctx context.Context, user string, r hosts.Record, cache *ClientCache) (map[string]string, error)

EnsureTrueNASAPIShellBridgeEnv attaches kv_tunnel for a TrueNAS row into the shared recipe stepkv session.

func (*RecipeKVCoordinator) InvalidateHost

func (c *RecipeKVCoordinator) InvalidateHost(user string, r hosts.Record)

InvalidateHost tears down this host's remote-forward or k8s exec bridge only (e.g. after cache evict). The shared stepkv session stays open for other hosts.

type RecipeMeta

type RecipeMeta struct {
	RecipePath        string                  `json:"recipe_path"`
	HostCount         int                     `json:"host_count"`
	RecipeContentHash string                  `json:"recipe_content_hash"`
	StartedAt         time.Time               `json:"started_at"`
	Hosts             []hosts.Record          `json:"hosts,omitempty"`
	Plan              string                  `json:"plan,omitempty"`
	Graph             *cuetry.RecipeGraphPlan `json:"graph,omitempty"`
}

RecipeMeta describes the recipe that a cue-exec batch is about to run. Recorded into the session file so a later "recent runs" enumeration can attribute the recording to a recipe and detect in-browser edits. RecipeMeta ...

type RecipeRunner

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

RecipeRunner owns the full recipe-execution lifecycle: prompt validation, secret resolution, run-params assembly, session recording, and dry-run or streaming execution. Callers translate their own inputs into a RunRequest.

func NewRecipeRunner

func NewRecipeRunner(opts RunnerOptions) *RecipeRunner

NewRecipeRunner builds a RecipeRunner from injected dependencies.

func (*RecipeRunner) AssessCommandRisk

func (r *RecipeRunner) AssessCommandRisk(ctx context.Context, req RunRequest) []StepRisk

AssessCommandRisk analyzes every command/script step in the request's recipe and returns a per-step risk assessment for review (no execution). When an OPA enforcer is configured it also evaluates the command_exec decision against the first target record as a representative context.

func (*RecipeRunner) DryRun

func (r *RecipeRunner) DryRun(ctx context.Context, req RunRequest) (string, error)

DryRun validates prompts and produces the recipe plan via the executor-based dry-run (each step's ExecuteDryRun), matching what a live run would attempt. When RecordSession is set (and no recorder is injected), it records the plan into a fresh recording.

func (*RecipeRunner) Execute

func (r *RecipeRunner) Execute(ctx context.Context, req RunRequest) (<-chan HostExecResult, error)

Execute validates prompts, builds run params, and streams the recipe over its target hosts. Pre-flight errors (prompt validation, secret resolver, recorder creation) are returned synchronously. Once execution starts, run errors arrive on the channel as a synthetic failed HostExecResult. The runner owns the recorder-close lifecycle (when not injected), completing when the returned channel closes.

func (*RecipeRunner) ExecuteAndWait

func (r *RecipeRunner) ExecuteAndWait(ctx context.Context, req RunRequest) error

ExecuteAndWait runs the recipe to completion and discards the streamed host results — for callers that only need the run's side effects (session recording) and not the per-host stream. Pre-flight errors are returned as-is; a run failure surfaces as a non-nil error.

type RecipeTunnelCoordinator

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

RecipeTunnelCoordinator tracks tunnel endpoints for one cue-exec run and releases pool refs on Close. RecipeTunnelCoordinator ...

func NewRecipeTunnelCoordinator

func NewRecipeTunnelCoordinator(pool *GlobalTunnelPool) *RecipeTunnelCoordinator

NewRecipeTunnelCoordinator creates a coordinator backed by the process-wide pool. NewRecipeTunnelCoordinator ...

func (*RecipeTunnelCoordinator) Acquire

func (c *RecipeTunnelCoordinator) Acquire(ctx context.Context, key string, factory func(context.Context) (TunnelEndpoint, func(), error)) (TunnelEndpoint, func(), error)

Acquire obtains or creates a tunnel from the global pool.

func (*RecipeTunnelCoordinator) Close

func (c *RecipeTunnelCoordinator) Close()

Close releases all pool references held by this run.

func (*RecipeTunnelCoordinator) Lookup

func (c *RecipeTunnelCoordinator) Lookup(stepID, user string, r hosts.Record) (TunnelEndpoint, bool)

Lookup returns the endpoint for a tunnel step id and host.

func (*RecipeTunnelCoordinator) LookupEndpoint

func (c *RecipeTunnelCoordinator) LookupEndpoint(stepID, user string, r hosts.Record) (string, int, bool)

LookupEndpoint implements plugins.TunnelCoordinator for postgres DSN rewrite.

func (*RecipeTunnelCoordinator) Register

func (c *RecipeTunnelCoordinator) Register(stepID, user string, r hosts.Record, ep TunnelEndpoint, release func())

Register stores an endpoint for tunnel_step lookup and holds the pool release until Close.

type RemoteFileEntry

type RemoteFileEntry = hostexec.RemoteFileEntry

RemoteFileEntry aliases remote file metadata for JSON APIs. RemoteFileEntry ...

type RiskStepFilter

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

RiskStepFilter wraps gateCommandRisk as a StepFilter so the risk gate participates in the same pipeline interface as policyStepFilter and whenStepFilter.

func NewRiskStepFilter

func NewRiskStepFilter(opts ExecutionOptions, kind, rawCommand, interpreter string) *RiskStepFilter

NewRiskStepFilter returns a StepFilter that gates targets via the command risk analysis (built-in critical signals + OPA command_exec decision).

func (*RiskStepFilter) Filter

func (f *RiskStepFilter) Filter(ctx context.Context, targets []TargetContext) ([]TargetContext, []HostExecResult, error)

Filter applies the command risk gate to the given targets.

type RunParams

type RunParams struct {
	Recipe         cuetry.Recipe
	RecipeDir      string
	Records        []hosts.Record
	SSHUser        string
	Execute        bool
	CliEnv         map[string]string
	ConfigPath     string
	SecretResolver cuetry.SecretResolver
	PluginMgr      *plugins.Manager
}

RunParams holds inputs for executing a recipe across hosts.

type RunReporter

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

RunReporter evaluates mail notification rules at the end of a recipe run and sends an HTML summary email if applicable.

func NewRunReporter

func NewRunReporter(host string, port int, username, password string) *RunReporter

NewRunReporter creates a new RunReporter instance with the provided SMTP configuration.

func (*RunReporter) Report

func (r *RunReporter) Report(ctx context.Context, recipe cuetry.Recipe, results []HostExecResult, runErr error)

Report sends a notification based on the run outcome and recipe configuration.

type RunRequest

type RunRequest struct {
	Recipe           cuetry.Recipe
	RecipeSourcePath string
	RecipeDir        string
	Target           *hostapi.SearchHostsInput
	Records          []hosts.Record // bypasses Target resolution if populated
	SSHUser          string
	// Source names the ingress that initiated this run ("web", "webhook",
	// "scheduler"); recorded on the recipe_run admission audit event.
	Source string
	// ActorID is the caller identity (JWT subject or trusted-proxy header),
	// used as OPA policy input. Empty resolves to "api" downstream.
	ActorID string
	// ApprovalID references a previously-created approval that, once approved,
	// lets a require_approval recipe proceed.
	ApprovalID string
	// BiometricToken is a WebAuthn step-up token that satisfies a require_biometric
	// verdict for the actor.
	BiometricToken string
	Env            map[string]string
	AISystemPrompt string
	RecordSession  bool
	RecordLabel    string
	// CmdTimeout bounds each per-host remote command; 0 = no timeout.
	CmdTimeout time.Duration
	// Recorder, when non-nil, is used as-is and NOT closed by the runner (the
	// caller owns its lifecycle — needed by the async webhook, which must know
	// the recording ID before deferred execution). When nil and RecordSession
	// is true, the runner opens and closes its own recorder.
	Recorder *SessionRecorder

	PluginPolicy PluginLifecycle
}

RunRequest is the high-level input: what recipe to run, against which hosts, with what env. The recipe is already parsed because parsing is caller-specific (webserver path/content resolution, webhook auth lookup, scheduler schedules).

type RunnerOptions

type RunnerOptions struct {
	ConfigPath     string
	Config         *config.File
	ExecRegistry   hostexec.Registry
	SearchRegistry *searchrun.Registry // required for host resolution
	Metrics        metrics.Observer
	Pools          *postgres.PoolManager
	Cache          *ClientCache       // optional shared SSH client cache; nil = per-run cache
	PluginCache    *plugincache.Cache // optional shared plugin manager; nil = fresh manager per run
	RecordDir      string             // "" disables session recording
	Enforcer       *policy.Enforcer   // optional OPA admission gate; nil = allow all
	Approvals      *approval.Store    // optional pending-approval store; nil = require_approval hard-denies
	Biometric      BiometricVerifier  // optional WebAuthn token verifier; nil = require_biometric hard-denies
	AuditSink      audit.Sink         // optional; nil = no recipe_run admission audit
}

RunnerOptions configures a RecipeRunner. All fields are injected at construction; the runner creates none of its own dependencies.

type SFTPDownloadJob

type SFTPDownloadJob struct {
	Record    hosts.Record
	RemoteAbs string
	LocalAbs  string
}

SFTPDownloadJob pairs a target host with a remote and local path for downloading. SFTPDownloadJob ...

type SSHPostHostResultFunc

type SSHPostHostResultFunc func(ctx context.Context, tc TargetContext, res *HostExecResult)

SSHPostHostResultFunc runs after each host's main SSH run and before the result is emitted (e.g. CUE step hooks). It may set res.HookPhase and res.HookOutput. Hook failures must not change the original step success fields. SSHPostHostResultFunc ...

func CueRecipeSSHPostHostResult

func CueRecipeSSHPostHostResult(_ context.Context, opts ExecutionOptions, stepIdx int, kind string, step cuetry.Step, recipeScopedKV bool) SSHPostHostResultFunc

CueRecipeSSHPostHostResult ...

type SSHRemoteCmdFunc

type SSHRemoteCmdFunc func(tc TargetContext, kv map[string]string) string

SSHRemoteCmdFunc builds the remote shell string. kv is nil when kv_tunnel is disabled; otherwise it contains HONEY_KV_URL (reachable from the remote via SSH remote forward) and HONEY_KV_TOKEN for Authorization. SSHRemoteCmdFunc ...

type ScriptExecutor

type ScriptExecutor struct{}

ScriptExecutor executes the corresponding recipe step.

func (*ScriptExecutor) ExecuteDryRun

func (e *ScriptExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*ScriptExecutor) ExecuteStream

func (e *ScriptExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type ScriptUploadRunOptions

type ScriptUploadRunOptions struct {
	ScriptInterpreter     string
	InterpreterArgsQuoted bool
	RemoveRemoteFile      bool
	// ScriptArgs are positional arguments passed to the script (Rundeck-style),
	// shell-quoted and appended after the interpreter/path.
	ScriptArgs []string
	// RunAs wraps the run step in sudo for that user (empty = run as the SSH user).
	RunAs string
}

ScriptUploadRunOptions controls upload/chmod/execute script runs. ScriptUploadRunOptions ...

type ServiceExecutor added in v0.3.7

type ServiceExecutor struct{}

ServiceExecutor executes the corresponding recipe step.

func (*ServiceExecutor) ExecuteDryRun added in v0.3.7

ExecuteDryRun performs a dry run of the step.

func (*ServiceExecutor) ExecuteStream added in v0.3.7

func (e *ServiceExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type SessionRecorder

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

SessionRecorder appends JSONL events to a single .hrec.jsonl file (TTY data, resize, errors, close). SessionRecorder ...

func NewBatchSessionRecorder

func NewBatchSessionRecorder(dir, trigger, user string, jobCount int) (*SessionRecorder, error)

NewBatchSessionRecorder creates a recorder for one parallel exec or CUE batch run (one file per invocation). NewBatchSessionRecorder ...

func NewSessionRecorder

func NewSessionRecorder(opts SessionRecorderOptions) (*SessionRecorder, error)

NewSessionRecorder creates a recorder writing to opts.Dir with a timestamped filename. NewSessionRecorder ...

func (*SessionRecorder) Close

func (r *SessionRecorder) Close() error

Close writes a "close" event and closes the underlying file.

func (*SessionRecorder) Path

func (r *SessionRecorder) Path() string

Path returns the absolute path of the recording file, or empty if r is nil.

func (*SessionRecorder) RecordData

func (r *SessionRecorder) RecordData(direction string, payload []byte)

RecordData writes a base64-encoded payload for the given direction (e.g. in/out).

func (*SessionRecorder) RecordError

func (r *SessionRecorder) RecordError(err error)

RecordError records a non-fatal error message on the session.

func (*SessionRecorder) RecordHostExecResult

func (r *SessionRecorder) RecordHostExecResult(res HostExecResult)

RecordHostExecResult writes one structured "result" event (parallel exec / batch output).

func (*SessionRecorder) RecordRecipeMeta

func (r *SessionRecorder) RecordRecipeMeta(meta RecipeMeta)

RecordRecipeMeta writes one "recipe-meta" structured event into the recording. Safe to call on a nil recorder.

func (*SessionRecorder) RecordResize

func (r *SessionRecorder) RecordResize(cols, rows int)

RecordResize records a terminal resize event.

func (*SessionRecorder) RecordingFileBase

func (r *SessionRecorder) RecordingFileBase() string

RecordingFileBase returns the recording filename (e.g. 20260102_120000_web-cue-exec_batch_mixed_batch-3.hrec.jsonl).

func (*SessionRecorder) RecordingID

func (r *SessionRecorder) RecordingID() string

RecordingID returns the recording id (filename without .hrec.jsonl).

type SessionRecorderOptions

type SessionRecorderOptions struct {
	Dir      string
	Trigger  string
	Mode     string
	Provider string
	HostName string
	HostIP   string
	User     string
	// HostSegment, when set, is used for the filename segment instead of HostName/IP (e.g. batch-12).
	HostSegment string
}

SessionRecorderOptions configures filename segments and metadata for a new session recording. SessionRecorderOptions ...

type StepEnvResolver

type StepEnvResolver interface {
	Resolve(ctx context.Context, step *cuetry.StepBase, target *hosts.Record, resolveSecrets, dryRun bool) (map[string]string, error)
}

StepEnvResolver resolves the effective env map for one step on one target. It is the single interface behind which all env wiring (defaults, CLI env, secrets, OutputStore, KV, env_from) is hidden. Executors call Resolve; they are unaware of CueRun internals.

Callers that need an error returned per-target should check the error inline; callers that embed the call in a closure (e.g. cmdFunc) should format the error into the remote command string as a fallback.

type StepExecutor

type StepExecutor interface {
	// ExecuteDryRun performs a dry run of the step, writing its plan to out.
	ExecuteDryRun(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

	// ExecuteStream performs actual execution of the step, sending results to resCh.
	ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error
}

StepExecutor defines a deep module responsible for a specific recipe step kind.

func GetStepExecutor

func GetStepExecutor(kind string) (StepExecutor, error)

GetStepExecutor retrieves the executor for a given step kind.

type StepFilter

type StepFilter interface {
	Filter(ctx context.Context, targets []hosts.Record) (allowed []hosts.Record, skipped []HostExecResult, err error)
}

StepFilter is a composable per-target gate applied before step dispatch. Each filter receives the targets that survived all preceding filters and returns the subset that may proceed plus skip records for those it removed. Implementations are constructed with their own dependencies pre-injected so the pipeline itself stays ignorant of CueRun internals.

type StepFilterPipeline

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

StepFilterPipeline composes StepFilter implementations and applies them in sequence. Skips accumulate across all filters so callers receive one unified list of reasons. An error from any filter stops the pipeline immediately.

func NewStepFilterPipeline

func NewStepFilterPipeline(filters ...StepFilter) *StepFilterPipeline

NewStepFilterPipeline returns a pipeline that applies filters in order.

func (*StepFilterPipeline) Apply

func (p *StepFilterPipeline) Apply(ctx context.Context, targets []hosts.Record) (allowed []hosts.Record, skipped []HostExecResult, err error)

Apply runs each filter in sequence, accumulating skips. Returns the final allowed targets and all skip records from every filter.

type StepRisk

type StepRisk struct {
	StepIndex   int                  `json:"step_index"`
	Kind        string               `json:"kind"`
	Host        string               `json:"host,omitempty"`
	Command     string               `json:"command,omitempty"`
	Interpreter string               `json:"interpreter,omitempty"`
	Analysis    commandrisk.Analysis `json:"analysis"`
	Decision    *policy.Decision     `json:"decision,omitempty"`
}

StepRisk is the risk assessment of one command/script step, for dry-run review.

type SummarizeExecutor added in v0.3.7

type SummarizeExecutor struct{}

SummarizeExecutor executes the corresponding recipe step.

func (*SummarizeExecutor) ExecuteDryRun added in v0.3.7

func (e *SummarizeExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*SummarizeExecutor) ExecuteStream added in v0.3.7

func (e *SummarizeExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type TargetContext

type TargetContext struct {
	Record hosts.Record
	Env    map[string]string
}

TargetContext binds a host record with its pre-resolved environment.

type TemplateExecutor

type TemplateExecutor struct{}

TemplateExecutor executes the corresponding recipe step.

func (*TemplateExecutor) ExecuteDryRun

func (e *TemplateExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*TemplateExecutor) ExecuteStream

func (e *TemplateExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

type TransferNode

type TransferNode interface {
	// HostLabel returns the display label for the node.
	HostLabel() string

	// Record returns the underlying inventory record.
	Record() hosts.Record

	// StageAgent ensures the agent binary is staged on the node.
	// Returns a boolean indicating if an upload actually occurred, a reason string, and an error.
	StageAgent(ctx context.Context, localAgentPath, remoteAgentPath string) (uploaded bool, reason string, err error)

	// RunAgentSession starts the agent binary in session mode over the transport streams.
	RunAgentSession(ctx context.Context, agentPath string, mintJWE func(string) (string, error), ops []agentSessionHostMsg) (jwe string, err error)

	// CleanupAgent removes the ephemeral agent binary from the node.
	CleanupAgent(ctx context.Context, agentPath string) error

	// RunScript executes a raw script on the node (used for the fallback path).
	RunScript(ctx context.Context, script string) (string, error)
}

TransferNode abstracts a target node for agent execution and staging. This deepens the module by encapsulating transport-specific details (e.g. bash scripts, OS stat).

type TunnelEndpoint

type TunnelEndpoint struct {
	Host       string
	Port       int
	Mode       string
	TunName    string
	RemoteHost string
	RemotePort int
	ShareKey   string
}

TunnelEndpoint describes an operator-side listen address for a recipe tunnel. TunnelEndpoint ...

type TunnelExecutor

type TunnelExecutor struct{}

TunnelExecutor executes the corresponding recipe step.

func (*TunnelExecutor) ExecuteDryRun

func (e *TunnelExecutor) ExecuteDryRun(_ context.Context, req ExecutionRequest, opts ExecutionOptions, out io.Writer) error

ExecuteDryRun executes a dry run of the step.

func (*TunnelExecutor) ExecuteStream

func (e *TunnelExecutor) ExecuteStream(ctx context.Context, req ExecutionRequest, opts ExecutionOptions, resCh chan<- HostExecResult) error

ExecuteStream streams the step execution.

Jump to

Keyboard shortcuts

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