# Inputs & Outputs

Every package in Bluebricks has an interface defined by **inputs** and **outputs**. Inputs are the values a package needs to run: a region, a CIDR block, a cluster name, a database password. Outputs are the values a package produces after execution: a VPC ID, an endpoint URL, a connection string.

This interface makes packages composable. One package's output can feed into another package's input, and Bluebricks handles the wiring, ordering, and execution automatically.

This page explains how inputs and outputs work across all layers of Bluebricks, from native IaC code to runtime environments.

## The data flow model

Inputs and outputs flow through four layers:

**Layer 1: Native IaC code** is the infrastructure code you write: Terraform variables, Helm values, CloudFormation parameters, or scripts. This is where inputs and outputs originate.

**Layer 2: Artifact** is the `bricks.json` manifest. Its `props` and `outs` fields define the package's external interface. Bluebricks auto-discovers these from your native code when you publish.

**Layer 3: Blueprint** wires packages together. It connects outputs from one package to inputs of another, passes blueprint-level properties down to packages, and references secrets.

**Layer 4: Environment + Collection** is where Bluebricks resolves values at runtime. Collection properties, secrets, context references, output references, and deployer overrides supply the concrete values.

## Inputs

An input is any value a package needs to execute. In `bricks.json`, inputs are declared in the `props` object.

### How native code maps to inputs

Each IaC tool defines inputs differently at the native level. Bluebricks maps them all to the same `props` interface:

<table><thead><tr><th width="187.41015625">IaC Tool</th><th width="236.94921875">Native input construct</th><th width="320.06640625">Example</th></tr></thead><tbody><tr><td><strong>Terraform/OpenTofu</strong></td><td><code>variable</code> blocks in <code>.tf</code> files</td><td><code>variable "region" { type = string }</code></td></tr><tr><td><strong>Helm</strong></td><td>Keys in <code>values.yaml</code></td><td><code>replicaCount: 1</code></td></tr><tr><td><strong>CloudFormation</strong></td><td><code>Parameters</code> section in the template</td><td><code>Parameters: VpcCidr: Type: String</code></td></tr><tr><td><strong>Generic</strong></td><td>No native construct; props defined in <code>bricks.json</code> only</td><td>N/A</td></tr><tr><td><strong>Bicep</strong></td><td><code>param</code> declarations</td><td><code>param location string</code></td></tr></tbody></table>

When you publish an artifact, Bluebricks reads your native code and auto-populates the `props` section in `bricks.json`.

### How inputs get their values

Inside a blueprint, each package input can receive its value from five sources:

#### 1. Hardcoded value

A fixed value set directly in the blueprint definition:

```yaml
# UI / YAML
props:
  instance_type: t3.medium
```

#### 2. Blueprint-level input

A value passed down from the blueprint's own inputs:

```yaml
# UI / YAML
props:
  region: inputs.region
```

#### 3. Another package's output

A value produced by a sibling package. This creates a dependency in the execution graph:

```yaml
# UI / YAML
props:
  vpc_id: data.network_stack.vpc_id
```

#### 4. Secret

A sensitive value stored in the target collection's secret store:

```yaml
# UI / YAML
props:
  db_password: secrets.db_password
```

#### 5. Collection property or context reference

Values that come from the collection or environment at runtime:

* **Collection properties**: matched by key name. When a blueprint input key matches a collection property name, Bluebricks injects the collection's value automatically
* **Context references**: dynamic placeholders like `${{bricks.collection.slug}}` or `${{bricks.environment.slug}}` that resolve at runtime

See [Properties](https://bluebricks.co/docs/core-concepts/collections/properties), [Secrets](https://bluebricks.co/docs/core-concepts/collections/secrets), and [Using Context References](https://github.com/bluebricks-dev/Bluebricks-Documentation/blob/main/core-concepts/deployments/using-context-references.md).

### How inputs are delivered at runtime

Each IaC tool receives inputs through a different mechanism:

<table><thead><tr><th width="186.4765625">IaC Tool</th><th width="223.1171875">Delivery mechanism</th><th>Details</th></tr></thead><tbody><tr><td><strong>Terraform/OpenTofu</strong></td><td><code>0_bbx_props.auto.tfvars</code></td><td>All props and secrets written to a single auto-vars file. Mark secrets <code>sensitive = true</code> in HCL.</td></tr><tr><td><strong>Helm</strong></td><td>Merged into Helm values</td><td>Props become Helm values; secrets are merged separately and never shown in diffs.</td></tr><tr><td><strong>CloudFormation</strong></td><td>CloudFormation Parameters</td><td>Each prop/secret becomes a <code>ParameterKey</code>/<code>ParameterValue</code> pair. Use <code>NoEcho: true</code> for secrets.</td></tr><tr><td><strong>Generic</strong></td><td>JSON files + environment variables</td><td>Props in <code>/workspace/vars.json</code>. Secrets in <code>/workspace/secrets.json</code>. Both also set as env vars.</td></tr></tbody></table>

## Outputs

An output is a value that a package produces after execution. In `bricks.json`, outputs are declared in the `outs` object.

### How native code maps to outputs

<table><thead><tr><th width="190.2734375">IaC Tool</th><th>Native output construct</th><th>How Bluebricks captures outputs</th></tr></thead><tbody><tr><td><strong>Terraform/OpenTofu</strong></td><td><code>output</code> blocks in <code>.tf</code> files</td><td><code>terraform output -json</code> after apply</td></tr><tr><td><strong>Helm</strong></td><td>No auto-generated outputs (coming soon)</td><td>Manually defined in <code>bricks.json</code></td></tr><tr><td><strong>CloudFormation</strong></td><td><code>Outputs</code> section in the template</td><td><code>DescribeStacks</code> API after apply</td></tr><tr><td><strong>Generic</strong></td><td><code>/workspace/outputs.json</code> written by your script</td><td>File parsed after container exits</td></tr></tbody></table>

### Referencing outputs downstream

Once a package produces outputs, other packages in the same blueprint can reference them using `Data` references:

```yaml
# UI / YAML syntax
vpc_id: data.network_stack.vpc_id
```

The reference format is:

```
Data.<package_id>.<output_key>
  │       │            │
  │       │            └── The output name from the source package's outs
  │       └────────────── The package ID within the blueprint
  └────────────────────── The Data object (runtime output store)
```

During planning, output values appear as "known after apply" placeholders. After apply, Bluebricks captures and stores the real values.

### Cross-environment output references

You can also reference outputs across environments. If a foundational environment (e.g., a shared VPC) produces outputs, dependent environments can consume them. See [Using Output References](https://github.com/bluebricks-dev/Bluebricks-Documentation/blob/main/core-concepts/deployments/using-outputs-references.md).

## Secrets

Secrets are inputs that carry sensitive data: API keys, passwords, tokens. They behave like regular inputs but with additional protections:

* **Stored in the collection's secret store**, encrypted at rest
* **Never shown in logs, diffs, or UI fields**
* **Injected only at runtime** within the secure execution context
* **Wiped from the runner** after execution completes

In a blueprint, you reference secrets using the `Secrets` keyword:

```yaml
# UI / YAML
db_password: secrets.db_password
```

Each IaC tool delivers secrets through a different mechanism:

<table><thead><tr><th width="185.31640625">IaC Tool</th><th>How secrets are delivered</th><th>Best practice</th></tr></thead><tbody><tr><td><strong>Terraform/OpenTofu</strong></td><td>Included in <code>0_bbx_props.auto.tfvars</code></td><td>Mark variables <code>sensitive = true</code> in HCL</td></tr><tr><td><strong>Helm</strong></td><td>Merged into values separately from props</td><td>Never shown in rendered diffs</td></tr><tr><td><strong>CloudFormation</strong></td><td>Passed as Parameters</td><td>Use <code>NoEcho: true</code> in template</td></tr><tr><td><strong>Generic</strong></td><td>Written to <code>/workspace/secrets.json</code> (0600 permissions) + set as env vars</td><td>Never <code>print(os.environ)</code></td></tr></tbody></table>

See [Secrets](https://bluebricks.co/docs/core-concepts/collections/secrets) for how to create and manage secrets at the collection level.

## Package-to-package wiring

When one package's input references another package's output via a `Data` reference, Bluebricks creates an implicit dependency between them. These dependencies form a directed acyclic graph (DAG) that determines execution order.

{% @mermaid/diagram content="flowchart LR
VPC\["<b>VPC</b><br/>outs: vpc\_id"] -- "Data ref" --> Subnet\["<b>Subnet</b><br/>outs: subnet\_id"] -- "Data ref" --> App\["<b>App Server</b>"]" %}

In this example:

* **Subnet** depends on **VPC** because its `vpc_id` input references `Data.vpc.vpc_id`
* **App Server** depends on **Subnet** because it references `Data.subnet.subnet_id`

Bluebricks resolves this graph at plan time and executes packages in the correct order: parallel where there are no dependencies, sequential where one package needs another's output.

The `Data` reference is an [expr](https://expr-lang.org/) expression, so you can manipulate values. For example, select the first subnet from a list with `data.vpc.private_subnets[0]`, or use a fallback with `data.vpc.vpc_id ?? inputs.fallback_vpc_id`.

## Syntax quick reference

Bluebricks uses two equivalent syntaxes depending on context:

<table><thead><tr><th width="222.46875">Concept</th><th>bricks.json syntax</th><th>UI / YAML syntax</th></tr></thead><tbody><tr><td>Blueprint-level input</td><td><code>Props.region</code></td><td><code>inputs.region</code></td></tr><tr><td>Package output reference</td><td><code>Data.pkg_id.output_key</code></td><td><code>data.pkg_id.output_key</code></td></tr><tr><td>Secret reference</td><td><code>Secrets.db_password</code></td><td><code>secrets.db_password</code></td></tr><tr><td>Hardcoded string</td><td><code>"'us-east-1'"</code></td><td><code>us-east-1</code></td></tr><tr><td>Hardcoded number</td><td><code>14</code></td><td><code>14</code></td></tr></tbody></table>

Both syntaxes are [expr](https://expr-lang.org/) expressions. The capitalized form (`Props`, `Data`, `Secrets`) appears in `bricks.json`. The lowercase form (`inputs`, `data`, `secrets`) appears in the UI and YAML configurations.

## End-to-end example

This example shows a blueprint with two packages: a Terraform VPC and a Helm application. The VPC output flows into the Helm chart input, and secrets are pulled from the collection.

**Blueprint YAML (UI-generated):**

```yaml
name: webapp_stack
version: 1.0.0
description: Deploys networking and a web application

inputs:
  region:
    type: string
    allowed_values:
      - us-east-1
      - eu-west-1
  cluster_name:
    type: string

packages:
  - name: vpc
    version: 2.1.0
    props:
      region: inputs.region
      cidr_block: 10.0.0.0/16

  - name: webapp
    version: 1.3.0
    props:
      cluster_name: inputs.cluster_name
      vpc_id: data.vpc.vpc_id
      subnet_ids: data.vpc.private_subnet_ids
      db_password: secrets.db_password

outputs:
  vpc_id:
    value: data.vpc.vpc_id
  app_endpoint:
    value: data.webapp.endpoint
```

**What happens at runtime:**

1. Bluebricks resolves the DAG: `vpc` has no dependencies, `webapp` depends on `vpc`
2. The `vpc` package runs first. Inputs `region` and `cidr_block` are delivered via `0_bbx_props.auto.tfvars`.
3. After `vpc` completes, Bluebricks captures its outputs (`vpc_id`, `private_subnet_ids`) via `terraform output -json`.
4. The `webapp` package runs next. Its inputs include the VPC outputs (resolved from `Data.vpc.*`) and the secret `db_password` (resolved from the collection's secret store).
5. The blueprint's outputs are populated and available to dependent environments.
