---
title: "Networking and Load Balancing"
slug: gcp-networking-and-load-balancing
section: GCP Infrastructure
status: stable
description: "This page covers the network layer shared by every environment: VPCs, firewall rules, Serverless VPC connectors, private service access, global HTTPS load balancers, certificates, Cloud Run domain mappings, DNS, Cloud Armor, IAP and Clou…"
last-updated: 2026-10-07
---

# Networking and Load Balancing

This page covers the network layer shared by every environment: VPCs, firewall rules, Serverless VPC connectors, private service access, global HTTPS load balancers, certificates, Cloud Run domain mappings, DNS, Cloud Armor, IAP and Cloud Run ingress settings. Per-environment detail is in [development](/docs/gcp-env-development), [QA](/docs/gcp-env-qa), [production](/docs/gcp-env-production) and [MCP](/docs/gcp-env-mcp). Module inventory is in [Terraform modules](/docs/gcp-terraform-modules), and the apply path is in [Terraform workflows](/docs/gcp-terraform-workflows).

## Networking resources

### Terraform networking: development

| Terraform address | Module or resource type | Identifier | Defined in |
| --- | --- | --- | --- |
| `google_compute_global_address.globus_development_ip` | `google_compute_global_address` | `globus-development-ip` | `main.tf:1044` |
| `google_compute_global_address.host_portal_development_lb_ip` | `google_compute_global_address` | `host-portal-development-lb-ip` | `main.tf:1076` |
| `google_compute_global_address.hostportal_dev_ip` | `google_compute_global_address` | `hostportal-dev-ip` | `main.tf:1070` |
| `google_compute_global_address.n8n_dev_ip` | `google_compute_global_address` | `n8n-dev-ip` | `main.tf:1049` |
| `google_compute_global_address.n8n_development2_ip` | `google_compute_global_address` | `n8n-development2-ip` | `main.tf:1061` |
| `google_compute_global_address.n8n_sandbox_ip` | `google_compute_global_address` | `n8n-sandbox-ip` | `n8n-sandbox-standalone.tf:90` |
| `google_compute_global_address.npe_participant_postgres_psa_range_orphaned` | `google_compute_global_address` | `sql-peering-range-us-central1-npe-participant-postgres-db` | `main.tf:146` |
| `google_compute_global_address.ppp2_applicants_dev_ip` | `google_compute_global_address` | `ppp2-applicants-dev-ip` | `main.tf:1081` |
| `google_compute_network_peering.dev_to_ocr` | `google_compute_network_peering` | `dev-to-ocr` | `main.tf:87` |
| `module.fw_default_allow_internal_development` | `firewall-rule` | `default-allow-internal` | `main.tf:165` |
| `module.fw_default_allow_ssh_development` | `firewall-rule` | `default-allow-ssh` | `main.tf:179` |
| `module.fw_npe_allow_internal` | `firewall-rule` | `fw-npe-allow-internal` | `main.tf:190` |
| `module.network_default_development` | `network` | `default` | `main.tf:59` |
| `module.network_skilled_script_vpc_npe` | `network` | `skilled-script-vpc-npe` | `main.tf:93` |

### Terraform networking: mcp

| Terraform address | Module or resource type | Identifier | Defined in |
| --- | --- | --- | --- |
| `module.mcp_gateway_lb` | `load-balancer-https-multihost` |  | `main.tf:3691` |

### Terraform networking: platform-services

| Terraform address | Module or resource type | Identifier | Defined in |
| --- | --- | --- | --- |
| `google_compute_backend_service.environment_index` | `google_compute_backend_service` | `environment-index-backend` | `environment-index.tf` |
| `google_compute_managed_ssl_certificate.environment_index` | `google_compute_managed_ssl_certificate` | `environment-index-ssl-cert` | `environment-index.tf` |
| `google_compute_region_network_endpoint_group.environment_index` | `google_compute_region_network_endpoint_group` | `environment-index-neg` | `environment-index.tf` |
| `module.sys_n8n_domain` | `domain-mapping` | `sys.n8n.allianceabroad.com` | `sys-n8n.tf:172` |

### Terraform networking: production

| Terraform address | Module or resource type | Identifier | Defined in |
| --- | --- | --- | --- |
| `google_certificate_manager_certificate_map_entry.host_portal_alliance` | `google_certificate_manager_certificate_map_entry` | `host-portal-cloudrun-lb-prod-cert-map-entry-alliance` | `host-portal-dual-domain-cloudrun-lb-design.tf:353` |
| `google_certificate_manager_certificate_map_entry.host_portal_wildpacks` | `google_certificate_manager_certificate_map_entry` | `host-portal-cloudrun-lb-prod-cert-map-entry-wildpacks` | `host-portal-dual-domain-cloudrun-lb-design.tf:361` |
| `google_certificate_manager_certificate_map.host_portal_cloudrun_lb_prod` | `google_certificate_manager_certificate_map` | `host-portal-cloudrun-lb-prod-cert-map` | `host-portal-dual-domain-cloudrun-lb-design.tf:348` |
| `google_certificate_manager_certificate.host_portal_alliance` | `google_certificate_manager_certificate` | `host-portal-cloudrun-lb-prod-cm-cert-alliance` | `host-portal-dual-domain-cloudrun-lb-design.tf:328` |
| `google_certificate_manager_certificate.host_portal_wildpacks` | `google_certificate_manager_certificate` | `host-portal-cloudrun-lb-prod-cm-cert-wildpacks` | `host-portal-dual-domain-cloudrun-lb-design.tf:338` |
| `google_certificate_manager_dns_authorization.host_portal_alliance` | `google_certificate_manager_dns_authorization` | `host-portal-cloudrun-lb-prod-dnsauth-alliance` | `host-portal-dual-domain-cloudrun-lb-design.tf:316` |
| `google_certificate_manager_dns_authorization.host_portal_wildpacks` | `google_certificate_manager_dns_authorization` | `host-portal-cloudrun-lb-prod-dnsauth-wildpacks` | `host-portal-dual-domain-cloudrun-lb-design.tf:322` |
| `google_compute_global_address.globus_prod_ip` | `google_compute_global_address` | `globus-prod-ip` | `main.tf:1811` |
| `google_compute_global_address.n8n_prod_ip` | `google_compute_global_address` | `n8n-prod-ip` | `main.tf:1816` |
| `google_compute_global_address.wildpacks_prod_ip` | `google_compute_global_address` | `wildpacks-prod-ip` | `main.tf:1821` |
| `module.fw_default_allow_internal_prod` | `firewall-rule` | `default-allow-internal` | `main.tf:194` |
| `module.fw_prod_allow_internal` | `firewall-rule` | `fw-prod-allow-internal` | `main.tf:209` |
| `module.host_portal_cloudrun_lb_prod` | `load-balancer-https-multihost` |  | `host-portal-dual-domain-cloudrun-lb-design.tf:203` |
| `module.network_default_prod` | `network` | `default` | `main.tf:89` |
| `module.network_skilled_script_vpc_prod` | `network` | `skilled-script-vpc-prod` | `main.tf:146` |
| `module.ppp2_applicants_prod_lb` | `load-balancer-https` |  | `main.tf:1826` |

### Terraform networking: qa

| Terraform address | Module or resource type | Identifier | Defined in |
| --- | --- | --- | --- |
| `google_compute_global_address.globus_qa_ip` | `google_compute_global_address` | `globus-qa-ip` | `main.tf:1930` |
| `google_compute_global_address.host_portal_qa_ip` | `google_compute_global_address` | `host-portal-qa-ip` | `main.tf:1935` |
| `google_compute_global_address.n8n_qa_ip` | `google_compute_global_address` | `n8n-qa-ip` | `main.tf:1944` |
| `module.fw_default_allow_internal_qa` | `firewall-rule` | `default-allow-internal` | `main.tf:195` |
| `module.fw_qa_allow_internal` | `firewall-rule` | `fw-qa-allow-internal` | `main.tf:210` |
| `module.network_default_qa` | `network` | `default` | `main.tf:89` |
| `module.network_skilled_script_vpc_qa` | `network` | `skilled-script-vpc-qa` | `main.tf:146` |
| `module.ppp2_applicants_qa_lb` | `load-balancer-https` |  | `main.tf:1949` |
| `module.qa_apply_domain_mapping` | `domain-mapping` | `qa.apply.allianceabroad.com` | `main.tf:1982` |

### Live networking: skilled-script-469819-f2

**forwarding rules:** `docaipscrule`, `host-portal-development-https-fr`, `k8s2-fr/fs-...-globus-development-globus-app-i0p9jh3u (http+https)`, `k8s2-fr/fs-...-n8n-dev-n8n-dev-gd3a2mdp (http+https)`, `k8s2-fr/fs-...-n8n-n8n-cyg9j5va (http+https)`, `k8s2-fr/fs-...-n8n-sandbox-n8n-sandbox-eub0j3bh (http+https)`, `ppp2-applicants-dev-http-fr`, `ppp2-applicants-dev-https-fr`

**url maps:** `host-portal-development-urlmap`, `k8s2-rm-afymudbx-globus-development-globus-app-i0p9jh3u`, `k8s2-rm-afymudbx-n8n-dev-n8n-dev-gd3a2mdp`, `k8s2-rm-afymudbx-n8n-n8n-cyg9j5va`, `k8s2-rm-afymudbx-n8n-sandbox-n8n-sandbox-eub0j3bh`, `k8s2-um-afymudbx-globus-development-globus-app-i0p9jh3u`, `k8s2-um-afymudbx-n8n-dev-n8n-dev-gd3a2mdp`, `k8s2-um-afymudbx-n8n-n8n-cyg9j5va`, `k8s2-um-afymudbx-n8n-sandbox-n8n-sandbox-eub0j3bh`, `ppp2-applicants-dev-http-redirect`, `ppp2-applicants-dev-url-map`

**backend services:** `applicant-backend`, `applicant-portal-backend`, `host-portal-client-backend`, `host-portal-server-backend`, `hostportal-dev-backend`, `k8s1-9845bf8d-globus-development-asana-mcp-80-7f65f437`, `k8s1-9845bf8d-globus-development-globus-app-80-bcb977e2`, `k8s1-9845bf8d-kube-system-default-http-backend-80-a274d2fc`, `k8s1-9845bf8d-n8n-dev-n8n-80-4ef6f831`, `k8s1-9845bf8d-n8n-n8n-80-7a7a1d2d`, `k8s1-9845bf8d-n8n-sandbox-n8n-80-7a1fa657`, `k8s1-bd0a8805-applicant-portal-q-applicant-portal-ap-8-69a879e7`, `k8s1-bd0a8805-kube-system-default-http-backend-80-5be99b2b`, `ppp2-participant-client-backend`

**target https proxies:** `host-portal-development-https-proxy`, `k8s2-ts-afymudbx-globus-development-globus-app-i0p9jh3u`, `k8s2-ts-afymudbx-n8n-dev-n8n-dev-gd3a2mdp`, `k8s2-ts-afymudbx-n8n-n8n-cyg9j5va`, `k8s2-ts-afymudbx-n8n-sandbox-n8n-sandbox-eub0j3bh`, `ppp2-applicants-dev-https-proxy`

**target http proxies:** `k8s2-tp-afymudbx-globus-development-globus-app-i0p9jh3u`, `k8s2-tp-afymudbx-n8n-dev-n8n-dev-gd3a2mdp`, `k8s2-tp-afymudbx-n8n-n8n-cyg9j5va`, `k8s2-tp-afymudbx-n8n-sandbox-n8n-sandbox-eub0j3bh`, `ppp2-applicants-dev-http-proxy`

**ssl certificates:** `host-portal-development-cert`, `host-portal-development-wildpacks-cert`, `mcrt-4cac7976-6b0a-469b-893f-905d51f497ab`, `mcrt-74b182c1-8fd7-4fc7-9c6d-448bcc84db24`, `mcrt-989b790b-fb08-4322-b20d-cde34ef0f7a9`, `mcrt-b953acbf-6ae0-4ff0-88aa-c4a0a9e13970`, `mcrt-ecc2ce96-c406-4e0c-be86-cc030911fa3a`, `mcrt-f9efe9d8-4d79-4143-bf98-18a672539d31`, `ppp2-applicants-dev-cert`, `ppp2-applicants-dev-wildpacks-cert`

**cloud armor policies:** `default-security-policy-for-applicant-portal-backend`, `default-security-policy-for-backend-service-applicant-backend`, `manus-mcp-security-policy`, `virtual-interviews-security-policy`

**vpc networks:** `default`, `skilled-script-vpc-npe`

**subnets custom:** `sb-npe-dmz`, `us-central1-db-subnet`, `us-central1-web-subnet`, `cloudrun-direct-egress-subnet`

**firewall rules:** `default-allow-internal`, `default-allow-ssh`, `fw-npe-allow-internal`, `gke-globus-cluster-development-5c06a123-all`, `gke-globus-cluster-development-5c06a123-exkubelet`, `gke-globus-cluster-development-5c06a123-inkubelet`, `gke-globus-cluster-development-5c06a123-vms`, `k8s-fw-l7--9845bf8df74ff07a`

**vpc access connectors:** `applicant-portal-connect`, `default-net-connect`, `host-portal-connect`

**addresses:** `docaipscip`, `globus-development-ip`, `google-managed-services-default`, `host-portal-development-lb-ip`, `hostportal-dev-ip`, `n8n-dev-ip`, `n8n-development2-ip`, `n8n-sandbox-ip`, `ppp2-applicants-dev-ip`, `sql-peering-range-us-central1`, `sql-peering-range-us-central1-npe-participant-postgres-db`, `globus-mcp-egress-ip`

**domain mappings:** `dev-1.sandbox.allianceabroad.com`, `dev-2.sandbox.allianceabroad.com`, `dev-3.sandbox.allianceabroad.com`, `dev.apply.allianceabroad.com`, `development.apply.allianceabroad.com`, `development.apply.wildpacks.com`, `nexus.allianceabroad.com`

### Live networking: alliance-mcp-services

**global addresses:** `mcp-gateway-lb-ip`, `openstatus-admin-lb-ip`, `openstatus-lb-ip`

**forwarding rules:** `mcp-https-fr`, `mcp-http-fr`, `k8s2-fs-...openstatus-ingress-71wwxfjl`, `k8s2-fr-...openstatus-ingress-71wwxfjl`, `k8s2-fs-...openstatus-admin-ingress-5wcpzb31`, `k8s2-fr-...openstatus-admin-ingress-5wcpzb31`

**target https proxies:** `mcp-https-proxy`, `k8s2-ts-...openstatus-ingress-71wwxfjl`, `k8s2-ts-...openstatus-admin-ingress-5wcpzb31`

**target http proxies:** `mcp-http-proxy`, `k8s2-tp-...openstatus-ingress`, `k8s2-tp-...openstatus-admin-ingress`

**url maps:** `mcp-lb`, `mcp-http-redirect`, `k8s2-um-...openstatus-ingress-71wwxfjl`, `k8s2-um-...openstatus-admin-ingress-5wcpzb31`, `k8s2-rm-... (2 http->https redirect maps for the openstatus ingresses)`

**backend services:** `mcp-gw-backend`, `mcp-admin-backend`, `mcp-admin-api-backend`, `platform-hub-backend`, `platform-hub-mcp-backend`, `k8s1-e0f2d94e-* (4 GKE ingress backends: default-http-backend, openstatus-dashboard, openstatus-mcp, openstatus-status-page)`

**ssl certificates:** `mcp-cert`, `platform-hub-cert`, `mcrt-626e1d39-3b4a-4400-b332-c5aff553b306`, `mcrt-6d353b44-d040-4d85-acd5-8bfc0ddccf1d`, `mcrt-dde5574f-f1a0-43f6-80da-359e427aee4e`

**vpc networks:** `default`

**firewall rules:** `default-allow-internal`, `gke-openstatus-cluster-e2bda491-all`, `gke-openstatus-cluster-e2bda491-exkubelet`, `gke-openstatus-cluster-e2bda491-inkubelet`, `gke-openstatus-cluster-e2bda491-vms`, `k8s-fw-l7--e0f2d94e66fa6a36`

**neg:** `mcp-gw-neg`, `mcp-admin-neg`, `platform-hub-neg`, `platform-hub-neg`, `k8s1-e0f2d94e-* (4 GKE-managed GCE_VM_IP_PORT NEGs: default-http-backend, openstatus-dashboard, openstatus-mcp, openstatus-status-page)`

**domain mappings:** `teams-mcp.mcp.allianceabroad.com`

### Live networking: production-499116

**forwarding rules:** `host-portal-cloudrun-lb-prod-http-fwd-rule`, `host-portal-cloudrun-lb-prod-https-fwd-rule`, `k8s2-fr/fs-...-globus-prod-globus-app (http+https)`, `k8s2-fr/fs-...-n8n-n8n (http+https)`, `k8s2-fr/fs-...-wildpacks-prod-wildpacks-app (http+https)`, `ppp2-applicants-prod-http-fr`, `ppp2-applicants-prod-https-fr`

**url maps:** `host-portal-cloudrun-lb-prod-http-redirect`, `host-portal-cloudrun-lb-prod-url-map`, `k8s2-rm/um-ntvib007-globus-prod-globus-app-m2o6eumc`, `k8s2-rm/um-ntvib007-n8n-n8n-oo31h519`, `k8s2-rm/um-ntvib007-wildpacks-prod-wildpacks-app-cv655hwn`, `ppp2-applicants-prod-http-redirect`, `ppp2-applicants-prod-url-map`

**backend services:** `host-portal-cloudrun-client-backend`, `host-portal-cloudrun-server-backend`, `k8s1-ccab3f00-globus-prod-globus-app-80-a92d7301`, `k8s1-ccab3f00-kube-system-default-http-backend-80-642cd59f`, `k8s1-ccab3f00-n8n-n8n-80-b00c6e74`, `k8s1-ccab3f00-wildpacks-prod-wildpacks-app-80-4527075f`, `ppp2-client-prod-backend`, `ppp2-server-prod-backend`

**https proxies:** `host-portal-cloudrun-lb-prod-https-proxy`, `k8s2-ts-...-globus-prod-globus-app`, `k8s2-ts-...-n8n-n8n`, `k8s2-ts-...-wildpacks-prod-wildpacks-app`, `ppp2-applicants-prod-https-proxy`

**vpcs:** `default`, `skilled-script-vpc-prod`

**firewall rules:** `default-allow-internal`, `fw-prod-allow-internal`, `gke-globus-cluster-prod-c4b72319-all`, `gke-globus-cluster-prod-c4b72319-vms`, `k8s-fw-l7--ccab3f00c36e3a86`

**vpc access connectors:** `applicant-kc-connect`, `host-portal-connect`, `keycloak-prod-connect`

**addresses:** `globus-prod-ip`, `google-managed-services-default`, `host-portal-cloudrun-lb-prod-ip`, `n8n-prod-ip`, `ppp2-applicants-prod-ip`, `sql-peering-range-skilled-script-vpc-prod`, `wildpacks-prod-ip`, `globus-mcp-egress-ip-prod`

**domain mappings:** `sandbox.allianceabroad.com`, 

### Live networking: quality-assurance-496022

**forwarding rules:** `host-portal-qa-http-fr`, `host-portal-qa-https-fr`, `k8s2-fr-dldhgxjl-globus-qa-globus-app-e4hk5n6x`, `k8s2-fs-dldhgxjl-globus-qa-globus-app-e4hk5n6x`, `k8s2-fr-dldhgxjl-n8n-n8n-byrpazcm`, `k8s2-fs-dldhgxjl-n8n-n8n-byrpazcm`, `ppp2-applicants-qa-http-fr`, `ppp2-applicants-qa-https-fr`

**url maps:** `host-portal-qa-urlmap`, `k8s2-rm-dldhgxjl-n8n-n8n-byrpazcm`, `k8s2-um-dldhgxjl-globus-qa-globus-app-e4hk5n6x`, `k8s2-um-dldhgxjl-n8n-n8n-byrpazcm`, `ppp2-applicants-qa-http-redirect`, `ppp2-applicants-qa-url-map`

**backend services:** `host-portal-qa-client-bes`, `host-portal-qa-server-bes`, `k8s1-2188e754-globus-qa-globus-app-80-b29406a7`, `k8s1-2188e754-kube-system-default-http-backend-80-52aa031e`, `k8s1-2188e754-n8n-n8n-80-567bbba8`, `ppp2-client-qa-backend`

**target https proxies:** `host-portal-qa-https-proxy`, `k8s2-ts-dldhgxjl-globus-qa-globus-app-e4hk5n6x`, `k8s2-ts-dldhgxjl-n8n-n8n-byrpazcm`, `ppp2-applicants-qa-https-proxy`

**target http proxies:** `host-portal-qa-http-proxy`, `k8s2-tp-dldhgxjl-globus-qa-globus-app-e4hk5n6x`, `k8s2-tp-dldhgxjl-n8n-n8n-byrpazcm`, `ppp2-applicants-qa-http-proxy`

**ssl certificates:** `host-portal-qa-cert`, `mcrt-48f3657e-ed2f-47ba-a04e-93b2af806fbe`, `mcrt-4bc55357-3e3c-4bf0-9de4-84110272ea9c`, `mcrt-be08f141-13fc-4213-98a6-1ec04cac4423`, `ppp2-applicants-qa-cert`, `ppp2-applicants-qa-wildpacks-cert`

**negs:** `host-portal-qa-client-neg (SERVERLESS)`, `host-portal-qa-server-neg (SERVERLESS)`, `ppp2-participant-client-qa-neg (SERVERLESS)`, `k8s1-2188e754-globus-qa-globus-app-80-b29406a7 (GCE_VM_IP_PORT, zonal x4)`, `k8s1-2188e754-kube-system-default-http-backend-80-52aa031e (GCE_VM_IP_PORT, zonal x4)`, `k8s1-2188e754-n8n-n8n-80-567bbba8 (GCE_VM_IP_PORT, zonal x4)`

**vpcs:** `default`, `skilled-script-vpc-qa`

**custom subnets:** `sb-qa-dmz`, `us-central1-db-subnet`, `us-central1-web-subnet`, `cloudrun-direct-egress-subnet`

**firewall rules:** `default-allow-internal`, `fw-qa-allow-internal`, `gke-globus-cluster-qa-0b3cf4aa-all`, `gke-globus-cluster-qa-0b3cf4aa-exkubelet`, `gke-globus-cluster-qa-0b3cf4aa-inkubelet`, `gke-globus-cluster-qa-0b3cf4aa-vms`, `k8s-fw-l7--2188e7542740cb43`

**vpc connectors:** `keycloak-qa-connect`, `applicant-kc-connect`, `host-portal-connect`

**routers:** `globus-cloud-router-qa`

**addresses:** `globus-qa-ip`, `host-portal-qa-ip`, `n8n-qa-ip`, `ppp2-applicants-qa-ip`, `globus-mcp-egress-ip-qa`, `google-managed-services-default`, `sql-peering-range-skilled-script-vpc-qa`

**domain mappings:** `qa-1.sandbox.allianceabroad.com`, `qa-2.sandbox.allianceabroad.com`, `qa-3.sandbox.allianceabroad.com`, `qa.apply.allianceabroad.com`, `qa.apply.wildpacks.com`

## How the pieces fit together

Each of development, QA and production has the same two-network shape, built with `modules/network`. The `default` auto-mode network carries GKE (`globus-cluster-<env>`), most Cloud SQL private IPs and Redis, and, in QA and production, the Keycloak connectors (`keycloak-<env>-connect`, `applicant-kc-connect`); in development it carries `default-net-connect`. A custom network (`skilled-script-vpc-npe`, `skilled-script-vpc-qa`, `skilled-script-vpc-prod`) has four fixed subnets: a DMZ, a DB subnet and a web subnet in `us-central1`, and `cloudrun-direct-egress-subnet` in `northamerica-northeast1`. Cloud Run services that need private addresses reach them through Serverless VPC connectors declared in the same module (`host-portal-connect` on the custom network, `applicant-kc-connect` and `keycloak-prod-connect` on `default`, and similar; development also has `applicant-portal-connect`). The `alliance-mcp-services` snapshot shows only the auto-mode `default` network, and the Serverless VPC Access API is not enabled there, so it has no connectors.

Private service access (`psa_range_name` in `modules/network`) reserves a `VPC_PEERING` range and a servicenetworking connection so Cloud SQL can use private IPs. Development also has a plain peering `dev-to-ocr` to the `globus-ocr-vpc` network in project `globus-ocr`, which the module cannot express, so it is a standalone resource in `environments/development/main.tf`. Every resource in `modules/network` and `modules/firewall-rule` carries `prevent_destroy`.

## Firewall rules

Terraform declares only the hand-made rules: `default-allow-internal` on the default network, one `fw-<env>-allow-internal` rule on the custom network (source `10.0.0.0/8`, target tag `allow-internal`), and in development `default-allow-ssh`. GKE-generated rules (`gke-*`, `k8s-fw-*`) are left to GKE. This is why the drift report shows firewall rules as platform-created rather than live-only.

The no-`0.0.0.0/0`-SSH rule: QA and production comments in `environments/qa/main.tf` and `environments/production/main.tf` state that `default-allow-ssh` and `default-allow-rdp` were deliberately not recreated, and the prod and QA snapshots list no SSH rule. Development keeps `default-allow-ssh` but limited to one `/32` address. A comment in the development file says QA and prod use `0.0.0.0/0` for this rule; that contradicts the QA and prod files and snapshots, so treat the comment as stale.

## Global HTTPS load balancers

Two modules build the Cloud Run front doors. `modules/load-balancer-https` is single-host: static IP, one classic managed certificate, one serverless NEG, an optional second NEG and backend for an `/api` split, an HTTP-to-HTTPS redirect URL map, and both forwarding rules. `modules/load-balancer-https-multihost` has one URL map with a host rule and path matcher per hostname, any number of NEGs and backends, per-backend `iap_enabled`, and path rules with an optional URL rewrite. Both use `create_before_destroy` on NEGs and certs because replacements otherwise fail on name reuse or on a NEG still referenced by a backend.

Live users of these modules:

- **Applicant Portal client** (`ppp2_applicants_qa_lb`, `ppp2_applicants_prod_lb`): single-host stacks; the prod cert covers the allianceabroad.com and wildpacks.com applicant domains. The cert was renamed to `-v2` because classic managed cert `domains` are immutable and cert names are unique.
- **Shared MCP LB** (`mcp_gateway_lb` in `environments/mcp/main.tf`): one multihost LB with hosts `mcp`, `mcp-admin` and `platform` on allianceabroad.com. `mcp` routes to the gateway backend without IAP and rewrites `/` to `/mcp`; `mcp-admin` defaults to the IAP-protected admin UI and sends `/api` and `/auth` to a second IAP backend that shares the gateway NEG; `platform` defaults to an IAP backend and sends `/mcp` to a non-IAP backend (the app does its own API-key auth). The backing `platform-hub` Cloud Run service is configured with the `MCP_GATEWAY_URL` environment variable (set to `https://mcp.allianceabroad.com`) and `GATEWAY_PAT` (from the `platform-hub-gateway-pat` secret). Certs are split in two (`mcp-cert`, `platform-hub-cert`) so a pending cert does not affect the working hosts. The `environment-index` board for the legacy portal hosts was first served by this LB; that first home in `alliance-mcp-services` is being removed, and the board has moved to `alliance-platform-services` (see below).
- **Production Host Portal** (`host_portal_cloudrun_lb_prod`): replaced the GKE ingress on 2026-09-18 per the comments in `host-portal-dual-domain-cloudrun-lb-design.tf`. Hosts `hosts.allianceabroad.com` and `hosts.wildpacks.com` send `/api` to the server Cloud Run service and everything else to the client.
- Development and QA Host Portal LBs (`host-portal-development-*`, `host-portal-qa-*`) and the development applicant LB (`ppp2-applicants-dev-*`) exist live but are not declared as load balancer resources in Terraform; only their static IPs are. See the environment pages.
- **environment-index board** (`environments/platform-services/environment-index.tf`): a singleton board on the existing hand-built LB in `alliance-platform-services`, using plain `google_*` resources rather than these modules. Its LB pieces were created by hand; the file records live intent plus import-ready definitions, and that root module has never been applied. The legacy hosts `development.applicants`, `qa.applicants`, `development.apply`, `dev.apply`, `qa.apply`, `development.hosts` and `qa.hosts` on allianceabroad.com are one host rule on `nexus-hub-url-map`, whose path matcher `environment-index-matcher` defaults to `environment-index-backend` (EXTERNAL, HTTP). That backend uses the serverless NEG `environment-index-neg` in `us-central1`, which fronts the `environment-index` Cloud Run service. The managed cert `environment-index-ssl-cert` covers the seven hostnames and is attached to `nexus-hub-https-proxy`, and the GoDaddy A records for the seven hosts point to `nexus-hub-lb-ip`.

GKE ingress load balancers (`k8s2-*`) for Globus, n8n and WildPacks are created by Kubernetes manifests in the app repos, not by Terraform. Terraform only reserves the static IPs they claim by name.

## Certificates

The Terraform load balancer modules create classic Google-managed certificates (`google_compute_managed_ssl_certificate`). Classic certs only reach ACTIVE after DNS for the domain already resolves to the LB, so the order is: create LB and IP, point the GoDaddy record, then wait for the cert. A Google-managed cert is only served once every domain on it is ACTIVE. In `environments/mcp/main.tf`, `env-board-cert` keeps all five of its domains, and a second cert, `env-board-applicants-cert`, carries just the three already-validated hosts (including `development.applicants.allianceabroad.com` and `qa.applicants.allianceabroad.com`) so they can serve. The multihost module can instead take a Certificate Manager `certificate_map_id`. In production the Certificate Manager resources (DNS authorizations, certs, map) are declared in `host-portal-dual-domain-cloudrun-lb-design.tf` but not referenced by the proxy: switching to the map would have destroyed two ACTIVE classic certs while the DNS-authorization CNAMEs were never added, risking an outage. The prod snapshot shows the Certificate Manager certs still PROVISIONING and `certificate_map` null on the proxy. Do not flip the proxy to the map until those CNAMEs exist and the certs are ACTIVE. In QA, `certificatemanager.googleapis.com` is enabled in `environments/qa/main.tf` for Certificate Manager DNS authorizations, certificates and maps for the Globus GKE QA pool; it is not enabled in `alliance-mcp-services`.

## Cloud Run domain mappings

`modules/domain-mapping` wraps `google_cloud_run_domain_mapping` for one hostname to one service and ignores `certificate_mode` and label changes, because the provider otherwise plans a destroy-and-recreate of a live public domain. Terraform declares `qa.apply.allianceabroad.com` (QA) and `sys.n8n.allianceabroad.com` (`environments/platform-services/sys-n8n.tf`). The sandbox hostnames (`dev-N`, `qa-N`, `sandbox`) are created by hand with `gcloud beta run domain-mappings create` because the Terraform identity is not a verified domain owner; a `removed` block in the development file makes state forget the old failed entries. The drift pattern is therefore consistent: live-only domain mappings are the sandbox slots, the WildPacks `apply` hosts in development (`dev.apply`, `development.apply`) and `qa.apply.wildpacks.com` in QA, and `teams-mcp.mcp.allianceabroad.com`, which is broken (Ready false) and superseded by the LB. Development also holds `nexus.allianceabroad.com` mapped to a service not in the Cloud Run list (dangling).

## DNS

Every Cloud DNS zone in the snapshots is private: a GKE `cluster.local.` zone in each of development, QA and production, plus Document AI and default private-service-connect zones in development. The `alliance-mcp-services` DNS section was not readable. No public zone for allianceabroad.com or wildpacks.com is declared in Terraform or visible in the snapshots; the files say public DNS is at GoDaddy. Domain-mapping hosts use a CNAME to `ghs.googlehosted.com`; LB hosts use A records to the static IP, created by hand. `repo-inventory` lists DNS records under the scope of `alliance-gcp-infra`, which the code does not support. Dangling CNAMEs for removed Keycloak mappings (`auth`, `qa.auth`) are noted in the prod and QA files.

## Cloud Armor, IAP and ingress

- **Cloud Armor**: no policy is declared in Terraform. The development snapshot lists four policies: two `default-security-policy-for-*` policies named for the applicant backends, `manus-mcp-security-policy`, and a stale `virtual-interviews-security-policy`; which backends each is attached to was not captured. The QA, production and MCP snapshots list none.
- **IAP**: enabled per backend service on the MCP LB (`mcp-admin-backend`, `mcp-admin-api-backend`, `platform-hub-backend`) using Google-managed OAuth, with no client ID in Terraform. The accessor grant is modeled only for `platform-hub-backend`; the other two are unverified. `iap.googleapis.com` is not enabled in QA.
- **Cloud Run ingress**: almost every Cloud Run service declared in Terraform sets ingress to `all`. The exceptions are the platform-hub service (`internal-and-cloud-load-balancing`, reached through the MCP LB) and the IT request portal in platform-services (`INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER`). `modules/cloud-run-service` defaults to the internal-and-LB value. The prod Host Portal comments list tightening ingress as an open follow-up, and the development snapshot reports ingress `all` on every service, so the load balancers are not the only way in. See [dev-only-deployment-policy](/docs/dev-only-deployment-policy) and [git-branching-release-model](/docs/git-branching-release-model) for how changes reach these resources.

## Security observations

- Every Cloud Run service in development has ingress `all`, and prod Host Portal services have ingress `all` plus `allUsers` invoker, behind a load balancer that does not enforce it. Review whether the services should accept only load balancer traffic.
- Development has `default-allow-ssh` open to a single external address; QA and prod have no SSH rule in the snapshots. The GKE-managed `exkubelet` rules show source `0.0.0.0/0` with no allowed protocols listed.
- No Cloud Armor policy is declared in Terraform, and the QA, production and MCP snapshots list none, so the public load balancers there have no Cloud Armor protection in the captured state.
- A dangling Cloud Run domain mapping (`nexus.allianceabroad.com`) and the dangling GoDaddy CNAMEs for removed Keycloak mappings (`auth`, `qa.auth`) are takeover candidates if the target is reused. Review them.

## Known gaps

- `alliance-platform-services` could not be read; its one declared domain mapping is unverified. `alliance-mcp-services` was read through a development token with several sections denied, and its DNS section is null.
- Terraform README says development and production are not under Terraform; the `.tf` files show they are.
- Subnet lists were truncated or partial in some snapshots; QA connector regions were inferred or not captured.
- GoDaddy records were not read, so public DNS correctness is not verified.
- Vertex project networking was not enumerable (compute API disabled).
