# `ReqManagedAgents.Provisioner.Environments`
[🔗](https://github.com/cash-mckeeman/req_managed_agents/blob/v0.12.0/req_managed_agents/lib/req_managed_agents/provisioner/environments.ex#L1)

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.

# `ensure_environment`

```elixir
@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).

A literal `nil` spec is rejected with
`{:error, {:invalid_environment_spec, nil}}` — `Environment.Spec.new/1` maps
`nil` to "no environment", and no environment cannot be provisioned.

# `prune_environments`

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`

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.

# `tag`

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`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
