# Features — terraform_scripts

Evidence date: 2026-10-01. Revision: `main` at `8af8aa6`.

Status words: **Current** means the resource is declared on `main`. **Unused** means the module is in the tree and no stack calls it. **Not in this repo** means the diagram or a comment names it and the code does not.

## Current

### Production environment root

- Path: `environments/production/`.
- Terraform Cloud organisation `Datafy-AWS-Deploy`, workspace `Production`.
- Providers: `aws` in `var.aws_region`, alias `aws.us-east-1`.
- Composes `stacks/networking` and `stacks/datafy`.

### Networking stack

- Path: `stacks/networking/`.
- VPC `datafy-prod-vpc`, CIDR `10.1.0.0/16`, two availability zones, single NAT, DNS support and hostnames.
- ALB access-log bucket `${client}-${stage}-alb-access-logs`.
- VPC flow logs into that bucket's module output.
- S3 gateway endpoint on public, private, and database route tables.
- Security groups: public ALB (80/443 from the internet), EC2 private (80, 3000, and 8000 from the ALB only), RDS proxy (5432 from EC2 and Lambda), Postgres (5432 from the proxy and from EC2), Lambda (egress only).
- Dedicated NACLs for public, supabase, waterwheel, qwen, lambda, and database subnet groups. Each NACL allows all traffic; the split is organisational.
- Port 3000 is open from the ALB to EC2, but no current instance or listener rule uses port 3000.

### Account baseline

- Path: `stacks/baseline/`, called from `stacks/datafy/baseline.tf`.
- Security Hub account plus FSBP v1.0.0 and CIS AWS Foundations Benchmark v1.4.0 (`modules/aws-so-security-hub`).
- GuardDuty with findings export (`modules/aws-guardduty`).
- AWS Config, six-hour delivery, global resources, conformance packs for IAM, S3, and security services (`modules/aws-so-config`).
- Multi-region CloudTrail, logging and log-file validation on, global service events (`modules/aws-cloudtrail`).
- Account contacts, password policy, public-access blocks, budgets, SNS technical alerts, backup plans, root-usage alarm, CloudTrail-change alarm (`modules/aws-account-settings`).

### EC2 workloads

- Path: `stacks/datafy/locals.tf`, `stacks/datafy/ec2.tf`, `modules/aws-so-ec2`.
- Supabase (`t3.xlarge`, port 8000, 100 GB), Water Wheel (`c7i.2xlarge`, port 80, 60 GB), Qwen (`g4dn.xlarge`, port 80, 50 GB).
- One instance each. Auto Scaling code exists in the module and is skipped because `create_asg = false`.
- Ubuntu 22.04 from Canonical. IMDSv2 required. Encrypted gp3 root volume kept on instance termination.
- Shared instance profile with SSM, CloudWatch Logs, Supabase bucket access, server-artifacts bucket access, and `secretsmanager:GetSecretValue` on `rds!db-*`.
- User data enables CodeDeploy agent and SSM agent. No application install.
- Target groups named `${instance-name}-${port}`, HTTP, three healthy and three unhealthy checks, interval 30 seconds, timeout 5 seconds.

### Load balancer and host routing

- Path: `stacks/datafy/load_balancers.tf`.
- Internet-facing ALB `datafy-prod-alb-public` on the first two public subnets.
- HTTP to HTTPS redirect. HTTPS default fixed response. Three host rules for waterwheel, supabase, and qwen.
- Host header preserved. Idle timeout 180 seconds. Deletion protection on.
- A commented association shows a private ALB that is not declared.

### Database

- Path: `stacks/datafy/database.tf`, `stacks/datafy/rds_proxy.tf`, `modules/aws-so-rds`, `modules/aws-so-rds-proxy`.
- PostgreSQL 15, `db.t3.xlarge`, Multi-AZ, 100–500 GB gp3, encrypted, deletion protection, 7-day automated backups, Performance Insights, enhanced monitoring every 60 seconds.
- RDS event subscription for deletion, failover, failure, low storage, maintenance, recovery, restoration, and security.
- RDS Proxy with TLS and the RDS-managed secret. The `env` tag is removed from the database so AWS Backup does not select it (change on 2026-10-01, `e184981` and `8af8aa6`).

### Object storage

- Path: `stacks/datafy/s3.tf`, `modules/aws-so-s3`.
- Buckets `datafy-prod-ml-image-scan` and `datafy-prod-supabase-storage`.
- Server artifacts bucket `datafy-prod-server-artifacts` inside the EC2 module (`force_destroy = true`).

### Edge: CloudFront, WAF, certificates

- Path: `stacks/datafy/cdn_and_waf.tf`, `stacks/datafy/dns_and_certs.tf`, `modules/aws-so-cdn`, `modules/aws-so-waf`, `modules/aws-so-ssl`.
- Distribution `datafy-prod-cdn` for `webportal.datafy.co.za`, S3 origin, SPA fallback to `/index.html` (commit `cef6442`, 2026-07-08).
- Regional WAF on the public ALB, including the 2026-10-01 allow rules for `pgadmin.waterwheel.datafy.co.za` and `POST /storage/v1/object/Reports/`.
- CloudFront WAF without those host exceptions.
- `SizeRestrictions_BODY` set to count (commit `bfa5cc3`, 2026-06-29).
- Requested certificate `*.datafy.co.za` in `eu-west-1` and again in `us-east-1`.
- Data source for an already issued `*.waterwheel.datafy.co.za` certificate.

### Detection Lambda

- Path: `stacks/datafy/lambda.tf`, `modules/aws-so-lambda`.
- Function `datafy-prod-detection`, Python 3.12, 3008 MB, 900 second timeout, placeholder handler, code changes ignored, alarm on more than 5 errors per minute.
- No event source mapping.

### Budgets and backup

- Monthly cost budget `datafy-prod-budget`, limit 1800 USD.
- Notifications at 50, 100, and 150 percent actual, and the same thresholds forecasted. Escalation mail is used at 150 percent actual. Monitor mail is used at 150 percent forecasted. Subscriber mail is used for the other four.
- AWS Backup vault `datafy-prod-backup-vault`. Daily (keep 14 days, 01:00 UTC), weekly (keep 120 days, Saturday 02:00 UTC), monthly (keep 420 days, 1st of the month 03:00 UTC). Selection tag `env` = `backup`. Cold storage transition is 0 (disabled) on all three plans.

### Diagram

- Path: `datafy project redeployment.jpg`.
- Title on the drawing: "Datafy AWS Architecture Production Environment", Europe (Ireland).
- Still tracked despite `.gitignore` containing `.jpg`.

## Unused modules (present, not called)

| Module | What it can create | Why it is unused |
|---|---|---|
| `modules/aws-so-cache` | ElastiCache, including serverless | Commit `36b62a7` (2026-06-21) says the architecture was aligned to EC2 and ECS/cache were removed. The module remains |
| `modules/aws-so-efs` | EFS | No stack source reference |
| `modules/aws-so-secret-manager` | Secrets Manager secret and optional rotation | RDS uses `manage_master_user_password` instead |
| `modules/aws-so-alerts` | EventBridge rules whose source includes `aws.ecs` | No stack source reference. Consistent with the ECS removal |

`modules/aws-kms` and `modules/aws-cloudwatch-loggroup` are used by the CloudTrail module, not by the datafy stack directly.

## Not implemented, though named

| Item | Where it is named | Code |
|---|---|---|
| `stacks/shared-services` | `environments/production/README.md` | Directory does not exist. `stacks/datafy` is what production calls |
| Private ALB | Variables `alb_internal*` and a comment in `cdn_and_waf.tf` | No `module.alb-private` |
| VPC peering | `peer_owner_id`, `peer_vpc_id` | No peering resource. Values unset |
| Private hosted zone `internal.datafy.co.za` | `private_dns` and a commented Route 53 module | Commented out |
| API Gateway, SES, Step Functions, Trusted Advisor | Architecture JPG footer and diagram | No matching resources. Trusted Advisor is an account feature, not a Terraform resource here |
| GitHub Actions OIDC | Commented variable in `environments/production/variables.tf` | Commented out |
| Second environment | `README.md` | Only `production/` exists |
| SonarQube project file | Task-creation scan of the working tree | Not in git history |
| CI pipeline | — | No `bitbucket-pipelines.yml` |
| Automated tests | — | No test directory |

## Changed recently

| Date | Commit | Change |
|---|---|---|
| 2026-10-01 | `8af8aa6` | Backup settings adjusted again in account settings and the RDS module |
| 2026-10-01 | `85eee8f` | Regional WAF allow rules for pgAdmin and the Reports storage upload; common-rule and SQLi scope-downs |
| 2026-10-01 | `e184981` | RDS drops the `env=backup` tag; datafy locals still set `env=backup` for other resources |
| 2026-07-31 | `a0b9be3` | Public ALB `preserve_host_header = true` |
| 2026-07-08 | `cef6442` | CloudFront returns `index.html` for S3 403/404 |

The onboarding snapshot stopped at `a0b9be3`. The three 2026-10-01 commits are part of the current feature set.

## Deprecated or removed

- ECS and cache as the running architecture. Commit message on `36b62a7`: "Align security groups to EC2-only architecture and remove ECS/cache". Security groups no longer mention ECS. The cache module file remains.
- No `removed` blocks and no changelog entry record a formal deprecation.

## Planned

Nothing in the repository is marked TODO as a future product feature. Commented blocks (private zone, private ALB association, GitHub OIDC thumbprints, some awsutils region providers) are inactive code, not an agreed plan. Treat them as **Unknown / Requires Confirmation** before calling them a roadmap.
