type: user

role: user

content:
You are a code quality reviewer for Terraform HCL. Review the file for quality issues.

Read: `/Users/steve.briggs/projects/operations/terraform/iac-library/aws/storage/database-tools-db/main.tf`

Also read the existing similar module for comparison patterns:
`/Users/steve.briggs/projects/operations/terraform/iac-library/aws/storage/database-retool-app/main.tf`

Check for:
1. **Consistency** — does the style match the existing `database-retool-app` module?
2. **Correctness** — any HCL syntax issues, wrong argument names, or logic errors?
3. **Unnecessary complexity** — anything that could be simplified?
4. **Missing best practices** — sensitive outputs not marked, missing lifecycle rules, etc.

End with:
- `QUALITY REVIEW: ✅ APPROVED` — no significant issues
- `QUALITY REVIEW: ❌ ISSUES` followed by specific problems ranked by severity (Critical / Important / Minor)

userType: external

entrypoint: cli


content:
- obsidian-load: Load context from Obsidian notes in the `Claude/` directory into the current conversation.
- obsidian-save: Save current conversation context to an Obsidian note under the `Claude/` directory.
- mind:search: Search memories for specific content or patterns
- mind:stats: Show memory statistics and storage information
- mind:ask: Ask questions about memories and get context-aware answers
- mind:recent: Show recent memories and activity timeline
- mind:memory: Claude Mind - Search and manage Claude's persistent memory stored in a single portable .mv2 file
- mind:mind: Claude Mind - Search and manage Claude's persistent memory stored in a single portable .mv2 file
- superpowers:dispatching-parallel-agents: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
- superpowers:test-driven-development: Use when implementing any feature or bugfix, before writing implementation code
- superpowers:systematic-debugging: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
- superpowers:executing-plans: Use when you have a written implementation plan to execute in a separate session with review checkpoints
- superpowers:using-superpowers: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
- superpowers:using-git-worktrees: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
- superpowers:requesting-code-review: Use when completing tasks, implementing major features, or before merging to verify work meets requirements
- superpowers:finishing-a-development-branch: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
- superpowers:brainstorming: You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.
- superpowers:writing-plans: Use when you have a spec or requirements for a multi-step task, before touching code
- superpowers:receiving-code-review: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
- superpowers:verification-before-completion: Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
- superpowers:writing-skills: Use when creating new skills, editing existing skills, or verifying skills work before deployment
- superpowers:subagent-driven-development: Use when executing implementation plans with independent tasks in the current session
- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors ("from now on when X", "each time X", "whenever X", "before/after X") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions ("allow X", "add permission", "move permission to"), env vars ("set X=Y"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: "allow npm commands", "add bq permission to global settings", "move permission to user settings", "set DEBUG=true", "when claude stops show X". For simple settings like theme/model, suggest the /config command.
- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: "rebind ctrl+s", "add a chord shortcut", "change the submit key", "customize keybindings".
- verify: Verify that a code change actually does what it's supposed to by running the app and observing behavior. Use when asked to verify a PR, confirm a fix works, test a change manually, check that a feature works, or validate local changes before pushing.
- simplify: Review changed code for reuse, quality, and efficiency, then fix any issues found.
- fewer-permission-prompts: Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project .claude/settings.json to reduce permission prompts.
- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo). Omit the interval to let the model self-pace. - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. "check the deploy every 5 minutes", "keep running /babysit-prs"). Do NOT invoke for one-off tasks.
- schedule: Create, update, list, or run scheduled remote agents (routines) that execute on a cron schedule. - When the user wants to schedule a recurring remote agent, set up automated tasks, create a cron job for Claude Code, or manage their scheduled agents/routines. Also use when the user wants a one-time scheduled run ("run this once at 3pm", "remind me to check X tomorrow").
- claude-api: Build, debug, and optimize Claude API / Anthropic SDK apps. Apps built with this skill should include prompt caching. Also handles migrating existing Claude API code between Claude model versions (4.5 → 4.6, 4.6 → 4.7, retired-model replacements).
TRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks for the Claude API, Anthropic SDK, or Managed Agents; user adds/modifies/tunes a Claude feature (caching, thinking, compaction, tool use, batch, files, citations, memory) or model (Opus/Sonnet/Haiku) in a file; questions about prompt caching / cache hit rate in an Anthropic SDK project.
SKIP: file imports `openai`/other-provider SDK, filename like `*-openai.py`/`*-generic.py`, provider-neutral code, general programming/ML.
- run: Launch and drive this project's app to see a change working. Use when asked to run, start, or screenshot the app, or to confirm a change works in the real app (not just tests). First looks for a project skill that already covers launching the app; otherwise falls back to built-in patterns per project type (CLI, server, TUI, Electron, browser-driven, library).
- init: Initialize a new CLAUDE.md file with codebase documentation
- review: Review a pull request
- security-review: Complete a security review of the pending changes on the current branch

type: attachment


type: message

role: assistant

type: text

text: I'll read both files in parallel to compare them.

service_tier: standard

attributionAgent: general-purpose

attributionPlugin: superpowers

type: assistant


Read

type: direct


speed: standard


content:
1	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2	# SET UP THE DATABASE FOR RETOOL-DATABASE APP
3	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5	# ---------------------------------------------------------------------------------------------------------------------
6	# SET TERRAFORM REQUIREMENTS FOR RUNNING THIS MODULE
7	# ---------------------------------------------------------------------------------------------------------------------
8
9	terraform {
10	  required_version = "~> 1.0"
11
12	  required_providers {
13	    aws = {
14	      source                = "hashicorp/aws"
15	      version               = "~> 4.0"
16	      configuration_aliases = [aws.backup]
17	    }
18	    postgresql = {
19	      source  = "cyrilgdn/postgresql"
20	      version = "~> 1.21"
21	    }
22	    random = {
23	      version = "~> 3.6.0"
24	    }
25	  }
26	}
27
28	provider "postgresql" {
29	  connect_timeout = 30
30	  host = module.database.address
31	  port = module.database.port
32	  database = "postgres"
33	  username = module.database.admin_username
34	  password = module.database.admin_password
35	  sslmode = "require"
36	  superuser = false
37	}
38
39	locals {
40	  name         = var.name != "" ? var.name : "retool-app-database-${var.env}"
41	  kms_key_name = "${local.name}-db-key"
42	}
43
44	# ----------------------------------------------------------------------------------------------------------------------
45	# CREATE KMS KEYS
46	# ----------------------------------------------------------------------------------------------------------------------
47	module "database_kms" {
48	  source  = "crow.infrastructure.immuta.io/internal/security-kms-key/aws"
49	  version = "1.4.0"
50	  count  = var.storage_encrypted ? 1 : 0
51
52	  customer_master_keys = {
53	    (local.kms_key_name) = {
54	      allow_manage_key_permissions_with_iam = true
55	      deletion_window_in_days               = var.kms_key_deletion_window_in_days
56	      enable_key_rotation                   = false
57	      multi_region                          = true
58	      tags                                  = var.tags
59	    }
60	  }
61	}
62
63	resource "aws_kms_replica_key" "replica_key" {
64	  count = var.storage_encrypted && var.encrypt_replicas ? 1 : 0
65
66	  provider   = aws.backup
67	  depends_on = [module.database_kms]
68
69	  description             = "KMS Replica Key for multitenant database"
70	  deletion_window_in_days = var.kms_key_deletion_window_in_days
71	  primary_key_arn         = module.database_kms[0].key_arns[local.kms_key_name]
72
73	  tags = var.tags
74	}
75
76	# ----------------------------------------------------------------------------------------------------------------------
77	# CREATE THE RDS INSTANCE AND DATABASE
78	# ----------------------------------------------------------------------------------------------------------------------
79
80	module "database" {
81	  source  = "crow.infrastructure.immuta.io/internal/data-database-rds/aws"
82	  version = "1.2.1"
83
84	  providers = {
85	    aws.backup = aws.backup
86	  }
87
88	  name               = local.name
89	  pg_version         = var.pg_version
90	  env                = var.env
91	  ca_cert_identifier = var.ca_cert_identifier
92
93	  parameters                   = var.parameters
94	  db_name                      = var.db_name
95	  admin_username               = var.admin_username
96	  instance_class               = var.rds_instance_size
97	  enhanced_monitoring_enabled  = var.enhanced_monitoring_enabled
98	  performance_insights_enabled = var.performance_insights_enabled
99	  multi_az                     = var.multi_az
100
101	  kms_key_arn             = var.storage_encrypted ? module.database_kms[0].key_arns[local.kms_key_name] : null
102	  kms_replication_key_arn = var.storage_encrypted && var.encrypt_replicas ? aws_kms_replica_key.replica_key[0].arn : null
103
104	  vpc_id              = var.vpc_id
105	  subnet_ids          = var.private_subnet_ids
106	  trusted_cidr_blocks = var.trusted_cidr_blocks
107
108	  subnet_group_name_override       = var.subnet_group_name_override
109	  dba_security_group_name_override = var.dba_security_group_name_override
110	  security_group_name_override     = var.security_group_name_override
111
112	  allocated_storage     = var.allocated_storage
113	  max_allocated_storage = var.max_allocated_storage
114	  storage_encrypted     = var.storage_encrypted
115	  storage_type          = var.storage_type
116
117	  backup_retention_period  = var.backup_retention_period
118	  replica_retention_period = var.replica_retention_period
119	  final_snapshot           = var.final_snapshot
120	  encrypt_replicas         = var.encrypt_replicas
121
122	  tags = var.tags
123
124	  depends_on = [module.database_kms, aws_kms_replica_key.replica_key]
125	}
126
127	resource postgresql_role immuta_admin {
128	  name                = "immuta_admin"
129	  create_database     = true
130	  create_role         = true
131	  login               = true
132	  skip_reassign_owned = true
133	  roles = [
134	    "rds_superuser",
135	    "rds_iam"
136	  ]
137	}
138
139	resource postgresql_role immuta_view {
140	  name                = "immuta_view"
141	  create_database     = false
142	  create_role         = false
143	  login               = true
144	  skip_reassign_owned = true
145	  roles = [
146	    "rds_iam"
147	  ]
148	}
149
150


content:
1	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2	# SET UP THE DATABASE FOR TOOLS
3	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5	terraform {
6	  required_version = "~> 1.0"
7
8	  required_providers {
9	    aws = {
10	      source                = "hashicorp/aws"
11	      version               = "~> 4.0"
12	      configuration_aliases = [aws.backup]
13	    }
14	    vault = {
15	      source  = "hashicorp/vault"
16	      version = "~> 3.0"
17	    }
18	    random = {
19	      version = "~> 3.6.0"
20	    }
21	  }
22	}
23
24	locals {
25	  name         = var.name != "" ? var.name : "tools-database-${var.env}"
26	  kms_key_name = "${local.name}-db-key"
27	}
28
29	# ----------------------------------------------------------------------------------------------------------------------
30	# CREATE KMS KEYS
31	# ----------------------------------------------------------------------------------------------------------------------
32
33	module "database_kms" {
34	  source  = "crow.infrastructure.immuta.io/internal/security-kms-key/aws"
35	  version = "1.4.0"
36	  count   = var.storage_encrypted ? 1 : 0
37
38	  customer_master_keys = {
39	    (local.kms_key_name) = {
40	      allow_manage_key_permissions_with_iam = true
41	      deletion_window_in_days               = var.kms_key_deletion_window_in_days
42	      enable_key_rotation                   = false
43	      multi_region                          = true
44	      tags                                  = var.tags
45	    }
46	  }
47	}
48
49	resource "aws_kms_replica_key" "replica_key" {
50	  count = var.storage_encrypted && var.encrypt_replicas ? 1 : 0
51
52	  provider   = aws.backup
53	  depends_on = [module.database_kms]
54
55	  description             = "KMS Replica Key for tools database"
56	  deletion_window_in_days = var.kms_key_deletion_window_in_days
57	  primary_key_arn         = module.database_kms[0].key_arns[local.kms_key_name]
58
59	  tags = var.tags
60	}
61
62	# ----------------------------------------------------------------------------------------------------------------------
63	# CREATE THE RDS INSTANCE
64	# ----------------------------------------------------------------------------------------------------------------------
65
66	module "database" {
67	  source  = "crow.infrastructure.immuta.io/internal/data-database-rds/aws"
68	  version = "3.0.1"
69
70	  providers = {
71	    aws.backup = aws.backup
72	  }
73
74	  name               = local.name
75	  pg_version         = var.pg_version
76	  env                = var.env
77	  ca_cert_identifier = var.ca_cert_identifier
78
79	  db_name        = var.db_name
80	  admin_username = var.admin_username
81	  instance_class = var.rds_instance_size
82
83	  enhanced_monitoring_enabled  = var.enhanced_monitoring_enabled
84	  performance_insights_enabled = var.performance_insights_enabled
85	  multi_az                     = var.multi_az
86
87	  kms_key_arn             = var.storage_encrypted ? module.database_kms[0].key_arns[local.kms_key_name] : ""
88	  kms_replication_key_arn = var.storage_encrypted && var.encrypt_replicas ? aws_kms_replica_key.replica_key[0].arn : ""
89
90	  vpc_id              = var.vpc_id
91	  subnet_ids          = var.private_subnet_ids
92	  trusted_cidr_blocks = var.trusted_cidr_blocks
93
94	  subnet_group_name_override       = var.subnet_group_name_override
95	  dba_security_group_name_override = var.dba_security_group_name_override
96	  security_group_name_override     = var.security_group_name_override
97
98	  allocated_storage     = var.allocated_storage
99	  max_allocated_storage = var.max_allocated_storage
100	  storage_encrypted     = var.storage_encrypted
101	  storage_type          = var.storage_type
102
103	  backup_retention_period  = var.backup_retention_period
104	  replica_retention_period = var.replica_retention_period
105	  final_snapshot           = var.final_snapshot
106	  encrypt_replicas         = var.encrypt_replicas
107
108	  tags = var.tags
109
110	  depends_on = [module.database_kms, aws_kms_replica_key.replica_key]
111	}
112
113	# ----------------------------------------------------------------------------------------------------------------------
114	# STORE ADMIN CREDENTIALS IN VAULT
115	# ----------------------------------------------------------------------------------------------------------------------
116
117	resource "vault_generic_secret" "admin_credentials" {
118	  path = var.vault_secret_path
119
120	  data_json = jsonencode({
121	    username = module.database.admin_username
122	    password = module.database.admin_password
123	    endpoint = module.database.endpoint
124	    address  = module.database.address
125	    port     = module.database.port
126	    db_name  = module.database.name
127	  })
128	}
129


text: Now let me also check the variables and outputs files for both modules to get the full picture.


Bash

description: List files in both module directories


content:
drwxr-xr-x steve.briggs staff 544 B  Wed May 20 15:12:45 2026 ..
.rw-r--r-- steve.briggs staff 4.4 KB Wed May 20 15:14:04 2026 main.tf
drwxr-xr-x steve.briggs staff  96 B  Wed May 20 15:14:04 2026 .
.rw-r--r-- steve.briggs staff 8.5 KB Tue May 12 16:37:45 2026 README.md
.rw-r--r-- steve.briggs staff   6 B  Tue May 12 16:37:45 2026 VERSION
.rw-r--r-- steve.briggs staff 4.9 KB Tue May 12 16:37:45 2026 main.tf
.rw-r--r-- steve.briggs staff 1.5 KB Tue May 12 16:37:45 2026 output.tf
drwxr-xr-x steve.briggs staff 224 B  Tue May 12 16:37:45 2026 .
.rw-r--r-- steve.briggs staff 5.0 KB Tue May 12 16:37:45 2026 variables.tf
drwxr-xr-x steve.briggs staff 544 B  Wed May 20 15:12:45 2026 ..


text: The `database-tools-db` module only has `main.tf` — no `variables.tf`, `output.tf`, or `README.md`. Let me check the retool-app's output and variables for full comparison.


content:
1	# ---------------------------------------------------------------------------------------------------------------------
2	# REQUIRED PARAMETERS
3	# These variables must be set.
4	# ---------------------------------------------------------------------------------------------------------------------
5	variable "env" {
6	  description = "The environment that the bucket is for, i.e. dev, staging, or prod"
7	  type        = string
8	  validation {
9	    condition = (
10	      var.env != null &&
11	      var.env != ""
12	    )
13	    error_message = "Env must be set"
14	  }
15	}
16
17	variable "vpc_id" {
18	  description = "The ID of the VPC that the RDS Instance(S) will be deployed into."
19	  type        = string
20	}
21	variable "private_subnet_ids" {
22	  description = "List of private subnets in the VPC that is used to create the RDS Subnet Group"
23	  type        = list(string)
24	}
25
26	variable "trusted_cidr_blocks" {
27	  description = "CIDR blocks that will be allowed to access the RDS instance on port 5432"
28	  type        = list(string)
29	}
30
31	variable "pg_version" {
32	  description = "Postgres database version prefix"
33	  type        = string
34	}
35
36	# ---------------------------------------------------------------------------------------------------------------------
37	# OPTIONAL PARAMETERS
38	# These variables are configurable, but have reasonable defaults set.
39	# ---------------------------------------------------------------------------------------------------------------------
40
41	variable "name" {
42	  description = "The name of the RDS instance."
43	  type        = string
44	  default     = ""
45	}
46
47	variable "db_name" {
48	  description = "Database name to create when creating the DB instance"
49	  type        = string
50	  default     = ""
51	}
52
53	variable "admin_username" {
54	  description = "Database admin user"
55	  type        = string
56	  default     = "immuta_postgres"
57	}
58
59	variable "rds_instance_size" {
60	  description = "RDS instance size to use."
61	  type        = string
62	  default     = "db.t4g.small"
63	}
64
65	variable "parameters" {
66	  description = "A map of DB parameters to apply via a parameter group.  If map is empty, the default parameter group will be used"
67	  type        = set(map(string))
68	  default     = []
69	}
70
71	variable "max_allocated_storage" {
72	  description = "Upper limit on storage expansion from Storage Autoscaling."
73	  type        = number
74	  default     = 50
75	}
76
77	variable "allocated_storage" {
78	  description = "Upper limit on storage expansion from Storage Autoscaling."
79	  type        = number
80	  default     = 20
81	}
82
83	variable "kms_key_arn" {
84	  description = "Optional variable for providing a pre-existing KMS key"
85	  type        = string
86	  default     = ""
87	}
88
89	variable "storage_encrypted" {
90	  description = "Whether or not to encrypt the RDS instance."
91	  type        = bool
92	  default     = true
93	}
94
95	variable "storage_type" {
96	  description = "Storage type of the RDS instance"
97	  type        = string
98	  default     = "gp3"
99	}
100
101	variable "encrypt_replicas" {
102	  description = "Whether or not to encrypt the replicas of the RDS instance."
103	  type        = bool
104	  default     = true
105	}
106
107	variable "enhanced_monitoring_enabled" {
108	  description = "Whether or not to enable enhanced monitoring."
109	  type        = bool
110	  default     = true
111	}
112
113	variable "performance_insights_enabled" {
114	  description = "Whether or not to enable performance insights."
115	  type        = bool
116	  default     = true
117	}
118
119	variable "final_snapshot" {
120	  description = "Must be true if you want to destroy backups AND the bucket, if false, bucket must be empty before destruction."
121	  type        = bool
122	  default     = false
123	}
124
125	variable "multi_az" {
126	  description = "Indicates whether or not the RDS instance should be deployed as a multi-az cluster for HA."
127	  type        = bool
128	  default     = false
129	}
130
131	variable "subnet_group_name_override" {
132	  description = "Optional override for subnet group name. Can be used when moving DB Subnet Groups."
133	  type        = string
134	  default     = ""
135	}
136
137	variable "dba_security_group_name_override" {
138	  description = "Optional override for external access SG name. Can be used when moving DB Subnet Groups."
139	  type        = string
140	  default     = ""
141	}
142
143	variable "security_group_name_override" {
144	  description = "Optional override for local access sg name. Can be used when moving DB Subnet Groups."
145	  type        = string
146	  default     = ""
147	}
148
149	variable "ca_cert_identifier" {
150	  description = "RDS CA cert identifier"
151	  type        = string
152	  default     = "rds-ca-rsa2048-g1"
153	}
154
155	variable "backup_retention_period" {
156	  description = "The days to retain backups for. Must be between 0 and 35."
157	  type        = number
158	  default     = 21
159	}
160
161	variable "replica_retention_period" {
162	  description = "The retention period for backup replication in days. Must be between 0 and 35."
163	  type        = number
164	  default     = 21
165	}
166
167	variable "kms_key_deletion_window_in_days" {
168	  description = "The default value to use for deletion_window_in_days (the number of days to keep the KMS master key & replica keys after deletion pending)"
169	  type        = number
170	  default     = 30
171	}
172
173	variable "tags" {
174	  description = "A map of tags to apply to the created resources."
175	  type        = map(string)
176	  default     = {}
177	}
178


content:
1	output "address" {
2	  value = module.database.address
3	}
4
5	output "admin_password_secret_arn" {
6	  value = module.database.admin_password_secret_arn
7	}
8
9	output "admin_password_secret_name" {
10	  value = module.database.admin_password_secret_name
11	}
12
13	output "admin_password" {
14	  sensitive = true
15	  value     = module.database.admin_password
16	}
17
18	output "admin_username" {
19	  value = module.database.admin_username
20	}
21
22	output "arn" {
23	  value = module.database.arn
24	}
25
26	output "availability_zone" {
27	  value = module.database.availability_zone
28	}
29
30	output "db_access_security_group_arn" {
31	  value = module.database.db_access_security_group_arn
32	}
33
34	output "db_access_security_group_id" {
35	  value = module.database.db_access_security_group_id
36	}
37
38	output "db_access_security_group_name" {
39	  value = module.database.db_access_security_group_name
40	}
41
42	output "endpoint" {
43	  value = module.database.endpoint
44	}
45
46	output "hosted_zone_id" {
47	  value = module.database.hosted_zone_id
48	}
49
50	output "id" {
51	  value = module.database.id
52	}
53
54	output "name" {
55	  value = module.database.name
56	}
57
58	output "port" {
59	  value = module.database.port
60	}
61
62	output "resource_id" {
63	  value = module.database.resource_id
64	}
65
66	output "status" {
67	  value = module.database.status
68	}
69
70	output "kms_arns" {
71	  value = one(module.database_kms[*].key_arns[local.kms_key_name])
72	}
73
74	output "kms_key_ids" {
75	  value = one(module.database_kms[*].key_ids[local.kms_key_name])
76	}
77
78	output "kms_replica_arn" {
79	  value = one(aws_kms_replica_key.replica_key[*].arn)
80	}
81
82	output "kms_replica_id" {
83	  value = one(aws_kms_replica_key.replica_key[*].key_id)
84	}
85


text:
I now have everything I need for a thorough review. Here's the full breakdown, Sir Charles of St Cheese.

---

Aight fam, real talk — this module is lowkey bussin' in some areas but high-key got some issues that are giving me the ick. No cap, here's the full vibe check:

---

## Code Quality Review: `database-tools-db/main.tf`

### Consistency vs. `database-retool-app`

**1. Missing `variables.tf` and `output.tf` files**
The `database-retool-app` module has a complete `variables.tf`, `output.tf`, and `README.md`. The `database-tools-db` module has only `main.tf`. This is the most glaring structural gap — the module is unusable as a proper Terraform module without variable declarations, and callers get zero outputs.

**2. Blank line missing after section comment headers**
In `database-retool-app`, a blank line separates the `# ---` comment from the first resource (`module "database_kms"` starts on line 47 with no blank line — actually this one is inconsistent in the reference too, minor). In `database-tools-db` the style is consistent with itself, so this is a wash.

**3. `random` provider has no `source` block**
Both modules omit `source` for the `random` provider. This matches between modules — consistent but technically incomplete per Terraform registry best practices. It will resolve via implicit lookup. Minor / inherited issue.

---

### Correctness Issues

**4. `kms_key_arn` and `kms_replication_key_arn` pass `""` instead of `null` when disabled**
`database-retool-app` (line 101–102) passes `null` for both KMS ARN arguments when encryption is disabled:
```hcl
kms_key_arn             = var.storage_encrypted ? module.database_kms[0].key_arns[local.kms_key_name] : null
kms_replication_key_arn = var.storage_encrypted && var.encrypt_replicas ? aws_kms_replica_key.replica_key[0].arn : null
```
`database-tools-db` (lines 87–88) passes `""` instead:
```hcl
kms_key_arn             = var.storage_encrypted ? module.database_kms[0].key_arns[local.kms_key_name] : ""
kms_replication_key_arn = var.storage_encrypted && var.encrypt_replicas ? aws_kms_replica_key.replica_key[0].arn : ""
```
Passing an empty string to an ARN argument is incorrect — the downstream `data-database-rds` module will receive `""` and potentially attempt to use it as a real ARN or fail validation. `null` signals "not set" in Terraform; `""` does not. This is a real correctness bug.

**5. `vault_generic_secret` stores `admin_password` in plaintext state**
The `vault_generic_secret` resource at line 117–128 writes the admin password into `data_json`. While this is intentional (the whole point is storing the creds in Vault), there is no `lifecycle { ignore_changes = [data_json] }` guard. If the password rotates externally in Vault, Terraform will detect drift and overwrite it. Additionally, the resource itself has no sensitivity annotation — this means the password flows through `data_json` in Terraform state in plaintext. Best practice is to ensure the backing `module.database.admin_password` output is `sensitive = true` (which it is in the retool module's `output.tf`), but the new module has no `output.tf` at all to enforce that contract.

**6. `parameters` variable missing from `module "database"` call**
The `database-retool-app` module passes `parameters = var.parameters` to the RDS module (line 93). The `database-tools-db` module omits this entirely. If the underlying `data-database-rds` module version `3.0.1` accepts a `parameters` argument (very likely given version `1.2.1` already did), the tools DB module provides no way to pass custom DB parameter group settings to callers. This is a missing capability, not a hard error — but it's an inconsistency and likely an oversight.

---

### Unnecessary Complexity

**7. `depends_on` on `module "database"` is redundant**
Both modules include:
```hcl
depends_on = [module.database_kms, aws_kms_replica_key.replica_key]
```
Because the `kms_key_arn` and `kms_replication_key_arn` arguments reference outputs from these resources directly, Terraform already infers the dependency graph. The explicit `depends_on` is harmless but unnecessary — it also inhibits some Terraform graph optimizations. The reference module has the same pattern, so this is inherited, but worth noting.

---

### Missing Best Practices

**8. No `output.tf` means sensitive outputs are unguarded**
The `admin_password` from `module.database` is sensitive. Without an `output.tf`, any caller wrapping this module has no outputs to consume at all — and if someone adds ad-hoc outputs later, there's a risk of forgetting `sensitive = true` on the password output. The `database-retool-app` module correctly marks `admin_password` with `sensitive = true` in its `output.tf`.

**9. No `README.md` or `VERSION` file**
Minor by itself, but the `database-retool-app` module has both. This is a documentation and module registry consistency issue.

---

## Summary Table

| # | Severity | Issue |
|---|----------|-------|
| 1 | **Critical** | Missing `variables.tf` — module cannot be instantiated without variable declarations |
| 2 | **Critical** | Missing `output.tf` — module produces no consumable outputs |
| 3 | **Important** | `kms_key_arn` / `kms_replication_key_arn` pass `""` instead of `null` when disabled — mismatches reference module and may cause downstream ARN validation errors |
| 4 | **Important** | `parameters` variable not plumbed through to `module "database"` — limits configurability vs. reference module |
| 5 | **Important** | No `sensitive = true` protection on password outputs (no `output.tf` exists to enforce this) |
| 6 | **Minor** | Redundant `depends_on` on `module "database"` (inherited from reference module pattern) |
| 7 | **Minor** | Missing `README.md` and `VERSION` file for module registry consistency |

---

`QUALITY REVIEW: ❌ ISSUES`

The two critical issues (missing `variables.tf` and `output.tf`) mean this module is structurally incomplete as a reusable Terraform module — it literally cannot be called by a root module without variable declarations. The `""` vs `null` issue on KMS ARNs is a real correctness bug that diverges from the established pattern in the reference module and could cause plan/apply failures depending on how the downstream `data-database-rds` module validates those inputs.