SmolBox.ExecutionSpec (SmolBox v0.1.0)

Copy Markdown View Source

Immutable managed execution intent; host code supplies policy and artifact approval.

The runtime artifact map contains exactly id, sha256, and architecture (x86_64 or aarch64). It is resolved against host configuration, never fetched as a caller-provided image URL. The specification contains no endpoint overrides.

Queue budgets are relative at construction; the store must persist an absolute deadline on first acceptance. Repeated submission never resets that deadline. fingerprint/2 uses a stable host secret (at least 32 bytes) to prevent guessing low-entropy environment/stdin values from a public hash. Rotate this key only with an explicit stored-identity migration. Do not log or persist its bytes.

The host store must protect command/environment/stdin contents at rest; inspection of this struct excludes them. Metadata is limited to 16 bounded scalar entries.

Summary

Functions

Fingerprint every semantic field with domain separation and a host-owned secret.

Validate a complete managed execution specification without dispatching it.

Revalidate a specification, including its command, profile, file declarations and budgets.

Types

t()

@type t() :: %SmolBox.ExecutionSpec{
  artifact: %{required(String.t()) => String.t()},
  command: SmolBox.Command.t(),
  id: String.t(),
  inputs: [SmolBox.Manifest.input()],
  metadata: %{required(String.t()) => String.t() | integer() | boolean() | nil},
  outputs: [SmolBox.Manifest.output()],
  profile: SmolBox.Profile.t(),
  queue_ms: pos_integer(),
  retention_ms: pos_integer(),
  scope: String.t()
}

Functions

fingerprint(spec, key)

@spec fingerprint(t(), binary()) :: {:ok, String.t()} | {:error, SmolBox.Error.t()}

Fingerprint every semantic field with domain separation and a host-owned secret.

new(options)

@spec new(term()) :: {:ok, t()} | {:error, SmolBox.Error.t()}

Validate a complete managed execution specification without dispatching it.

Required options are :scope, :id, :command (SmolBox.Command), :profile (SmolBox.Profile), and :artifact. Scope and ID are 1–128 ASCII letters, digits, dots, underscores, colons or hyphens, starting with a letter/digit. The artifact has exactly string keys "id", "sha256", and "architecture"; its approved worker path is resolved from SmolBox.Runtime.WorkerConfig.

Optional fieldDefaultMeaning
:inputs[]Up to 32 exact input declarations; see SmolBox.Manifest
:outputs[]Up to 32 exact output declarations; see SmolBox.Manifest
:queue_ms60_0001–86,400,000 ms from first acceptance until queue expiry
:retention_ms86_400_00060,000–2,592,000,000 ms after the execution deadline for unknown-outcome retention
:metadata%{}Up to 16 string identifier keys with string (up to 256 bytes), bounded integer, boolean or nil values

The command timeout in seconds must fit the profile's execution budget in milliseconds. Successful construction proves shape and bounds, not worker availability or artifact approval; SmolBox.submit/2 checks configured support. All semantic fields participate in identity conflict detection.

Example

iex> {:ok, command} = SmolBox.Command.new(["python", "-c", "print(42)"])
iex> {:ok, profile} = SmolBox.Profile.new("offline-v1", storage_gb: 20, overlay_gb: 10, host_overhead_mb: 768)
iex> artifact = %{"id" => "python-v1", "sha256" => SmolBox.Files.sha256("example image bytes"), "architecture" => "aarch64"}
iex> {:ok, spec} = SmolBox.ExecutionSpec.new(scope: "demo", id: "request-1", command: command, profile: profile, artifact: artifact)
iex> {spec.scope, spec.id, spec.queue_ms}
{"demo", "request-1", 60_000}

The digest above is only a constructor example. Actual execution requires the digest of an approved prepared image, as shown in Getting started.

validate(spec)

@spec validate(term()) :: :ok | {:error, SmolBox.Error.t()}

Revalidate a specification, including its command, profile, file declarations and budgets.