Back to skills
SkillHub ClubRun DevOpsFull StackDevOps

terraform-stacks

Comprehensive guide for working with HashiCorp Terraform Stacks. Use when creating, modifying, or validating Terraform Stack configurations (.tfcomponent.hcl, .tfdeploy.hcl files), working with stack components and deployments from local modules, public registry, or private registry sources, managing multi-region or multi-environment infrastructure, or troubleshooting Terraform Stacks syntax and structure.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
473
Hot score
99
Updated
March 20, 2026
Overall rating
C3.6
Composite score
3.6
Best-practice grade
B73.6

Install command

npx @skill-hub/cli install hashicorp-agent-skills-terraform-stacks

Repository

hashicorp/agent-skills

Skill path: terraform/module-generation/skills/terraform-stacks

Comprehensive guide for working with HashiCorp Terraform Stacks. Use when creating, modifying, or validating Terraform Stack configurations (.tfcomponent.hcl, .tfdeploy.hcl files), working with stack components and deployments from local modules, public registry, or private registry sources, managing multi-region or multi-environment infrastructure, or troubleshooting Terraform Stacks syntax and structure.

Open repository

Best for

Primary workflow: Run DevOps.

Technical facets: Full Stack, DevOps.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: hashicorp.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install terraform-stacks into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/hashicorp/agent-skills before adding terraform-stacks to shared team environments
  • Use terraform-stacks for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: terraform-stacks
description: Comprehensive guide for working with HashiCorp Terraform Stacks. Use when creating, modifying, or validating Terraform Stack configurations (.tfcomponent.hcl, .tfdeploy.hcl files), working with stack components and deployments from local modules, public registry, or private registry sources, managing multi-region or multi-environment infrastructure, or troubleshooting Terraform Stacks syntax and structure.
metadata:
  copyright: Copyright IBM Corp. 2026
  version: "0.0.1"
---

# Terraform Stacks

Terraform Stacks simplify infrastructure provisioning and management at scale by providing a configuration layer above traditional Terraform modules. Stacks enable declarative orchestration of multiple components across environments, regions, and cloud accounts.

## Core Concepts

**Stack**: A complete unit of infrastructure composed of components and deployments that can be managed together.

**Component**: An abstraction around a Terraform module that defines infrastructure pieces. Each component specifies a source module, inputs, and providers.

**Deployment**: An instance of all components in a stack with specific input values. Use deployments for different environments (dev/staging/prod), regions, or cloud accounts.

**Stack Language**: A separate HCL-based language (not regular Terraform HCL) with distinct blocks and file extensions.

## File Structure

Terraform Stacks use specific file extensions:

- **Component configuration**: `.tfcomponent.hcl`
- **Deployment configuration**: `.tfdeploy.hcl`
- **Provider lock file**: `.terraform.lock.hcl` (generated by CLI)

All configuration files must be at the root level of the Stack repository. HCP Terraform processes all files in dependency order.

### Recommended File Organization

```
my-stack/
├── variables.tfcomponent.hcl        # Variable declarations
├── providers.tfcomponent.hcl        # Provider configurations
├── components.tfcomponent.hcl       # Component definitions
├── outputs.tfcomponent.hcl          # Stack outputs
├── deployments.tfdeploy.hcl         # Deployment definitions
├── .terraform.lock.hcl              # Provider lock file (generated)
└── modules/                         # Local modules (optional - only if using local modules)
    ├── vpc/
    └── compute/
```

**Note**: The `modules/` directory is only required when using local module sources. Components can reference modules from:
- Local file paths: `./modules/vpc`
- Public registry: `terraform-aws-modules/vpc/aws`
- Private registry: `app.terraform.io/<org-name>/vpc/aws`

When validating Stack configurations, check component source declarations rather than assuming a local `modules/` directory must exist.

## Component Configuration (.tfcomponent.hcl)

### Variable Block

Declare input variables for the Stack configuration. Variables must define a `type` field and do not support the `validation` argument.

```hcl
variable "aws_region" {
  type        = string
  description = "AWS region for deployments"
  default     = "us-west-1"
}

variable "identity_token" {
  type        = string
  description = "OIDC identity token"
  ephemeral   = true  # Does not persist to state file
}

variable "instance_count" {
  type     = number
  nullable = false
}
```

### Required Providers Block

Works the same as traditional Terraform configurations:

```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
  random = {
    source  = "hashicorp/random"
    version = "~> 3.5.0"
  }
}
```

### Provider Block

Provider blocks differ from traditional Terraform:

1. Support `for_each` meta-argument
2. Define aliases in the block header (not as an argument)
3. Accept configuration through a `config` block

**Single Provider Configuration:**

```hcl
provider "aws" "this" {
  config {
    region = var.aws_region
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

**Multiple Provider Configurations with for_each:**

```hcl
provider "aws" "configurations" {
  for_each = var.regions
  
  config {
    region = each.value
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

### Component Block

Each Stack requires at least one component block. Add a component for each module to include in the Stack.

**Component Source**: Each component's `source` argument must specify one of the following source types:
- Local file path: `./modules/vpc`
- Public registry: `terraform-aws-modules/vpc/aws`
- Private registry: `app.terraform.io/my-org/vpc/aws`
- Git repository: `git::https://github.com/org/repo.git//modules/vpc?ref=v1.0.0`

```hcl
component "vpc" {
  source = "./modules/vpc"

  inputs = {
    cidr_block  = var.vpc_cidr
    name_prefix = var.name_prefix
  }

  providers = {
    aws = provider.aws.this
  }
}

component "networking" {
  source  = "app.terraform.io/my-org/vpc/aws"
  version = "2.1.0"

  inputs = {
    cidr_block  = var.vpc_cidr
    environment = var.environment
  }

  providers = {
    aws = provider.aws.this
  }
}

component "compute" {
  source = "./modules/compute"

  inputs = {
    vpc_id          = component.vpc.vpc_id
    subnet_ids      = component.vpc.private_subnet_ids
    instance_type   = var.instance_type
  }

  providers = {
    aws = provider.aws.this
  }
}
```

**Component with for_each for Multi-Region:**

```hcl
component "s3" {
  for_each = var.regions
  
  source = "./modules/s3"
  
  inputs = {
    region = each.value
    tags   = var.common_tags
  }
  
  providers = {
    aws = provider.aws.configurations[each.value]
  }
}
```

**Key Points:**
- Reference component outputs using `component.<name>.<output>`
- All inputs are provided as a single `inputs` object
- Provider references are normal values: `provider.<type>.<alias>`
- Dependencies are automatically inferred from component references

### Output Block

Outputs require a `type` argument and do not support `preconditions`:

```hcl
output "vpc_id" {
  type        = string
  description = "VPC ID"
  value       = component.vpc.vpc_id
}

output "endpoint_urls" {
  type      = map(string)
  value     = {
    for region, comp in component.api : region => comp.endpoint_url
  }
  sensitive = false
}
```

### Locals Block

Works exactly as in traditional Terraform:

```hcl
locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform Stacks"
    Project     = var.project_name
  }
  
  region_config = {
    for region in var.regions : region => {
      name_suffix = "${var.environment}-${region}"
    }
  }
}
```

### Removed Block

Use to safely remove components from a Stack. HCP Terraform requires the component's providers to remove it.

```hcl
removed {
  from   = component.old_component
  source = "./modules/old-module"
  
  providers = {
    aws = provider.aws.this
  }
}
```

## Deployment Configuration (.tfdeploy.hcl)

### Identity Token Block

Generate JWT tokens for OIDC authentication with cloud providers:

```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

identity_token "azure" {
  audience = ["api://AzureADTokenExchange"]
}
```

Reference tokens in deployments using `identity_token.<name>.jwt`

### Locals Block

Define local values for deployment configuration:

```hcl
locals {
  aws_regions = ["us-west-1", "us-east-1", "eu-west-1"]
  role_arn    = "arn:aws:iam::123456789012:role/hcp-terraform-stacks"
}
```

### Deployment Block

Define deployment instances. Each Stack requires at least one deployment (maximum 20 per Stack).

**Single Environment Deployment:**

```hcl
deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 3
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}
```

**Multiple Environment Deployments:**

```hcl
deployment "development" {
  inputs = {
    aws_region     = "us-east-1"
    instance_count = 1
    name_suffix    = "dev"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "staging" {
  inputs = {
    aws_region     = "us-east-1"
    instance_count = 2
    name_suffix    = "staging"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 5
    name_suffix    = "prod"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}
```

**Destroying a Deployment:**

To safely remove a deployment:

```hcl
deployment "old_environment" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 2
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
  destroy = true  # Mark for destruction
}
```

After applying the plan and the deployment is destroyed, remove the deployment block from your configuration.

### Deployment Group Block

Group deployments together to configure shared settings (Premium feature). **Best Practice**: Always create deployment groups for all deployments, even single deployments, to enable future auto-approval rules and maintain consistent configuration patterns.

```hcl
deployment_group "canary" {
  deployments = [
    deployment.dev,
    deployment.staging
  ]
}

deployment_group "production" {
  deployments = [
    deployment.prod_us_east,
    deployment.prod_us_west
  ]
}
```

### Deployment Auto-Approve Block

Define rules that automatically approve deployment plans based on specific conditions (Premium feature):

```hcl
deployment_auto_approve "safe_changes" {
  deployment_group = deployment_group.canary
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Cannot auto-approve plans with resource deletions"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

deployment_auto_approve "applyable_only" {
  deployment_group = deployment_group.production
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be successful"
  }
}
```

**Available Context Variables:**
- `context.plan.applyable` - Plan succeeded without errors
- `context.plan.changes.add` - Number of resources to add
- `context.plan.changes.change` - Number of resources to change
- `context.plan.changes.remove` - Number of resources to remove

**Note:** `orchestrate` blocks are deprecated. Use `deployment_group` and `deployment_auto_approve` instead.

### Publish Output Block

Export outputs from a Stack for use in other Stacks (linked Stacks):

```hcl
publish_output "vpc_id_network" {
  type  = string
  value = deployment.network.vpc_id
}

publish_output "subnet_ids" {
  type  = list(string)
  value = deployment.network.private_subnet_ids
}
```

### Upstream Input Block

Reference published outputs from another Stack:

```hcl
upstream_input "network_stack" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/networking-stack"
}

deployment "application" {
  inputs = {
    vpc_id     = upstream_input.network_stack.vpc_id_network
    subnet_ids = upstream_input.network_stack.subnet_ids
  }
}
```

## Terraform Stacks CLI

### Initialize and Validate

Generate provider lock file:

```bash
terraform stacks providers-lock
```

Validate Stack configuration:

```bash
terraform stacks validate
```

### Plan and Apply

Plan a specific deployment:

```bash
terraform stacks plan --deployment=production
```

Apply a deployment:

```bash
terraform stacks apply --deployment=production
```

## Common Patterns

### Multi-Region Deployment

```hcl
# variables.tfcomponent.hcl
variable "regions" {
  type = set(string)
  default = ["us-west-1", "us-east-1", "eu-west-1"]
}

# providers.tfcomponent.hcl
provider "aws" "regional" {
  for_each = var.regions
  
  config {
    region = each.value
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}

# components.tfcomponent.hcl
component "regional_infra" {
  for_each = var.regions
  source   = "./modules/regional"
  
  inputs = {
    region = each.value
  }
  
  providers = {
    aws = provider.aws.regional[each.value]
  }
}
```

### Component Dependencies

Dependencies are automatically inferred when one component references another's output:

```hcl
component "database" {
  source = "./modules/rds"
  
  inputs = {
    subnet_ids = component.vpc.private_subnet_ids  # Creates dependency
  }
  
  providers = {
    aws = provider.aws.this
  }
}
```

## Best Practices

1. **Component Granularity**: Create components for logical infrastructure units that share a lifecycle
2. **Module Compatibility**: Modules used with Stacks cannot include provider blocks (configure providers in Stack configuration)
3. **State Isolation**: Each deployment has its own isolated state
4. **Input Variables**: Use variables for values that differ across deployments; use locals for shared values
5. **Provider Lock Files**: Always generate and commit `.terraform.lock.hcl` to version control
6. **Naming Conventions**: Use descriptive names for components and deployments
7. **Deployment Groups**: Always organize deployments into deployment groups, even if you only have one deployment. Deployment groups enable auto-approval rules, logical organization, and provide a foundation for scaling. While deployment groups are a Premium feature, organizing your configurations to use them is a best practice for all Stacks
8. **Testing**: Test Stack configurations in dev/staging deployments before production

## Troubleshooting

### Circular Dependencies

**Issue**: Component A references Component B, and Component B references Component A
**Solution**: Refactor to break the circular reference or use intermediate components

### Deployment Limit

HCP Terraform supports maximum 20 deployments per Stack. For more instances, use multiple Stacks or `for_each` within components.

## References

For detailed block specifications and advanced features, see:
- `references/component-blocks.md` - Complete component block reference
- `references/deployment-blocks.md` - Complete deployment block reference
- `references/examples.md` - Complete working examples for common scenarios


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/component-blocks.md

```markdown
# Component Configuration Block Reference

Complete reference for all blocks available in Terraform Stack component configuration files (`.tfcomponent.hcl`).

## Table of Contents

1. [Variable Block](#variable-block)
2. [Required Providers Block](#required-providers-block)
3. [Provider Block](#provider-block)
4. [Component Block](#component-block)
5. [Output Block](#output-block)
6. [Locals Block](#locals-block)
7. [Removed Block](#removed-block)

## Variable Block

Declares input variables for Stack configuration.

### Syntax

```hcl
variable "variable_name" {
  type        = <type>
  description = "<description>"
  default     = <value>
  sensitive   = <bool>
  nullable    = <bool>
  ephemeral   = <bool>
}
```

### Arguments

- **type** (required): Data type (string, number, bool, list, map, object, set, tuple, any)
- **description** (optional): Variable description
- **default** (optional): Default value
- **sensitive** (optional, default false): Mark as sensitive to redact from logs
- **nullable** (optional, default true): Whether null is allowed
- **ephemeral** (optional, default false): Do not persist to state file

### Differences from Traditional Terraform

- **type** is required (not optional)
- **validation** argument is not supported

### Examples

```hcl
variable "aws_region" {
  type        = string
  description = "AWS region for infrastructure"
  default     = "us-west-1"
}

variable "instance_count" {
  type        = number
  description = "Number of instances"
  nullable    = false
}

variable "identity_token" {
  type        = string
  description = "OIDC identity token"
  ephemeral   = true
}

variable "tags" {
  type = map(string)
  default = {
    Environment = "dev"
    ManagedBy   = "Terraform"
  }
}

variable "subnet_config" {
  type = object({
    cidr_block           = string
    availability_zone    = string
    map_public_ip        = bool
  })
}
```

## Required Providers Block

Declares provider dependencies.

### Syntax

```hcl
required_providers {
  <provider_name> = {
    source  = "<source>"
    version = "<version_constraint>"
  }
}
```

### Arguments

- **source** (required): Provider source address (e.g., "hashicorp/aws")
- **version** (optional): Version constraint (e.g., "~> 5.0")

### Examples

```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
  
  random = {
    source  = "hashicorp/random"
    version = "~> 3.5.0"
  }
  
  azurerm = {
    source  = "hashicorp/azurerm"
    version = ">= 3.0"
  }
}
```

## Provider Block

Configures provider instances.

### Syntax

```hcl
provider "<provider_type>" "<alias>" {
  for_each = <map_or_set>  # Optional
  
  config {
    <provider_arguments>
  }
}
```

### Arguments

- **provider_type** (label 1, required): Provider type (e.g., "aws", "azurerm")
- **alias** (label 2, required): Unique identifier for this provider configuration
- **for_each** (optional): Create multiple provider instances from a map or set
- **config** (required): Nested block containing provider-specific configuration

### Key Differences from Traditional Terraform

1. Alias is defined in block header, not as an argument
2. Configuration goes in a nested `config` block
3. Supports `for_each` meta-argument
4. Provider configurations are treated as first-class values

### Examples

**Single Provider:**

```hcl
provider "aws" "main" {
  config {
    region = var.aws_region
    
    default_tags {
      tags = var.common_tags
    }
  }
}
```

**Provider with OIDC Authentication:**

```hcl
provider "aws" "authenticated" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

**Multiple Providers with for_each:**

```hcl
provider "aws" "regional" {
  for_each = toset(var.regions)
  
  config {
    region = each.value
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

**Multiple Cloud Accounts:**

```hcl
provider "aws" "accounts" {
  for_each = var.aws_accounts
  
  config {
    region = var.default_region
    
    assume_role {
      role_arn = "arn:aws:iam::${each.value.account_id}:role/${var.role_name}"
    }
  }
}
```

## Component Block

Defines infrastructure components to include in the Stack.

### Syntax

```hcl
component "<component_name>" {
  for_each = <map_or_set>  # Optional
  
  source = "<module_source>"
  
  inputs = {
    <input_name> = <value>
  }
  
  providers = {
    <provider_local_name> = provider.<type>.<alias>[<key>]
  }
}
```

### Arguments

- **component_name** (label, required): Unique identifier for this component
- **for_each** (optional): Create multiple component instances
- **source** (required): Module source (see [Source Argument](#source-argument) below)
- **version** (optional): Version constraint for registry-based sources only
- **inputs** (required): Map of input variables for the module
- **providers** (required): Map of provider configurations

### Source Argument

The `source` argument accepts the same module sources as traditional Terraform configurations.

**Local File Path:**
```hcl
source = "./modules/vpc"
source = "../shared-modules/networking"
```

**Public Terraform Registry:**
```hcl
source = "terraform-aws-modules/vpc/aws"
source = "hashicorp/consul/aws"
```
Format: `<NAMESPACE>/<NAME>/<PROVIDER>`

**Private HCP Terraform Registry:**
```hcl
source = "app.terraform.io/my-org/vpc/aws"
source = "app.terraform.io/example-corp/networking/azurerm"
```
Format: `<HOSTNAME>/<ORGANIZATION>/<MODULE_NAME>/<PROVIDER_NAME>`

- **HCP Terraform (SaaS)**: Use hostname `app.terraform.io`
- **Terraform Enterprise**: Use your instance hostname (e.g., `terraform.mycompany.com`)
- **Generic hostname**: Use `localterraform.com` for deployments spanning multiple Terraform Enterprise instances

**Git Repository:**
```hcl
source = "git::https://github.com/org/repo.git//modules/vpc?ref=v1.0.0"
source = "git::ssh://[email protected]/org/repo.git//modules/vpc?ref=main"
```

**HTTP/HTTPS Archive:**
```hcl
source = "https://example.com/modules/vpc-module.tar.gz"
```

### Version Argument

The `version` argument is supported only for registry-based sources (public and private registries). Local file paths and Git sources do not support the `version` argument.

```hcl
component "vpc" {
  source  = "app.terraform.io/my-org/vpc/aws"
  version = "~> 2.0"  # Semantic versioning constraint

  inputs = {
    cidr_block = var.vpc_cidr
  }

  providers = {
    aws = provider.aws.main
  }
}
```

**Note**: Modules sourced from local file paths always share the same version as their caller and cannot have independent version constraints.

### Component References

Access component outputs using: `component.<name>.<output>`

For components with `for_each`: `component.<name>[<key>].<output>`

### Examples

**Basic Component (Local Module):**

```hcl
component "vpc" {
  source = "./modules/vpc"

  inputs = {
    cidr_block  = var.vpc_cidr
    name_prefix = var.name_prefix
  }

  providers = {
    aws = provider.aws.main
  }
}
```

**Component from Public Registry:**

```hcl
component "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  inputs = {
    cidr            = var.vpc_cidr
    azs             = var.availability_zones
    private_subnets = var.private_subnet_cidrs
    public_subnets  = var.public_subnet_cidrs
  }

  providers = {
    aws = provider.aws.main
  }
}
```

**Component from Private Registry:**

```hcl
component "vpc" {
  source  = "app.terraform.io/my-org/vpc/aws"
  version = "2.1.0"

  inputs = {
    cidr_block  = var.vpc_cidr
    name_prefix = var.name_prefix
    environment = var.environment
  }

  providers = {
    aws = provider.aws.main
  }
}
```

**Component with Dependencies:**

```hcl
component "database" {
  source = "./modules/rds"
  
  inputs = {
    vpc_id             = component.vpc.vpc_id
    subnet_ids         = component.vpc.private_subnet_ids
    security_group_ids = [component.security.database_sg_id]
    engine_version     = var.db_engine_version
  }
  
  providers = {
    aws = provider.aws.main
  }
}
```

**Component with for_each (Multi-Region):**

```hcl
component "regional_s3" {
  for_each = toset(var.regions)
  
  source = "./modules/s3"
  
  inputs = {
    region      = each.value
    bucket_name = "${var.app_name}-${each.value}"
    tags        = local.common_tags
  }
  
  providers = {
    aws = provider.aws.regional[each.value]
  }
}
```

**Component with Multiple Providers:**

```hcl
component "cross_region_replication" {
  source = "./modules/s3-replication"
  
  inputs = {
    source_bucket = var.source_bucket
    dest_bucket   = var.dest_bucket
  }
  
  providers = {
    aws.source = provider.aws.us_east
    aws.dest   = provider.aws.eu_west
  }
}
```

**Component with for_each over Map:**

```hcl
component "applications" {
  for_each = var.applications
  
  source = "./modules/application"
  
  inputs = {
    app_name        = each.key
    instance_type   = each.value.instance_type
    instance_count  = each.value.count
    vpc_id          = component.vpc.vpc_id
  }
  
  providers = {
    aws = provider.aws.main
  }
}
```

## Output Block

Exposes values from Stack configuration.

### Syntax

```hcl
output "<output_name>" {
  type        = <type>
  description = "<description>"
  value       = <expression>
  sensitive   = <bool>
  ephemeral   = <bool>
}
```

### Arguments

- **output_name** (label, required): Unique identifier for this output
- **type** (required): Data type of the output
- **description** (optional): Output description
- **value** (required): Expression to output
- **sensitive** (optional, default false): Mark as sensitive
- **ephemeral** (optional, default false): Ephemeral value

### Differences from Traditional Terraform

- **type** is required
- **precondition** block is not supported

### Examples

```hcl
output "vpc_id" {
  type        = string
  description = "VPC ID"
  value       = component.vpc.vpc_id
}

output "database_endpoint" {
  type        = string
  description = "Database endpoint"
  value       = component.database.endpoint
  sensitive   = true
}

output "regional_endpoints" {
  type        = map(string)
  description = "API endpoints by region"
  value       = {
    for region, comp in component.api_gateway : region => comp.endpoint_url
  }
}

output "instance_details" {
  type = object({
    id         = string
    public_ip  = string
    private_ip = string
  })
  description = "EC2 instance details"
  value = {
    id         = component.compute.instance_id
    public_ip  = component.compute.public_ip
    private_ip = component.compute.private_ip
  }
}
```

## Locals Block

Defines local values for reuse within the Stack configuration.

### Syntax

```hcl
locals {
  <name> = <expression>
}
```

### Examples

```hcl
locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform Stacks"
    Project     = var.project_name
    CostCenter  = var.cost_center
  }
  
  name_prefix = "${var.project_name}-${var.environment}"
  
  region_config = {
    for region in var.regions : region => {
      name_suffix    = region
      instance_count = var.environment == "prod" ? 3 : 1
    }
  }
  
  availability_zones = [
    for az in var.availability_zones : az
    if can(regex("^${var.aws_region}", az))
  ]
}
```

## Removed Block

Declares components to be removed from the Stack.

### Syntax

```hcl
removed {
  from   = component.<component_name>
  source = "<original_module_source>"
  
  providers = {
    <provider_name> = provider.<type>.<alias>
  }
}
```

### Arguments

- **from** (required): Reference to the component being removed
- **source** (required): Original module source
- **providers** (required): Provider configurations needed for removal

### Important Notes

- Required for safe component removal
- Must include all providers the component used
- Do not remove providers before removing components that use them

### Examples

```hcl
removed {
  from   = component.old_component
  source = "./modules/deprecated-module"
  
  providers = {
    aws = provider.aws.main
  }
}

removed {
  from   = component.legacy_regional
  source = "registry.terraform.io/example/legacy/aws"
  
  providers = {
    aws    = provider.aws.main
    random = provider.random.main
  }
}
```

## Provider References in Component Blocks

### Single Provider

```hcl
providers = {
  aws = provider.aws.main
}
```

### Multiple Providers

```hcl
providers = {
  aws    = provider.aws.main
  random = provider.random.main
  tls    = provider.tls.main
}
```

### Provider from for_each

```hcl
providers = {
  aws = provider.aws.regional[each.value]
}
```

### Aliased Providers in Module

If module requires specific provider aliases:

```hcl
providers = {
  aws.source = provider.aws.us_east
  aws.dest   = provider.aws.eu_west
}
```

```

### references/deployment-blocks.md

```markdown
# Deployment Configuration Block Reference

Complete reference for all blocks available in Terraform Stack deployment configuration files (`.tfdeploy.hcl`).

## Table of Contents

1. [Identity Token Block](#identity-token-block)
2. [Locals Block](#locals-block)
3. [Deployment Block](#deployment-block)
4. [Deployment Group Block](#deployment-group-block)
5. [Deployment Auto-Approve Block](#deployment-auto-approve-block)
6. [Publish Output Block](#publish-output-block)
7. [Upstream Input Block](#upstream-input-block)

## Identity Token Block

Generates JWT tokens for OIDC authentication with cloud providers.

### Syntax

```hcl
identity_token "<token_name>" {
  audience = [<audience_strings>]
}
```

### Arguments

- **token_name** (label, required): Unique identifier for this token
- **audience** (required): List of audience strings for the JWT

### Accessing Token

Reference the JWT using: `identity_token.<n>.jwt`

### Cloud Provider Audiences

**AWS:**
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}
```

**Azure:**
```hcl
identity_token "azure" {
  audience = ["api://AzureADTokenExchange"]
}
```

**Google Cloud:**
```hcl
identity_token "gcp" {
  audience = ["//iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/providers/<PROVIDER_ID>"]
}
```

### Examples

**Single Token:**

```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

deployment "production" {
  inputs = {
    identity_token = identity_token.aws.jwt
    role_arn       = var.role_arn
  }
}
```

**Multiple Tokens for Different Regions:**

```hcl
identity_token "aws_east" {
  audience = ["aws.workload.identity.east"]
}

identity_token "aws_west" {
  audience = ["aws.workload.identity.west"]
}

deployment "east_deployment" {
  inputs = {
    identity_token = identity_token.aws_east.jwt
    role_arn       = var.east_role_arn
  }
}

deployment "west_deployment" {
  inputs = {
    identity_token = identity_token.aws_west.jwt
    role_arn       = var.west_role_arn
  }
}
```

## Locals Block

Defines local values for reuse within deployment configuration.

### Syntax

```hcl
locals {
  <n> = <expression>
}
```

### Examples

```hcl
locals {
  aws_regions = ["us-west-1", "us-east-1", "eu-west-1"]
  
  role_arn = "arn:aws:iam::123456789012:role/hcp-terraform-stacks"
  
  common_inputs = {
    project_name = "my-app"
    environment  = "production"
  }
  
  environments = {
    dev = {
      region         = "us-east-1"
      instance_count = 1
      instance_type  = "t3.micro"
    }
    staging = {
      region         = "us-west-1"
      instance_count = 2
      instance_type  = "t3.small"
    }
    prod = {
      region         = "us-west-1"
      instance_count = 5
      instance_type  = "t3.large"
    }
  }
}
```

## Deployment Block

Defines deployment instances of the Stack.

### Syntax

```hcl
deployment "<deployment_name>" {
  inputs = {
    <input_name> = <value>
  }
}
```

### Arguments

- **deployment_name** (label, required): Unique identifier for this deployment
- **inputs** (required): Map of input variable values
- **destroy** (optional, default: false): Boolean flag to destroy this deployment

### Constraints

- Minimum 1 deployment per Stack
- Maximum 20 deployments per Stack
- No meta-arguments supported (no `for_each`, `count`)

### Destroying a Deployment

To safely remove a deployment from your Stack:

1. Set `destroy = true` in the deployment block
2. Apply the plan through HCP Terraform
3. After successful destruction, remove the deployment block from your configuration

**Important**: Using the `destroy` argument ensures your configuration has the provider authentication necessary to properly destroy the deployment's resources.

**Example:**
```hcl
deployment "old_environment" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 2
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
  destroy = true  # Mark for destruction
}
```

After applying this plan and the deployment is destroyed, remove the entire `deployment "old_environment"` block from your configuration.

### Examples

**Single Deployment:**

```hcl
deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 5
    instance_type  = "t3.large"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}
```

**Multiple Environment Deployments:**

```hcl
deployment "development" {
  inputs = {
    aws_region     = "us-east-1"
    instance_count = 1
    instance_type  = "t3.micro"
    name_suffix    = "dev"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "staging" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 2
    instance_type  = "t3.small"
    name_suffix    = "staging"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 5
    instance_type  = "t3.large"
    name_suffix    = "prod"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}
```

**Multi-Region Deployments:**

```hcl
deployment "us_prod_east" {
  inputs = {
    aws_region     = "us-east-1"
    instance_count = 3
    name_suffix    = "prod-east"
    role_arn       = local.role_arn
    identity_token = identity_token.aws_east.jwt
  }
}

deployment "us_prod_west" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 3
    name_suffix    = "prod-west"
    role_arn       = local.role_arn
    identity_token = identity_token.aws_west.jwt
  }
}

deployment "eu_prod" {
  inputs = {
    aws_region     = "eu-west-1"
    instance_count = 3
    name_suffix    = "prod-eu"
    role_arn       = local.role_arn
    identity_token = identity_token.aws_eu.jwt
  }
}
```

**Using Locals for DRY Configuration:**

```hcl
locals {
  common_inputs = {
    role_arn       = "arn:aws:iam::123456789012:role/terraform"
    identity_token = identity_token.aws.jwt
    project_name   = "my-app"
  }
}

deployment "dev" {
  inputs = merge(local.common_inputs, {
    aws_region     = "us-east-1"
    instance_count = 1
    environment    = "dev"
  })
}

deployment "prod" {
  inputs = merge(local.common_inputs, {
    aws_region     = "us-west-1"
    instance_count = 5
    environment    = "prod"
  })
}
```

## Deployment Group Block

Groups deployments together to configure shared settings and auto-approval rules (HCP Terraform Premium feature).

**Best Practice**: Always create deployment groups for all deployments, even when you have only a single deployment. This establishes a consistent configuration pattern, enables future auto-approval rules, and provides a foundation for scaling your Stack.

### Syntax

```hcl
deployment_group "<group_name>" {
  deployments = [<deployment_references>]
}
```

### Arguments

- **group_name** (label, required): Unique identifier for this deployment group
- **deployments** (required): List of deployment references to include in this group

### Purpose

Deployment groups allow you to:
- Organize deployments logically (by environment, team, region, etc.)
- Configure shared auto-approval rules for multiple deployments
- Manage deployments more effectively at scale
- Establish consistent configuration patterns across all Stacks

### Examples

**Single Deployment Group (Best Practice):**

```hcl
deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    instance_count = 5
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment_group "production" {
  deployments = [deployment.production]
}
```

**Multiple Deployment Groups:**

```hcl
deployment_group "non_production" {
  deployments = [
    deployment.development,
    deployment.staging
  ]
}

deployment_group "production" {
  deployments = [
    deployment.prod_us_east,
    deployment.prod_us_west,
    deployment.prod_eu_west
  ]
}
```

**Environment-Based Groups:**

```hcl
deployment_group "development_environments" {
  deployments = [
    deployment.dev_feature_a,
    deployment.dev_feature_b,
    deployment.dev_integration
  ]
}

deployment_group "production_environments" {
  deployments = [
    deployment.prod_primary,
    deployment.prod_dr
  ]
}
```

**Regional Groups:**

```hcl
deployment_group "americas" {
  deployments = [
    deployment.us_east,
    deployment.us_west,
    deployment.brazil
  ]
}

deployment_group "europe" {
  deployments = [
    deployment.eu_west,
    deployment.eu_central
  ]
}
```

## Deployment Auto-Approve Block

Defines rules that automatically approve deployment plans based on specific conditions (HCP Terraform Premium feature).

### Syntax

```hcl
deployment_auto_approve "<rule_name>" {
  deployment_group = deployment_group.<group_name>
  
  check {
    condition = <boolean_expression>
    reason    = "<failure_message>"
  }
}
```

### Arguments

- **rule_name** (label, required): Unique identifier for this auto-approve rule
- **deployment_group** (required): Reference to the deployment group this rule applies to
- **check** (required, one or more): Condition that must be met for auto-approval

### Context Variables

Access plan information through `context` object:

- `context.plan.applyable` - Boolean: plan succeeded without errors
- `context.plan.changes.add` - Number: resources to add
- `context.plan.changes.change` - Number: resources to change
- `context.plan.changes.remove` - Number: resources to remove
- `context.plan.changes.import` - Number: resources to import

### Important Notes

- All checks must pass for auto-approval to occur
- If any check fails, manual approval is required
- HCP Terraform displays the failure reason from failed checks
- Auto-approve rules only apply to deployments in the specified deployment group

### Examples

**Auto-approve Successful Plans:**

```hcl
deployment_group "canary" {
  deployments = [
    deployment.dev,
    deployment.staging
  ]
}

deployment_auto_approve "applyable_plans" {
  deployment_group = deployment_group.canary
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable without errors"
  }
}
```

**Auto-approve Only Additions (No Changes or Deletions):**

```hcl
deployment_group "non_prod" {
  deployments = [
    deployment.development,
    deployment.qa
  ]
}

deployment_auto_approve "additions_only" {
  deployment_group = deployment_group.non_prod
  
  check {
    condition = context.plan.changes.change == 0
    reason    = "Cannot auto-approve changes to existing resources"
  }
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Cannot auto-approve resource deletions"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}
```

**Auto-approve Small Changes:**

```hcl
deployment_group "staging" {
  deployments = [deployment.staging]
}

deployment_auto_approve "small_changes" {
  deployment_group = deployment_group.staging
  
  check {
    condition = (
      context.plan.changes.add + 
      context.plan.changes.change + 
      context.plan.changes.remove
    ) <= 10
    reason    = "Cannot auto-approve changes affecting more than 10 resources"
  }
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Cannot auto-approve plans with deletions"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}
```

**Auto-approve Non-Destructive Changes:**

```hcl
deployment_group "production" {
  deployments = [
    deployment.prod_primary,
    deployment.prod_secondary
  ]
}

deployment_auto_approve "safe_production_changes" {
  deployment_group = deployment_group.production
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Production deletions require manual approval"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be successful"
  }
}
```

**Multiple Auto-Approve Rules for Different Groups:**

```hcl
deployment_group "development" {
  deployments = [deployment.dev]
}

deployment_group "staging" {
  deployments = [deployment.staging]
}

deployment_group "production" {
  deployments = [deployment.production]
}

# Auto-approve all successful dev plans
deployment_auto_approve "dev_auto" {
  deployment_group = deployment_group.development
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

# Auto-approve staging plans with no deletions
deployment_auto_approve "staging_safe" {
  deployment_group = deployment_group.staging
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "No deletions allowed in staging auto-approve"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

# Production requires manual approval (no auto-approve rule defined)
```

**Graduated Rollout Pattern:**

```hcl
deployment_group "canary" {
  deployments = [deployment.canary]
}

deployment_group "production" {
  deployments = [
    deployment.prod_us,
    deployment.prod_eu,
    deployment.prod_asia
  ]
}

# Canary auto-approves with strict checks
deployment_auto_approve "canary_strict" {
  deployment_group = deployment_group.canary
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Canary cannot delete resources"
  }
  
  check {
    condition = context.plan.changes.change <= 5
    reason    = "Canary limited to 5 resource changes"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

# Production requires manual approval after canary validation
```

## Deprecated: Orchestrate Block

**Note:** The `orchestrate` block is deprecated. Use `deployment_group` and `deployment_auto_approve` blocks instead.

The `orchestrate` block was used in public beta but has been replaced by deployment groups for better scalability and flexibility:

```hcl
# ❌ DEPRECATED - Do not use
orchestrate "auto_approve" "rule_name" {
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

# ✅ Use deployment_group and deployment_auto_approve instead
deployment_group "my_group" {
  deployments = [deployment.my_deployment]
}

deployment_auto_approve "my_rule" {
  deployment_group = deployment_group.my_group
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}
```

## Publish Output Block

Exports outputs from a Stack for consumption by other Stacks (linked Stacks).

### Syntax

```hcl
publish_output "<output_name>" {
  type  = <type>
  value = <expression>
}
```

### Arguments

- **output_name** (label, required): Unique identifier for this published output
- **type** (required): Data type of the output
- **value** (required): Expression to export

### Accessing Deployment Outputs

Reference deployment outputs using: `deployment.<deployment_name>.<output_name>`

### Important Notes

- Must apply the Stack's deployment configuration before downstream Stacks can reference outputs
- Published outputs create a snapshot that other Stacks can read
- Changes to published outputs automatically trigger runs in downstream Stacks

### Examples

**Basic Published Output:**

```hcl
publish_output "vpc_id" {
  type  = string
  value = deployment.network.vpc_id
}

publish_output "subnet_ids" {
  type  = list(string)
  value = deployment.network.private_subnet_ids
}
```

**Multiple Deployment Outputs:**

```hcl
publish_output "regional_vpc_ids" {
  type = map(string)
  value = {
    us_east = deployment.us_east.vpc_id
    us_west = deployment.us_west.vpc_id
    eu_west = deployment.eu_west.vpc_id
  }
}
```

**Complex Output:**

```hcl
publish_output "database_config" {
  type = object({
    endpoint = string
    port     = number
    name     = string
  })
  value = {
    endpoint = deployment.production.db_endpoint
    port     = deployment.production.db_port
    name     = deployment.production.db_name
  }
}
```

**Regional Endpoints:**

```hcl
publish_output "api_endpoints" {
  type = map(object({
    url    = string
    region = string
  }))
  value = {
    for env in ["dev", "staging", "prod"] : env => {
      url    = deployment[env].api_url
      region = deployment[env].region
    }
  }
}
```

## Upstream Input Block

References published outputs from another Stack (linked Stacks).

### Syntax

```hcl
upstream_input "<input_name>" {
  type   = "stack"
  source = "<stack_address>"
}
```

### Arguments

- **input_name** (label, required): Local name for this upstream input
- **type** (required): Must be "stack"
- **source** (required): Full Stack address in format: `app.terraform.io/<org>/<project>/<stack-name>`

### Accessing Upstream Outputs

Reference upstream outputs using: `upstream_input.<input_name>.<output_name>`

### Important Notes

- Creates a dependency on the upstream Stack
- Upstream Stack must have applied its deployment configuration
- Changes in upstream Stack automatically trigger downstream Stack runs
- Only works with Stacks in the same HCP Terraform project

### Examples

**Basic Upstream Reference:**

```hcl
upstream_input "network" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/networking-stack"
}

deployment "application" {
  inputs = {
    vpc_id     = upstream_input.network.vpc_id
    subnet_ids = upstream_input.network.subnet_ids
  }
}
```

**Multiple Upstream Stacks:**

```hcl
upstream_input "network" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/network-stack"
}

upstream_input "database" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/database-stack"
}

deployment "application" {
  inputs = {
    vpc_id              = upstream_input.network.vpc_id
    subnet_ids          = upstream_input.network.private_subnet_ids
    database_endpoint   = upstream_input.database.endpoint
    database_credentials = upstream_input.database.credentials
  }
}
```

**Regional Upstream Dependencies:**

```hcl
upstream_input "regional_network" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/regional-networks"
}

deployment "us_east_app" {
  inputs = {
    region     = "us-east-1"
    vpc_id     = upstream_input.regional_network.regional_vpc_ids["us_east"]
    subnet_ids = upstream_input.regional_network.regional_subnet_ids["us_east"]
  }
}

deployment "eu_west_app" {
  inputs = {
    region     = "eu-west-1"
    vpc_id     = upstream_input.regional_network.regional_vpc_ids["eu_west"]
    subnet_ids = upstream_input.regional_network.regional_subnet_ids["eu_west"]
  }
}
```

**Complete Linked Stack Example:**

Upstream Stack (network-stack):
```hcl
# deployments.tfdeploy.hcl
deployment "network" {
  inputs = {
    vpc_cidr = "10.0.0.0/16"
  }
}

publish_output "vpc_id_network" {
  type  = string
  value = deployment.network.vpc_id
}

publish_output "private_subnet_ids" {
  type  = list(string)
  value = deployment.network.private_subnet_ids
}

publish_output "security_group_id" {
  type  = string
  value = deployment.network.default_sg_id
}
```

Downstream Stack (application-stack):
```hcl
# deployments.tfdeploy.hcl
upstream_input "networking" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/network-stack"
}

deployment "application" {
  inputs = {
    vpc_id             = upstream_input.networking.vpc_id_network
    subnet_ids         = upstream_input.networking.private_subnet_ids
    security_group_id  = upstream_input.networking.security_group_id
    instance_type      = "t3.large"
  }
}
```

## Complete Deployment Configuration Example

```hcl
# Identity tokens for cloud authentication
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

# Local values
locals {
  role_arn    = "arn:aws:iam::123456789012:role/terraform-stacks"
  project     = "my-application"
  cost_center = "engineering"
}

# Upstream dependencies
upstream_input "shared_services" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/shared-services"
}

# Deployments
deployment "development" {
  inputs = {
    aws_region     = "us-east-1"
    environment    = "dev"
    instance_count = 1
    instance_type  = "t3.micro"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
    vpc_id         = upstream_input.shared_services.dev_vpc_id
  }
}

deployment "staging" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "staging"
    instance_count = 2
    instance_type  = "t3.small"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
    vpc_id         = upstream_input.shared_services.staging_vpc_id
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "prod"
    instance_count = 5
    instance_type  = "t3.large"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
    vpc_id         = upstream_input.shared_services.prod_vpc_id
  }
}

# Deployment groups
deployment_group "non_production" {
  deployments = [
    deployment.development,
    deployment.staging
  ]
}

deployment_group "production" {
  deployments = [
    deployment.production
  ]
}

# Auto-approval rules
deployment_auto_approve "non_prod_auto" {
  deployment_group = deployment_group.non_production
  
  check {
    condition = context.plan.applyable
    reason    = "Non-production plans must be applyable"
  }
}

deployment_auto_approve "prod_safe" {
  deployment_group = deployment_group.production
  
  check {
    condition = context.plan.changes.remove == 0
    reason    = "Production cannot auto-approve deletions"
  }
  
  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}

# Published outputs
publish_output "application_url" {
  type  = string
  value = deployment.production.load_balancer_url
}
```

```

### references/examples.md

```markdown
# Terraform Stacks Complete Examples

Complete, working examples for common Terraform Stacks scenarios.

## Table of Contents

1. [Simple Single-Region Stack](#simple-single-region-stack)
2. [Stack with Private Registry Modules](#stack-with-private-registry-modules)
3. [Multi-Environment Stack](#multi-environment-stack)
4. [Multi-Region Stack](#multi-region-stack)
5. [Linked Stacks (Cross-Stack Dependencies)](#linked-stacks-cross-stack-dependencies)
6. [Multi-Cloud Stack](#multi-cloud-stack)
7. [Complete AWS Production Stack](#complete-aws-production-stack)
8. [Destroying Deployments](#destroying-deployments)

## Simple Single-Region Stack

Basic Stack with a single environment deployment.

### File Structure
```
simple-stack/
├── variables.tfcomponent.hcl
├── providers.tfcomponent.hcl
├── components.tfcomponent.hcl
├── deployments.tfdeploy.hcl
└── modules/
    └── webapp/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf
```

### variables.tfcomponent.hcl
```hcl
variable "aws_region" {
  type    = string
  default = "us-west-1"
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}

variable "app_name" {
  type = string
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

provider "aws" "main" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

### components.tfcomponent.hcl
```hcl
component "webapp" {
  source = "./modules/webapp"
  
  inputs = {
    app_name = var.app_name
    region   = var.aws_region
  }
  
  providers = {
    aws = provider.aws.main
  }
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    app_name       = "my-webapp"
    role_arn       = "arn:aws:iam::123456789012:role/terraform-stacks"
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "production" {
  deployments = [deployment.production]
}
```

## Stack with Private Registry Modules

Example Stack using modules from a private HCP Terraform registry, combining both private and public registry sources.

### File Structure
```
private-registry-stack/
├── variables.tfcomponent.hcl
├── providers.tfcomponent.hcl
├── components.tfcomponent.hcl
├── outputs.tfcomponent.hcl
└── deployments.tfdeploy.hcl
```

### variables.tfcomponent.hcl
```hcl
variable "aws_region" {
  type    = string
  default = "us-west-2"
}

variable "environment" {
  type = string
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}

variable "vpc_cidr" {
  type    = string
  default = "10.0.0.0/16"
}

variable "app_name" {
  type = string
}

variable "db_password" {
  type      = string
  sensitive = true
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
  random = {
    source  = "hashicorp/random"
    version = "~> 3.5.0"
  }
}

provider "aws" "main" {
  config {
    region = var.aws_region

    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }

    default_tags {
      tags = {
        Environment = var.environment
        ManagedBy   = "Terraform Stacks"
        Application = var.app_name
      }
    }
  }
}

provider "random" "main" {
  config {}
}
```

### components.tfcomponent.hcl
```hcl
locals {
  name_prefix = "${var.app_name}-${var.environment}"
  common_tags = {
    Project     = var.app_name
    Environment = var.environment
  }
}

# Using a private registry module for VPC
component "vpc" {
  source  = "app.terraform.io/my-org/vpc/aws"
  version = "2.1.0"

  inputs = {
    name_prefix         = local.name_prefix
    cidr_block          = var.vpc_cidr
    availability_zones  = ["${var.aws_region}a", "${var.aws_region}b", "${var.aws_region}c"]
    enable_nat_gateway  = true
    single_nat_gateway  = var.environment != "prod"
    tags                = local.common_tags
  }

  providers = {
    aws = provider.aws.main
  }
}

# Using a private registry module for security groups
component "security_groups" {
  source  = "app.terraform.io/my-org/security-groups/aws"
  version = "1.5.2"

  inputs = {
    vpc_id      = component.vpc.vpc_id
    name_prefix = local.name_prefix
    environment = var.environment
  }

  providers = {
    aws = provider.aws.main
  }
}

# Using a public registry module for RDS
component "database" {
  source  = "terraform-aws-modules/rds/aws"
  version = "~> 6.0"

  inputs = {
    identifier           = "${local.name_prefix}-db"
    engine               = "postgres"
    engine_version       = "15.3"
    family               = "postgres15"
    major_engine_version = "15"
    instance_class       = var.environment == "prod" ? "db.t3.large" : "db.t3.micro"

    allocated_storage     = var.environment == "prod" ? 100 : 20
    db_name               = replace(var.app_name, "-", "_")
    username              = "dbadmin"
    password              = var.db_password
    port                  = 5432

    db_subnet_group_name   = component.vpc.database_subnet_group_name
    vpc_security_group_ids = [component.security_groups.database_sg_id]

    backup_retention_period = var.environment == "prod" ? 30 : 7
    skip_final_snapshot     = var.environment != "prod"
    deletion_protection     = var.environment == "prod"

    tags = local.common_tags
  }

  providers = {
    aws = provider.aws.main
  }
}

# Using a private registry module for application infrastructure
component "application" {
  source  = "app.terraform.io/my-org/ecs-application/aws"
  version = "3.2.1"

  inputs = {
    name_prefix           = local.name_prefix
    vpc_id                = component.vpc.vpc_id
    private_subnet_ids    = component.vpc.private_subnet_ids
    public_subnet_ids     = component.vpc.public_subnet_ids
    app_security_group_id = component.security_groups.app_sg_id

    container_image       = "my-org/my-app:latest"
    container_port        = 8080
    desired_count         = var.environment == "prod" ? 3 : 1

    environment_variables = {
      ENVIRONMENT    = var.environment
      DATABASE_HOST  = component.database.db_instance_endpoint
      DATABASE_NAME  = component.database.db_instance_name
    }

    tags = local.common_tags
  }

  providers = {
    aws = provider.aws.main
  }
}
```

### outputs.tfcomponent.hcl
```hcl
output "vpc_id" {
  type        = string
  description = "VPC ID"
  value       = component.vpc.vpc_id
}

output "application_url" {
  type        = string
  description = "Application load balancer URL"
  value       = component.application.load_balancer_dns
}

output "database_endpoint" {
  type        = string
  description = "Database endpoint"
  value       = component.database.db_instance_endpoint
  sensitive   = true
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
}

deployment "development" {
  inputs = {
    aws_region     = "us-west-2"
    environment    = "dev"
    app_name       = "myapp"
    vpc_cidr       = "10.0.0.0/16"
    db_password    = "dev-password-change-me"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-east-1"
    environment    = "prod"
    app_name       = "myapp"
    vpc_cidr       = "10.1.0.0/16"
    db_password    = "prod-password-use-secrets-manager"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "development" {
  deployments = [deployment.development]
}

deployment_group "production" {
  deployments = [deployment.production]
}
```

### Key Points

- **Private registry modules** use the format `app.terraform.io/<org>/<module>/<provider>`
- **Version constraints** ensure consistent module versions across environments
- **Mixed sources**: Combining private registry modules (VPC, security groups, application) with public registry modules (RDS)
- **Authentication**: HCP Terraform workspaces automatically authenticate to private registries; CLI users need credentials configured
- **Terraform Enterprise**: Replace `app.terraform.io` with your instance hostname

## Multi-Environment Stack

Stack with development, staging, and production deployments.

### variables.tfcomponent.hcl
```hcl
variable "aws_region" {
  type = string
}

variable "environment" {
  type = string
}

variable "instance_count" {
  type = number
}

variable "instance_type" {
  type = string
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

provider "aws" "this" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
    
    default_tags {
      tags = {
        Environment = var.environment
        ManagedBy   = "Terraform Stacks"
      }
    }
  }
}
```

### components.tfcomponent.hcl
```hcl
locals {
  name_prefix = "myapp-${var.environment}"
}

component "vpc" {
  source = "./modules/vpc"
  
  inputs = {
    name_prefix = local.name_prefix
    cidr_block  = "10.0.0.0/16"
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "compute" {
  source = "./modules/compute"
  
  inputs = {
    name_prefix    = local.name_prefix
    vpc_id         = component.vpc.vpc_id
    subnet_ids     = component.vpc.private_subnet_ids
    instance_count = var.instance_count
    instance_type  = var.instance_type
  }
  
  providers = {
    aws = provider.aws.this
  }
}
```

### outputs.tfcomponent.hcl
```hcl
output "vpc_id" {
  type  = string
  value = component.vpc.vpc_id
}

output "load_balancer_url" {
  type  = string
  value = component.compute.load_balancer_url
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
  
  environments = {
    dev = {
      region         = "us-east-1"
      instance_count = 1
      instance_type  = "t3.micro"
    }
    staging = {
      region         = "us-west-1"
      instance_count = 2
      instance_type  = "t3.small"
    }
    prod = {
      region         = "us-west-1"
      instance_count = 5
      instance_type  = "t3.large"
    }
  }
}

deployment "development" {
  inputs = {
    aws_region     = local.environments.dev.region
    environment    = "dev"
    instance_count = local.environments.dev.instance_count
    instance_type  = local.environments.dev.instance_type
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "staging" {
  inputs = {
    aws_region     = local.environments.staging.region
    environment    = "staging"
    instance_count = local.environments.staging.instance_count
    instance_type  = local.environments.staging.instance_type
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = local.environments.prod.region
    environment    = "prod"
    instance_count = local.environments.prod.instance_count
    instance_type  = local.environments.prod.instance_type
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "development" {
  deployments = [deployment.development]
}

deployment_group "non_production" {
  deployments = [deployment.staging]
}

deployment_group "production" {
  deployments = [deployment.production]
}

# Auto-approve dev deployments
deployment_auto_approve "dev_auto" {
  deployment_group = deployment_group.development

  check {
    condition = context.plan.applyable
    reason    = "Development plans must be applyable"
  }
}
```

## Multi-Region Stack

Stack that deploys identical infrastructure across multiple AWS regions.

### variables.tfcomponent.hcl
```hcl
variable "regions" {
  type = set(string)
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}

variable "app_name" {
  type = string
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

provider "aws" "regional" {
  for_each = var.regions
  
  config {
    region = each.value
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
    
    default_tags {
      tags = {
        Region    = each.value
        ManagedBy = "Terraform Stacks"
        AppName   = var.app_name
      }
    }
  }
}
```

### components.tfcomponent.hcl
```hcl
component "regional_infrastructure" {
  for_each = var.regions
  
  source = "./modules/regional-infra"
  
  inputs = {
    region      = each.value
    app_name    = var.app_name
    name_suffix = each.value
  }
  
  providers = {
    aws = provider.aws.regional[each.value]
  }
}

component "global_route53" {
  source = "./modules/route53"
  
  inputs = {
    app_name     = var.app_name
    domain_name  = "example.com"
    regional_lbs = {
      for region, comp in component.regional_infrastructure :
      region => comp.load_balancer_dns
    }
  }
  
  # Use one region's provider for global resources
  providers = {
    aws = provider.aws.regional["us-west-1"]
  }
}
```

### outputs.tfcomponent.hcl
```hcl
output "regional_endpoints" {
  type = map(string)
  value = {
    for region, comp in component.regional_infrastructure :
    region => comp.load_balancer_url
  }
}

output "global_domain" {
  type  = string
  value = component.global_route53.domain_name
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  regions = ["us-west-1", "us-east-1", "eu-west-1"]
}

deployment "multi_region_prod" {
  inputs = {
    regions        = toset(local.regions)
    app_name       = "my-global-app"
    role_arn       = "arn:aws:iam::123456789012:role/terraform-stacks"
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "production" {
  deployments = [deployment.multi_region_prod]
}
```

## Linked Stacks (Cross-Stack Dependencies)

Two Stacks where the application Stack depends on the network Stack.

### Network Stack

#### network-stack/variables.tfcomponent.hcl
```hcl
variable "vpc_cidr" {
  type = string
}

variable "environment" {
  type = string
}

variable "aws_region" {
  type = string
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}
```

#### network-stack/providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

provider "aws" "this" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

#### network-stack/components.tfcomponent.hcl
```hcl
component "vpc" {
  source = "./modules/vpc"
  
  inputs = {
    cidr_block  = var.vpc_cidr
    environment = var.environment
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "security_groups" {
  source = "./modules/security-groups"
  
  inputs = {
    vpc_id      = component.vpc.vpc_id
    environment = var.environment
  }
  
  providers = {
    aws = provider.aws.this
  }
}
```

#### network-stack/outputs.tfcomponent.hcl
```hcl
output "vpc_id" {
  type  = string
  value = component.vpc.vpc_id
}

output "private_subnet_ids" {
  type  = list(string)
  value = component.vpc.private_subnet_ids
}

output "public_subnet_ids" {
  type  = list(string)
  value = component.vpc.public_subnet_ids
}

output "app_security_group_id" {
  type  = string
  value = component.security_groups.app_sg_id
}
```

#### network-stack/deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
}

deployment "network" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "production"
    vpc_cidr       = "10.0.0.0/16"
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Publish outputs for other stacks
publish_output "vpc_id_network" {
  type  = string
  value = deployment.network.vpc_id
}

publish_output "private_subnet_ids" {
  type  = list(string)
  value = deployment.network.private_subnet_ids
}

publish_output "public_subnet_ids" {
  type  = list(string)
  value = deployment.network.public_subnet_ids
}

publish_output "app_security_group_id" {
  type  = string
  value = deployment.network.app_security_group_id
}

# Deployment groups
deployment_group "network" {
  deployments = [deployment.network]
}
```

### Application Stack

#### application-stack/variables.tfcomponent.hcl
```hcl
variable "vpc_id" {
  type = string
}

variable "subnet_ids" {
  type = list(string)
}

variable "security_group_id" {
  type = string
}

variable "instance_count" {
  type = number
}

variable "aws_region" {
  type = string
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}
```

#### application-stack/providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
}

provider "aws" "this" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
  }
}
```

#### application-stack/components.tfcomponent.hcl
```hcl
component "application" {
  source = "./modules/app"
  
  inputs = {
    vpc_id            = var.vpc_id
    subnet_ids        = var.subnet_ids
    security_group_id = var.security_group_id
    instance_count    = var.instance_count
  }
  
  providers = {
    aws = provider.aws.this
  }
}
```

#### application-stack/deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

# Reference the network stack
upstream_input "network" {
  type   = "stack"
  source = "app.terraform.io/my-org/my-project/network-stack"
}

deployment "application" {
  inputs = {
    aws_region        = "us-west-1"
    vpc_id            = upstream_input.network.vpc_id_network
    subnet_ids        = upstream_input.network.private_subnet_ids
    security_group_id = upstream_input.network.app_security_group_id
    instance_count    = 3
    role_arn          = "arn:aws:iam::123456789012:role/terraform-stacks"
    identity_token    = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "application" {
  deployments = [deployment.application]
}
```

## Multi-Cloud Stack

Stack that deploys to both AWS and Azure.

### variables.tfcomponent.hcl
```hcl
variable "aws_region" {
  type = string
}

variable "azure_location" {
  type = string
}

variable "aws_identity_token" {
  type      = string
  ephemeral = true
}

variable "aws_role_arn" {
  type = string
}

variable "azure_identity_token" {
  type      = string
  ephemeral = true
}

variable "azure_subscription_id" {
  type = string
}

variable "azure_tenant_id" {
  type = string
}

variable "azure_client_id" {
  type = string
}

variable "app_name" {
  type = string
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
  azurerm = {
    source  = "hashicorp/azurerm"
    version = "~> 3.0"
  }
}

provider "aws" "this" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.aws_role_arn
      web_identity_token = var.aws_identity_token
    }
  }
}

provider "azurerm" "this" {
  config {
    features {}
    
    subscription_id = var.azure_subscription_id
    tenant_id       = var.azure_tenant_id
    client_id       = var.azure_client_id
    
    use_oidc = true
    oidc_token = var.azure_identity_token
  }
}
```

### components.tfcomponent.hcl
```hcl
component "aws_infrastructure" {
  source = "./modules/aws-infra"
  
  inputs = {
    region   = var.aws_region
    app_name = var.app_name
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "azure_infrastructure" {
  source = "./modules/azure-infra"
  
  inputs = {
    location = var.azure_location
    app_name = var.app_name
  }
  
  providers = {
    azurerm = provider.azurerm.this
  }
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

identity_token "azure" {
  audience = ["api://AzureADTokenExchange"]
}

deployment "multi_cloud" {
  inputs = {
    aws_region             = "us-west-1"
    azure_location         = "westus2"
    app_name               = "my-multi-cloud-app"
    aws_role_arn           = "arn:aws:iam::123456789012:role/terraform-stacks"
    aws_identity_token     = identity_token.aws.jwt
    azure_subscription_id  = "12345678-1234-1234-1234-123456789012"
    azure_tenant_id        = "87654321-4321-4321-4321-210987654321"
    azure_client_id        = "11111111-1111-1111-1111-111111111111"
    azure_identity_token   = identity_token.azure.jwt
  }
}

# Deployment groups
deployment_group "multi_cloud" {
  deployments = [deployment.multi_cloud]
}
```

## Complete AWS Production Stack

Full production-grade Stack with VPC, RDS, ECS, and monitoring.

### variables.tfcomponent.hcl
```hcl
variable "aws_region" {
  type        = string
  description = "AWS region"
}

variable "environment" {
  type        = string
  description = "Environment name"
}

variable "vpc_cidr" {
  type        = string
  description = "VPC CIDR block"
}

variable "app_name" {
  type        = string
  description = "Application name"
}

variable "db_instance_class" {
  type        = string
  description = "RDS instance class"
}

variable "ecs_desired_count" {
  type        = number
  description = "Desired ECS task count"
}

variable "identity_token" {
  type      = string
  ephemeral = true
}

variable "role_arn" {
  type = string
}
```

### providers.tfcomponent.hcl
```hcl
required_providers {
  aws = {
    source  = "hashicorp/aws"
    version = "~> 5.7.0"
  }
  random = {
    source  = "hashicorp/random"
    version = "~> 3.5.0"
  }
}

provider "aws" "this" {
  config {
    region = var.aws_region
    
    assume_role_with_web_identity {
      role_arn           = var.role_arn
      web_identity_token = var.identity_token
    }
    
    default_tags {
      tags = {
        Environment = var.environment
        Application = var.app_name
        ManagedBy   = "Terraform Stacks"
      }
    }
  }
}

provider "random" "this" {
  config {}
}
```

### components.tfcomponent.hcl
```hcl
locals {
  name_prefix = "${var.app_name}-${var.environment}"
}

component "vpc" {
  source = "./modules/vpc"
  
  inputs = {
    name_prefix = local.name_prefix
    cidr_block  = var.vpc_cidr
    azs_count   = 3
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "security_groups" {
  source = "./modules/security-groups"
  
  inputs = {
    name_prefix = local.name_prefix
    vpc_id      = component.vpc.vpc_id
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "rds" {
  source = "./modules/rds"
  
  inputs = {
    name_prefix        = local.name_prefix
    instance_class     = var.db_instance_class
    subnet_ids         = component.vpc.private_subnet_ids
    security_group_ids = [component.security_groups.database_sg_id]
  }
  
  providers = {
    aws    = provider.aws.this
    random = provider.random.this
  }
}

component "ecs_cluster" {
  source = "./modules/ecs-cluster"
  
  inputs = {
    name_prefix = local.name_prefix
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "ecs_service" {
  source = "./modules/ecs-service"
  
  inputs = {
    name_prefix      = local.name_prefix
    cluster_id       = component.ecs_cluster.cluster_id
    desired_count    = var.ecs_desired_count
    subnet_ids       = component.vpc.private_subnet_ids
    security_group_id = component.security_groups.app_sg_id
    database_endpoint = component.rds.endpoint
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "alb" {
  source = "./modules/alb"
  
  inputs = {
    name_prefix       = local.name_prefix
    vpc_id            = component.vpc.vpc_id
    subnet_ids        = component.vpc.public_subnet_ids
    security_group_id = component.security_groups.alb_sg_id
    target_group_arn  = component.ecs_service.target_group_arn
  }
  
  providers = {
    aws = provider.aws.this
  }
}

component "cloudwatch" {
  source = "./modules/cloudwatch"
  
  inputs = {
    name_prefix  = local.name_prefix
    cluster_name = component.ecs_cluster.cluster_name
    service_name = component.ecs_service.service_name
  }
  
  providers = {
    aws = provider.aws.this
  }
}
```

### outputs.tfcomponent.hcl
```hcl
output "load_balancer_url" {
  type        = string
  description = "Application load balancer URL"
  value       = component.alb.dns_name
}

output "database_endpoint" {
  type        = string
  description = "RDS endpoint"
  value       = component.rds.endpoint
  sensitive   = true
}

output "vpc_id" {
  type  = string
  value = component.vpc.vpc_id
}

output "ecs_cluster_name" {
  type  = string
  value = component.ecs_cluster.cluster_name
}
```

### deployments.tfdeploy.hcl
```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
}

deployment "staging" {
  inputs = {
    aws_region        = "us-west-1"
    environment       = "staging"
    app_name          = "myapp"
    vpc_cidr          = "10.1.0.0/16"
    db_instance_class = "db.t3.small"
    ecs_desired_count = 2
    role_arn          = local.role_arn
    identity_token    = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region        = "us-west-1"
    environment       = "production"
    app_name          = "myapp"
    vpc_cidr          = "10.0.0.0/16"
    db_instance_class = "db.r5.large"
    ecs_desired_count = 5
    role_arn          = local.role_arn
    identity_token    = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "staging" {
  deployments = [deployment.staging]
}

deployment_group "production" {
  deployments = [deployment.production]
}

# Auto-approve staging with safety checks
deployment_auto_approve "staging_safe" {
  deployment_group = deployment_group.staging

  check {
    condition = context.plan.changes.remove == 0
    reason    = "Cannot auto-approve deletions in staging"
  }

  check {
    condition = context.plan.applyable
    reason    = "Plan must be applyable"
  }
}
```

## Testing Configurations

### Validate Stack Configuration
```bash
terraform stacks providers lock
terraform stacks validate
```

### Plan Specific Deployment
```bash
terraform stacks plan --deployment=development
terraform stacks plan --deployment=production
```

### Apply Deployment
```bash
terraform stacks apply --deployment=staging
```

## Destroying Deployments

Example of safely removing a deployment from your Stack.

### Scenario

You want to decommission the "development" deployment while keeping staging and production active.

### Step 1: Mark Deployment for Destruction

Update your `deployments.tfdeploy.hcl` file to set `destroy = true`:

```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
}

# Mark this deployment for destruction
deployment "development" {
  inputs = {
    aws_region     = "us-east-1"
    environment    = "dev"
    instance_count = 1
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
  destroy = true  # This tells HCP Terraform to destroy all resources
}

# Keep these deployments active
deployment "staging" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "staging"
    instance_count = 2
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "prod"
    instance_count = 5
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "staging" {
  deployments = [deployment.staging]
}

deployment_group "production" {
  deployments = [deployment.production]
}
```

### Step 2: Plan and Apply

```bash
# Review the destruction plan
terraform stacks plan --deployment=development

# Apply the destruction
terraform stacks apply --deployment=development
```

HCP Terraform will destroy all resources in the development deployment.

### Step 3: Remove the Deployment Block

After the deployment is successfully destroyed, remove the entire deployment block from your configuration:

```hcl
identity_token "aws" {
  audience = ["aws.workload.identity"]
}

locals {
  role_arn = "arn:aws:iam::123456789012:role/terraform-stacks"
}

# deployment "development" block has been removed

deployment "staging" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "staging"
    instance_count = 2
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

deployment "production" {
  inputs = {
    aws_region     = "us-west-1"
    environment    = "prod"
    instance_count = 5
    role_arn       = local.role_arn
    identity_token = identity_token.aws.jwt
  }
}

# Deployment groups
deployment_group "staging" {
  deployments = [deployment.staging]
}

deployment_group "production" {
  deployments = [deployment.production]
}
```

### Important Notes

- **Provider Authentication**: The `destroy` argument ensures your configuration retains the provider authentication needed to destroy resources
- **Do Not Remove Immediately**: Don't remove the deployment block until after the destruction is complete
- **Verify Before Removing**: Check HCP Terraform UI to confirm all resources are destroyed before removing the block
- **Alternative**: You could manually destroy resources through HCP Terraform UI, but using `destroy = true` is the recommended approach for maintaining infrastructure-as-code practices

```