Lightning.Projects.Sandboxes (Lightning v2.14.5-pre1)

View Source

Provision sandbox projects as children of an existing project.

A sandbox is a full project that:

  • clones core project settings from the parent,
  • references the same credentials via project_credentials (no new credentials are created),
  • clones the workflow DAG (workflows, jobs, triggers, edges),
  • disables all triggers in the sandbox,
  • remaps positions (node coordinates) to the new node IDs,
  • copies the latest WorkflowVersion per workflow to seed version history,
  • can optionally copy a subset of named dataclips,
  • clones Keychain credentials (metadata only) actually used by parent jobs and rewires sandbox jobs to those cloned keychains, and
  • assigns the creator as :owner; any non-owner collaborators provided are included at creation time (duplicate/owner entries are filtered).

Authorization

The actor must be :owner or :admin on the parent project. Otherwise {:error, :unauthorized} is returned and nothing is created.

Invariants & side effects

  • The sandbox is created in a single DB transaction.
  • The creator is added as the owner and any non-owner collaborators from :collaborators are also added at creation time (we ensure exactly one owner).
  • Credentials are not duplicated; we create project_credentials rows that reference the parent’s existing credentials.
  • Keychain credentials are cloned as metadata (name/path/default_credential) into the sandbox project; no secrets are duplicated. Because we copy project_credentials first, the keychain’s default_credential_id remains valid in the sandbox and passes validation.
  • Trigger rows are cloned but always persisted with enabled: false.
  • Positions are remapped by translating old node IDs to new ones; if no valid positions remain, we store nil (UI → auto-layout).
  • There are no runs or dataclips copied by default.

See the provision/3 docs below for attribute details and return values.

Summary

Types

Attributes accepted by provision/3.

Functions

Provisions a sandbox project under parent on behalf of actor.

Types

provision_attrs()

@type provision_attrs() :: %{
  :name => String.t(),
  optional(:color) => String.t() | nil,
  optional(:env) => String.t() | nil,
  optional(:collaborators) => [%{user_id: Ecto.UUID.t(), role: atom()}],
  optional(:dataclip_ids) => [Ecto.UUID.t()]
}

Attributes accepted by provision/3.

  • :name (required) – sandbox name (scoped unique per parent_id)
  • :color (optional) – UI color string (e.g. "#336699")
  • :env (optional) – environment slug for the project (e.g. "staging")
  • :collaborators (optional) – list of %{user_id: Ecto.UUID.t(), role: atom()} to add in addition to the creator (owner). Any :owner entries are ignored and duplicates by user_id are removed.
  • :dataclip_ids (optional) – list of dataclip IDs to copy if they are:
    • named (name not nil) and
    • of type in [:global, :saved_input, :http_request].

Functions

provision(parent, actor, attrs)

@spec provision(
  Lightning.Projects.Project.t(),
  Lightning.Accounts.User.t(),
  provision_attrs()
) ::
  {:ok, Lightning.Projects.Project.t()}
  | {:error, :unauthorized | Ecto.Changeset.t() | term()}

Provisions a sandbox project under parent on behalf of actor.

This function performs the full sandbox provisioning workflow described in the module documentation. It returns either the newly created sandbox project or an error tuple without side effects outside the transaction.

Parameters

  • parent – the parent %Lightning.Projects.Project{} to clone from
  • actor – the %Lightning.Accounts.User{} performing the action; must be :owner or :admin on the parent
  • attrs – map of attributes (see provision_attrs/0 for details)

Returns

  • {:ok, %Lightning.Projects.Project{}} on success
  • {:error, :unauthorized} if actor lacks permission on parent
  • {:error, Ecto.Changeset.t() | term()} for validation/DB errors

What gets cloned

  • Project settings: allow_support_access, concurrency, description, requires_mfa, retention_policy, history_retention_period, dataclip_retention_period.
  • Credentials: project_credentials rows pointing at the same underlying credentials (no new credentials).
  • Keychain credentials (metadata): only the keychains actually used by parent jobs are cloned into the sandbox (name, path, default_credential_id); sandbox jobs are rewired to those cloned keychains.
  • DAG: workflows, jobs, triggers (disabled), edges, webhook auth methods.
  • Positions: remapped from parent node IDs to child node IDs; nil when nothing remaps (UI → auto-layout).
  • Version heads: latest WorkflowVersion per workflow (hash, source).