# Loader configuration

`dcupl.lc.json` is the manifest an app loader reads to learn **what** to pull
into a dcupl core and **how** to reach it. A file in your project is only ever
loaded because this file declares it. Everything else in the project is just
storage.

## Anatomy

The file has four top-level keys:

- **`resources[]`** — the payload list. Each entry has a `url`, a `type`, and
  optional `tags[]`.
- **`applications[]`** — named presets. Each bundles a `resourceTags` selection
  and its own `variables`, and is chosen by key when the app is run.
- **`environments[]`** — named bundles of `variables`, HTTP `headers` and
  `queryParams`. They are opt-in: an environment affects a run only when that run
  selects it. Its headers are sent only for resources that carry at least one
  tag. A query parameter without tags goes to every resource, a tagged one to
  the resources that share a tag.
- **`options`** — loader-wide settings such as missing-model handling and CSV
  parser options. Missing-model handling is on by default
  (`missingModelHandling.autoGenerateProperties: true`): a `data` resource whose
  `model` is not declared gets a model of that key, inferred from its rows.

Every `url` is a template. `${baseUrl}` and friends are resolved from the
variable layers before anything is fetched, which is why the same config works
against the CDN, a local `dcupl serve`, or any other host.

By convention each resource type has its folder: `models/`, `data/`,
`scripts/`, `operators/` and `transformers/`, the folders the console proposes
for a new resource. The scoped [API keys](/console/api-keys) a new project is
seeded with read only `dcupl.lc.json` and those folders (the browser key leaves
out `scripts/`), so on a private project a resource kept elsewhere needs a key
that covers its path.

## The five resource types, in load order

Resources are grouped by `type` and each group finishes before the next one
starts. The order is a correctness contract, not a performance tweak.

```mermaid
flowchart LR
  S[scripts] --> O[operators] --> T[transformers] --> M[models] --> D[data]
```

1. **`script`** — text registered under a `scriptKey`.
2. **`operator`** — a custom query operator, registered before any query runs.
3. **`transformer`** — a function applied to a data resource, either to the raw
   payload or to the parsed rows.
4. **`model`** — a model definition (or a view).
5. **`data`** — rows. A data resource names the `model` it feeds, so models must
   already be registered when this stage starts.

Every resource has a `url`, a `type`, optional `tags` and an optional `key`.
The other fields depend on the type:

| Type          | Fields                                                                                                                                                                                          |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `script`      | `scriptKey` (required) — the key the script is registered under                                                                                                                                 |
| `operator`    | `operator` (required) — the operator name queries use                                                                                                                                           |
| `transformer` | `applyTo` — tags of the data resources it runs on; `transformerType` — `parsedFileTransformer` (default) or `rawFileTransformer`                                                                |
| `model`       | none                                                                                                                                                                                            |
| `data`        | `model` (required); `options` — `updateType`, `keyProperty` (one name or an array for a composite key), `keyPropertySeparator`, `autoGenerateKey`, `autoGenerateProperties`, `csvParserOptions` |

A transformer without `applyTo` runs only on data resources that have no tags.
The full types are in the [SDK loader reference](/sdk/api/loader#resource-types).

A `scriptKey` and an `operator` with the same value collide: a query resolves
an operator name among scripts first, so the script runs and the operator is
never called, with no loader error. Keep the keys unique across both; the
console's loader form flags a duplicate. See
[Custom Operators](/sdk/api/query-operators#custom-operators).

Within a stage, resources are fetched in parallel, and a failure is isolated to
that one resource: it is logged and recorded as a quality error (a loader error
such as `InvalidResource` or `TransformerError`), whether or not quality checks
are enabled, and the rest of the run continues.

## Tags and applications

A tag is a label you choose, such as `catalog` or `sales`. Tags group resources;
they do not change them. An application names the tags it wants:

```json
{
  "applications": [
    { "key": "catalog", "name": "Catalog", "resourceTags": ["catalog"] },
    { "key": "default", "name": "Default" }
  ],
  "resources": [
    {
      "url": "${baseUrl}/models/product.dcupl.json",
      "type": "model",
      "tags": ["catalog"]
    },
    {
      "url": "${baseUrl}/data/products.csv",
      "type": "data",
      "model": "Product",
      "tags": ["catalog"]
    }
  ]
}
```

The matching rule has two halves, and the second one surprises people:

- **No tags on the application loads everything.** An empty `resourceTags` is
  "all", not "none" — the default application above loads both resources.
- **Once the application has tags, a resource with no tags is skipped.** Adding
  `resourceTags` to an app silently drops every untagged resource from that run.
  Tag all of them, or leave the application's list empty.

Top-level entries in `resourceTags` are an **OR** match. A nested array is an
**AND** match: the resource must carry all the tags in it.

## Declared vs loaded

The console shows the same resource list in two places, with two meanings:

- **Loader Configuration** (a tab of **Applications**) reads `dcupl.lc.json`
  straight from the file: every resource the project declares, without an
  outcome. Its health chips count what the config gets wrong, in seven kinds:
  missing files, broken model references, unreferenced files, unassigned
  resources, empty applications, duplicate resources and orphan models.
- **Loader Insights** (a view on a run) shows what one run did with each
  resource: **loaded**, **failed** (recorded as a loader error, the rest of the
  load continues), **pending** while it is still loading, or **not in this
  app**, because the resource has no tags while the application selects tags,
  or its tags do not match the application's.

## Next steps

- [Applications](/console/applications) — running a config and the five views on a run
- [Models in the Console](/console/models) — what a `model` resource points at
- [SDK loader API](/sdk/api/loader) — driving the same file from code
