Partition Mail Topology
The four active Application Runtime partitions (dev, stage, demo, prod) each own a mail sub-zone under ardamails.com. This page is the operator-facing reference for what each partition’s mail surface contains, where the moving parts live across accounts, and which Postmark account owns each Signature.
For the system-wide mail-root design (Corporate’s arda.ardamails.com zone, the cross-account NS-delegation role topology, the choice of ardamails.com as a standalone domain), see DNS Structure. This page describes only the per-partition leaves of that tree.
Sub-zone layout
Section titled “Sub-zone layout”Platform Root account (Route 53)└── ardamails.com (apex) ├── arda.ardamails.com — Corporate (Free Kanban Tool + future Corporate consumers) ├── dev.ardamails.com — Application Runtime — Alpha002 / dev ├── stage.ardamails.com — Application Runtime — Alpha002 / stage ├── demo.ardamails.com — Application Runtime — Alpha001 / demo └── prod.ardamails.com — Application Runtime — Alpha001 / prodEach partition sub-zone lives in the partition’s own AWS account (Alpha001 or Alpha002), not in the Platform Root account. The NS-delegation from the apex ardamails.com zone (which lives in Platform Root) into the partition zone is the only cross-account write — performed by the partition’s PartitionEmailStack via the AllowCreatingDnsRecordsRole STS chain.
Partition-to-Account binding
Section titled “Partition-to-Account binding”| Partition | AWS Account (Infrastructure) | Postmark Account | Sub-zone |
|---|---|---|---|
dev | Alpha002 | PostmarkNonProd | dev.ardamails.com |
stage | Alpha002 | PostmarkNonProd | stage.ardamails.com |
demo | Alpha001 | PostmarkProd | demo.ardamails.com |
prod | Alpha001 | PostmarkProd | prod.ardamails.com |
The binding is canonically declared in infrastructure/src/main/cdk/platforms.ts on each partition’s entry under a mail block (postmarkAccount + credentialOpReference). The Postmark side groups non-production partitions on PostmarkNonProd to keep their reputation isolated from the production account, and groups demo with prod on PostmarkProd because customer-visible demos require production-grade IP warm-up.
The kyle partition under SandboxKyle002 is not in this set — its partition entry in ENVIRONMENTS carries no mail block, so it is skipped by every consumer that iterates over Phase-4-active partitions.
DNS records owned by each partition sub-zone
Section titled “DNS records owned by each partition sub-zone”Every active partition’s PartitionEmailStack creates the same record set inside its mail sub-zone:
| Record | Type | Source of value | Purpose |
|---|---|---|---|
{partition}.ardamails.com. | TXT (SPF) | SPF_RECORD_VALUE in ari-configuration.ts | Authorises Postmark’s MTA-S sending infrastructure (include:spf.mtasv.net ~all) |
_dmarc.{partition}.ardamails.com. | TXT (DMARC) | DMARC_RECORD_VALUE in ari-configuration.ts | Initial monitoring policy (p=quarantine; sp=quarantine; rua=mailto:dmarc-reports@arda.cards) |
<selector>._domainkey.{partition}.ardamails.com. | TXT (DKIM) | cdk.context.json → partitionMail:<infra>:<partition>.dkimSelector + .dkimPublicKey | DKIM public key Postmark generates when the Sender Signature is registered |
pm-bounces.{partition}.ardamails.com. | CNAME | cdk.context.json → partitionMail:<infra>:<partition>.returnPathTarget (typically pm.mtasv.net) | Custom Return-Path so bounce traffic stays under the partition’s domain |
The Pre-Deploy entry script (tools/register-partition-mail-signature.ts, run from amm.sh step 5.x.0.5) is what populates the DKIM + Return-Path values in cdk.context.json — by querying Postmark for the Sender Signature it just registered.
Why cdk.context.json is the handoff channel
Section titled “Why cdk.context.json is the handoff channel”The DKIM selector is issued by Postmark at Sender-Signature registration time and is not knowable before then — so it cannot be hardcoded in the CDK source. Yet cdk synth must see it to render the DKIM TXT record into the synthesised template. cdk.context.json is CDK’s sanctioned “values that must be deterministic at synth time but came from outside the source tree” channel: CDK itself writes here for AWS-side lookups (hosted-zone IDs, VPC IDs, etc.), caching them so future synths are reproducible. The Pre-Deploy CLI follows the same pattern — query the external system once, write the result under a namespaced key (partitionMail:<infra>:<partition>), let synth read it deterministically afterwards. This is the second use of the pattern in this project; the first is Corporate’s postmark.free-kanban.* keys (DQ-R1-014). The write strategy (atomic JSON merge, no CDK runtime bootstrap) is captured in DQ-R1-025.
The long-term mechanism for fetch-at-deploy-time values is a Lambda-backed CFN Custom Resource that calls Postmark inside CFN’s own Create/Update lifecycle, removing the tool-side pre-deploy step. Migration is intentionally deferred — it is a coordinated change across Phase 3’s Corporate Signature, Phase 4’s per-partition Signatures, and any future per-tenant Signatures, so the platform migrates the pattern as a whole rather than per-phase.
If the operator runs cdk synth against a partition before the Pre-Deploy CLI has populated the context (e.g., CI synth on a fresh PR), PartitionEmailStack falls back to obvious-placeholder DKIM / Return-Path values and emits a PartitionEmailStackPlaceholderContext: "true" CfnOutput so the un-provisioned state is visible on the deployed stack rather than masked.
NS delegation chain
Section titled “NS delegation chain”Operator runs ./amm.sh Alpha002 dev └── Pre-Deploy CLI registers Postmark Sender Signature for dev.ardamails.com └── cdk deploy creates Alpha002-dev-Email stack in Alpha002: ├── Route 53 hosted zone "dev.ardamails.com" in Alpha002 ├── SPF / DMARC / DKIM / Return-Path records inside the new zone └── Lambda-backed WriteNSRecordsToUpstreamDns custom resource: STS-assumes AllowCreatingDnsRecordsRole in Platform Root └── writes the new zone's NS records into ardamails.com (in Platform Root)Once amm.sh Alpha002 dev completes, public resolvers can answer queries for *.dev.ardamails.com because the cross-account NS delegation has been published into the apex zone in Platform Root.
IAM roles created per partition
Section titled “IAM roles created per partition”Each PartitionEmailStack creates two STS-assumable roles, both scoped via ArnLike on aws:PrincipalArn to the partition’s pod-role family (arn:aws:iam::<account>:role/<partition>-*):
EmailDnsProvisioningRole—route53:ChangeResourceRecordSets/route53:ListResourceRecordSets/route53:ListHostedZonesByNameon the partition’s mail sub-zone only. Consumed by the operations email module’sRoute53ZoneProxy(per-call STS assume-role) to write per-tenant DKIM + Return-Path records during provisioning — active as of Phase 5b.EmailEncryptionKeyFallbackRole—secretsmanager:GetSecretValueon the partition’sEmailEncryptionKeySM secret only. Provides the third axis of token-cipher resolution per DQ-R1-019 (after AWSCURRENT and AWSPREVIOUS ESO mounts).
Both roles emit -API- CFN exports ({infrastructure}-{partition}-API-EmailDnsProvisioningRoleArn and {infrastructure}-{partition}-API-EmailEncryptionKeyFallbackRoleArn) for the operations Helm chart to consume via aws cloudformation list-exports. The trust-policy shape is a single statement with the ArnLike condition folded into the principal (PrincipalWithConditions) — no additive unconditional AccountPrincipal statement.
Secrets created per partition
Section titled “Secrets created per partition”Two AWS Secrets Manager secrets per partition, both with RemovalPolicy.RETAIN:
{infrastructure}-{partition}-I-EmailPostmarkAccountToken— sourced from 1Password at deploy time and passed in as a CFN NoEcho parameter (the Secret Delivery Pattern δ.1). The token value lives in the partition’sArda-{Env}OAM1Password vault; rotation goes 1P →amm.shre-run.{infrastructure}-{partition}-I-EmailEncryptionKey— CFN-nativeGenerateSecretString(per DQ-R1-024), 64-character random value generated on first deploy. Immutable post-launch: CFN does not regenerate on re-deploy if theGenerateSecretStringblock is unchanged. Consumed by the operations component’sTokenCipherfor at-rest encryption of per-tenant Postmark server tokens (per DQ-R1-019, two-axis envelopea{N}.k{SM-VERSION-ID}). For rotation procedure, see the Encryption-Key Rotation Runbook.
CFN exports — the contract with the Helm chart
Section titled “CFN exports — the contract with the Helm chart”Six -API- exports per partition, all consumed by the operations component’s Helm chart at runtime:
| Export name | Value |
|---|---|
{infrastructure}-{partition}-API-PartitionMailZoneId | Route 53 hosted-zone ID for the partition’s mail sub-zone |
{infrastructure}-{partition}-API-PartitionMailZoneName | FQDN of the partition’s mail sub-zone (e.g. dev.ardamails.com) |
{infrastructure}-{partition}-API-EmailPostmarkAccountTokenArn | SM secret ARN for the Postmark account-level token |
{infrastructure}-{partition}-API-EmailEncryptionKeyArn | SM secret ARN for the encryption key |
{infrastructure}-{partition}-API-EmailDnsProvisioningRoleArn | IAM role ARN — STS target for Route 53 writes |
{infrastructure}-{partition}-API-EmailEncryptionKeyFallbackRoleArn | IAM role ARN — STS target for encryption-key SM reads |
Naming follows the workspace’s -API- convention (see CDK Infrastructure — Export-key pattern) so the operations Helm chart can query a single namespace with aws cloudformation list-exports and find every value it needs without hard-coding the per-partition resource names.
How the operations email module consumes the partition surface
Section titled “How the operations email module consumes the partition surface”The Email module is a module inside the operations component; it owns none of the infrastructure on this page and consumes it entirely through the six exports above. At deploy time read-cloudFormation-values.cmd resolves each export (substituting the purpose fqn for ${PURPOSE}) into the module’s HOCON config under system.shopAccess.email.extras.*, projected as SYSTEM_SHOPACCESS_EMAIL_EXTRAS_* pod env vars:
| Export | Module config key | Consumed by | Purpose |
|---|---|---|---|
PartitionMailZoneName | aws.route53.mailZoneName | the sending-domain synthesizer | Composes {slug}.{mailZoneName} (e.g. acme.dev.ardamails.com) — parametric, never a hard-coded apex |
PartitionMailZoneId | aws.route53.hostedZoneId | Route53ZoneProxy | Targets the partition zone for per-tenant DKIM / Return-Path writes |
EmailDnsProvisioningRoleArn | aws.route53.provisioningRoleArn | Route53ZoneProxy | STS assume-role for those writes |
EmailPostmarkAccountTokenArn | (ESO-projected secret) | PostmarkAccountProxy | Account-level Postmark API token |
EmailEncryptionKeyArn | (ESO-projected secret) | TokenCipher | At-rest encryption of per-tenant server tokens |
EmailEncryptionKeyFallbackRoleArn | secrets.* fallback role | TokenCipher | Third resolution axis (DQ-R1-019) |
Because PartitionMailZoneName is the published name of the very zone the DKIM / Return-Path records are written into (PartitionMailZoneId), the synthesized sending domain is guaranteed to match the zone the records land in — the partition segment can never drift from the records’ home. The two secret values arrive via External Secrets Operator, not read from Secrets Manager at runtime; the fallback role is the STS path used only when the ESO mounts are unavailable. The Postmark Server name the module mints (ardamails-{partition}-{slug}) embeds the partition for the same reason the domain does — uniqueness across partitions sharing one Postmark account.
Operator interactions
Section titled “Operator interactions”-
Initial deploy of a partition’s mail surface:
./amm.sh --profile <profile> <infrastructure> <partition>from theinfrastructurerepo. This runs the Pre-Deploy CLI (registers the Postmark Sender Signature, captures DKIM + Return-Path intocdk.context.json) and thencdk deployof the{infrastructure}-{partition}-Emailstack. Operator confirmsdigchecks pass for the four records after the deploy completes. -
Re-running after a Postmark token rotation: re-run
./amm.sh --profile <profile> <infrastructure> <partition>— the Pre-Deploy CLI’s idempotentlist-then-fetchpath skips re-registration, the new token flows through to the SM secret.amm.shpasses--forcetocdk deployso the no-op-deploy detection does not skip the update.--profileis load-bearing for the Phase-4 infrastructures: with no--profile,amm.shauto-derivesAdmin-${infrastructure}, which does not matchAlpha002-Admin(dev / stage) orAdmin-Alpha1(demo / prod) — so the invocation fails before deploy or rotation. Pass the binding-specific value (ENVIRONMENTSinplatforms.tsis the source of truth; see the Postmark service operator runbook). -
Verifying a partition is healthy: see the scheduled
runtime-platform-driftworkflow (delivered in Phase 4 Run-6) — probes each partition’s Postmark Sender Signature state, DNS records, and cross-seam alignment.
References
Section titled “References”- DNS Structure — the broader
arda.cards/ardamails.comDNS hierarchy this slots into. - Secret Delivery Pattern — δ.1 NoEcho-CFN-parameter flow used for the Postmark account token.
- Postmark Service Operator Runbook — manual provisioning steps that precede the automated per-partition deploys.
infrastructure/src/main/cdk/stacks/purpose/partition-email.ts— the CDK stack that creates everything described on this page.infrastructure/src/main/cdk/platforms.ts—ENVIRONMENTScarries the canonical partition → account / Postmark / op-vault bindings.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved