> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/azfar-imtiaz/PayPulse-Cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Terraform setup

> Initialize, configure, and apply the PayPulse Cloud Terraform infrastructure.

## Prerequisites

Before running any Terraform commands, make sure you have the following in place:

* **Terraform** `>= 1.5.0` — required by the `required_version` constraint in `main.tf`
* **AWS CLI** configured with credentials that have sufficient permissions (see [IAM roles](/infrastructure/iam-roles))
* **AWS region**: `eu-west-1` (default; overridable via `terraform.tfvars`)
* A `terraform.tfvars` file with all required sensitive variables (see below)

## Module structure

The Terraform configuration lives in `aws-infra-terraform/` and is organized into three layers:

```
aws-infra-terraform/
├── main.tf                    # Root module — orchestrates IAM and Lambda modules
├── variables.tf               # Global input variables
├── outputs.tf                 # Infrastructure outputs (table names, API URL, etc.)
├── terraform.tfvars           # Sensitive values — gitignored
├── moved.tf                   # State migration for refactored resources
├── s3.tf                      # S3 buckets and S3 event notifications
├── dynamodb.tf                # DynamoDB table definitions
├── dynamodb_autoscaling.tf    # Autoscaling for RentalInvoices table
├── cloudwatch.tf              # CloudWatch log groups
├── cognito.tf                 # Cognito identity pool (iOS push notifications)
├── eventbridge.tf             # Scheduled EventBridge triggers
├── api_gateway.tf             # API Gateway HTTP API and routes
├── sns.tf                     # SNS topic for invoice notifications
├── secrets.tf                 # AWS Secrets Manager resources
├── iam/                       # IAM module
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   ├── iam.tf                 # Users, groups, and shared roles
│   ├── iam_signup_lambda.tf
│   ├── iam_login_lambda.tf
│   ├── iam_delete_user_lambda.tf
│   ├── iam_get_rental_invoice_lambda.tf
│   ├── iam_get_rental_invoices_lambda.tf
│   ├── iam_get_user_profile_lambda.tf
│   └── iam_gmail_store_tokens_lambda.tf
└── lambdas/                   # Lambda module
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf
    ├── lambda_*.tf             # One file per Lambda function
    └── lambda_layers.tf        # Lambda layers (utils, JWT, bcrypt, Google API)
```

The **root module** (`main.tf`) calls the `iam` and `lambdas` child modules and wires their inputs and outputs together. Resources that are not Lambda- or IAM-specific (DynamoDB, S3, CloudWatch, etc.) are defined directly in the root module.

## Required providers

```hcl theme={null}
terraform {
  required_providers {
    klayers = {
      source  = "ldcorentin/klayer"
      version = "~> 1.0.0"
    }
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  required_version = ">=1.5.0"
}

provider "aws" {
  region = var.aws_region
}
```

The `klayers` provider is used to fetch the latest ARN of the community-maintained [KLayers](https://github.com/keithrozario/Klayers) Lambda layer for `bcrypt`.

## terraform.tfvars

Sensitive and environment-specific values are passed through `terraform.tfvars`. This file is **not committed to version control**.

<Note>
  `terraform.tfvars` is listed in `.gitignore`. Never commit this file — it contains secrets such as Gmail credentials, the Google OAuth client ID, and the Gemini API key.
</Note>

The following variables must be set in `terraform.tfvars`:

| Variable                   | Type                 | Description                                       |
| -------------------------- | -------------------- | ------------------------------------------------- |
| `gmail_secret_credentials` | `string` (sensitive) | JSON credentials for Gmail API access             |
| `google_oauth_client_id`   | `string` (sensitive) | iOS OAuth client ID for Gmail API                 |
| `gemini_api_key`           | `string` (sensitive) | API key for Gemini Flash (retail invoice parsing) |

All other variables have defaults defined in `variables.tf` and can optionally be overridden here (e.g., `aws_region`, bucket names, table names).

Example structure (do not include real values):

```hcl theme={null}
gmail_secret_credentials = "{...}"
google_oauth_client_id   = "your-client-id.apps.googleusercontent.com"
gemini_api_key           = "your-gemini-key"
```

## Deploying the infrastructure

<Steps>
  <Step title="Initialize Terraform">
    Download providers and initialize the module registry.

    ```bash theme={null}
    terraform init
    ```
  </Step>

  <Step title="Review the plan">
    Preview all changes before applying them. Inspect the output carefully — especially for destructive actions (replacements or deletions).

    ```bash theme={null}
    terraform plan
    ```
  </Step>

  <Step title="Apply the changes">
    Apply the planned changes to your AWS account.

    ```bash theme={null}
    terraform apply
    ```

    Terraform will prompt for confirmation before making any changes. Type `yes` to proceed.

    <Warning>
      Running `terraform apply` in a production environment will modify live AWS resources. Always review the plan output before confirming, and consider using a separate workspace or state file for production.
    </Warning>
  </Step>
</Steps>

## State management and resource migrations

Terraform state is stored locally in `aws-infra-terraform/terraform.tfstate`. This file is not committed to version control.

When resources are refactored — for example, moved from the root module into the `iam` or `lambdas` child modules — their state addresses change. The `moved.tf` file records these address renames so Terraform can reconcile existing state without destroying and re-creating resources.

Example entry from `moved.tf`:

```hcl theme={null}
moved {
  from = aws_iam_role.wallenstam_lambda_role
  to   = module.iam.aws_iam_role.wallenstam_lambda_role
}
```

When Terraform encounters a `moved` block it updates the state in-place and plans no infrastructure changes. This makes module refactoring safe to apply.

To inspect current state or diagnose issues:

```bash theme={null}
# List all resources tracked in state
terraform state list

# Show details for a specific resource
terraform state show module.iam.aws_iam_role.wallenstam_lambda_role
```
