Gateway Cloudflare Terraform IaC#3
Conversation
…ign spec
Mirrors background-agents TF pattern scoped to the gateway: modules/cloudflare-{kv,worker} + environments/production, R2 S3 state backend, secrets as tfvars. apps/gateway gets a build script for the TF local-exec. terraform fmt + validate pass. Gateway application code stays the C3 scaffold (separate workstream).
There was a problem hiding this comment.
Pull request overview
Adds Cloudflare Terraform IaC scoped to the mobile gateway: a reusable cloudflare-kv + cloudflare-worker module pair and a production/ root that wires up a single Worker (with KV, plain-text/secret bindings, optional custom domain, and a push cron) backed by an R2 S3 state backend. The PR also adds a build script for the gateway (used by a TF local-exec), repo-wide .gitignore hardening for TF/secrets artifacts, pins the package manager, and ships a design spec + README runbook. It is independent of the mobile-app PR.
Changes:
- New
terraform/tree: KV + Worker modules and aproductionenvironment with R2 S3 backend, variables, locals, outputs, and acheckblock for required inputs. - Gateway build wiring:
apps/gatewaygains abuildscript;null_resource.gateway_buildruns it via local-exec before deploy. - Repo hygiene/docs:
.gitignoreexpansion (secrets, TF state/tfvars), pnpm version pin in rootpackage.json, design spec +terraform/README.mdrunbook.
Reviewed changes
Copilot reviewed 23 out of 25 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| terraform/README.md | Runbook + prerequisites + secret-hygiene notes. |
| terraform/modules/cloudflare-worker/{main,variables,outputs,versions}.tf | Worker module: 3-resource v5 pattern, KV/plain/secret bindings, optional custom domain/route, cron trigger. |
| terraform/modules/cloudflare-kv/{main,variables,outputs,versions}.tf | Minimal KV namespace module. |
| terraform/environments/production/versions.tf | Pins terraform >=1.14, cloudflare ~>5.16, null ~>3.0, configures provider. |
| terraform/environments/production/backend.tf | R2 S3 backend with R2-compat skip flags. |
| terraform/environments/production/backend.tfvars.example | Backend credentials template. |
| terraform/environments/production/variables.tf | Inputs incl. account/api token, build path, urls, secrets. |
| terraform/environments/production/locals.tf | Worker/KV names and built script path. |
| terraform/environments/production/kv.tf | Instantiates KV module. |
| terraform/environments/production/worker-gateway.tf | Build local-exec + worker module wiring with bindings/cron/custom domain. |
| terraform/environments/production/outputs.tf | gateway_url, worker name, KV id outputs. |
| terraform/environments/production/checks.tf | Asserts required inputs are non-empty. |
| terraform/environments/production/moved.tf | Placeholder for future state moves. |
| terraform/environments/production/terraform.tfvars.example | Tfvars template (contains a personal absolute path). |
| terraform/environments/production/.terraform.lock.hcl | Committed provider lock file. |
| apps/gateway/package.json | Adds build script invoked by TF. |
| package.json | Adds packageManager pin. |
| .gitignore | Repo-wide secrets + Terraform artifact ignores. |
| docs/superpowers/specs/2026-05-17-gateway-terraform-design.md | Design spec. |
Files not reviewed (1)
- terraform/environments/production/.terraform.lock.hcl: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| cloudflare_api_token = "" # Workers Scripts + KV + Routes edit | ||
|
|
||
| # Absolute path to this monorepo checkout (for the build local-exec): | ||
| project_root = "/Users/quantumly/Documents/Development/Refrakts/constructor-mobile" |
| resource "cloudflare_workers_cron_trigger" "this" { | ||
| count = length(var.cron_triggers) > 0 ? 1 : 0 | ||
|
|
||
| account_id = var.account_id | ||
| script_name = cloudflare_worker.this.name | ||
| schedules = [for expr in var.cron_triggers : { cron = expr }] | ||
|
|
||
| depends_on = [cloudflare_workers_deployment.this] | ||
| } |
| resource "null_resource" "gateway_build" { | ||
| triggers = { | ||
| always_run = timestamp() | ||
| } | ||
|
|
||
| provisioner "local-exec" { | ||
| command = "pnpm --filter gateway run build" | ||
| working_dir = var.project_root | ||
| } | ||
| } |
| zone_id = var.zone_id | ||
| custom_domain = var.gateway_custom_domain |
| length(trimspace(var.github_oauth_client_secret)) > 0 && | ||
| length(trimspace(var.control_plane_url)) > 0 && | ||
| length(trimspace(var.ws_url)) > 0 | ||
| ) | ||
| error_message = "internal_callback_secret, app_jwt_signing_key, github_oauth_client_secret, control_plane_url and ws_url must all be set in terraform.tfvars." |
Adds terraform/ (modules/cloudflare-{kv,worker} + environments/production, R2 state backend) + apps/gateway build script + design spec. Independent of the mobile app.
Scope
Infrastructure-as-Code for the mobile gateway only — mirrors background-agents's Terraform pattern, scoped to one Worker + one KV. Independent of the mobile-app PR.
Contents
Verification
terraform fmt clean; terraform validate -> Success (provider v5 schema confirmed); commit GPG-signed; no secrets/state committed (only *.example).
Notes
This provisions infrastructure only — apps/gateway/src is still the create-cloudflare scaffold; the HMAC proxy / OAuth / cron-poll logic is a separate workstream. Shares the final .gitignore/package.json with PR #2 (identical content -> conflict-free in any merge order).