Environments as immutable images: content-addressed by spec digest, built once, reused forever, superseded by NEW images (never mutated), destroyed only by explicit prune.
The provider-side name is <base>_<digest8> — repo@digest — so a name
collision can only ever mean "this exact image already exists", and recovery
by name is definitionally version-correct even with an empty store.
Summary
Functions
Build-if-absent for an environment image. Returns {:ok, %Handle{}}.
Explicit image GC: archives <base>_* environment versions beyond the newest
keep: (REQUIRED — there is no default for a permanent operation), never
touching tagged digests or already-archived versions. Returns
{:ok, %{archived: names, kept: names}} or
{:error, {:partial, archived_names, {failed_name, reason}}}.
Resolve "base:tag" to the tagged image's handle. Never falls back:
{:error, :unknown_tag} when the tag doesn't exist,
{:error, {:untracked_digest, digest}} when the tag points at a digest whose
provision entry is gone (e.g. pruned store) — re-ensure the spec to heal.
Point base:tag at an image digest (or a handle's digest). A movable
pointer — retagging replaces it. Tagged digests are protected from prune/3.
Functions
@spec ensure_environment( term(), ReqManagedAgents.Environment.Spec.t() | map(), keyword() ) :: {:ok, ReqManagedAgents.Provisioner.Environment.Handle.t()} | {:error, term()}
Build-if-absent for an environment image. Returns {:ok, %Handle{}}.
When the spec declares runtimes, the RETURNED %Handle{} additionally
carries bootstrap: %{script: ..., instructions: ...} — DERIVED from the
spec on every call (all paths: fresh create, recovery, store hit), never
stored. The persisted handle stays exactly three fields (bootstrap is
excluded from the Jason.Encoder derivation); only the in-memory struct
returned here carries it. Sessions execute the script via the agent's bash
on first need; the library only renders it.
Opts: :name (repository base, default "env"), :store
({module, store_opts}), :create_fun / :list_fun (test seams; default
to ReqManagedAgents.Client calls on the given client).
Explicit image GC: archives <base>_* environment versions beyond the newest
keep: (REQUIRED — there is no default for a permanent operation), never
touching tagged digests or already-archived versions. Returns
{:ok, %{archived: names, kept: names}} or
{:error, {:partial, archived_names, {failed_name, reason}}}.
Resolve "base:tag" to the tagged image's handle. Never falls back:
{:error, :unknown_tag} when the tag doesn't exist,
{:error, {:untracked_digest, digest}} when the tag points at a digest whose
provision entry is gone (e.g. pruned store) — re-ensure the spec to heal.
ref must be of the form "base:tag" — a ref without a colon raises ArgumentError.
The split is on the FIRST colon only, so tag names may themselves contain
colons ("a:b:c" resolves tag "b:c" under base "a").
The resolved handle's :bootstrap is always nil — no env spec is in
scope here to derive it from; call ensure_environment/3 with the spec
when the bootstrap content is needed.
Point base:tag at an image digest (or a handle's digest). A movable
pointer — retagging replaces it. Tagged digests are protected from prune/3.