Documentation
¶
Overview ¶
Package script implements the extraction-ready Goja JavaScript step kind.
The adapter is intentionally a local, synchronous data-transform sandbox. A script receives only validated inline workflow inputs and returns a plain object that becomes typed workflow outputs. It does not install filesystem, network, environment, secret-resolution, module-loading, clock, random, console, timer, or ambient Hadron APIs. Artifact and secret-reference inputs are rejected because this package has no resolver or policy capability seam.
ResourceLimits impose deterministic structural memory bounds over source, canonical input/output JSON, nesting, aggregate items, strings, and call stack, while Goja interruption enforces wall time and caller cancellation. Goja does not expose a per-runtime heap quota. Therefore this in-process adapter does not claim byte-accurate arbitrary working-heap isolation; a host that runs hostile multi-tenant scripts needs a separately designed isolation runner in addition to these fail-closed structural limits. Input and output schemas are explicit config declarations rather than inferred from JavaScript syntax, so the contract remains stable across Goja parser releases and can be validated before execution.
Python support remains separate because it requires an explicit subprocess, filesystem, environment, package, signal, and operating-system sandbox contract. Those authorities cannot be inferred from this in-process Goja adapter without weakening its boundary.
Index ¶
- Constants
- Variables
- type Executor
- func (e *Executor) Execute(ctx context.Context, prepared stepkind.PreparedInvocation) (stepkind.StepResult, error)
- func (e *Executor) Limits() ResourceLimits
- func (e *Executor) Spec() stepkind.StepKindSpec
- func (e *Executor) ValidateConfig(_ context.Context, input graph.Config) []diagnostic.Diagnostic
- type ResourceLimits
Constants ¶
const ( // Name is the canonical registered script kind name. Name = "script" // Version is the immutable initial Goja script contract version. Version = "v1" // RuntimeGoja is the only runtime accepted by script@v1. RuntimeGoja = "goja" CodeInvalidConfig = "script_invalid_config" CodeCapabilityDenied = "script_capability_denied" CodeInputInvalid = "script_input_invalid" CodeOutputInvalid = "script_output_invalid" CodeResourceLimit = "script_resource_limit" CodeExecutionFailed = "script_execution_failed" CodeExecutionTimeout = "script_execution_timeout" CodeExecutionCanceled = "script_execution_canceled" CodeEntrypointInvalid = "script_entrypoint_invalid" )
const ( DefaultMaxSourceBytes = 64 << 10 DefaultMaxInputBytes = 1 << 20 DefaultMaxOutputBytes = 1 << 20 DefaultMaxDepth = 64 DefaultMaxItems = 16_384 DefaultMaxStringBytes = 256 << 10 DefaultMaxCallStack = 128 DefaultWallTime = time.Second MaximumSourceBytes = 1 << 20 MaximumDataBytes = 16 << 20 MaximumDepth = 128 MaximumItems = 1_000_000 MaximumStringBytes = 16 << 20 MaximumCallStack = 1_024 MaximumWallTime = time.Minute )
Variables ¶
var ( ErrInvalidLimits = errors.New("invalid script resource limits") ErrCapabilityDenied = errors.New("script capability denied") ErrResourceLimit = errors.New("script resource limit exceeded") ErrInvalidInput = errors.New("invalid script input") ErrInvalidOutput = errors.New("invalid script output") ErrUnsafeJSONNumber = errors.New("JSON number cannot be represented exactly by JavaScript") )
Functions ¶
This section is empty.
Types ¶
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor runs one fresh Goja runtime per invocation and is safe for concurrent use.
func NewWithLimits ¶
func NewWithLimits(limits ResourceLimits) (*Executor, error)
NewWithLimits returns an executor with explicit hard limits.
func (*Executor) Execute ¶
func (e *Executor) Execute(ctx context.Context, prepared stepkind.PreparedInvocation) (stepkind.StepResult, error)
Execute runs validated JavaScript in a fresh capability-free Goja runtime.
func (*Executor) Limits ¶
func (e *Executor) Limits() ResourceLimits
Limits returns a defensive value copy of the executor's limits.
func (*Executor) Spec ¶
func (e *Executor) Spec() stepkind.StepKindSpec
Spec returns immutable metadata for the deterministic local script kind.
func (*Executor) ValidateConfig ¶
func (e *Executor) ValidateConfig(_ context.Context, input graph.Config) []diagnostic.Diagnostic
ValidateConfig validates schemas, syntax, the entrypoint declaration, and fail-closed sandbox policy without executing author code.
type ResourceLimits ¶
type ResourceLimits struct {
MaxSourceBytes int `json:"max_source_bytes"`
MaxInputBytes int `json:"max_input_bytes"`
MaxOutputBytes int `json:"max_output_bytes"`
MaxDepth int `json:"max_depth"`
MaxItems int `json:"max_items"`
MaxStringBytes int `json:"max_string_bytes"`
MaxCallStack int `json:"max_call_stack"`
WallTime time.Duration `json:"wall_time"`
}
ResourceLimits are hard per-invocation structural and execution bounds. They deliberately do not claim a per-Goja-runtime heap quota.
func DefaultResourceLimits ¶
func DefaultResourceLimits() ResourceLimits
DefaultResourceLimits returns conservative extraction-safe limits.
func (ResourceLimits) Validate ¶
func (l ResourceLimits) Validate() error
Validate rejects disabled or misleadingly broad resource declarations.