# Env block

File-level and group-level environment parameter surface: typed keys, defaults, named enums, and list types. Syntax uses `env = { ... }` to disambiguate from declarative blocks.

## Usage

```ops
@enum datacenter(alpha, beta, production)
@enum direction(up, down, redo)

env = {
  @string GIT_USER: "Blizz"
  DEPLOY_TARGET
  @int THRESHOLD: 80
  @bool VERBOSE
  @enum.datacenter[space] DATACENTERS: [alpha beta production]
  @string BRANCH
  @bool RELEASE_ON_MAIN: true
  @secret DEPLOY_TOKEN
  @secret DB_CONNECTION_STRING
  @enum.direction DIRECTION: up
  @duration TIMEOUT: 300s
  @int COVERAGE_THRESHOLD: 80
  @string RUST_TOOLCHAIN: "stable"
  @string[space] TARGETS: [linux darwin]
}
```

## Grammar

```
EnvBlock        = 'env' '=' '{' EnvEntry* '}'
EnvEntry        = ('@' DslType)? ENV_KEY (':' EnvDefault)?
EnvDefault      = '[' (Atom ','?)* ']' | Literal
ENV_KEY         = [A-Z_][A-Z0-9_]*

EnumDecl        = '@enum' IDENT '(' IDENT (',' IDENT)* ')'
```

`DslType` is defined in [type-system.md](type-system.md).

## IR representation

Canonical env field shape and source-map expectations live in [ir_schema](../ir_schema.md) and [values-and-types](../ir/values-and-types.md). This local example shows the intended env lowering surface.

```json
{
  "role": "env",
  "payload": [
    {
      "role": "entry",
      "name": "KEY",
      "payload": [
        { "role": "type", "payload": "string" },
        { "role": "default", "payload": "value" }
      ]
    },
    {
      "role": "entry",
      "name": "KEY2",
      "payload": [
        { "role": "type", "payload": "int" }
      ]
    },
    {
      "role": "entry",
      "name": "KEY3",
      "payload": [
        { "role": "type", "payload": "string" }
      ]
    },
    {
      "role": "entry",
      "name": "KEY4",
      "payload": [
        { "role": "type", "payload": [
          { "role": "name", "payload": "enum" },
          { "role": "variants", "payload": ["alpha", "beta", "production"] },
          { "role": "list", "payload": true },
          { "role": "separator", "payload": "comma" }
        ]},
        { "role": "default", "payload": ["alpha", "beta", "production"] }
      ]
    }
  ]
}
```

## Types

All types from the type system are usable in env blocks. See [type-system.md](type-system.md) for the full reference.

## Runtime

- `@operation` inputs declared via `@in.type` — the env surface validates against those expectations when values are supplied from CLI or invocation.

## Data flow

- **Variable naming:** `$UPPER_CASE` for env parameters and cross-group exports.
- **Layers:** `env = { }` is the file (or group) parameter surface, accessed as `$UPPER_CASE`, resolved from CLI flags at the root or invocation args when nested.
- **No bash `export`:** variables are local to the ops model; only emitted code performs reads. If a group does not need `$VERSION`, no read is generated.

## Implementation

**Build tier:** Tier 7 — Env Block & Named Enums

| Layer | Responsibility |
| --- | --- |
| `ast.rs` | `TopLevel::EnumDecl`, `EnvEntry { key, type_ann, default }` |
| `parser.rs` | `@enum NAME(...)` at top level; `env = {` → entries; `@type` prefix for annotation; `:` for default; `[]` on type for list + optional separator |
| `lower.rs` | Resolve named enums by lookup; emit rich env schema; untyped entries → `string`; list without separator → comma default |

**Validates:** Rust tests for typed env, list types, enum resolution, error cases. Duplicate enum names → error. Unresolved enum refs → error.

## Design decisions

- **`env = { }`:** disambiguates env parameter blocks from declarative `name = { }` blocks.
- **Untyped entries:** default to `string`.
- **Lists:** omitting separator uses comma default (aligned with `@<type>[]` CLI encoding).

## Caveats

- Behavioral details for CLI generation (kebab flags, `--env`, `--skip-env`) live with the drilling/runtime spec; this page focuses on grammar and lowering.

## Drilling (CLI surface)

- **Root:** full env surface flags (`--kebab-case`), `--env KEY=VALUE`, `--skip-env`, `--help`.
- **Group:** only env flags the group’s ops actually consume (including transitive deps), plus `--help`.
- **Flag provenance:** e.g. `--target <string>  required by: docker.push`.
- **Env flag disambiguation:** when multiple ops declare the same env key, it is a compile error. The pipeline author must disambiguate in their `env = { }` block. This keeps the CLI surface stable — it never shifts silently when ops are added or removed. An explicit `env = { }` declaration is the stable public API.

## Behavioral reference

- **Env keys:** regex `[A-Z_][A-Z0-9_]*`.

## Open questions

None.
