ExDaytona.Secrets (ex_daytona v0.4.0)

Copy Markdown View Source

Vault-backed secrets: management, sandbox bindings, and resolution.

Secrets hold sensitive values server-side; sandboxes mount them as environment variables through bindings (%{"ENV_VAR" => "secret-name"}), so plaintext never travels through ordinary sandbox metadata:

{:ok, secret} = ExDaytona.Secrets.create(client, "db-prod", "s3cr3t")

{:ok, sandbox} =
  ExDaytona.Sandbox.create(client, secrets: [%{"DB_PASSWORD" => "db-prod"}])

# or later, replacing the mounted set:
{:ok, _} = ExDaytona.Secrets.set_sandbox_bindings(sandbox, [%{"DB_PASSWORD" => "db-prod"}])

Inside the sandbox, a bound env var does not contain the plaintext: it carries a placeholder handle (dtn_secret_...); the real value is materialized by the platform according to the secret's hosts allowlist (verified against the live API). resolve/1 is the operator-side view that returns actual values.

Every value-bearing input and result renders redacted under inspect/1 — resolved plaintext is reachable only by reading struct fields explicitly.

Summary

Functions

Create a secret. Options: :description, :hosts (list of hosts the secret may be exposed to).

Delete a secret. Returns :ok.

Fetch a secret's metadata by id (values are never returned here).

List secrets with pagination. Accepts :cursor, :limit, :name, :sort, :order; returns {:ok, %{items: [%ExDaytona.Model.Secret{}], next_cursor: cursor, total: n}}.

Resolve the sandbox's secret bindings. Returns ExDaytona.Model.ResolveSandboxSecrets200ResponseInner structs whose value fields are redacted under inspect/1 — plaintext is only reachable by reading .value explicitly.

Replace the sandbox's mounted secret set with bindings — a list of single-entry maps %{"ENV_VAR" => "secret-name"}. Pass [] to detach all secrets. Returns the updated sandbox.

Update a secret. Options: :value, :description, :hosts — only the given fields change.

Functions

create(client, name, value, opts \\ [])

@spec create(ExDaytona.Client.t(), String.t(), String.t(), keyword()) ::
  {:ok, ExDaytona.Model.Secret.t()} | {:error, ExDaytona.Error.t()}

Create a secret. Options: :description, :hosts (list of hosts the secret may be exposed to).

delete(client, secret_id)

@spec delete(ExDaytona.Client.t(), String.t()) :: :ok | {:error, ExDaytona.Error.t()}

Delete a secret. Returns :ok.

get(client, secret_id)

@spec get(ExDaytona.Client.t(), String.t()) ::
  {:ok, ExDaytona.Model.Secret.t()} | {:error, ExDaytona.Error.t()}

Fetch a secret's metadata by id (values are never returned here).

list(client, opts \\ [])

@spec list(
  ExDaytona.Client.t(),
  keyword()
) ::
  {:ok,
   %{
     items: [ExDaytona.Model.Secret.t()],
     next_cursor: String.t() | nil,
     total: non_neg_integer() | nil
   }}
  | {:error, ExDaytona.Error.t()}

List secrets with pagination. Accepts :cursor, :limit, :name, :sort, :order; returns {:ok, %{items: [%ExDaytona.Model.Secret{}], next_cursor: cursor, total: n}}.

resolve(sandbox)

Resolve the sandbox's secret bindings. Returns ExDaytona.Model.ResolveSandboxSecrets200ResponseInner structs whose value fields are redacted under inspect/1 — plaintext is only reachable by reading .value explicitly.

Authentication

This endpoint authenticates platform infrastructure (the component that materializes secret values) — with a regular user API key it returns 403 "Invalid authentication context" (verified live). User code sees only placeholder handles inside the sandbox.

set_sandbox_bindings(sandbox, bindings)

@spec set_sandbox_bindings(ExDaytona.Sandbox.t(), [map()]) ::
  {:ok, ExDaytona.Sandbox.t()} | {:error, ExDaytona.Error.t()}

Replace the sandbox's mounted secret set with bindings — a list of single-entry maps %{"ENV_VAR" => "secret-name"}. Pass [] to detach all secrets. Returns the updated sandbox.

update(client, secret_id, opts)

@spec update(ExDaytona.Client.t(), String.t(), keyword()) ::
  {:ok, ExDaytona.Model.Secret.t()} | {:error, ExDaytona.Error.t()}

Update a secret. Options: :value, :description, :hosts — only the given fields change.