Lightning.Projects.Sandboxes (Lightning v2.14.5-pre1)
View SourceProvision 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 existingcredentials
. - 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’sdefault_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
@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 perparent_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 byuser_id
are removed.:dataclip_ids
(optional) – list of dataclip IDs to copy if they are:- named (
name
notnil
) and - of type in
[:global, :saved_input, :http_request]
.
- named (
Functions
@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 fromactor
– the%Lightning.Accounts.User{}
performing the action; must be:owner
or:admin
on the parentattrs
– map of attributes (seeprovision_attrs/0
for details)
Returns
{:ok, %Lightning.Projects.Project{}}
on success{:error, :unauthorized}
ifactor
lacks permission onparent
{: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 newcredentials
). - 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
).