# Parameter binding files

`convert-tree` can layer two optional JSON files over a package's design-time
parameter defaults (brief §2.2):

- `--environment-file` — SSISDB environment-reference values (one file per
  environment: DEV/UAT/PROD).
- `--overrides-file` — execution-time overrides (`dtexec /SET` / `/Par` / SSISDB
  execution parameter values), the highest-precedence binding layer.

Live SSISDB reads are never attempted (this repo is air-gapped, generate-only);
both layers are supplied as files.

## JSON schema

Each file is a flat JSON object mapping a fully-qualified parameter name to a
value. Three key/value shapes are accepted:

| Shape | Example | Meaning |
| --- | --- | --- |
| Namespace-qualified scalar | `"$Project::StagingServer": "sql-uat-07"` | Bind `$Project::StagingServer` to the value. |
| Bare-name scalar | `"BatchSize": "9000"` | A key with no `::` defaults to the `Project` namespace, so this binds `$Project::BatchSize`. |
| Withheld object | `"$Project::ApiKey": {"value": "", "sensitive": true}` | A sensitive parameter; the value is never carried through (mirrors SSIS withholding). An object may also carry an explicit non-sensitive `"value"`. |

The leading `$` is optional (`Project::Name` and `$Project::Name` are
equivalent). A sensitive entry's value is always dropped, so a secret never lives
in a binding file.

Copy-ready examples live next to this file:

- [`templates/environment-file.example.json`](templates/environment-file.example.json)
- [`templates/overrides-file.example.json`](templates/overrides-file.example.json)

### Seeding a binding file

`emit-binding-template --project <dir> --out <file>` pre-fills a starter binding
file from the parameters discovered in an expanded project (or a loose `.dtsx`
tree), so a user can bind without reading the source. Non-sensitive parameters
default to their design value; sensitive ones are withheld as
`{"value": "", "sensitive": true}`. A tree with no bindable parameters still
writes a usable, empty `{}` template.

## Precedence

Later layers win on the same `$Namespace::Name`:

```
design (Project.params / <DTS:PackageParameters>)
  -> manifest (@Project.manifest / project context)
    -> environment (--environment-file)
      -> override (--overrides-file)   [highest]
```

`sensitive` marks a parameter as a secret so tooling *withholds* its value: the
parameter audit report and `emit-binding-template` both emit sensitive params
with an empty `value`. The flag governs withholding, **not** resolution — if you
write a plaintext value for a sensitive parameter into an environment/override
file it is still bound and can be interpolated into the generated SQL. Keep real
secrets out of committed binding files and supply them at deploy time instead.

## The literal-wins caveat

These layers govern parameter **bindings** only. A token-free literal in a
`.dtsx` connection string (e.g. a hard-coded `Initial Catalog=SalesDW`) beats
every binding layer, because `transforms.base._resolve_connection_field` treats
such a literal as authoritative. An environment/override of a literal connection
field therefore cannot take effect — brief §2.2's precedence covers bindings, not
hard-coded literals. To make a connection field bindable it must be parameterised
in the `.dtsx` (a `@[$Project::…]` token in the connection-string property
expression) rather than hard-coded.
