# `Lightning.Projects.Provisioner`
[🔗](https://github.com/OpenFn/lightning/blob/main/lib/lightning/projects/provisioner.ex#L1)

Provides functions for importing projects. This module is used by the
provisioning HTTP API.

When providing a project to import, all records must have an `id` field.
It's up to the caller to ensure that the `id` is unique and generated
ahead of time in the case of new records.

# `import_document`

```elixir
@spec import_document(
  Lightning.Projects.Project.t() | nil,
  Lightning.Accounts.User.t()
  | Lightning.VersionControl.ProjectRepoConnection.t(),
  map(),
  keyword()
) ::
  {:ok, Lightning.Projects.Project.t()}
  | {:error, Ecto.Changeset.t(Lightning.Projects.Project.t())}
  | {:error, :concurrent_edit}
  | Lightning.Extensions.UsageLimiting.error()
```

Import a project document into the database.

Upserts the project and the associations carried in the document
(workflows, project credentials, collections) inside a single transaction,
then fires audit, version-bump, and snapshot side effects.

Returns `{:error, :concurrent_edit}`, with nothing written, when another
request changed a workflow or channel the document writes, or deleted any
row it writes, while the import ran, unless `:allow_stale` is set.

Generic pipeline shared by YAML provisioning, CLI deploys, GitHub syncs,
and sandbox merges. It only acts on what the document contains —
sandbox-specific behaviours (credential cloning, dataclip copying,
collection name sync) are composed around this call in
`Lightning.Projects.Sandboxes`.

## Options
  * `:allow_stale` - If true, allows stale operations during import (useful for
    merge operations where concurrent modifications are expected). Defaults to false.
  * `:reconcile_collaboration` - If true, broadcasts a collaboration reconcile
    request for each affected workflow AFTER the import transaction commits,
    so any live collaborative document re-syncs from the database.

    Defaults to FALSE, which is what a deploy did before this work: an editor
    that was open stayed as it was. Rebuilding someone's document under them
    mid-edit is a visible change, and it would reach every collaborator in the
    room whether or not they asked for any of this. Callers that need it ask
    for it, and none of them is a plain import.

# `parse_document`

```elixir
@spec parse_document(
  Lightning.Projects.Project.t(),
  map(),
  Lightning.Accounts.User.t()
  | Lightning.VersionControl.ProjectRepoConnection.t()
  | nil
) :: Ecto.Changeset.t(Lightning.Projects.Project.t())
```

# `preload_dependencies`

```elixir
@spec preload_dependencies(Lightning.Projects.Project.t(), nil | [Ecto.UUID.t(), ...]) ::
  Lightning.Projects.Project.t()
```

Preload all dependencies for a project.

Exclude deleted workflows.

# `reconcilable_workflow_ids`

```elixir
@spec reconcilable_workflow_ids(map()) :: [Ecto.UUID.t()]
```

Extracts the workflow ids carried by an import/merge document that a live
collaborative document should reconcile against, excluding workflows the
document marks for deletion. Only workflows present in the document are
returned, so sibling workflows on the target are never touched.

# `validate_extraneous_params`

Validate that there are no extraneous parameters in the changeset.

For all params in the changeset, ensure that the param is in the list of
known fields in the schema.

---

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