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.comMX 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.comis DNS data, not a paid OCI Email Delivery domain registration. -
Operational surface:
- Two
cloudflare-dnsmodule calls in each env composition file, one per zone. Zone IDs must be maintained as tfvars per env;infra-agentaddsvar.marnissi_zone_idandvar.quantmods_zone_id. - Two
cloudflare-wafmodule 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.commust be applied before DMARCp=rejectis reached. DMARC progression forquantmods.comfollows the same Day 0/30/60 ladder defined in ADR-0006 formarnissi-holdings.com, starting from when the first@quantmods.comemail is sent. -
moved {}blocks ortofu state mvrequired for all renamed resources incloudflare-dnsmodule. A dry-runtofu planshowing zero destroys must be verified by the operator beforetofu apply. -
Security posture:
- HSTS with
includeSubDomainsis applied toquantmods.comfrom day one. Any future subdomain added underquantmods.commust serve HTTPS.secops-agentenforces this on every infra PR. - SPF for
quantmods.comis narrow:include:_spf.google.com ~all. No OCI Email Delivery include is added (no outbound from this domain). SPF hardens to-allafter DMARCp=rejectfor this zone, following the same progression logic asmarnissi-holdings.com. - DMARC
aspf=s; adkim=sstrict alignment from day one onquantmods.com. No relaxed alignment. - Token scope is unchanged —
mgh-iac-accountis already account-scoped and coversquantmods.comwithout modification.secops-agentconfirms no permission rows are added. -
secops-agentchecklist additions for PRs touchingquantmods.comzone: (a) HSTS settings present and matchmarnissi-holdings.composture; (b) MX records point at Google, not CF Email Routing servers; (c) DKIM CNAME deployed beforep=rejectescalation; (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.comis 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. |