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
@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
@spec fingerprint(t(), binary()) :: {:ok, String.t()} | {:error, SmolBox.Error.t()}
Fingerprint every semantic field with domain separation and a host-owned secret.
@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 field | Default | Meaning |
|---|---|---|
:inputs | [] | Up to 32 exact input declarations; see SmolBox.Manifest |
:outputs | [] | Up to 32 exact output declarations; see SmolBox.Manifest |
:queue_ms | 60_000 | 1–86,400,000 ms from first acceptance until queue expiry |
:retention_ms | 86_400_000 | 60,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.
@spec validate(term()) :: :ok | {:error, SmolBox.Error.t()}
Revalidate a specification, including its command, profile, file declarations and budgets.