From 9e813d83a4e3f5cb1756400fd17fe92d0d4812d3 Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sat, 31 Oct 2026 15:15:21 -0700 Subject: [PATCH 1/4] Manage operationcode.org zone and kept records in Terraform via import blocks Co-Authored-By: Claude Sonnet 5.5 --- terraform/route53.tf | 375 ++++++++++++++++++++++++++++++++++- terraform/route53_imports.tf | 177 +++++++++++++++++ 2 files changed, 543 insertions(+), 9 deletions(-) create mode 100644 terraform/route53_imports.tf diff --git a/terraform/route53.tf b/terraform/route53.tf index 6f83346..d959138 100644 --- a/terraform/route53.tf +++ b/terraform/route53.tf @@ -1,11 +1,16 @@ -# Reference existing Route53 hosted zone -data "aws_route53_zone" "operationcode" { - name = "operationcode.org." +# Hosted zone for operationcode.org (imported; never destroy) +resource "aws_route53_zone" "operationcode" { + name = "operationcode.org" + comment = "" + + lifecycle { + prevent_destroy = true + } } # MX record for SES email receiving resource "aws_route53_record" "coders_mx" { - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "coders.operationcode.org" type = "MX" ttl = 300 @@ -14,7 +19,7 @@ resource "aws_route53_record" "coders_mx" { # SPF record for email authentication resource "aws_route53_record" "coders_spf" { - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "coders.operationcode.org" type = "TXT" ttl = 300 @@ -27,7 +32,7 @@ resource "aws_route53_record" "coders_spf" { # DKIM records (3 tokens from SES) resource "aws_route53_record" "coders_dkim" { count = 3 - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "${module.ses_email_forwarder.ses_dkim_tokens[count.index]}._domainkey.coders.operationcode.org" type = "CNAME" ttl = 300 @@ -36,7 +41,7 @@ resource "aws_route53_record" "coders_dkim" { # Custom MAIL FROM domain - MX record resource "aws_route53_record" "coders_bounce_mx" { - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "bounce.coders.operationcode.org" type = "MX" ttl = 300 @@ -45,7 +50,7 @@ resource "aws_route53_record" "coders_bounce_mx" { # Custom MAIL FROM domain - SPF record resource "aws_route53_record" "coders_bounce_spf" { - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "bounce.coders.operationcode.org" type = "TXT" ttl = 300 @@ -57,9 +62,361 @@ resource "aws_route53_record" "coders_bounce_spf" { # adkim=r, aspf=r: Relaxed alignment (allows subdomain alignment like bounce.coders.operationcode.org) # pct=100: Apply policy to 100% of failing messages resource "aws_route53_record" "coders_dmarc" { - zone_id = data.aws_route53_zone.operationcode.zone_id + zone_id = aws_route53_zone.operationcode.zone_id name = "_dmarc.coders.operationcode.org" type = "TXT" ttl = 300 records = ["v=DMARC1; p=quarantine; adkim=r; aspf=r; pct=100"] } + +# Vercel: apex website +resource "aws_route53_record" "apex_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "A" + ttl = 300 + records = ["76.76.21.21"] +} + +# CA policy: restricts wildcard issuance to Amazon, reports to tech@ +resource "aws_route53_record" "apex_caa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "CAA" + ttl = 300 + records = [ + "0 issuewild \"amazontrust.com\"", + "0 issuewild \"amazon.com\"", + "0 iodef \"mailto:tech@operationcode.org\"", + ] +} + +# Google Workspace mail +resource "aws_route53_record" "apex_mx" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "MX" + ttl = 3600 + records = [ + "1 ASPMX.L.GOOGLE.COM.", + "5 ALT1.ASPMX.L.GOOGLE.COM.", + "5 ALT2.ASPMX.L.GOOGLE.COM.", + "10 ALT3.ASPMX.L.GOOGLE.COM.", + "10 ALT4.ASPMX.L.GOOGLE.COM.", + ] +} + +# SPF (Google, Mailgun, Mandrill) and Google site verification. INVESTIGATE: trim SPF once live senders are confirmed +resource "aws_route53_record" "apex_txt" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "TXT" + ttl = 3600 + records = [ + "v=spf1 a include:_spf.google.com include:mailgun.org include:spf.mandrillapp.com ~all", + "google-site-verification=XFeRZYknCzfwk5LTAuVDKf6T99S-DGafkhOfUlFXwFI", + "google-site-verification=s2E7tZyPlszu8LHIcYlRT8s6oq6hSoGQ70gMXKP08aE", + ] +} + +# SendGrid account 5672389 link/open tracking. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_link_tracking" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "5672389.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["sendgrid.net."] +} + +# ACM DNS validation for the in-use wildcard certificate (us-east-2, ALB) +resource "aws_route53_record" "acm_validation_apex" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "_62bdef8daffb0b85a77bd7a7c4be6e36.operationcode.org" + type = "CNAME" + ttl = 300 + records = ["_b1d3619a779f40c956b5f204733bbf79.acm-validations.aws"] +} + +# DMARC policy for the apex domain (monitoring only, p=none) +resource "aws_route53_record" "apex_dmarc" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "_dmarc.operationcode.org" + type = "TXT" + ttl = 60 + records = ["v=DMARC1; p=none;"] +} + +# Mailchimp DKIM. INVESTIGATE: confirm account is active +resource "aws_route53_record" "mailchimp_dkim_k2" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "k2._domainkey.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["dkim2.mcsv.net"] +} + +# Mailchimp DKIM. INVESTIGATE: confirm account is active +resource "aws_route53_record" "mailchimp_dkim_k3" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "k3._domainkey.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["dkim3.mcsv.net"] +} + +# Mandrill DKIM (1024-bit key). INVESTIGATE: confirm account is active +resource "aws_route53_record" "mandrill_dkim" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "mandrill._domainkey.operationcode.org" + type = "TXT" + ttl = 3600 + records = ["v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrLHiExVd55zd/IQ/J/mRwSRMAocV/hMB3jXwaHH36d9NaVynQFYV8NaWi69c1veUtRzGt7yAioXqLj7Z4TeEUoOLgrKsn8YnckGs9i3B3tVFB+Ch/4mPhXWiNfNdynHWBcPcbJ8kjEQ2U8y78dHZj1YeRXXVvWob2OaKynO8/lQIDAQAB;"] +} + +# SendGrid DKIM. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_dkim_s1" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "s1._domainkey.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["s1.domainkey.u5672389.wl140.sendgrid.net."] +} + +# SendGrid DKIM. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_dkim_s2" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "s2._domainkey.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["s2.domainkey.u5672389.wl140.sendgrid.net."] +} + +# Legacy Vercel (ZEIT Now) domain verification. INVESTIGATE: likely safe to delete +resource "aws_route53_record" "vercel_now_verification" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "_now.operationcode.org" + type = "TXT" + ttl = 3600 + records = ["Qmd8XawRvuECtFLQm8SytbgcW2PV2jthtfMy7ujLnTN2gL"] +} + +# ALB alias for the production backend API (ECS python_backend_prod) +resource "aws_route53_record" "api_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.operationcode.org" + type = "A" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# ALB alias for the production backend API (ECS python_backend_prod) +resource "aws_route53_record" "api_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# Old community host on DigitalOcean. INVESTIGATE: likely delete +resource "aws_route53_record" "community_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "community.operationcode.org" + type = "A" + ttl = 600 + records = ["192.241.185.68"] +} + +# Kibana on the services host. INVESTIGATE: likely dead +resource "aws_route53_record" "kibana" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "kibana.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["services.operationcode.org."] +} + +# Mautic on the services host. INVESTIGATE: likely dead +resource "aws_route53_record" "mautic" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "mautic.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["services.operationcode.org."] +} + +# SendGrid link branding. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_link" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "link.notify.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["sendgrid.net."] +} + +# SendGrid return-path. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_mail" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "mail.notify.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["u5672389.wl140.sendgrid.net."] +} + +# SendGrid sending IP. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_o1" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "o1.notify.operationcode.org" + type = "A" + ttl = 3600 + records = ["168.245.5.176"] +} + +# ALB alias for pybot (ECS pybot_prod) +resource "aws_route53_record" "pybot_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "pybot.operationcode.org" + type = "A" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# ALB alias for pybot (ECS pybot_prod) +resource "aws_route53_record" "pybot_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "pybot.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# ALB alias; listener rule redirects to https://www.operationcode.org +resource "aws_route53_record" "resources_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "resources.operationcode.org" + type = "A" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# ALB alias; listener rule redirects to https://www.operationcode.org +resource "aws_route53_record" "resources_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "resources.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = true + } +} + +# Cloudways host for services (unknown app). INVESTIGATE: check Cloudways account +resource "aws_route53_record" "services_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "services.operationcode.org" + type = "A" + ttl = 60 + records = ["174.138.92.215"] +} + +# DigitalOcean NFS host. INVESTIGATE: likely dead +resource "aws_route53_record" "services_nfs_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "nfs.services.operationcode.org" + type = "A" + ttl = 60 + records = ["138.197.94.99"] +} + +# Slack slash commands on the services host. INVESTIGATE: check Slack app request URLs +resource "aws_route53_record" "slash_commands" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "slash-commands.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["services.operationcode.org."] +} + +# ACM DNS validation for *.staging (same in-use wildcard certificate) +resource "aws_route53_record" "acm_validation_staging" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "_38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org" + type = "CNAME" + ttl = 300 + records = ["_cacb57a7608af0dcc34e1c19cef298f1.vhzmpjdqfx.acm-validations.aws."] +} + +# ALB alias for the staging backend API (ECS python_backend_staging) +resource "aws_route53_record" "api_staging_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.staging.operationcode.org" + type = "A" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# ALB alias for the staging backend API (ECS python_backend_staging) +resource "aws_route53_record" "api_staging_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.staging.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." + zone_id = "Z3AADJGX6KTTL2" + evaluate_target_health = false + } +} + +# Vercel: Storybook +resource "aws_route53_record" "storybook" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "storybook.operationcode.org" + type = "CNAME" + ttl = 600 + records = ["cname.vercel-dns.com."] +} + +# Test host on the services host. INVESTIGATE: check Cloudways account +resource "aws_route53_record" "test" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "test.operationcode.org" + type = "CNAME" + ttl = 60 + records = ["services.operationcode.org."] +} + +# Vercel: website +resource "aws_route53_record" "www_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "www.operationcode.org" + type = "A" + ttl = 300 + records = ["76.76.21.21"] +} diff --git a/terraform/route53_imports.tf b/terraform/route53_imports.tf new file mode 100644 index 0000000..aca0c1e --- /dev/null +++ b/terraform/route53_imports.tf @@ -0,0 +1,177 @@ +# Import blocks for the operationcode.org zone and its pre-existing records. +# They can be removed after the first successful apply. + +import { + to = aws_route53_zone.operationcode + id = "Z08173331NAK6ZJUBZENQ" +} + +import { + to = aws_route53_record.apex_a + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_A" +} + +import { + to = aws_route53_record.apex_caa + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_CAA" +} + +import { + to = aws_route53_record.apex_mx + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_MX" +} + +import { + to = aws_route53_record.apex_txt + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_TXT" +} + +import { + to = aws_route53_record.sendgrid_link_tracking + id = "Z08173331NAK6ZJUBZENQ_5672389.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.acm_validation_apex + id = "Z08173331NAK6ZJUBZENQ__62bdef8daffb0b85a77bd7a7c4be6e36.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.apex_dmarc + id = "Z08173331NAK6ZJUBZENQ__dmarc.operationcode.org_TXT" +} + +import { + to = aws_route53_record.mailchimp_dkim_k2 + id = "Z08173331NAK6ZJUBZENQ_k2._domainkey.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.mailchimp_dkim_k3 + id = "Z08173331NAK6ZJUBZENQ_k3._domainkey.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.mandrill_dkim + id = "Z08173331NAK6ZJUBZENQ_mandrill._domainkey.operationcode.org_TXT" +} + +import { + to = aws_route53_record.sendgrid_dkim_s1 + id = "Z08173331NAK6ZJUBZENQ_s1._domainkey.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_dkim_s2 + id = "Z08173331NAK6ZJUBZENQ_s2._domainkey.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.vercel_now_verification + id = "Z08173331NAK6ZJUBZENQ__now.operationcode.org_TXT" +} + +import { + to = aws_route53_record.api_a + id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_A" +} + +import { + to = aws_route53_record.api_aaaa + id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.community_a + id = "Z08173331NAK6ZJUBZENQ_community.operationcode.org_A" +} + +import { + to = aws_route53_record.kibana + id = "Z08173331NAK6ZJUBZENQ_kibana.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.mautic + id = "Z08173331NAK6ZJUBZENQ_mautic.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_notify_link + id = "Z08173331NAK6ZJUBZENQ_link.notify.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_notify_mail + id = "Z08173331NAK6ZJUBZENQ_mail.notify.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_notify_o1 + id = "Z08173331NAK6ZJUBZENQ_o1.notify.operationcode.org_A" +} + +import { + to = aws_route53_record.pybot_a + id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_A" +} + +import { + to = aws_route53_record.pybot_aaaa + id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.resources_a + id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_A" +} + +import { + to = aws_route53_record.resources_aaaa + id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.services_a + id = "Z08173331NAK6ZJUBZENQ_services.operationcode.org_A" +} + +import { + to = aws_route53_record.services_nfs_a + id = "Z08173331NAK6ZJUBZENQ_nfs.services.operationcode.org_A" +} + +import { + to = aws_route53_record.slash_commands + id = "Z08173331NAK6ZJUBZENQ_slash-commands.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.acm_validation_staging + id = "Z08173331NAK6ZJUBZENQ__38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.api_staging_a + id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_A" +} + +import { + to = aws_route53_record.api_staging_aaaa + id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.storybook + id = "Z08173331NAK6ZJUBZENQ_storybook.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.test + id = "Z08173331NAK6ZJUBZENQ_test.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.www_a + id = "Z08173331NAK6ZJUBZENQ_www.operationcode.org_A" +} From 8d56c48747739e79da6e578b1c4b832b45098a7a Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sun, 1 Nov 2026 07:28:31 -0800 Subject: [PATCH 2/4] Consolidate operationcode.org DNS into dns_operationcode_org.tf, use ALB references Co-Authored-By: Claude Sonnet 5.5 --- .../{route53.tf => dns_operationcode_org.tf} | 641 ++++++++++++------ terraform/route53_imports.tf | 177 ----- 2 files changed, 431 insertions(+), 387 deletions(-) rename terraform/{route53.tf => dns_operationcode_org.tf} (63%) delete mode 100644 terraform/route53_imports.tf diff --git a/terraform/route53.tf b/terraform/dns_operationcode_org.tf similarity index 63% rename from terraform/route53.tf rename to terraform/dns_operationcode_org.tf index d959138..d1e6a4c 100644 --- a/terraform/route53.tf +++ b/terraform/dns_operationcode_org.tf @@ -1,6 +1,10 @@ +# Route53 zone: operationcode.org +# A sibling dns_operationcode_net.tf is planned for operationcode.net. + # Hosted zone for operationcode.org (imported; never destroy) resource "aws_route53_zone" "operationcode" { - name = "operationcode.org" + name = "operationcode.org" + # Live zone has an empty comment; keep it empty to avoid drift (provider would otherwise default it) comment = "" lifecycle { @@ -8,6 +12,208 @@ resource "aws_route53_zone" "operationcode" { } } +# ====================================================================== +# Apex and web +# ====================================================================== + +# Vercel: apex website +resource "aws_route53_record" "apex_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "A" + ttl = 300 + records = ["76.76.21.21"] +} + +# CA policy: restricts wildcard issuance to Amazon, reports to tech@ +resource "aws_route53_record" "apex_caa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "CAA" + ttl = 300 + records = [ + "0 issuewild \"amazontrust.com\"", + "0 issuewild \"amazon.com\"", + "0 iodef \"mailto:tech@operationcode.org\"", + ] +} + +# Vercel: website +resource "aws_route53_record" "www_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "www.operationcode.org" + type = "A" + ttl = 300 + records = ["76.76.21.21"] +} + +# Vercel: Storybook +resource "aws_route53_record" "storybook" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "storybook.operationcode.org" + type = "CNAME" + ttl = 600 + records = ["cname.vercel-dns.com."] +} + +# ====================================================================== +# App hosts (ALB aliases to the ECS cluster) +# ====================================================================== + +# ALB alias for the production backend API (ECS python_backend_prod) +resource "aws_route53_record" "api_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.operationcode.org" + type = "A" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ALB alias for the production backend API (ECS python_backend_prod) +resource "aws_route53_record" "api_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ALB alias for pybot (ECS pybot_prod) +resource "aws_route53_record" "pybot_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "pybot.operationcode.org" + type = "A" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ALB alias for pybot (ECS pybot_prod) +resource "aws_route53_record" "pybot_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "pybot.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ALB alias; listener rule redirects to https://www.operationcode.org +resource "aws_route53_record" "resources_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "resources.operationcode.org" + type = "A" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# Note: evaluate_target_health = true here but false on resources_a; this matches live, do not unify. +# ALB alias; listener rule redirects to https://www.operationcode.org +resource "aws_route53_record" "resources_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "resources.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = true + } +} + +# ====================================================================== +# Staging +# ====================================================================== + +# ALB alias for the staging backend API (ECS python_backend_staging) +resource "aws_route53_record" "api_staging_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.staging.operationcode.org" + type = "A" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ALB alias for the staging backend API (ECS python_backend_staging) +resource "aws_route53_record" "api_staging_aaaa" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "api.staging.operationcode.org" + type = "AAAA" + + alias { + name = "dualstack.${aws_lb.ecs.dns_name}" + zone_id = aws_lb.ecs.zone_id + evaluate_target_health = false + } +} + +# ====================================================================== +# Email: Google Workspace, apex SPF/DMARC +# ====================================================================== + +# Google Workspace mail +resource "aws_route53_record" "apex_mx" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "MX" + ttl = 3600 + records = [ + "1 ASPMX.L.GOOGLE.COM.", + "5 ALT1.ASPMX.L.GOOGLE.COM.", + "5 ALT2.ASPMX.L.GOOGLE.COM.", + "10 ALT3.ASPMX.L.GOOGLE.COM.", + "10 ALT4.ASPMX.L.GOOGLE.COM.", + ] +} + +# SPF (Google, Mailgun, Mandrill) and Google site verification. INVESTIGATE: trim SPF once live senders are confirmed +resource "aws_route53_record" "apex_txt" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "operationcode.org" + type = "TXT" + ttl = 3600 + records = [ + "v=spf1 a include:_spf.google.com include:mailgun.org include:spf.mandrillapp.com ~all", + "google-site-verification=XFeRZYknCzfwk5LTAuVDKf6T99S-DGafkhOfUlFXwFI", + "google-site-verification=s2E7tZyPlszu8LHIcYlRT8s6oq6hSoGQ70gMXKP08aE", + ] +} + +# DMARC policy for the apex domain (monitoring only, p=none) +resource "aws_route53_record" "apex_dmarc" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "_dmarc.operationcode.org" + type = "TXT" + ttl = 60 + records = ["v=DMARC1; p=none;"] +} + +# ====================================================================== +# Email: SES for coders.operationcode.org +# ====================================================================== + # MX record for SES email receiving resource "aws_route53_record" "coders_mx" { zone_id = aws_route53_zone.operationcode.zone_id @@ -69,64 +275,22 @@ resource "aws_route53_record" "coders_dmarc" { records = ["v=DMARC1; p=quarantine; adkim=r; aspf=r; pct=100"] } -# Vercel: apex website -resource "aws_route53_record" "apex_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "operationcode.org" - type = "A" - ttl = 300 - records = ["76.76.21.21"] -} - -# CA policy: restricts wildcard issuance to Amazon, reports to tech@ -resource "aws_route53_record" "apex_caa" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "operationcode.org" - type = "CAA" - ttl = 300 - records = [ - "0 issuewild \"amazontrust.com\"", - "0 issuewild \"amazon.com\"", - "0 iodef \"mailto:tech@operationcode.org\"", - ] -} - -# Google Workspace mail -resource "aws_route53_record" "apex_mx" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "operationcode.org" - type = "MX" - ttl = 3600 - records = [ - "1 ASPMX.L.GOOGLE.COM.", - "5 ALT1.ASPMX.L.GOOGLE.COM.", - "5 ALT2.ASPMX.L.GOOGLE.COM.", - "10 ALT3.ASPMX.L.GOOGLE.COM.", - "10 ALT4.ASPMX.L.GOOGLE.COM.", - ] -} +# ====================================================================== +# Verification TXT +# ====================================================================== -# SPF (Google, Mailgun, Mandrill) and Google site verification. INVESTIGATE: trim SPF once live senders are confirmed -resource "aws_route53_record" "apex_txt" { +# Legacy Vercel (ZEIT Now) domain verification. INVESTIGATE: likely safe to delete +resource "aws_route53_record" "vercel_now_verification" { zone_id = aws_route53_zone.operationcode.zone_id - name = "operationcode.org" + name = "_now.operationcode.org" type = "TXT" ttl = 3600 - records = [ - "v=spf1 a include:_spf.google.com include:mailgun.org include:spf.mandrillapp.com ~all", - "google-site-verification=XFeRZYknCzfwk5LTAuVDKf6T99S-DGafkhOfUlFXwFI", - "google-site-verification=s2E7tZyPlszu8LHIcYlRT8s6oq6hSoGQ70gMXKP08aE", - ] + records = ["Qmd8XawRvuECtFLQm8SytbgcW2PV2jthtfMy7ujLnTN2gL"] } -# SendGrid account 5672389 link/open tracking. INVESTIGATE: confirm account is active -resource "aws_route53_record" "sendgrid_link_tracking" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "5672389.operationcode.org" - type = "CNAME" - ttl = 3600 - records = ["sendgrid.net."] -} +# ====================================================================== +# ACM validation +# ====================================================================== # ACM DNS validation for the in-use wildcard certificate (us-east-2, ALB) resource "aws_route53_record" "acm_validation_apex" { @@ -137,15 +301,19 @@ resource "aws_route53_record" "acm_validation_apex" { records = ["_b1d3619a779f40c956b5f204733bbf79.acm-validations.aws"] } -# DMARC policy for the apex domain (monitoring only, p=none) -resource "aws_route53_record" "apex_dmarc" { +# ACM DNS validation for *.staging (same in-use wildcard certificate) +resource "aws_route53_record" "acm_validation_staging" { zone_id = aws_route53_zone.operationcode.zone_id - name = "_dmarc.operationcode.org" - type = "TXT" - ttl = 60 - records = ["v=DMARC1; p=none;"] + name = "_38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org" + type = "CNAME" + ttl = 300 + records = ["_cacb57a7608af0dcc34e1c19cef298f1.vhzmpjdqfx.acm-validations.aws."] } +# ====================================================================== +# Third-party mail senders (Mailchimp, Mandrill, SendGrid) +# ====================================================================== + # Mailchimp DKIM. INVESTIGATE: confirm account is active resource "aws_route53_record" "mailchimp_dkim_k2" { zone_id = aws_route53_zone.operationcode.zone_id @@ -173,6 +341,15 @@ resource "aws_route53_record" "mandrill_dkim" { records = ["v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrLHiExVd55zd/IQ/J/mRwSRMAocV/hMB3jXwaHH36d9NaVynQFYV8NaWi69c1veUtRzGt7yAioXqLj7Z4TeEUoOLgrKsn8YnckGs9i3B3tVFB+Ch/4mPhXWiNfNdynHWBcPcbJ8kjEQ2U8y78dHZj1YeRXXVvWob2OaKynO8/lQIDAQAB;"] } +# SendGrid account 5672389 link/open tracking. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_link_tracking" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "5672389.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["sendgrid.net."] +} + # SendGrid DKIM. INVESTIGATE: confirm account is active resource "aws_route53_record" "sendgrid_dkim_s1" { zone_id = aws_route53_zone.operationcode.zone_id @@ -191,41 +368,37 @@ resource "aws_route53_record" "sendgrid_dkim_s2" { records = ["s2.domainkey.u5672389.wl140.sendgrid.net."] } -# Legacy Vercel (ZEIT Now) domain verification. INVESTIGATE: likely safe to delete -resource "aws_route53_record" "vercel_now_verification" { +# SendGrid link branding. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_link" { zone_id = aws_route53_zone.operationcode.zone_id - name = "_now.operationcode.org" - type = "TXT" + name = "link.notify.operationcode.org" + type = "CNAME" ttl = 3600 - records = ["Qmd8XawRvuECtFLQm8SytbgcW2PV2jthtfMy7ujLnTN2gL"] + records = ["sendgrid.net."] } -# ALB alias for the production backend API (ECS python_backend_prod) -resource "aws_route53_record" "api_a" { +# SendGrid return-path. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_mail" { zone_id = aws_route53_zone.operationcode.zone_id - name = "api.operationcode.org" - type = "A" - - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } + name = "mail.notify.operationcode.org" + type = "CNAME" + ttl = 3600 + records = ["u5672389.wl140.sendgrid.net."] } -# ALB alias for the production backend API (ECS python_backend_prod) -resource "aws_route53_record" "api_aaaa" { +# SendGrid sending IP. INVESTIGATE: confirm account is active +resource "aws_route53_record" "sendgrid_notify_o1" { zone_id = aws_route53_zone.operationcode.zone_id - name = "api.operationcode.org" - type = "AAAA" - - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } + name = "o1.notify.operationcode.org" + type = "A" + ttl = 3600 + records = ["168.245.5.176"] } +# ====================================================================== +# Legacy hosts (services, DigitalOcean, Cloudways) +# ====================================================================== + # Old community host on DigitalOcean. INVESTIGATE: likely delete resource "aws_route53_record" "community_a" { zone_id = aws_route53_zone.operationcode.zone_id @@ -235,6 +408,24 @@ resource "aws_route53_record" "community_a" { records = ["192.241.185.68"] } +# Cloudways host for services (unknown app). INVESTIGATE: check Cloudways account +resource "aws_route53_record" "services_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "services.operationcode.org" + type = "A" + ttl = 60 + records = ["174.138.92.215"] +} + +# DigitalOcean NFS host. INVESTIGATE: likely dead +resource "aws_route53_record" "services_nfs_a" { + zone_id = aws_route53_zone.operationcode.zone_id + name = "nfs.services.operationcode.org" + type = "A" + ttl = 60 + records = ["138.197.94.99"] +} + # Kibana on the services host. INVESTIGATE: likely dead resource "aws_route53_record" "kibana" { zone_id = aws_route53_zone.operationcode.zone_id @@ -253,170 +444,200 @@ resource "aws_route53_record" "mautic" { records = ["services.operationcode.org."] } -# SendGrid link branding. INVESTIGATE: confirm account is active -resource "aws_route53_record" "sendgrid_notify_link" { +# Slack slash commands on the services host. INVESTIGATE: check Slack app request URLs +resource "aws_route53_record" "slash_commands" { zone_id = aws_route53_zone.operationcode.zone_id - name = "link.notify.operationcode.org" + name = "slash-commands.operationcode.org" type = "CNAME" - ttl = 3600 - records = ["sendgrid.net."] + ttl = 60 + records = ["services.operationcode.org."] } -# SendGrid return-path. INVESTIGATE: confirm account is active -resource "aws_route53_record" "sendgrid_notify_mail" { +# Test host on the services host. INVESTIGATE: check Cloudways account +resource "aws_route53_record" "test" { zone_id = aws_route53_zone.operationcode.zone_id - name = "mail.notify.operationcode.org" + name = "test.operationcode.org" type = "CNAME" - ttl = 3600 - records = ["u5672389.wl140.sendgrid.net."] + ttl = 60 + records = ["services.operationcode.org."] } -# SendGrid sending IP. INVESTIGATE: confirm account is active -resource "aws_route53_record" "sendgrid_notify_o1" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "o1.notify.operationcode.org" - type = "A" - ttl = 3600 - records = ["168.245.5.176"] +# ====================================================================== +# Import blocks for operationcode.org (zone and pre-existing records). +# They can be removed after the first successful apply. +# ====================================================================== + +import { + to = aws_route53_zone.operationcode + id = "Z08173331NAK6ZJUBZENQ" } -# ALB alias for pybot (ECS pybot_prod) -resource "aws_route53_record" "pybot_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "pybot.operationcode.org" - type = "A" +import { + to = aws_route53_record.apex_a + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_A" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } +import { + to = aws_route53_record.apex_caa + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_CAA" } -# ALB alias for pybot (ECS pybot_prod) -resource "aws_route53_record" "pybot_aaaa" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "pybot.operationcode.org" - type = "AAAA" +import { + to = aws_route53_record.apex_mx + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_MX" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } +import { + to = aws_route53_record.apex_txt + id = "Z08173331NAK6ZJUBZENQ_operationcode.org_TXT" } -# ALB alias; listener rule redirects to https://www.operationcode.org -resource "aws_route53_record" "resources_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "resources.operationcode.org" - type = "A" +import { + to = aws_route53_record.sendgrid_link_tracking + id = "Z08173331NAK6ZJUBZENQ_5672389.operationcode.org_CNAME" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } +import { + to = aws_route53_record.acm_validation_apex + id = "Z08173331NAK6ZJUBZENQ__62bdef8daffb0b85a77bd7a7c4be6e36.operationcode.org_CNAME" } -# ALB alias; listener rule redirects to https://www.operationcode.org -resource "aws_route53_record" "resources_aaaa" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "resources.operationcode.org" - type = "AAAA" +import { + to = aws_route53_record.apex_dmarc + id = "Z08173331NAK6ZJUBZENQ__dmarc.operationcode.org_TXT" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = true - } +import { + to = aws_route53_record.mailchimp_dkim_k2 + id = "Z08173331NAK6ZJUBZENQ_k2._domainkey.operationcode.org_CNAME" } -# Cloudways host for services (unknown app). INVESTIGATE: check Cloudways account -resource "aws_route53_record" "services_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "services.operationcode.org" - type = "A" - ttl = 60 - records = ["174.138.92.215"] +import { + to = aws_route53_record.mailchimp_dkim_k3 + id = "Z08173331NAK6ZJUBZENQ_k3._domainkey.operationcode.org_CNAME" } -# DigitalOcean NFS host. INVESTIGATE: likely dead -resource "aws_route53_record" "services_nfs_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "nfs.services.operationcode.org" - type = "A" - ttl = 60 - records = ["138.197.94.99"] +import { + to = aws_route53_record.mandrill_dkim + id = "Z08173331NAK6ZJUBZENQ_mandrill._domainkey.operationcode.org_TXT" } -# Slack slash commands on the services host. INVESTIGATE: check Slack app request URLs -resource "aws_route53_record" "slash_commands" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "slash-commands.operationcode.org" - type = "CNAME" - ttl = 60 - records = ["services.operationcode.org."] +import { + to = aws_route53_record.sendgrid_dkim_s1 + id = "Z08173331NAK6ZJUBZENQ_s1._domainkey.operationcode.org_CNAME" } -# ACM DNS validation for *.staging (same in-use wildcard certificate) -resource "aws_route53_record" "acm_validation_staging" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "_38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org" - type = "CNAME" - ttl = 300 - records = ["_cacb57a7608af0dcc34e1c19cef298f1.vhzmpjdqfx.acm-validations.aws."] +import { + to = aws_route53_record.sendgrid_dkim_s2 + id = "Z08173331NAK6ZJUBZENQ_s2._domainkey.operationcode.org_CNAME" } -# ALB alias for the staging backend API (ECS python_backend_staging) -resource "aws_route53_record" "api_staging_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "api.staging.operationcode.org" - type = "A" +import { + to = aws_route53_record.vercel_now_verification + id = "Z08173331NAK6ZJUBZENQ__now.operationcode.org_TXT" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } +import { + to = aws_route53_record.api_a + id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_A" } -# ALB alias for the staging backend API (ECS python_backend_staging) -resource "aws_route53_record" "api_staging_aaaa" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "api.staging.operationcode.org" - type = "AAAA" +import { + to = aws_route53_record.api_aaaa + id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_AAAA" +} - alias { - name = "dualstack.oc20221218011536279100000004-1436061894.us-east-2.elb.amazonaws.com." - zone_id = "Z3AADJGX6KTTL2" - evaluate_target_health = false - } +import { + to = aws_route53_record.community_a + id = "Z08173331NAK6ZJUBZENQ_community.operationcode.org_A" } -# Vercel: Storybook -resource "aws_route53_record" "storybook" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "storybook.operationcode.org" - type = "CNAME" - ttl = 600 - records = ["cname.vercel-dns.com."] +import { + to = aws_route53_record.kibana + id = "Z08173331NAK6ZJUBZENQ_kibana.operationcode.org_CNAME" } -# Test host on the services host. INVESTIGATE: check Cloudways account -resource "aws_route53_record" "test" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "test.operationcode.org" - type = "CNAME" - ttl = 60 - records = ["services.operationcode.org."] +import { + to = aws_route53_record.mautic + id = "Z08173331NAK6ZJUBZENQ_mautic.operationcode.org_CNAME" } -# Vercel: website -resource "aws_route53_record" "www_a" { - zone_id = aws_route53_zone.operationcode.zone_id - name = "www.operationcode.org" - type = "A" - ttl = 300 - records = ["76.76.21.21"] +import { + to = aws_route53_record.sendgrid_notify_link + id = "Z08173331NAK6ZJUBZENQ_link.notify.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_notify_mail + id = "Z08173331NAK6ZJUBZENQ_mail.notify.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.sendgrid_notify_o1 + id = "Z08173331NAK6ZJUBZENQ_o1.notify.operationcode.org_A" +} + +import { + to = aws_route53_record.pybot_a + id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_A" +} + +import { + to = aws_route53_record.pybot_aaaa + id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.resources_a + id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_A" +} + +import { + to = aws_route53_record.resources_aaaa + id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.services_a + id = "Z08173331NAK6ZJUBZENQ_services.operationcode.org_A" +} + +import { + to = aws_route53_record.services_nfs_a + id = "Z08173331NAK6ZJUBZENQ_nfs.services.operationcode.org_A" +} + +import { + to = aws_route53_record.slash_commands + id = "Z08173331NAK6ZJUBZENQ_slash-commands.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.acm_validation_staging + id = "Z08173331NAK6ZJUBZENQ__38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.api_staging_a + id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_A" +} + +import { + to = aws_route53_record.api_staging_aaaa + id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_AAAA" +} + +import { + to = aws_route53_record.storybook + id = "Z08173331NAK6ZJUBZENQ_storybook.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.test + id = "Z08173331NAK6ZJUBZENQ_test.operationcode.org_CNAME" +} + +import { + to = aws_route53_record.www_a + id = "Z08173331NAK6ZJUBZENQ_www.operationcode.org_A" } diff --git a/terraform/route53_imports.tf b/terraform/route53_imports.tf deleted file mode 100644 index aca0c1e..0000000 --- a/terraform/route53_imports.tf +++ /dev/null @@ -1,177 +0,0 @@ -# Import blocks for the operationcode.org zone and its pre-existing records. -# They can be removed after the first successful apply. - -import { - to = aws_route53_zone.operationcode - id = "Z08173331NAK6ZJUBZENQ" -} - -import { - to = aws_route53_record.apex_a - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_A" -} - -import { - to = aws_route53_record.apex_caa - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_CAA" -} - -import { - to = aws_route53_record.apex_mx - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_MX" -} - -import { - to = aws_route53_record.apex_txt - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_TXT" -} - -import { - to = aws_route53_record.sendgrid_link_tracking - id = "Z08173331NAK6ZJUBZENQ_5672389.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.acm_validation_apex - id = "Z08173331NAK6ZJUBZENQ__62bdef8daffb0b85a77bd7a7c4be6e36.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.apex_dmarc - id = "Z08173331NAK6ZJUBZENQ__dmarc.operationcode.org_TXT" -} - -import { - to = aws_route53_record.mailchimp_dkim_k2 - id = "Z08173331NAK6ZJUBZENQ_k2._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mailchimp_dkim_k3 - id = "Z08173331NAK6ZJUBZENQ_k3._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mandrill_dkim - id = "Z08173331NAK6ZJUBZENQ_mandrill._domainkey.operationcode.org_TXT" -} - -import { - to = aws_route53_record.sendgrid_dkim_s1 - id = "Z08173331NAK6ZJUBZENQ_s1._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_dkim_s2 - id = "Z08173331NAK6ZJUBZENQ_s2._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.vercel_now_verification - id = "Z08173331NAK6ZJUBZENQ__now.operationcode.org_TXT" -} - -import { - to = aws_route53_record.api_a - id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_A" -} - -import { - to = aws_route53_record.api_aaaa - id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.community_a - id = "Z08173331NAK6ZJUBZENQ_community.operationcode.org_A" -} - -import { - to = aws_route53_record.kibana - id = "Z08173331NAK6ZJUBZENQ_kibana.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mautic - id = "Z08173331NAK6ZJUBZENQ_mautic.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_link - id = "Z08173331NAK6ZJUBZENQ_link.notify.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_mail - id = "Z08173331NAK6ZJUBZENQ_mail.notify.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_o1 - id = "Z08173331NAK6ZJUBZENQ_o1.notify.operationcode.org_A" -} - -import { - to = aws_route53_record.pybot_a - id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_A" -} - -import { - to = aws_route53_record.pybot_aaaa - id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.resources_a - id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_A" -} - -import { - to = aws_route53_record.resources_aaaa - id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.services_a - id = "Z08173331NAK6ZJUBZENQ_services.operationcode.org_A" -} - -import { - to = aws_route53_record.services_nfs_a - id = "Z08173331NAK6ZJUBZENQ_nfs.services.operationcode.org_A" -} - -import { - to = aws_route53_record.slash_commands - id = "Z08173331NAK6ZJUBZENQ_slash-commands.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.acm_validation_staging - id = "Z08173331NAK6ZJUBZENQ__38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.api_staging_a - id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_A" -} - -import { - to = aws_route53_record.api_staging_aaaa - id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.storybook - id = "Z08173331NAK6ZJUBZENQ_storybook.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.test - id = "Z08173331NAK6ZJUBZENQ_test.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.www_a - id = "Z08173331NAK6ZJUBZENQ_www.operationcode.org_A" -} From 4452466af08c2d50e91d9e1fdefbd1005d863e8c Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sun, 1 Nov 2026 07:33:18 -0800 Subject: [PATCH 3/4] Clarify DNS record comments for records that need an owner check Co-Authored-By: Claude Opus 5.5 --- terraform/dns_operationcode_org.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/terraform/dns_operationcode_org.tf b/terraform/dns_operationcode_org.tf index d1e6a4c..b240f02 100644 --- a/terraform/dns_operationcode_org.tf +++ b/terraform/dns_operationcode_org.tf @@ -188,7 +188,7 @@ resource "aws_route53_record" "apex_mx" { ] } -# SPF (Google, Mailgun, Mandrill) and Google site verification. INVESTIGATE: trim SPF once live senders are confirmed +# SPF (Google, Mailgun, Mandrill) and Google site verification. Keep the Mandrill include (production mail uses it). INVESTIGATE: Mailgun include is unused by code, confirm with the Mailgun account resource "aws_route53_record" "apex_txt" { zone_id = aws_route53_zone.operationcode.zone_id name = "operationcode.org" @@ -314,7 +314,7 @@ resource "aws_route53_record" "acm_validation_staging" { # Third-party mail senders (Mailchimp, Mandrill, SendGrid) # ====================================================================== -# Mailchimp DKIM. INVESTIGATE: confirm account is active +# Mailchimp DKIM. Used by code (mailchimp3 in the back-end). INVESTIGATE: confirm the Mailchimp account is active resource "aws_route53_record" "mailchimp_dkim_k2" { zone_id = aws_route53_zone.operationcode.zone_id name = "k2._domainkey.operationcode.org" @@ -323,7 +323,7 @@ resource "aws_route53_record" "mailchimp_dkim_k2" { records = ["dkim2.mcsv.net"] } -# Mailchimp DKIM. INVESTIGATE: confirm account is active +# Mailchimp DKIM. Used by code (mailchimp3 in the back-end). INVESTIGATE: confirm the Mailchimp account is active resource "aws_route53_record" "mailchimp_dkim_k3" { zone_id = aws_route53_zone.operationcode.zone_id name = "k3._domainkey.operationcode.org" @@ -332,7 +332,7 @@ resource "aws_route53_record" "mailchimp_dkim_k3" { records = ["dkim3.mcsv.net"] } -# Mandrill DKIM (1024-bit key). INVESTIGATE: confirm account is active +# Mandrill DKIM (1024-bit key). Live: production Django mail sends through Mandrill. Keep resource "aws_route53_record" "mandrill_dkim" { zone_id = aws_route53_zone.operationcode.zone_id name = "mandrill._domainkey.operationcode.org" @@ -399,7 +399,7 @@ resource "aws_route53_record" "sendgrid_notify_o1" { # Legacy hosts (services, DigitalOcean, Cloudways) # ====================================================================== -# Old community host on DigitalOcean. INVESTIGATE: likely delete +# DigitalOcean community host. INVESTIGATE: live server (SSH answers); find its owner before deletion. resource "aws_route53_record" "community_a" { zone_id = aws_route53_zone.operationcode.zone_id name = "community.operationcode.org" From 7948ae6dbd3dc27172a469c607efd250ae951cc9 Mon Sep 17 00:00:00 2001 From: Irving Popovetsky Date: Sun, 1 Nov 2026 07:48:24 -0800 Subject: [PATCH 4/4] Remove applied import blocks for operationcode.org DNS The 35 imports were applied locally. terraform plan now reports No changes. Co-Authored-By: Claude Opus 5.5 --- terraform/dns_operationcode_org.tf | 180 ----------------------------- 1 file changed, 180 deletions(-) diff --git a/terraform/dns_operationcode_org.tf b/terraform/dns_operationcode_org.tf index b240f02..f82d7b2 100644 --- a/terraform/dns_operationcode_org.tf +++ b/terraform/dns_operationcode_org.tf @@ -461,183 +461,3 @@ resource "aws_route53_record" "test" { ttl = 60 records = ["services.operationcode.org."] } - -# ====================================================================== -# Import blocks for operationcode.org (zone and pre-existing records). -# They can be removed after the first successful apply. -# ====================================================================== - -import { - to = aws_route53_zone.operationcode - id = "Z08173331NAK6ZJUBZENQ" -} - -import { - to = aws_route53_record.apex_a - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_A" -} - -import { - to = aws_route53_record.apex_caa - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_CAA" -} - -import { - to = aws_route53_record.apex_mx - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_MX" -} - -import { - to = aws_route53_record.apex_txt - id = "Z08173331NAK6ZJUBZENQ_operationcode.org_TXT" -} - -import { - to = aws_route53_record.sendgrid_link_tracking - id = "Z08173331NAK6ZJUBZENQ_5672389.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.acm_validation_apex - id = "Z08173331NAK6ZJUBZENQ__62bdef8daffb0b85a77bd7a7c4be6e36.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.apex_dmarc - id = "Z08173331NAK6ZJUBZENQ__dmarc.operationcode.org_TXT" -} - -import { - to = aws_route53_record.mailchimp_dkim_k2 - id = "Z08173331NAK6ZJUBZENQ_k2._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mailchimp_dkim_k3 - id = "Z08173331NAK6ZJUBZENQ_k3._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mandrill_dkim - id = "Z08173331NAK6ZJUBZENQ_mandrill._domainkey.operationcode.org_TXT" -} - -import { - to = aws_route53_record.sendgrid_dkim_s1 - id = "Z08173331NAK6ZJUBZENQ_s1._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_dkim_s2 - id = "Z08173331NAK6ZJUBZENQ_s2._domainkey.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.vercel_now_verification - id = "Z08173331NAK6ZJUBZENQ__now.operationcode.org_TXT" -} - -import { - to = aws_route53_record.api_a - id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_A" -} - -import { - to = aws_route53_record.api_aaaa - id = "Z08173331NAK6ZJUBZENQ_api.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.community_a - id = "Z08173331NAK6ZJUBZENQ_community.operationcode.org_A" -} - -import { - to = aws_route53_record.kibana - id = "Z08173331NAK6ZJUBZENQ_kibana.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.mautic - id = "Z08173331NAK6ZJUBZENQ_mautic.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_link - id = "Z08173331NAK6ZJUBZENQ_link.notify.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_mail - id = "Z08173331NAK6ZJUBZENQ_mail.notify.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.sendgrid_notify_o1 - id = "Z08173331NAK6ZJUBZENQ_o1.notify.operationcode.org_A" -} - -import { - to = aws_route53_record.pybot_a - id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_A" -} - -import { - to = aws_route53_record.pybot_aaaa - id = "Z08173331NAK6ZJUBZENQ_pybot.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.resources_a - id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_A" -} - -import { - to = aws_route53_record.resources_aaaa - id = "Z08173331NAK6ZJUBZENQ_resources.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.services_a - id = "Z08173331NAK6ZJUBZENQ_services.operationcode.org_A" -} - -import { - to = aws_route53_record.services_nfs_a - id = "Z08173331NAK6ZJUBZENQ_nfs.services.operationcode.org_A" -} - -import { - to = aws_route53_record.slash_commands - id = "Z08173331NAK6ZJUBZENQ_slash-commands.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.acm_validation_staging - id = "Z08173331NAK6ZJUBZENQ__38e269ddbc8fefe222fbb84bdd604ea1.staging.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.api_staging_a - id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_A" -} - -import { - to = aws_route53_record.api_staging_aaaa - id = "Z08173331NAK6ZJUBZENQ_api.staging.operationcode.org_AAAA" -} - -import { - to = aws_route53_record.storybook - id = "Z08173331NAK6ZJUBZENQ_storybook.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.test - id = "Z08173331NAK6ZJUBZENQ_test.operationcode.org_CNAME" -} - -import { - to = aws_route53_record.www_a - id = "Z08173331NAK6ZJUBZENQ_www.operationcode.org_A" -}