# PRD: Layer 01 - DNS (Domain Account)

**Scope:** Domain account. Create the IAM DNS role (**dns_assume_role_arn**) in the account that owns the Hosted Zone; other layers (e.g. layer 50) assume this role to manage Route 53 records. This layer does **not** create or manage Route 53 records; it only provisions **dns_assume_role_arn** and publishes its ARN as `dns_role_arn` in Parameter Store. **Roles:** (1) **deployment_account_role_arn** - role for the deployment account (used in all layers); (2) **domain_account_role_arn** - role in the domain account, used only by this layer to create the DNS role; (3) **dns_assume_role_arn** - the DNS role created here, assumed by the deployment role for Route 53.

**Dependencies:** PRD_00-cross-cutting, PRD_00-bootstrap (Parameter Store contract). No dependency on layer 50.

## 1. Purpose and Execution Order

| ID | Requirement |
| ---- | ------------- |
| R-D01-001 | This layer SHALL create an IAM role (**dns_assume_role_arn**) in the domain account that is assumable by **deployment_account_role_arn** (e.g. GitHub Actions OIDC role) with least privilege on the specific hosted zone. |
| R-D01-002 | This layer SHALL run in the deployment account (as **deployment_account_role_arn**; state and Parameter Store in deployment account) and SHALL use a provider alias to assume **domain_account_role_arn** in the domain account to create **dns_assume_role_arn** there. |
| R-D01-003 | This layer SHALL NOT create or manage Route 53 records; the Route 53 record for the Wiki.js FQDN is created and managed by layer 50 (app-wikijs), which assumes **dns_assume_role_arn**. |

## 2. Identity and Parameter Store Inputs

| ID | Requirement |
| ---- | ------------- |
| R-D01-101 | The layer SHALL read from Parameter Store: `hosted_zone_id` under the bootstrap prefix `wikijs/<region>/<env>/00-bootstrap/` (to scope the DNS role permissions). |
| R-D01-102 | The layer SHALL require a variable for the domain-account role ARN (`domain_account_role_arn`) - the role in the account where the domain and hosted zone are; this layer assumes it to create **dns_assume_role_arn**. That role must have permission to create IAM roles in the domain account. This is NOT the deployment role. |
| R-D01-103 | The layer SHALL require a variable for the deployment role ARN (`deployment_account_role_arn`) - the role used in all layers; where all resources are deployed. When dispatching the 01-dns-main workflows, this is one of two role inputs (the other is domain_account_role_arn); the workflow also assumes this role to run Terraform. The **dns_assume_role_arn** trust policy SHALL allow **deployment_account_role_arn** to assume it. |
| R-D01-104 | The layer SHALL NOT use `terraform_remote_state`; it SHALL use only Parameter Store for inputs. |

## 3. DNS Role (IAM)

| ID | Requirement |
| ---- | ------------- |
| R-D01-201 | An IAM role (**dns_assume_role_arn**) SHALL be created in the domain account with a **trust relationship**: its trust policy SHALL allow **deployment_account_role_arn** (principal = `deployment_account_role_arn`) to assume it; action `sts:AssumeRole`. So when layer 50 runs as the deployment role, it can assume **dns_assume_role_arn** to manage Route 53 in the domain account. |
| R-D01-202 | **dns_assume_role_arn** SHALL have permissions for **domain/hosted zone information**: `route53:GetHostedZone`, `route53:ListResourceRecordSets` on the resource `arn:aws:route53:::hostedzone/<hosted_zone_id>`. |
| R-D01-203 | **dns_assume_role_arn** SHALL have permissions for **CRUD on the hosted zone**: `route53:ChangeResourceRecordSets` on `arn:aws:route53:::hostedzone/<hosted_zone_id>` and `route53:GetChange` on `arn:aws:route53:::change/*`. |
| R-D01-204 | Permissions SHALL be scoped to the hosted zone ID from the bootstrap Parameter Store (least privilege). |

## 4. Parameter Store Outputs

| ID | Requirement |
| ---- | ------------- |
| R-D01-301 | The layer SHALL publish to Parameter Store under `wikijs/<region>/<env>/01-dns-main/`: `dns_role_arn` (the ARN of **dns_assume_role_arn** so other layers can assume it). |
| R-D01-302 | The layer SHALL publish only under its own prefix and SHALL NOT overwrite other layers' keys. |

## 5. Destroy Behavior

| ID | Requirement |
| ---- | ------------- |
| R-D01-401 | On `terraform destroy`, the layer SHALL remove **dns_assume_role_arn** (the DNS IAM role it created in the domain account). |
| R-D01-402 | The layer SHALL delete its own Parameter Store prefix under `wikijs/<region>/<env>/01-dns-main/` after successful destroy. |
| R-D01-403 | A provision workflow and a destroy workflow SHALL exist for this layer; destroy SHALL run after 10-network and before 00-bootstrap in the teardown order (so **dns_assume_role_arn** still exists when layer 50 is destroyed). |

## 6. Implementation Notes

- **Terraform:** Root module at `terraform/01-dns-main/`. Runs in deployment account as **deployment_account_role_arn**; uses provider alias to assume **domain_account_role_arn** in the domain account to create **dns_assume_role_arn**.
- **Workflows:** `tf-01-dns-main-provision.yaml` and `tf-01-dns-main-destroy.yaml` (extension `.yaml`), calling `_terraform-layer.yaml`. Each workflow has **two** role inputs: `domain_account_role_arn` and `deployment_account_role_arn`; the reusable workflow is called with `deployment_account_role_arn`.
- **Parameter Store (reads):** `hosted_zone_id` under `wikijs/<region>/<env>/00-bootstrap/`.
- **Parameter Store (writes):** `dns_role_arn` (ARN of **dns_assume_role_arn**) under `wikijs/<region>/<env>/01-dns-main/`.
- **Variables:** `domain_account_role_arn` (role in domain account with permission to create IAM roles), `deployment_account_role_arn` (trusted principal for **dns_assume_role_arn**).
