dojo.md 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/courses/GENERATION_LOG.md +20 -0
  2. package/courses/api-documentation-writing/course.yaml +12 -0
  3. package/courses/api-documentation-writing/scenarios/level-1/authentication-basics.yaml +46 -0
  4. package/courses/api-documentation-writing/scenarios/level-1/data-types-formats.yaml +45 -0
  5. package/courses/api-documentation-writing/scenarios/level-1/endpoint-description.yaml +45 -0
  6. package/courses/api-documentation-writing/scenarios/level-1/error-documentation.yaml +45 -0
  7. package/courses/api-documentation-writing/scenarios/level-1/first-documentation-shift.yaml +47 -0
  8. package/courses/api-documentation-writing/scenarios/level-1/getting-started-guide.yaml +42 -0
  9. package/courses/api-documentation-writing/scenarios/level-1/pagination-docs.yaml +51 -0
  10. package/courses/api-documentation-writing/scenarios/level-1/request-parameters.yaml +46 -0
  11. package/courses/api-documentation-writing/scenarios/level-1/request-response-examples.yaml +48 -0
  12. package/courses/api-documentation-writing/scenarios/level-1/status-codes.yaml +45 -0
  13. package/courses/api-documentation-writing/scenarios/level-2/error-patterns.yaml +48 -0
  14. package/courses/api-documentation-writing/scenarios/level-2/intermediate-documentation-shift.yaml +48 -0
  15. package/courses/api-documentation-writing/scenarios/level-2/oauth-documentation.yaml +47 -0
  16. package/courses/api-documentation-writing/scenarios/level-2/openapi-specification.yaml +46 -0
  17. package/courses/api-documentation-writing/scenarios/level-2/rate-limiting-docs.yaml +45 -0
  18. package/courses/api-documentation-writing/scenarios/level-2/request-body-schemas.yaml +46 -0
  19. package/courses/api-documentation-writing/scenarios/level-2/schema-definitions.yaml +41 -0
  20. package/courses/api-documentation-writing/scenarios/level-2/swagger-redoc-rendering.yaml +43 -0
  21. package/courses/api-documentation-writing/scenarios/level-2/validation-documentation.yaml +47 -0
  22. package/courses/api-documentation-writing/scenarios/level-2/versioning-changelog.yaml +42 -0
  23. package/courses/api-documentation-writing/scenarios/level-3/advanced-documentation-shift.yaml +43 -0
  24. package/courses/api-documentation-writing/scenarios/level-3/api-style-guide.yaml +40 -0
  25. package/courses/api-documentation-writing/scenarios/level-3/code-samples-multilang.yaml +40 -0
  26. package/courses/api-documentation-writing/scenarios/level-3/content-architecture.yaml +47 -0
  27. package/courses/api-documentation-writing/scenarios/level-3/deprecation-communication.yaml +44 -0
  28. package/courses/api-documentation-writing/scenarios/level-3/interactive-api-explorer.yaml +42 -0
  29. package/courses/api-documentation-writing/scenarios/level-3/migration-guides.yaml +42 -0
  30. package/courses/api-documentation-writing/scenarios/level-3/sdk-documentation.yaml +40 -0
  31. package/courses/api-documentation-writing/scenarios/level-3/webhook-documentation.yaml +48 -0
  32. package/courses/api-documentation-writing/scenarios/level-3/websocket-sse-docs.yaml +47 -0
  33. package/courses/api-documentation-writing/scenarios/level-4/api-changelog-management.yaml +44 -0
  34. package/courses/api-documentation-writing/scenarios/level-4/api-governance-standards.yaml +41 -0
  35. package/courses/api-documentation-writing/scenarios/level-4/api-product-strategy.yaml +41 -0
  36. package/courses/api-documentation-writing/scenarios/level-4/developer-portal-design.yaml +48 -0
  37. package/courses/api-documentation-writing/scenarios/level-4/docs-as-code.yaml +41 -0
  38. package/courses/api-documentation-writing/scenarios/level-4/documentation-localization.yaml +46 -0
  39. package/courses/api-documentation-writing/scenarios/level-4/documentation-metrics.yaml +45 -0
  40. package/courses/api-documentation-writing/scenarios/level-4/documentation-testing.yaml +41 -0
  41. package/courses/api-documentation-writing/scenarios/level-4/expert-documentation-shift.yaml +45 -0
  42. package/courses/api-documentation-writing/scenarios/level-4/multi-audience-docs.yaml +46 -0
  43. package/courses/api-documentation-writing/scenarios/level-5/ai-powered-documentation.yaml +44 -0
  44. package/courses/api-documentation-writing/scenarios/level-5/api-first-documentation.yaml +45 -0
  45. package/courses/api-documentation-writing/scenarios/level-5/api-marketplace-docs.yaml +42 -0
  46. package/courses/api-documentation-writing/scenarios/level-5/board-api-strategy.yaml +48 -0
  47. package/courses/api-documentation-writing/scenarios/level-5/documentation-program-strategy.yaml +42 -0
  48. package/courses/api-documentation-writing/scenarios/level-5/documentation-team-structure.yaml +47 -0
  49. package/courses/api-documentation-writing/scenarios/level-5/dx-competitive-advantage.yaml +46 -0
  50. package/courses/api-documentation-writing/scenarios/level-5/ecosystem-documentation.yaml +45 -0
  51. package/courses/api-documentation-writing/scenarios/level-5/industry-documentation-patterns.yaml +46 -0
  52. package/courses/api-documentation-writing/scenarios/level-5/master-documentation-shift.yaml +46 -0
  53. package/courses/code-review-feedback-writing/course.yaml +12 -0
  54. package/courses/code-review-feedback-writing/scenarios/level-1/approve-vs-request-changes.yaml +48 -0
  55. package/courses/code-review-feedback-writing/scenarios/level-1/asking-questions.yaml +50 -0
  56. package/courses/code-review-feedback-writing/scenarios/level-1/clear-comment-writing.yaml +45 -0
  57. package/courses/code-review-feedback-writing/scenarios/level-1/constructive-tone.yaml +43 -0
  58. package/courses/code-review-feedback-writing/scenarios/level-1/first-review-shift.yaml +46 -0
  59. package/courses/code-review-feedback-writing/scenarios/level-1/giving-praise.yaml +44 -0
  60. package/courses/code-review-feedback-writing/scenarios/level-1/nitpick-etiquette.yaml +44 -0
  61. package/courses/code-review-feedback-writing/scenarios/level-1/providing-context.yaml +46 -0
  62. package/courses/code-review-feedback-writing/scenarios/level-1/reviewing-small-prs.yaml +43 -0
  63. package/courses/code-review-feedback-writing/scenarios/level-1/style-vs-logic.yaml +48 -0
  64. package/courses/code-review-feedback-writing/scenarios/level-2/architectural-feedback.yaml +52 -0
  65. package/courses/code-review-feedback-writing/scenarios/level-2/intermediate-review-shift.yaml +46 -0
  66. package/courses/code-review-feedback-writing/scenarios/level-2/performance-feedback.yaml +50 -0
  67. package/courses/code-review-feedback-writing/scenarios/level-2/reviewing-breaking-changes.yaml +44 -0
  68. package/courses/code-review-feedback-writing/scenarios/level-2/reviewing-complex-prs.yaml +43 -0
  69. package/courses/code-review-feedback-writing/scenarios/level-2/reviewing-documentation.yaml +47 -0
  70. package/courses/code-review-feedback-writing/scenarios/level-2/reviewing-error-handling.yaml +50 -0
  71. package/courses/code-review-feedback-writing/scenarios/level-2/reviewing-tests.yaml +53 -0
  72. package/courses/code-review-feedback-writing/scenarios/level-2/security-review-comments.yaml +50 -0
  73. package/courses/code-review-feedback-writing/scenarios/level-2/suggesting-alternatives.yaml +42 -0
  74. package/courses/code-review-feedback-writing/scenarios/level-3/cross-team-review.yaml +45 -0
  75. package/courses/code-review-feedback-writing/scenarios/level-3/mentoring-through-review.yaml +46 -0
  76. package/courses/code-review-feedback-writing/scenarios/level-3/reviewing-unfamiliar-code.yaml +43 -0
  77. package/courses/terraform-infrastructure-setup/scenarios/level-1/first-debugging-shift.yaml +66 -0
  78. package/courses/terraform-infrastructure-setup/scenarios/level-1/hcl-syntax-errors.yaml +65 -0
  79. package/courses/terraform-infrastructure-setup/scenarios/level-1/plan-output-reading.yaml +71 -0
  80. package/courses/terraform-infrastructure-setup/scenarios/level-1/provider-configuration.yaml +62 -0
  81. package/courses/terraform-infrastructure-setup/scenarios/level-1/resource-creation-failures.yaml +54 -0
  82. package/courses/terraform-infrastructure-setup/scenarios/level-1/resource-references.yaml +70 -0
  83. package/courses/terraform-infrastructure-setup/scenarios/level-1/state-file-basics.yaml +73 -0
  84. package/courses/terraform-infrastructure-setup/scenarios/level-1/terraform-fmt-validate.yaml +58 -0
  85. package/courses/terraform-infrastructure-setup/scenarios/level-1/variable-and-output-errors.yaml +78 -0
  86. package/courses/terraform-infrastructure-setup/scenarios/level-2/count-vs-for-each.yaml +58 -0
  87. package/courses/terraform-infrastructure-setup/scenarios/level-2/dependency-management.yaml +80 -0
  88. package/courses/terraform-infrastructure-setup/scenarios/level-2/intermediate-debugging-shift.yaml +66 -0
  89. package/courses/terraform-infrastructure-setup/scenarios/level-2/lifecycle-rules.yaml +51 -0
  90. package/courses/terraform-infrastructure-setup/scenarios/level-2/locals-and-expressions.yaml +58 -0
  91. package/courses/terraform-infrastructure-setup/scenarios/level-2/module-structure.yaml +75 -0
  92. package/courses/terraform-infrastructure-setup/scenarios/level-2/provisioner-pitfalls.yaml +64 -0
  93. package/courses/terraform-infrastructure-setup/scenarios/level-2/remote-state-backend.yaml +55 -0
  94. package/courses/terraform-infrastructure-setup/scenarios/level-2/terraform-import.yaml +55 -0
  95. package/courses/terraform-infrastructure-setup/scenarios/level-2/workspace-management.yaml +51 -0
  96. package/courses/terraform-infrastructure-setup/scenarios/level-3/advanced-debugging-shift.yaml +63 -0
  97. package/courses/terraform-infrastructure-setup/scenarios/level-3/api-rate-limiting.yaml +50 -0
  98. package/courses/terraform-infrastructure-setup/scenarios/level-3/conditional-resources.yaml +66 -0
  99. package/courses/terraform-infrastructure-setup/scenarios/level-3/drift-detection.yaml +66 -0
  100. package/courses/terraform-infrastructure-setup/scenarios/level-3/dynamic-blocks.yaml +71 -0
  101. package/courses/terraform-infrastructure-setup/scenarios/level-3/large-scale-refactoring.yaml +59 -0
  102. package/courses/terraform-infrastructure-setup/scenarios/level-3/multi-provider-config.yaml +69 -0
  103. package/courses/terraform-infrastructure-setup/scenarios/level-3/state-surgery.yaml +57 -0
  104. package/courses/terraform-infrastructure-setup/scenarios/level-3/terraform-cloud-enterprise.yaml +59 -0
  105. package/courses/terraform-infrastructure-setup/scenarios/level-3/terraform-debugging.yaml +51 -0
  106. package/courses/terraform-infrastructure-setup/scenarios/level-4/blast-radius-management.yaml +51 -0
  107. package/courses/terraform-infrastructure-setup/scenarios/level-4/cicd-pipeline-design.yaml +50 -0
  108. package/courses/terraform-infrastructure-setup/scenarios/level-4/compliance-as-code.yaml +46 -0
  109. package/courses/terraform-infrastructure-setup/scenarios/level-4/cost-estimation-governance.yaml +42 -0
  110. package/courses/terraform-infrastructure-setup/scenarios/level-4/expert-debugging-shift.yaml +51 -0
  111. package/courses/terraform-infrastructure-setup/scenarios/level-4/iac-organization-strategy.yaml +45 -0
  112. package/courses/terraform-infrastructure-setup/scenarios/level-4/incident-response-iac.yaml +47 -0
  113. package/courses/terraform-infrastructure-setup/scenarios/level-4/infrastructure-testing.yaml +41 -0
  114. package/courses/terraform-infrastructure-setup/scenarios/level-4/module-registry-design.yaml +45 -0
  115. package/courses/terraform-infrastructure-setup/scenarios/level-4/multi-account-strategy.yaml +57 -0
  116. package/courses/terraform-infrastructure-setup/scenarios/level-5/board-infrastructure-investment.yaml +53 -0
  117. package/courses/terraform-infrastructure-setup/scenarios/level-5/disaster-recovery-iac.yaml +47 -0
  118. package/courses/terraform-infrastructure-setup/scenarios/level-5/enterprise-iac-transformation.yaml +48 -0
  119. package/courses/terraform-infrastructure-setup/scenarios/level-5/iac-technology-evolution.yaml +49 -0
  120. package/courses/terraform-infrastructure-setup/scenarios/level-5/ma-infrastructure-consolidation.yaml +54 -0
  121. package/courses/terraform-infrastructure-setup/scenarios/level-5/master-debugging-shift.yaml +53 -0
  122. package/courses/terraform-infrastructure-setup/scenarios/level-5/multi-cloud-strategy.yaml +49 -0
  123. package/courses/terraform-infrastructure-setup/scenarios/level-5/platform-engineering.yaml +47 -0
  124. package/courses/terraform-infrastructure-setup/scenarios/level-5/regulatory-compliance-automation.yaml +47 -0
  125. package/courses/terraform-infrastructure-setup/scenarios/level-5/terraform-vs-alternatives.yaml +46 -0
  126. package/dist/cli/commands/generate.d.ts.map +1 -1
  127. package/dist/cli/commands/generate.js +2 -1
  128. package/dist/cli/commands/generate.js.map +1 -1
  129. package/dist/cli/commands/train.d.ts.map +1 -1
  130. package/dist/cli/commands/train.js +6 -3
  131. package/dist/cli/commands/train.js.map +1 -1
  132. package/dist/cli/index.js +9 -6
  133. package/dist/cli/index.js.map +1 -1
  134. package/dist/cli/run-demo.js +3 -2
  135. package/dist/cli/run-demo.js.map +1 -1
  136. package/dist/engine/model-utils.d.ts +6 -0
  137. package/dist/engine/model-utils.d.ts.map +1 -1
  138. package/dist/engine/model-utils.js +28 -1
  139. package/dist/engine/model-utils.js.map +1 -1
  140. package/dist/engine/training.d.ts.map +1 -1
  141. package/dist/engine/training.js +4 -3
  142. package/dist/engine/training.js.map +1 -1
  143. package/dist/generator/course-generator.d.ts.map +1 -1
  144. package/dist/generator/course-generator.js +4 -3
  145. package/dist/generator/course-generator.js.map +1 -1
  146. package/dist/mcp/server.d.ts.map +1 -1
  147. package/dist/mcp/server.js +7 -3
  148. package/dist/mcp/server.js.map +1 -1
  149. package/dist/mcp/session-manager.d.ts.map +1 -1
  150. package/dist/mcp/session-manager.js +3 -2
  151. package/dist/mcp/session-manager.js.map +1 -1
  152. package/package.json +3 -2
@@ -0,0 +1,80 @@
1
+ meta:
2
+ id: dependency-management
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Manage resource dependencies — debug dependency graphs, resolve circular references, use depends_on correctly, and understand the DAG"
7
+ tags: [Terraform, dependencies, DAG, circular, depends-on, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your infrastructure has a complex dependency chain that's causing
13
+ issues during apply:
14
+
15
+ ```hcl
16
+ resource "aws_iam_role" "lambda" {
17
+ name = "lambda-role"
18
+ assume_role_policy = jsonencode({...})
19
+ }
20
+
21
+ resource "aws_iam_role_policy" "lambda" {
22
+ role = aws_iam_role.lambda.name
23
+ policy = jsonencode({
24
+ Statement = [{
25
+ Action = "s3:GetObject"
26
+ Resource = aws_s3_bucket.data.arn
27
+ }]
28
+ })
29
+ }
30
+
31
+ resource "aws_lambda_function" "processor" {
32
+ function_name = "processor"
33
+ role = aws_iam_role.lambda.arn
34
+ handler = "index.handler"
35
+ runtime = "nodejs18.x"
36
+ filename = "lambda.zip"
37
+ }
38
+
39
+ resource "aws_s3_bucket_notification" "trigger" {
40
+ bucket = aws_s3_bucket.data.id
41
+ lambda_function {
42
+ lambda_function_arn = aws_lambda_function.processor.arn
43
+ events = ["s3:ObjectCreated:*"]
44
+ }
45
+ }
46
+
47
+ resource "aws_lambda_permission" "s3" {
48
+ action = "lambda:InvokeFunction"
49
+ function_name = aws_lambda_function.processor.function_name
50
+ principal = "s3.amazonaws.com"
51
+ source_arn = aws_s3_bucket.data.arn
52
+ }
53
+ ```
54
+
55
+ Error:
56
+ ```
57
+ Error: error creating S3 Bucket Notification: Unable to validate
58
+ the following destination configurations: Lambda function ARN
59
+
60
+ The Lambda function doesn't have permission to be invoked by S3 yet
61
+ (the permission resource hasn't been created).
62
+ ```
63
+
64
+ Task: Explain the Terraform dependency graph (DAG), implicit vs
65
+ explicit dependencies, how to debug dependency ordering issues,
66
+ terraform graph command, and depends_on best practices.
67
+
68
+ assertions:
69
+ - type: llm_judge
70
+ criteria: "DAG and implicit dependencies are explained — Terraform builds a directed acyclic graph (DAG) from resource references. Implicit: when resource A uses resource B's attribute, A depends on B. The chain: role → role_policy (references role.name), role → lambda (references role.arn), bucket → notification (references bucket.id), lambda → notification (references lambda.arn). The error: s3_bucket_notification depends on lambda (implicit) but NOT on lambda_permission (no attribute reference). S3 notification tries to verify the Lambda ARN but permission doesn't exist yet"
71
+ weight: 0.35
72
+ description: "DAG explained"
73
+ - type: llm_judge
74
+ criteria: "The fix uses depends_on correctly — add depends_on = [aws_lambda_permission.s3] to the aws_s3_bucket_notification resource. This creates an explicit dependency where no implicit one exists. depends_on is needed because the notification resource doesn't reference any attribute of the permission resource, but the permission must exist for the notification to succeed. terraform graph: visualize dependencies with terraform graph | dot -Tsvg > graph.svg. Look for missing edges that represent real-world dependencies"
75
+ weight: 0.35
76
+ description: "Fix with depends_on"
77
+ - type: llm_judge
78
+ criteria: "depends_on best practices are covered — use depends_on sparingly: prefer implicit dependencies (reference attributes). depends_on forces sequential creation (reduces parallelism). Common scenarios needing depends_on: IAM permissions before resources that need them, DNS records before health checks, network resources before resources placed in them (when ID isn't directly referenced). Anti-pattern: depends_on everywhere 'just in case' — slows down apply. Use terraform graph to verify dependency order before adding depends_on. Module-level depends_on: depends_on on module blocks waits for entire module to complete"
79
+ weight: 0.30
80
+ description: "Best practices"
@@ -0,0 +1,66 @@
1
+ meta:
2
+ id: intermediate-debugging-shift
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Combined intermediate shift — handle module errors, state corruption, and lifecycle issues during a busy infrastructure day"
7
+ tags: [Terraform, troubleshooting, combined, shift-simulation, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Three issues hit your team today:
13
+
14
+ Issue 1 — Module version conflict:
15
+ ```
16
+ $ terraform init -upgrade
17
+
18
+ Error: Failed to query available provider packages
19
+
20
+ Module "vpc" (source: terraform-aws-modules/vpc/aws, version 5.5.0)
21
+ requires aws provider >= 5.30.0, but the root module constrains
22
+ aws to ~> 4.0.
23
+ ```
24
+ The VPC module was upgraded but the root module still pins an old
25
+ provider version.
26
+
27
+ Issue 2 — State file corruption:
28
+ ```
29
+ $ terraform plan
30
+
31
+ Error: Failed to load state: unsupported state file format
32
+
33
+ The state file could not be loaded. Terraform detected that the
34
+ state file is not a supported format.
35
+ ```
36
+ Someone manually edited the state file and introduced a JSON syntax
37
+ error.
38
+
39
+ Issue 3 — Unexpected resource replacement:
40
+ ```
41
+ $ terraform plan
42
+
43
+ # aws_db_instance.main must be replaced
44
+ -/+ resource "aws_db_instance" "main" {
45
+ ~ engine_version = "14.9" -> "14.11" # forces replacement
46
+ }
47
+ ```
48
+ Updating the PostgreSQL minor version triggers a full database
49
+ replacement (destroy + create) instead of an in-place upgrade!
50
+
51
+ Task: Diagnose and resolve all three issues with proper explanations
52
+ and preventive measures.
53
+
54
+ assertions:
55
+ - type: llm_judge
56
+ criteria: "Issue 1 (provider version conflict) is resolved — the module requires aws >= 5.30.0 but root constrains to ~> 4.0 (allows 4.x only). Fix options: (1) update root provider constraint to ~> 5.0 (breaking changes between v4 and v5 — review changelog), (2) pin module to an older version compatible with aws ~> 4.0, (3) gradually migrate by testing with aws ~> 5.0 in dev first. Prevention: use version ranges that allow updates (~> 5.0 not = 5.5.0), test module upgrades in non-prod first, terraform init -upgrade in CI to catch conflicts early"
57
+ weight: 0.35
58
+ description: "Version conflict"
59
+ - type: llm_judge
60
+ criteria: "Issue 2 (state corruption) is resolved — state file is JSON, manual edits can break it. Recovery: (1) if using S3 backend with versioning: restore previous version from S3 version history. (2) terraform state pull from backup. (3) If no backup: terraform import all resources again (last resort). Prevention: NEVER manually edit state files — use terraform state mv/rm/import commands. Enable S3 versioning on state bucket. Set up automated state backups. Use DynamoDB locking to prevent concurrent writes"
61
+ weight: 0.35
62
+ description: "State corruption"
63
+ - type: llm_judge
64
+ criteria: "Issue 3 (unexpected replacement) is resolved — some RDS parameter changes force replacement instead of in-place modification. The engine_version change: check AWS provider docs for which attributes force replacement. Fix options: (1) use allow_major_version_upgrade or apply_immediately for in-place upgrades, (2) check if the provider version has a bug (some versions incorrectly force replacement), (3) use lifecycle { ignore_changes = [engine_version] } and manage upgrades outside Terraform. Prevention: always review plan for -/+ changes, test infrastructure changes in dev before prod, pin exact engine versions and upgrade deliberately"
65
+ weight: 0.30
66
+ description: "Unexpected replacement"
@@ -0,0 +1,51 @@
1
+ meta:
2
+ id: lifecycle-rules
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Use lifecycle meta-arguments — configure create_before_destroy, prevent_destroy, ignore_changes, and replace_triggered_by for safe resource management"
7
+ tags: [Terraform, lifecycle, create-before-destroy, prevent-destroy, ignore-changes, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Three lifecycle issues in your infrastructure:
13
+
14
+ Issue 1 — Zero-downtime deployment:
15
+ Changing the launch template for an ASG causes recreation. During the
16
+ gap between destroy and create, no instances serve traffic:
17
+ ```
18
+ -/+ aws_launch_template.web (forces replacement)
19
+ ```
20
+
21
+ Issue 2 — Accidental database deletion:
22
+ A developer runs terraform destroy targeting a specific module but
23
+ accidentally includes the RDS instance:
24
+ ```
25
+ aws_db_instance.production: Destroying... [id=prod-db]
26
+ aws_db_instance.production: Destruction complete
27
+ ```
28
+
29
+ Issue 3 — Auto-scaling interference:
30
+ Terraform keeps resetting the ASG desired_capacity back to 2, undoing
31
+ auto-scaling that scaled to 5 during peak traffic:
32
+ ```
33
+ ~ desired_capacity = 5 -> 2
34
+ ```
35
+
36
+ Task: Explain all lifecycle meta-arguments, when to use each,
37
+ common pitfalls, and real-world patterns for safe resource management.
38
+
39
+ assertions:
40
+ - type: llm_judge
41
+ criteria: "create_before_destroy is explained — lifecycle { create_before_destroy = true }: creates the new resource before destroying the old one. Fixes Issue 1: new launch template created first, ASG updated to use it, then old template destroyed. Use for: resources that must have zero downtime (load balancers, launch templates, security groups). Pitfall: some resources have unique constraints (names must be unique) — use name_prefix instead of name to allow both to exist simultaneously. Not all resources support this — some have global uniqueness requirements"
42
+ weight: 0.35
43
+ description: "create_before_destroy"
44
+ - type: llm_judge
45
+ criteria: "prevent_destroy and ignore_changes are explained — prevent_destroy = true: Terraform errors if any operation would destroy the resource. Fixes Issue 2: protects databases, S3 buckets, encryption keys. To actually destroy: remove prevent_destroy first, then destroy. ignore_changes = [desired_capacity]: tells Terraform to ignore changes to specific attributes. Fixes Issue 3: auto-scaling can change desired_capacity without Terraform reverting it. Use ignore_changes for: attributes managed by external systems (auto-scaling, external controllers). ignore_changes = all: ignore all attribute changes (resource only managed for creation)"
46
+ weight: 0.35
47
+ description: "prevent and ignore"
48
+ - type: llm_judge
49
+ criteria: "replace_triggered_by and patterns are covered — replace_triggered_by = [aws_ami.latest.id]: force replacement when a different resource changes. Use for: instances that should be recreated when AMI updates. Lifecycle patterns: databases always get prevent_destroy, ASGs get ignore_changes on desired_capacity, stateless resources get create_before_destroy for zero downtime. Pitfall: ignore_changes can mask drift — use sparingly and document why. Lifecycle rules are meta-arguments, not resource arguments — they go in the lifecycle {} block inside the resource"
50
+ weight: 0.30
51
+ description: "Patterns"
@@ -0,0 +1,58 @@
1
+ meta:
2
+ id: locals-and-expressions
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Use locals and expressions effectively — simplify complex configurations with local values, for expressions, conditionals, and built-in functions"
7
+ tags: [Terraform, locals, expressions, functions, conditionals, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your Terraform configuration has duplicated logic everywhere:
13
+
14
+ ```hcl
15
+ resource "aws_instance" "web" {
16
+ tags = {
17
+ Name = "web-${var.environment}-${var.region}"
18
+ Environment = var.environment
19
+ Project = var.project
20
+ ManagedBy = "terraform"
21
+ CostCenter = var.environment == "prod" ? "CC-100" : "CC-200"
22
+ }
23
+ }
24
+
25
+ resource "aws_s3_bucket" "data" {
26
+ tags = {
27
+ Name = "data-${var.environment}-${var.region}"
28
+ Environment = var.environment
29
+ Project = var.project
30
+ ManagedBy = "terraform"
31
+ CostCenter = var.environment == "prod" ? "CC-100" : "CC-200"
32
+ }
33
+ }
34
+
35
+ # Same tags repeated on 20 more resources...
36
+ ```
37
+
38
+ You also need to transform a list of subnet CIDRs into a map keyed
39
+ by availability zone, and conditionally create resources based on
40
+ environment.
41
+
42
+ Task: Explain locals (local values), Terraform expressions (for,
43
+ conditionals, splat), built-in functions (lookup, merge, concat,
44
+ flatten, try), and how to use them to simplify configurations.
45
+
46
+ assertions:
47
+ - type: llm_judge
48
+ criteria: "Locals are explained — locals { common_tags = { Environment = var.environment, Project = var.project, ManagedBy = 'terraform', CostCenter = var.environment == 'prod' ? 'CC-100' : 'CC-200' } }. Reference: tags = merge(local.common_tags, { Name = 'web-server' }). Locals compute values once and reuse them. Use for: common tags, computed names, complex expressions used multiple times. Locals vs variables: variables are inputs from outside, locals are computed inside the configuration. Don't overuse locals — if a value is used once, just inline it"
49
+ weight: 0.35
50
+ description: "Locals"
51
+ - type: llm_judge
52
+ criteria: "Expressions are covered — for expression: [for s in var.subnets : s.cidr] (list), {for s in var.subnets : s.az => s.cidr} (map). Conditional: var.create_vpc ? 1 : 0 with count for conditional resource creation. Splat: aws_instance.web[*].id gets all IDs. Ternary: condition ? true_val : false_val. for with filtering: [for s in var.subnets : s.cidr if s.public]. String templates: 'Hello ${var.name}'. Heredoc: <<-EOT for multi-line strings"
53
+ weight: 0.35
54
+ description: "Expressions"
55
+ - type: llm_judge
56
+ criteria: "Built-in functions are practical — merge(): combine maps (merge(local.common_tags, local.extra_tags)). lookup(): safe map access with default (lookup(var.amis, var.region, 'ami-default')). concat(): join lists. flatten(): flatten nested lists. try(): return first non-error value (try(var.config.setting, 'default')). coalesce(): first non-null value. keys()/values(): extract from maps. length(): collection size. format/formatlist(): string formatting. cidrsubnet(): calculate subnet CIDRs. templatefile(): render template files. Type conversion: toset(), tomap(), tolist(), tonumber(), tostring()"
57
+ weight: 0.30
58
+ description: "Functions"
@@ -0,0 +1,75 @@
1
+ meta:
2
+ id: module-structure
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Design Terraform modules — create reusable module structure, handle input/output contracts, and debug module composition errors"
7
+ tags: [Terraform, modules, reusability, composition, inputs, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your team copies and pastes VPC configuration across 8 environments.
13
+ Every copy has drifted slightly. You're tasked with creating a reusable
14
+ VPC module, but your first attempt has issues:
15
+
16
+ ```
17
+ modules/vpc/
18
+ ├── main.tf
19
+ ├── variables.tf
20
+ └── outputs.tf
21
+ ```
22
+
23
+ ```hcl
24
+ # modules/vpc/main.tf
25
+ resource "aws_vpc" "this" {
26
+ cidr_block = var.cidr_block
27
+ tags = var.tags
28
+ }
29
+
30
+ resource "aws_subnet" "public" {
31
+ count = length(var.public_subnets)
32
+ vpc_id = aws_vpc.this.id
33
+ cidr_block = var.public_subnets[count.index]
34
+ availability_zone = var.azs[count.index]
35
+ }
36
+ ```
37
+
38
+ ```hcl
39
+ # Root module calling it
40
+ module "vpc" {
41
+ source = "./modules/vpc"
42
+ # forgot to pass required variables
43
+ }
44
+
45
+ resource "aws_instance" "web" {
46
+ subnet_id = module.vpc.public_subnet_ids[0]
47
+ }
48
+ ```
49
+
50
+ Errors:
51
+ ```
52
+ Error: Missing required argument
53
+ The argument "cidr_block" is required, but no definition was found.
54
+
55
+ Error: Unsupported attribute
56
+ module.vpc.public_subnet_ids is object with no attribute "public_subnet_ids"
57
+ ```
58
+
59
+ Task: Explain Terraform module design, required vs optional variables
60
+ with defaults, output contracts between modules, module sources
61
+ (local, registry, git), and module composition best practices.
62
+
63
+ assertions:
64
+ - type: llm_judge
65
+ criteria: "Module structure is explained — a module is a directory with .tf files: main.tf (resources), variables.tf (inputs), outputs.tf (exported values), versions.tf (required providers). Modules encapsulate reusable infrastructure. Required variables have no default — callers must provide them. The error: cidr_block has no default in the module, and the root module didn't pass it. Fix: module 'vpc' { source = './modules/vpc', cidr_block = '10.0.0.0/16', public_subnets = [...], azs = [...], tags = {...} }. Module outputs must be explicitly declared — the second error is because public_subnet_ids wasn't defined in outputs.tf"
66
+ weight: 0.35
67
+ description: "Module structure"
68
+ - type: llm_judge
69
+ criteria: "Module sources are covered — local: source = './modules/vpc'. Terraform Registry: source = 'terraform-aws-modules/vpc/aws', version = '~> 5.0'. Git: source = 'git::https://github.com/org/modules.git//vpc?ref=v1.0.0'. S3: source = 's3::https://bucket.s3.amazonaws.com/modules/vpc.zip'. Best practice: use versioned sources (git tags, registry versions) for stability. Local modules for project-specific code. Registry modules for common patterns (VPC, EKS, RDS). Pin versions: never use unversioned git sources in production"
70
+ weight: 0.35
71
+ description: "Module sources"
72
+ - type: llm_judge
73
+ criteria: "Composition best practices are practical — module contract: clearly document required vs optional inputs with descriptions. Use validation blocks on variables. Output everything consumers might need. Keep modules focused (one concern per module). Avoid deeply nested modules (max 2-3 levels). Module composition: root module calls multiple child modules, passes outputs between them. Example: module.vpc.vpc_id → module.eks.vpc_id. Don't put provider configuration in modules — pass it from root. Use for_each on modules to create multiple instances"
74
+ weight: 0.30
75
+ description: "Best practices"
@@ -0,0 +1,64 @@
1
+ meta:
2
+ id: provisioner-pitfalls
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Avoid provisioner pitfalls — understand why provisioners are a last resort, debug connection failures, and use better alternatives"
7
+ tags: [Terraform, provisioners, remote-exec, local-exec, user-data, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ A developer uses remote-exec to install software on EC2 instances:
13
+
14
+ ```hcl
15
+ resource "aws_instance" "web" {
16
+ ami = "ami-0c55b159cbfafe1f0"
17
+ instance_type = "t3.micro"
18
+ key_name = "deploy-key"
19
+
20
+ provisioner "remote-exec" {
21
+ inline = [
22
+ "sudo apt-get update",
23
+ "sudo apt-get install -y nginx",
24
+ "sudo systemctl enable nginx"
25
+ ]
26
+ connection {
27
+ type = "ssh"
28
+ user = "ubuntu"
29
+ private_key = file("~/.ssh/deploy-key.pem")
30
+ host = self.public_ip
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Problems encountered:
37
+ ```
38
+ Error: timeout - last error: dial tcp 54.1.2.3:22:
39
+ connect: connection refused
40
+
41
+ Error: remote-exec provisioner error
42
+ Status: 100 (apt-get returned non-zero)
43
+ ```
44
+
45
+ The instance was created but the provisioner failed. Now the resource
46
+ is tainted and will be destroyed and recreated on next apply.
47
+
48
+ Task: Explain provisioners (local-exec, remote-exec, file), why
49
+ they're problematic, connection debugging, taint behavior on failure,
50
+ and better alternatives (user_data, Packer, Ansible).
51
+
52
+ assertions:
53
+ - type: llm_judge
54
+ criteria: "Provisioner types and problems are explained — local-exec: runs command on the machine running Terraform. remote-exec: runs command on the created resource via SSH/WinRM. file: copies files to the resource. Problems: (1) not declarative — can't detect drift, (2) failure taints the resource (forces recreation), (3) non-idempotent (running twice may break), (4) SSH connection is fragile (timing, security groups, key issues), (5) Terraform can't model what provisioners do in state. The connection refused error: instance not ready yet when SSH attempted, or security group doesn't allow port 22"
55
+ weight: 0.35
56
+ description: "Provisioner problems"
57
+ - type: llm_judge
58
+ criteria: "Debugging and taint behavior are covered — connection debugging: (1) check security group allows SSH from Terraform runner, (2) instance may not be ready (cloud-init still running), (3) wrong SSH user for AMI (ubuntu vs ec2-user vs admin), (4) private key permissions or format issues. Taint on failure: when provisioner fails, Terraform marks the resource as tainted. Next apply: destroy and recreate the entire instance. This is wasteful and disruptive. on_failure = continue skips the error (resource not tainted but may be misconfigured). on_failure = fail (default) taints the resource"
59
+ weight: 0.35
60
+ description: "Debugging and taint"
61
+ - type: llm_judge
62
+ criteria: "Better alternatives are recommended — (1) user_data: cloud-init script runs on first boot, no SSH needed, retries handled by OS, idempotent with proper scripting. (2) Packer: build pre-configured AMIs with all software installed, Terraform just launches them. (3) Ansible/Chef/Puppet: proper configuration management tools run after Terraform creates infrastructure. (4) AWS Systems Manager Run Command: no SSH needed, agents already on Amazon AMIs. Best practice: Terraform creates infrastructure, other tools configure it. Use provisioners only as absolute last resort"
63
+ weight: 0.30
64
+ description: "Alternatives"
@@ -0,0 +1,55 @@
1
+ meta:
2
+ id: remote-state-backend
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Configure remote state backend — set up S3+DynamoDB locking, migrate from local to remote state, and troubleshoot backend errors"
7
+ tags: [Terraform, state, backend, S3, DynamoDB, locking, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your team has been using local state files. Problems are mounting:
13
+ - Two engineers ran apply simultaneously, corrupting the state
14
+ - A laptop crash lost the state file for the staging environment
15
+ - No one knows who changed what or when
16
+
17
+ You're migrating to S3 backend with DynamoDB locking. During migration:
18
+
19
+ ```
20
+ $ terraform init -migrate-state
21
+
22
+ Initializing the backend...
23
+ Do you want to copy existing state to the new backend?
24
+ Enter a value: yes
25
+
26
+ Error: Failed to save state
27
+
28
+ Error saving state: failed to upload state: AccessDenied:
29
+ Access Denied
30
+ ```
31
+
32
+ After fixing permissions, another error:
33
+ ```
34
+ Error: Error acquiring the state lock
35
+
36
+ Error message: ConditionalCheckFailedException
37
+ ```
38
+
39
+ Task: Explain remote state setup (S3 + DynamoDB), state migration
40
+ from local to remote, state locking mechanics, backend configuration
41
+ options, and how to share state across teams using terraform_remote_state.
42
+
43
+ assertions:
44
+ - type: llm_judge
45
+ criteria: "S3 backend setup is complete — backend configuration: bucket (S3 bucket name), key (state file path), region, encrypt = true (SSE), dynamodb_table (for locking). Bootstrap: create S3 bucket with versioning enabled, create DynamoDB table with LockID partition key (String). The AccessDenied error: IAM policy needs s3:GetObject, s3:PutObject, s3:ListBucket on the bucket, plus dynamodb:GetItem, dynamodb:PutItem, dynamodb:DeleteItem on the lock table. State migration: terraform init -migrate-state copies local state to S3"
46
+ weight: 0.35
47
+ description: "Backend setup"
48
+ - type: llm_judge
49
+ criteria: "State locking mechanics are explained — DynamoDB locking: before any state-modifying operation, Terraform writes a lock record to DynamoDB with a unique ID, who holds it, and operation type. If lock exists, operation fails with ConditionalCheckFailedException. Lock released after operation completes. Stale locks: if process crashes, lock remains. Fix: terraform force-unlock <LOCK_ID> (only if holder process is confirmed dead). S3 versioning: enables state recovery if corruption occurs. terraform state pull to download, terraform state push to upload manually"
50
+ weight: 0.35
51
+ description: "Locking mechanics"
52
+ - type: llm_judge
53
+ criteria: "Cross-team state sharing is covered — terraform_remote_state data source reads another team's state outputs: data 'terraform_remote_state' 'network' { backend = 's3', config = { bucket = '...', key = 'network/terraform.tfstate' } }. Reference: data.terraform_remote_state.network.outputs.vpc_id. State file organization: separate state per environment and per team/service to limit blast radius. Pattern: s3://state-bucket/<env>/<service>/terraform.tfstate. IAM: restrict which teams can read/write which state files using S3 bucket policies"
54
+ weight: 0.30
55
+ description: "State sharing"
@@ -0,0 +1,55 @@
1
+ meta:
2
+ id: terraform-import
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Import existing resources into Terraform — bring console-created infrastructure under IaC management without recreation"
7
+ tags: [Terraform, import, existing-resources, migration, IaC-adoption, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your company has 50 AWS resources created via console that need to
13
+ come under Terraform management. You start importing:
14
+
15
+ ```
16
+ $ terraform import aws_instance.legacy i-0abc123def456
17
+
18
+ aws_instance.legacy: Importing from ID "i-0abc123def456"...
19
+ aws_instance.legacy: Import prepared!
20
+ Imported aws_instance.legacy
21
+
22
+ $ terraform plan
23
+
24
+ # aws_instance.legacy will be updated in-place
25
+ ~ resource "aws_instance" "legacy" {
26
+ ~ ami = "ami-current123" -> "ami-wrong456"
27
+ ~ instance_type = "t3.large" -> "t3.micro"
28
+ ~ tags = {
29
+ - "ManagedBy" = "console" -> null
30
+ + "Environment" = "prod"
31
+ }
32
+ # ... 20 more attribute changes
33
+ }
34
+ ```
35
+
36
+ The plan shows changes because your .tf file doesn't match the
37
+ actual resource configuration!
38
+
39
+ Task: Explain terraform import workflow, how to write matching
40
+ configuration after import, the new import block syntax (Terraform 1.5+),
41
+ bulk import strategies, and common import pitfalls.
42
+
43
+ assertions:
44
+ - type: llm_judge
45
+ criteria: "Import workflow is explained — (1) write a resource block in .tf file, (2) run terraform import <address> <id>, (3) run terraform plan to see differences, (4) update .tf file to match actual configuration until plan shows no changes. The plan shows changes because the .tf config was written with incorrect values — must match reality exactly. Use terraform state show aws_instance.legacy to see imported attributes and copy them to .tf file. Iterate: import → plan → fix config → plan again until clean"
46
+ weight: 0.35
47
+ description: "Import workflow"
48
+ - type: llm_judge
49
+ criteria: "Import block syntax (1.5+) is covered — import { to = aws_instance.legacy, id = 'i-0abc123def456' }. Benefits over CLI import: (1) can be code-reviewed in PRs, (2) terraform plan -generate-config-out=generated.tf generates matching configuration automatically, (3) supports for_each for bulk imports. The generated config is a starting point — review and clean up. Import blocks are removed after successful apply. This is the recommended approach for Terraform 1.5+"
50
+ weight: 0.35
51
+ description: "Import blocks"
52
+ - type: llm_judge
53
+ criteria: "Bulk import and pitfalls are practical — bulk strategy: (1) inventory all resources (AWS Config, resource explorer), (2) write import blocks for all, (3) generate config, (4) review and customize, (5) apply. Pitfalls: (1) some resources don't support import (check provider docs), (2) imported resources may reference other non-imported resources, (3) secrets in imported state (passwords, keys) — rotate after import, (4) complex resources (EKS, RDS) may need manual config adjustment. Tools: terraformer for auto-generating both config and import commands from existing cloud infrastructure"
54
+ weight: 0.30
55
+ description: "Bulk import"
@@ -0,0 +1,51 @@
1
+ meta:
2
+ id: workspace-management
3
+ level: 2
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Manage Terraform workspaces — understand workspace isolation, limitations, and when to use workspaces vs directory-based environments"
7
+ tags: [Terraform, workspaces, environments, isolation, multi-env, intermediate]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Your team uses workspaces for environment separation:
13
+
14
+ ```
15
+ $ terraform workspace list
16
+ default
17
+ dev
18
+ staging
19
+ * prod
20
+
21
+ $ terraform workspace select staging
22
+ Switched to workspace "staging".
23
+
24
+ $ terraform plan
25
+ # Accidentally planning against staging with prod-sized resources
26
+ # because terraform.tfvars has prod values!
27
+ ```
28
+
29
+ A developer selected the wrong workspace and applied prod-sized
30
+ (expensive) resources to staging. Monthly bill spiked by $5K.
31
+
32
+ Another issue: you can't use different provider versions for dev
33
+ vs prod because all workspaces share the same root module.
34
+
35
+ Task: Explain Terraform workspaces, their proper use cases,
36
+ limitations, the terraform.workspace variable, and compare
37
+ workspaces vs directory-based environment separation.
38
+
39
+ assertions:
40
+ - type: llm_judge
41
+ criteria: "Workspaces are explained — workspaces create separate state files within the same backend. terraform workspace new dev creates a new workspace. State stored at: env:/dev/terraform.tfstate. terraform.workspace variable returns current workspace name — use for conditional logic: locals { instance_type = terraform.workspace == 'prod' ? 't3.large' : 't3.micro' }. Workspaces share the same code, providers, and backend config. The accident: wrong workspace selected, wrong tfvars applied because workspaces don't enforce which tfvars to use"
42
+ weight: 0.35
43
+ description: "Workspaces explained"
44
+ - type: llm_judge
45
+ criteria: "Limitations are clearly stated — workspaces are NOT ideal for environment separation because: (1) same code for all environments (can't have different provider versions), (2) easy to apply to wrong workspace (no guardrails), (3) shared backend makes cross-environment blast radius larger, (4) terraform.workspace checks scattered through code make it hard to read. Proper use cases: testing infrastructure changes (ephemeral workspaces), feature branch environments, temporary environments for demos. NOT for: long-lived dev/staging/prod separation"
46
+ weight: 0.35
47
+ description: "Limitations"
48
+ - type: llm_judge
49
+ criteria: "Directory-based alternative is recommended — separate directories per environment: environments/dev/, environments/staging/, environments/prod/. Each has its own backend config, tfvars, and can pin different module/provider versions. Benefits: complete isolation, clear boundaries, can't accidentally apply to wrong environment, independent state. Shared logic through modules: environments call common modules with environment-specific variables. Terraform Cloud workspaces are different from CLI workspaces — they provide true isolation with separate runs, variables, and permissions"
50
+ weight: 0.30
51
+ description: "Directory alternative"
@@ -0,0 +1,63 @@
1
+ meta:
2
+ id: advanced-debugging-shift
3
+ level: 3
4
+ course: terraform-infrastructure-setup
5
+ type: output
6
+ description: "Combined advanced shift — handle state surgery, cross-account issues, and drift remediation in a single complex incident"
7
+ tags: [Terraform, troubleshooting, combined, shift-simulation, advanced]
8
+
9
+ state: {}
10
+
11
+ trigger: |
12
+ Three interconnected issues escalate during your on-call shift:
13
+
14
+ Issue 1 — State divergence after team split:
15
+ Team A split their resources from the shared state last week using
16
+ state mv. But they missed moving aws_iam_policy.shared, which is
17
+ now in both state files:
18
+ ```
19
+ Team A state: contains aws_iam_policy.shared
20
+ Team B state: contains aws_iam_policy.shared (original)
21
+
22
+ Team A runs apply → modifies the policy
23
+ Team B runs apply → overwrites Team A's changes
24
+ ```
25
+ The same resource is managed by two state files!
26
+
27
+ Issue 2 — Cross-account module failure:
28
+ A module deployed to the DR account references resources in the
29
+ primary account via terraform_remote_state:
30
+ ```
31
+ Error: error reading S3 bucket: AccessDenied
32
+
33
+ The DR account's Terraform role doesn't have cross-account
34
+ permission to read the primary account's state bucket.
35
+ ```
36
+
37
+ Issue 3 — Drift from security incident response:
38
+ The security team disabled public access on 15 S3 buckets during
39
+ an incident. Now terraform plan shows 15 buckets will have public
40
+ access re-enabled (reverting the security fix):
41
+ ```
42
+ ~ resource "aws_s3_bucket_public_access_block" "data" {
43
+ ~ block_public_acls = true -> false
44
+ ~ block_public_policy = true -> false
45
+ }
46
+ ```
47
+
48
+ Task: Resolve all three issues with proper procedures and
49
+ establish preventive measures.
50
+
51
+ assertions:
52
+ - type: llm_judge
53
+ criteria: "Issue 1 (dual-managed resource) is resolved — a resource in two state files is extremely dangerous: both try to manage it, last writer wins. Fix: (1) immediately terraform state rm aws_iam_policy.shared from Team A's state (they don't own it). (2) If Team A needs it: create a separate policy for Team A. (3) If shared: move to a shared-infrastructure state that both teams read via terraform_remote_state. Prevention: during state splits, verify no resource appears in multiple states using terraform state list on all states. Use terraform state list | sort to compare"
54
+ weight: 0.35
55
+ description: "Dual-managed resource"
56
+ - type: llm_judge
57
+ criteria: "Issue 2 (cross-account state access) is resolved — the DR account's Terraform role needs S3 read permissions on the primary account's state bucket. Fix: (1) add S3 bucket policy on primary's state bucket allowing DR account's role to s3:GetObject, (2) or use assume_role in the terraform_remote_state data source to assume a role in the primary account. Alternative: use Terraform Cloud with cross-workspace state sharing (no S3 permissions needed). Prevention: when setting up multi-account, plan state access patterns upfront and document IAM requirements"
58
+ weight: 0.35
59
+ description: "Cross-account access"
60
+ - type: llm_judge
61
+ criteria: "Issue 3 (security drift) is resolved — the security fix was correct, Terraform code is wrong. Fix: update all 15 S3 bucket configurations to block_public_acls = true, block_public_policy = true. This aligns code with the desired secure state. Do NOT apply the current plan (it would revert the security fix). Workflow: (1) update .tf files, (2) run plan to verify no changes, (3) commit code. Prevention: security changes should always be reflected in Terraform code. Establish a process: security team opens PR with Terraform changes, not just console modifications"
62
+ weight: 0.30
63
+ description: "Security drift"