Email Integration -- Infrastructure Design
Infrastructure resources that must be provisioned before the email-sending components can be deployed and function.
Scopes
Section titled “Scopes”Infrastructure resources are scoped to be global to the complete platform (Platform scope), managed as part of an Infrastructure, or as part of a Partition within an Infrastructure
Parameters
Section titled “Parameters”This document is parametrized on the mail root domain — the top-level domain under which all tenant sending subdomains are created. The choice of root domain is an open decision (see DQ-009).
| Parameter | Notation | Example values |
|---|---|---|
| Mail root domain | {mail-root-domain} | One of: ardamails.com, ardamails.net, already owned |
| DNS registrar | {registrar} | Amazon (Route53) |
- Root Account (hosting root domain zone):
platformRoot, account Id841876193886
Route53 DNS
Section titled “Route53 DNS”Hosted Zones
Section titled “Hosted Zones”| # | Resource | Scope | Notes |
|---|---|---|---|
| DNS-Z1 | Hosted zone {mail-root-domain} | Platform | Created as part of domain registration in platformRoot account. NS set at {registrar} (one-time). |
| DNS-Z2 | Hosted zone dev.{mail-root-domain} | Partition: Alpha002/dev | Delegated from root zone |
| DNS-Z3 | Hosted zone stage.{mail-root-domain} | Partition: Alpha002/stage | Delegated from root zone |
| DNS-Z4 | Hosted zone prod.{mail-root-domain} | Partition: Alpha001/prod | Delegated from root zone |
| DNS-Z5 | Hosted zone demo.{mail-root-domain} | Partition: Alpha001/demo | Delegated from root zone |
Static Records (in root zone)
Section titled “Static Records (in root zone)”The root zone is managed as infrastructure. It contains only NS delegations and parent email authentication records. No runtime-provisioned tenant records live here (see DQ-010).
| # | Type | Name | Value / Target | Scope |
|---|---|---|---|---|
| DNS-R1 | TXT | @ (SPF) | v=spf1 include:spf.mtasv.net ~all | Platform |
| DNS-R2 | TXT | _dmarc | v=DMARC1; p=reject; sp=reject | Platform |
| DNS-R3 | NS | dev | → DNS-Z2 nameservers | Partition: Alpha002/dev |
| DNS-R4 | NS | stage | → DNS-Z3 nameservers | Partition: Alpha002/stage |
| DNS-R5 | NS | prod | → DNS-Z4 nameservers | Partition: Alpha001/prod |
| DNS-R6 | NS | demo | → DNS-Z5 nameservers | Partition: Alpha001/demo |
Tenant Domain Shape
Section titled “Tenant Domain Shape”All partitions use the same FQDN structure: {config-slug}.{tenant-slug}.<partition>.{mail-root-domain}.
Even in v1 (single configuration per tenant), the {config-slug} is present. Its value is TBD. See DQ-002.
| Environment | Sending Domain FQDN | Example |
|---|---|---|
| Prod | {config-slug}.{tenant-slug}.prod.{mail-root-domain} | orders.acme.prod.{mail-root-domain} |
| Demo | {config-slug}.{tenant-slug}.demo.{mail-root-domain} | orders.acme.demo.{mail-root-domain} |
| Dev | {config-slug}.{tenant-slug}.dev.{mail-root-domain} | orders.acme.dev.{mail-root-domain} |
| Stage | {config-slug}.{tenant-slug}.stage.{mail-root-domain} | orders.acme.stage.{mail-root-domain} |
Per-Tenant DNS Records (runtime provisioned)
Section titled “Per-Tenant DNS Records (runtime provisioned)”When a tenant is onboarded, the following records are created in the partition zone for the sending domain {config-slug}.{tenant-slug}.<partition>.{mail-root-domain}. These are not infrastructure resources — they are created at runtime by the emailConfiguration service.
| Record Type | Name | Value | Purpose |
|---|---|---|---|
| TXT | {DKIMPendingHost} (from Postmark) | {DKIMPendingTextValue} (from Postmark) | DKIM signature verification |
| CNAME | pm-bounces.{config-slug}.{tenant-slug} | pm.mtasv.net | Return-Path / SPF alignment |
| TXT | _dmarc.{config-slug}.{tenant-slug} | v=DMARC1; p=none (ramped to quarantine then reject) | DMARC policy for the sending domain |
| MX | {config-slug}.{tenant-slug} | Not in v1 (Reply-To external). v2+: Postmark inbound MX | Inbound email routing (procurement inbox) |
See Postmark Service Design for the full provisioning flow and API details.
Reserved Subdomains
Section titled “Reserved Subdomains”The following names must be excluded from tenant slug allocation (enforced at provisioning time and in validation logic):
mail, dmarc, postmaster, abuse, api, www, admin, arda, arda-cards, platform
DNS records may be created for some of these at a later time to support specific features. For now they are simply blocked from use as tenant slugs.
Postmark Accounts
Section titled “Postmark Accounts”| # | Resource | Scope | Notes |
|---|---|---|---|
| PM-1 | PostmarkProd account | Infrastructure: Alpha001 | Manual, one-time. Live delivery (prod, demo). |
| PM-2 | PostmarkNonProd account | Infrastructure: Alpha002 | Manual, one-time. Sandbox delivery (dev, stage). |
| PM-3 | Platform plan on both accounts | Infrastructure: Alpha001, Alpha002 | Manual, one-time. Unlimited servers, domains, streams. |
| PM-4 | Account-level API token for PostmarkProd | Infrastructure: Alpha001 | Manual. Stored in SM-1/SM-2 below. |
| PM-5 | Account-level API token for PostmarkNonProd | Infrastructure: Alpha002 | Manual. Stored in SM-3/SM-4 below. |
Postmark Account Mapping
Section titled “Postmark Account Mapping”| Postmark Account | Partitions | Server Type |
|---|---|---|
| PostmarkProd | prod, demo | Live servers (real delivery) |
| PostmarkNonProd | dev, stage | Sandbox servers (delivery to blackhole) |
Per-Tenant Provisioning (runtime, not infrastructure)
Section titled “Per-Tenant Provisioning (runtime, not infrastructure)”The following are provisioned per tenant at runtime by the emailConfiguration service. They are not infrastructure prerequisites:
- Create Postmark server in the appropriate account
- Create sending domain; receive DKIM TXT record values and Return-Path CNAME target
- Publish per-tenant DNS records in the partition zone
- Configure webhooks with Bearer token auth (
POST /webhooks) - Encrypt server token with partition-wide encryption key and persist in database
- DNS verification proceeds asynchronously (see Scenario 1b)
AWS Secrets Manager
Section titled “AWS Secrets Manager”Secrets follow the Arda naming convention: {infrastructure}-{namespace}-I-{secretName}.
| # | Resource | Name | Scope | Holds |
|---|---|---|---|---|
| SM-1 | Postmark account API token | Alpha001-prod-I-EmailPostmarkAccountToken | Partition: Alpha001/prod | PM-4 token |
| SM-2 | Postmark account API token | Alpha001-demo-I-EmailPostmarkAccountToken | Partition: Alpha001/demo | PM-4 token (same value as SM-1) |
| SM-3 | Postmark account API token | Alpha002-dev-I-EmailPostmarkAccountToken | Partition: Alpha002/dev | PM-5 token |
| SM-4 | Postmark account API token | Alpha002-stage-I-EmailPostmarkAccountToken | Partition: Alpha002/stage | PM-5 token (same value as SM-3) |
| SM-5 | Tenant server token encryption key | Alpha001-prod-I-EmailEncryptionKey | Partition: Alpha001/prod | Symmetric key for encrypting per-tenant Postmark server tokens in the database |
| SM-6 | Tenant server token encryption key | Alpha001-demo-I-EmailEncryptionKey | Partition: Alpha001/demo | Symmetric key for encrypting per-tenant Postmark server tokens in the database |
| SM-7 | Tenant server token encryption key | Alpha002-dev-I-EmailEncryptionKey | Partition: Alpha002/dev | Symmetric key for encrypting per-tenant Postmark server tokens in the database |
| SM-8 | Tenant server token encryption key | Alpha002-stage-I-EmailEncryptionKey | Partition: Alpha002/stage | Symmetric key for encrypting per-tenant Postmark server tokens in the database |
Each partition gets its own secret entries, even when the underlying value is shared (e.g., PostmarkProd token is the same for prod and demo). This follows the convention that secrets are scoped per partition.
Per-tenant Postmark server tokens are not stored in Secrets Manager. They are encrypted with the partition-wide encryption key and persisted in the database by the emailConfiguration service. See functional.md for the encryption approach.
Secret Delivery Mechanism
Section titled “Secret Delivery Mechanism”Secrets are delivered to the component via the existing External Secrets Operator (ESO) pattern, the same mechanism used for database credentials:
- Secrets are created in AWS Secrets Manager (SM-1 through SM-8)
- ESO syncs them to Kubernetes Secrets (polled every 1 hour)
- Kubernetes mounts secrets as files at
/app/secret/in the pod - HOCON configuration reads values from
secrets.propertiesat startup
The component does not call Secrets Manager at runtime. All secret values are available as HOCON configuration properties after pod startup.
The ESO ExternalSecret definitions and the HOCON property mapping are configured in the ShopAccess/Email module. See functional.md for the module-level configuration.
IAM Roles
Section titled “IAM Roles”| # | Resource | Access | Scope | Zones |
|---|---|---|---|---|
| IAM-1 | Email DNS provisioning role | Route53 write (scoped to zone ARNs). AssumeBy trust for pod service account role. | Infrastructure: Alpha002 | DNS-Z2, DNS-Z3 |
| IAM-2 | Email DNS provisioning role | Route53 write (scoped to zone ARNs). AssumeBy trust for pod service account role. | Infrastructure: Alpha001 | DNS-Z4, DNS-Z5 |
Each role:
- Is scoped to the partition zone ARNs — the zone ARN inherently restricts writes to records within that zone
- Has an
AssumeBytrust policy withArnLikecondition matching the pod service account role pattern, following the same pattern as the S3 presigning role for image upload - Does not include Secrets Manager permissions (secrets are handled by ESO)
Scoping Constraints
Section titled “Scoping Constraints”- Alpha001 provisioning role cannot touch Alpha002 zones and vice versa (separate roles per infrastructure)
- Reserved subdomain names are enforced at the application layer (
emailConfigurationservice validation), not IAM
Summary by Scope
Section titled “Summary by Scope”Platform
Section titled “Platform”Resources in the platformRoot account, applying to the platform as a whole.
| # | Type | Resource |
|---|---|---|
| DNS-Z1 | Route53 Zone | Root hosted zone {mail-root-domain} |
| DNS-R1 | Route53 Record | SPF TXT at {mail-root-domain} |
| DNS-R2 | Route53 Record | DMARC TXT at _dmarc.{mail-root-domain} |
Infrastructure: Alpha001
Section titled “Infrastructure: Alpha001”Resources shared across prod and demo partitions.
| # | Type | Resource |
|---|---|---|
| PM-1 | Postmark | PostmarkProd account (Platform plan) |
| PM-4 | Postmark | PostmarkProd account API token |
| IAM-2 | IAM Role | DNS provisioning role (zones: DNS-Z4, DNS-Z5) |
Infrastructure: Alpha002
Section titled “Infrastructure: Alpha002”Resources shared across dev and stage partitions.
| # | Type | Resource |
|---|---|---|
| PM-2 | Postmark | PostmarkNonProd account (Platform plan) |
| PM-5 | Postmark | PostmarkNonProd account API token |
| IAM-1 | IAM Role | DNS provisioning role (zones: DNS-Z2, DNS-Z3) |
Partition: Alpha001/prod
Section titled “Partition: Alpha001/prod”| # | Type | Resource |
|---|---|---|
| DNS-Z4 | Route53 Zone | prod.{mail-root-domain} |
| DNS-R5 | Route53 Record | NS delegation prod in root zone |
| SM-1 | Secret | Holds: PM-4 token |
| SM-5 | Secret | Tenant server token encryption key |
Partition: Alpha001/demo
Section titled “Partition: Alpha001/demo”| # | Type | Resource |
|---|---|---|
| DNS-Z5 | Route53 Zone | demo.{mail-root-domain} |
| DNS-R6 | Route53 Record | NS delegation demo in root zone |
| SM-2 | Secret | Holds: PM-4 token (same value as SM-1) |
| SM-6 | Secret | Tenant server token encryption key |
Partition: Alpha002/dev
Section titled “Partition: Alpha002/dev”| # | Type | Resource |
|---|---|---|
| DNS-Z2 | Route53 Zone | dev.{mail-root-domain} |
| DNS-R3 | Route53 Record | NS delegation dev in root zone |
| SM-3 | Secret | Holds: PM-5 token |
| SM-7 | Secret | Tenant server token encryption key |
Partition: Alpha002/stage
Section titled “Partition: Alpha002/stage”| # | Type | Resource |
|---|---|---|
| DNS-Z3 | Route53 Zone | stage.{mail-root-domain} |
| DNS-R4 | Route53 Record | NS delegation stage in root zone |
| SM-4 | Secret | Holds: PM-5 token (same value as SM-3) |
| SM-8 | Secret | Tenant server token encryption key |
Copyright: © Arda Systems 2025-2026, All rights reserved