Skip to content

ADR-0012: Multi-brand Cloudflare zone topology — quantmods.com as a peer zone sharing the same CF account and API token

  • Status: Accepted — implemented 2026-06-06 (quantmods.com zone live in CF; Workspace alias DNS applied: 5 MX + SPF + DMARC + DKIM TXT; stale smtp.google.com MX removed)
  • Date: 2026-06-06
  • Deciders: cloud-architect, cloudflare-expert, oci-expert, finops-agent, secops-agent, marnissi.investments

Context

MGH is adding a second brand, Quantmods, which provides quant-finance solutions across banking, asset management, fintech, trading, public, gaming, and e-commerce verticals. The domain quantmods.com is registered and already present as a Cloudflare zone in the same account (caf03872e5c0063df82eb353430b7e78) that hosts marnissi-holdings.com. It is also configured as a Google Workspace alias domain of the primary tenant marnissi-holdings.com — one Workspace organisation, two addressable email domains. The user skander@marnissi-holdings.com is simultaneously reachable at skander@quantmods.com; all mailboxes are the same Workspace accounts.

Today the infra/modules/cloudflare-dns/ module is written against a single, hard-assumed zone (marnissi-holdings.com). ADR-0006 established the DNS baseline and zone topology for that zone but did not anticipate a second brand. The Tofu module must be extended to support N zones without duplicating module code, and a clear ownership model for zone resources (settings, email auth records, hostname CNAMEs, CF Access apps) must be recorded before infra-agent touches the HCL.

The quantmods.com zone requires at a minimum: zone hardening settings mirroring marnissi-holdings.com (SSL strict, HSTS, minimum TLS 1.2 — ADR-0006), email auth DNS records for the Google Workspace alias relationship (MX, SPF, DKIM CNAME, DMARC), and a public-website hostname for the apex and www. No Cloudflare Access applications are needed today — quantmods.com exposes a public-facing website only.

The Cloudflare API token mgh-iac-account (account-scoped, expiry 2028-01-01, documented in workspace CLAUDE.md) currently holds Zone DNS: Edit, Zone Settings: Edit, Zone WAF: Edit, and other zone-level permissions. Because the token is account-scoped, it already has authority over every zone in the account, including quantmods.com. No new token is needed.

Decision

Add quantmods.com as a peer Cloudflare zone managed in the same Tofu workspace as marnissi-holdings.com. Parameterise the infra/modules/cloudflare-dns/ module to accept a brand profile input object that carries all zone-specific values — zone_id, zone_name, optional MX/SPF/DKIM inputs, a boolean enable_access_apps, and an optional list of custom hostname entries. Each brand zone becomes one module call in the environment composition (envs/dev/main.tf, envs/prod/main.tf). Both zones are owned by envs/dev/ initially; promotion of either zone to envs/prod/ follows the same state-migration runbook already established for marnissi-holdings.com (pattern documented in ADR-0006 migration path).

Module parameterisation. The existing cloudflare-dns module is refactored by infra-agent to accept the brand profile as a Tofu variable object. All resource names and tags that today embed the string "marnissi-holdings" are replaced with var.brand.zone_name or a sanitised slug derived from it. infra-agent must ensure no existing resource is destroyed during this refactor — a moved {} block or explicit tofu state mv is required for every renamed resource. cloudflare-expert reviews the renamed resource set before apply.

Zone hardening settings for quantmods.com. Apply the same zone hardening settings specified in ADR-0006 to quantmods.com: SSL/TLS full_strict, Always Use HTTPS on, Automatic HTTPS Rewrites on, Minimum TLS 1.2, HSTS (max_age=31536000; includeSubDomains; preload), Security Level medium. These are not negotiable; secops-agent verifies them on every infra PR touching the quantmods.com zone.

Email auth records for quantmods.com — Workspace alias scope only. quantmods.com is a Google Workspace alias domain, not a separate tenant. The DNS records required are:

Record Type Value CF proxied
quantmods.com MX 1 ASPMX.L.GOOGLE.COM false
quantmods.com MX 5 ALT1.ASPMX.L.GOOGLE.COM false
quantmods.com MX 5 ALT2.ASPMX.L.GOOGLE.COM false
quantmods.com MX 10 ALT3.ASPMX.L.GOOGLE.COM false
quantmods.com MX 10 ALT4.ASPMX.L.GOOGLE.COM false
quantmods.com TXT (SPF) v=spf1 include:_spf.google.com ~all false
google._domainkey.quantmods.com CNAME (DKIM) <workspace-dkim-target> (operator-provided after enabling DKIM in Workspace Admin Console for this alias domain) false
_dmarc.quantmods.com TXT (DMARC) v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@marnissi-holdings.com; aspf=s; adkim=s false

The DMARC rua address deliberately points back to marnissi-holdings.com. Alias domains share the primary domain's Workspace account; DMARC aggregate reports for mail sent as @quantmods.com addresses are collected at the primary domain's reporting address. Enabling DKIM for an alias domain is a one-time action in the Workspace Admin Console (Admin Console → Apps → Google Workspace → Gmail → Authenticate email → select quantmods.com → Generate new record). The resulting CNAME host and value are operator-provided tfvars inputs (var.quantmods_dkim_cname_host, var.quantmods_dkim_cname_value). These are not secrets; they are DNS record data and belong in infra/envs/dev/terraform.tfvars.

No CF Email Routing on quantmods.com. Cloudflare Email Routing requires MX records to point at CF's routing servers. The quantmods.com zone MX records point at Google instead (for Workspace alias inbound delivery). These are mutually exclusive. No inbound catch-all routing is needed on quantmods.com — Workspace handles inbound for both @marnissi-holdings.com and @quantmods.com via the single primary tenant.

No OCI Email Delivery for quantmods.com. Transactional email (password resets, notifications, billing emails) continues to originate from no-reply@marnissi-holdings.com via OCI Email Delivery (ADR-0005). The brand voice for transactional email treats marnissi-holdings.com as the corporate-of-record. Adding a second OCI Email Delivery domain for quantmods.com would require a second domain verification sequence, a second DKIM selector, and a separate SPF include — operational cost with no user-facing benefit for v1. Revisit if Quantmods requires separate transactional brand identity.

Workspace alias relationship — operator-side actions. Adding the alias domain to Workspace (Admin Console → Account → Domains → Add a domain → Add an alias domain) is a one-time manual operation not expressible in Tofu. The operator completes this action and then retrieves the Workspace-generated TXT verification token and DKIM CNAME values, which become tfvars inputs. This dependency is recorded in the env composition comment and the relevant runbook section.

CF Access apps for quantmods.com. None are created by this ADR. The quantmods-website is a public-facing property. If a future admin surface is added to quantmods.com, an Access app is created at that time per ADR-0008 pattern.

WAF for quantmods.com. The modules/cloudflare-waf/ module (ADR-0010) must be called once per zone. A second module invocation for the quantmods.com zone ID applies the same Free Managed Ruleset and zone-level hardening. The hostname_allowlist for the quantmods.com zone covers: quantmods.com, www.quantmods.com, and any *.dev.quantmods.com dev-tier hostnames introduced in ADR-0013.

OCIR repo additions. The OCI Container Image Registry receives one new repo: quantmods-website (for the quantmods-website Next.js static Worker deploy artifact, if any Worker image is needed). The existing repos mgh-admin-backend and mgh-admin-frontend are renamed to mgh-admin-api and mgh-admin-ui respectively (the backend has no images pushed, making this a clean rename window). These OCIR changes are infra-agent scope; this ADR records the intent.

Cross-references. This ADR supersedes the single-zone assumption of ADR-0006 (DNS baseline now per-zone, not zone-singular). It is compatible with ADR-0008 (Access apps remain per-hostname; quantmods.com has none today). It is compatible with ADR-0010 (WAF hostname_allowlist extends per-zone as noted above). ADR-0013 (dev subdomain layering) codifies the hostname matrix for both zones.

Consequences

  • Cost (delta vs free tier): $0. Cloudflare Free plan allows multiple zones per account at no cost. The additional zone adds DNS records, zone settings, and a WAF managed ruleset call — all free. OCI costs are unchanged (no new compute or storage for the zone itself). The DKIM CNAME for quantmods.com is DNS data, not a paid OCI Email Delivery domain registration.

  • Operational surface:

  • Two cloudflare-dns module calls in each env composition file, one per zone. Zone IDs must be maintained as tfvars per env; infra-agent adds var.marnissi_zone_id and var.quantmods_zone_id.
  • Two cloudflare-waf module calls, one per zone.
  • DMARC aggregate reports for both domains land at dmarc-reports@marnissi-holdings.com. Operator reviews both domain streams together. The reporting alias is already configured via CF Email Routing (ADR-0009).
  • Workspace alias domain setup is a one-time operator action; document the step sequence in infra/scripts/runbooks/add-brand-domain.md.
  • DKIM CNAME for quantmods.com must be applied before DMARC p=reject is reached. DMARC progression for quantmods.com follows the same Day 0/30/60 ladder defined in ADR-0006 for marnissi-holdings.com, starting from when the first @quantmods.com email is sent.
  • moved {} blocks or tofu state mv required for all renamed resources in cloudflare-dns module. A dry-run tofu plan showing zero destroys must be verified by the operator before tofu apply.

  • Security posture:

  • HSTS with includeSubDomains is applied to quantmods.com from day one. Any future subdomain added under quantmods.com must serve HTTPS. secops-agent enforces this on every infra PR.
  • SPF for quantmods.com is narrow: include:_spf.google.com ~all. No OCI Email Delivery include is added (no outbound from this domain). SPF hardens to -all after DMARC p=reject for this zone, following the same progression logic as marnissi-holdings.com.
  • DMARC aspf=s; adkim=s strict alignment from day one on quantmods.com. No relaxed alignment.
  • Token scope is unchanged — mgh-iac-account is already account-scoped and covers quantmods.com without modification. secops-agent confirms no permission rows are added.
  • secops-agent checklist additions for PRs touching quantmods.com zone: (a) HSTS settings present and match marnissi-holdings.com posture; (b) MX records point at Google, not CF Email Routing servers; (c) DKIM CNAME deployed before p=reject escalation; (d) no CF Access app accidentally omitted on an internal hostname; (e) WAF module call present for the zone.

  • Migration path if we revisit: If quantmods.com is removed from the MGH portfolio, the Tofu module call for the zone is deleted, the zone is removed from the CF account via the dashboard, and the Workspace alias domain is removed in Admin Console. No OCI resources change. Estimated effort: one PR plus operator Workspace action. Fully reversible.

Alternatives considered

Option Why rejected
Separate CF account for quantmods.com Requires a second CF account login, separate token management, separate Zero Trust organisation, and cannot share the same tunnel (mgh-dev/mgh-prod) directly. Operational overhead of two accounts outweighs any isolation benefit for a single-operator team.
Subdomain of marnissi-holdings.com (e.g., quantmods.marnissi-holdings.com) Loses the brand identity of a dedicated apex domain. HSTS preload for the parent zone would already cover a subdomain, but the product positioning requires quantmods.com as the customer-facing URL. Also cannot host independent email auth records at a subdomain apex.
Separate Google Workspace tenant for quantmods.com Doubles the Workspace subscription cost and splits user identity across two IdPs. CF Access would need a second OIDC IdP configuration (ADR-0008). The alias-domain approach satisfies all operational requirements with zero additional cost and single-IdP simplicity.
One monolithic cloudflare-dns module call with zone lists Using a for_each over a list of zones in a single module invocation couples zone configurations tightly and makes per-zone differences (email auth records, Access app presence, DKIM targets) awkward to express. One parameterised module call per zone is more readable, testable, and independently applicable.
Hardcode quantmods.com zone settings outside the existing module A one-off HCL file for the second zone accumulates technical debt immediately — every change to zone hardening settings must be applied to two files. Parameterising the shared module and calling it twice is the correct DRY approach.