Skip to content

Phase 4 -- Runtime Platform Updates -- Verification

Verification catalogue for Phase 4. Each V-PART-NNN, V-IAC-NNN, V-CLI-NNN, V-OPS-NNN, V-CI-NNN, V-DOC-NNN entry maps bidirectionally to a requirement in requirements.md and a task in specification.md.

Each V-test below names one or more of these methods:

  • Unit (Jest + CDK Template matcher)npx jest <path>; the test asserts properties of the synthesized CloudFormation template (resource type, Properties fields, Outputs, retention policies). Used heavily for stack-level assertions on partition-email.ts.
  • Unit (Jest + injected mocks)npx jest <path>; the test injects mocks for external dependencies (Postmark client, 1Password SDK, filesystem, dig) and exercises code paths. Used for register-partition-mail-signature.ts, drift driver, helpers in tools/lib/.
  • Unit (CDK Template.fromStack() snapshot equality) — compares a stack’s synthesized template against a checked-in baseline JSON fixture. Used for the Root no-drift guard (V-IAC-002).
  • Synth-only smokenpx cdk synth --app <app>; asserts the App synthesizes without errors against a fixture context for all four active partitions.
  • cdk diff against deployed — compares the synthesized template to the deployed CloudFormation stack; passes when expected diffs are present and unexpected diffs are absent. Used per-partition pre-deploy and for the Root no-drift verification (V-IAC-002 operator step).
  • dig query — DNS resolution from a controlled host (or @8.8.8.8 for public-resolver semantics); asserts record presence, type, value, TTL.
  • Postmark Account API callcurl -X GET https://api.postmarkapp.com/... (or the Postmark TS client); asserts the response shape and content (Sender Signature exists / verified, DKIM + Return-Path values).
  • 1Password resolutionop read 'op://...' (or SDK-equivalent); asserts the reference resolves to a non-empty value.
  • AWS CLI / SDK callaws secretsmanager describe-secret, aws iam get-role, aws cloudformation get-template, aws sts get-caller-identity; asserts resource state.
  • gh CLI assertiongh issue list --label drift, gh workflow run; asserts the workflow’s issue-on-failure behavior and triggers.
  • Repo-state grep / lintgrep -rn, git ls-files, or a TS lint rule; asserts a code or doc state.
  • make pr-checks — the documentation repo’s local equivalent of CI; asserts CHANGELOG validity, link integrity, and smoke tests.
  • Manual / runbook — a step that requires an operator action (no API equivalent or no automation in scope); the result is captured in operator notes during the rollout (T-O3..T-O7) and written into the long-lived runbook at the location pinned in REQ-DOC-004.

Tests prefixed V-PART-NNN and V-IAC-NNN mostly run via Jest unit tests in infrastructure; tests prefixed V-CLI-NNN are method-mixed (Jest + filesystem assertions); V-OPS-NNN are operator-driven; V-CI-NNN are workflow-level; V-DOC-NNN exercise make pr-checks.

V-testRequirementMethodStatus
V-PART-001REQ-PART-001Unit (Template matcher) + cdk diff per-partitioncomplete (Run-2 unit; cdk diff post-deploy)
V-PART-002REQ-PART-002Unit (Template matcher)complete (Run-2)
V-PART-003REQ-PART-003Unit (Template matcher) + digcomplete (Run-3 cascade dig + Template matcher)
V-PART-004REQ-PART-004Unit (Template matcher) + digcomplete (Run-3 cascade dig + Template matcher)
V-PART-005REQ-PART-005Unit (Template matcher) + digcomplete (Run-3 cascade dig + Template matcher)
V-PART-007REQ-PART-007Unit (injected mocks)complete (Run-1)
V-PART-008REQ-PART-008Postmark Account API callcomplete (Run-3 cascade; Postmark API verify-domain)
V-PART-009REQ-PART-009Postmark Account API callcomplete (Run-3 cascade; Postmark API verifyDkim + verifyReturnPath)
V-PART-010REQ-PART-010Unit (Template matcher) + digcomplete (Run-2 unit; dig post-deploy)
V-PART-011REQ-PART-011Unit (Template matcher) + AWS CLIcomplete (Run-2 unit; AWS CLI post-deploy)
V-PART-012REQ-PART-012Unit (Template matcher)complete (Run-2)
V-PART-014REQ-PART-014Unit (Template matcher) + AWS CLIcomplete (Run-2 unit; AWS CLI post-deploy)
V-PART-015REQ-PART-015Unit (Template matcher)complete (Run-2)
V-PART-016REQ-PART-016AWS CLI (describe-secret versionId before/after)pending
V-PART-017REQ-PART-017Unit (Template matcher) + AWS CLIcomplete (Run-2 unit; AWS CLI post-deploy)
V-PART-018REQ-PART-018Unit (Template matcher)complete (Run-2)
V-PART-019REQ-PART-019Unit (Template matcher) + AWS CLIcomplete (Run-2 unit; AWS CLI post-deploy)
V-PART-020REQ-PART-020Unit (Template matcher)complete (Run-2)
V-testRequirementMethodStatus
V-IAC-001REQ-IAC-001Unit (Template matcher; both trust-principal modes)complete (Run-1)
V-IAC-002REQ-IAC-002Unit (Template snapshot equality) + cdk diff against Rootpartial (unit gate: Run-1; operator T-O2 gate: post-merge)
V-IAC-003REQ-IAC-003Unit (Template matcher) + synth-only smokecomplete (Run-2)
V-IAC-004REQ-IAC-004Synth-only smoke per partitioncomplete (Run-2)
V-IAC-005REQ-IAC-005Unit (config-shape assertions) + synth-only smokecomplete (Run-2)
V-IAC-006REQ-IAC-006Repo-state grep (no env-var bridges) + Unitcomplete (Run-2)
V-IAC-007REQ-IAC-007Unit (reserved-words list assertion)complete (Run-1)
V-IAC-008REQ-IAC-008Unit (idempotent re-synth) + Template snapshotcomplete (Run-2)
V-testRequirementMethodStatus
V-CLI-001REQ-CLI-001Unit (injected mocks) + bash sub-process invocationcomplete (Run-2)
V-CLI-002REQ-CLI-002Unit (injected mocks; repeat invocation produces same result)complete (Run-2)
V-CLI-003REQ-CLI-003Unit (helpers tests) + grep (no inline reimplementation)complete (Run-1)
V-CLI-004REQ-CLI-004Bash dry-run + GHA mask integration testpartial (Run-2 static; CI mask post-deploy)
V-CLI-005REQ-CLI-005Unit (injected mocks; failure paths)complete (Run-2)

Operator prerequisites and post-deploy verification (OPS)

Section titled “Operator prerequisites and post-deploy verification (OPS)”
V-testRequirementMethodStatus
V-OPS-001REQ-OPS-0011Password resolution (operator-driven)pending
V-OPS-002REQ-OPS-002AWS CLI (sts get-caller-identity)pending
V-OPS-003REQ-OPS-003Manual / mailbox checkpending
V-OPS-004REQ-OPS-004Manual (Postmark Compliance email)pending
V-OPS-005REQ-OPS-005Manual / runbookcomplete
V-testRequirementMethodStatus
V-CI-001REQ-CI-001YAML lint + workflow workflow_dispatch runcomplete
V-CI-002REQ-CI-002Unit (injected mocks) + synthetic-drift fixturepending
V-CI-003REQ-CI-003Unit (helpers tests) + corporate-drift regression runpending
V-testRequirementMethodStatus
V-DOC-001REQ-DOC-001make pr-checks + technical-writer reviewpending
V-DOC-002REQ-DOC-002make pr-checks + technical-writer reviewpending
V-DOC-003REQ-DOC-003make pr-checks + technical-writer reviewpending
V-DOC-004REQ-DOC-004make pr-checks + technical-writer reviewpending

V-PART-001 — Per-partition mail sub-zone declared

Section titled “V-PART-001 — Per-partition mail sub-zone declared”

Method: Unit (Template matcher) + cdk diff per-partition.

Procedure:

  1. Unit — in partition-email.test.ts, for each fixture partition (prod, demo, dev, stage), use the canonical hasResource partial-match shape from cdk-infrastructure.md § 7:
    template.hasResource("AWS::Route53::HostedZone", {
    Properties: {
    Name: `${partition}.ardamails.com.`,
    },
    DeletionPolicy: "Retain",
    UpdateReplacePolicy: "Retain",
    });
    hasResource partial-matches via Match.objectLike by default, so this single call covers both the property check and the retention-policy check (no need for a separate hasResourceProperties call).
  2. Post-deploy — cdk diff per partition reports zero differences for the zone resource against the deployed CFN stack.

V-PART-002 — Partition mail zone exports

Section titled “V-PART-002 — Partition mail zone exports”

Method: Unit (Template matcher).

Procedure: in partition-email.test.ts. Use the canonical findOutputs("*", {...}) pattern from cdk-infrastructure.md § 7 — publish() emits two Outputs per ExportKey (one -API- prefixed with the clean value; one un-prefixed carrying the CFN_IO_MARKER-wrapped “guarded witness”), and findOutputs searches by Export.Name without depending on the CDK logical ID:

// Clean consumer-facing output (what readImports() resolves)
const apiOutputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-PartitionMailZoneId` },
});
expect(Object.keys(apiOutputs)).toHaveLength(1);
const nameOutputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-PartitionMailZoneName` },
});
expect(Object.keys(nameOutputs)).toHaveLength(1);
// Optional sanity-check: publish() also emits a CFN_IO_MARKER-wrapped
// "guarded witness" with the un-prefixed name. Asserting its presence
// confirms publish() ran and produced both outputs per § Cross-stack
// references / CFN_IO_MARKER. Skip if not needed.
const witnessOutputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-PartitionMailZoneId` },
});
expect(Object.keys(witnessOutputs)).toHaveLength(1);

Verify both ExportKeys end with API and the corresponding consumer-facing export names contain -API- (the publish() regex enforces alignment at synth time; this test confirms the regex’s coverage).


V-PART-003 — NS-delegation record per partition

Section titled “V-PART-003 — NS-delegation record per partition”

Method: Unit (Template matcher) + dig.

Procedure:

  1. Unit — in partition-email.test.ts: assert the WriteNSRecordsToUpstreamDns Custom Resource is declared with subdomain: <partition> and references the zone’s hostedZoneNameServers token.
  2. Post-deploy — dig NS {partition}.ardamails.com @8.8.8.8 returns the partition zone’s authoritative nameservers via root-delegation.

V-PART-004 — SPF record per partition apex

Section titled “V-PART-004 — SPF record per partition apex”

Method: Unit (Template matcher) + dig.

Procedure:

  1. Unit — assert a AWS::Route53::RecordSet with Type: "TXT", Name: "<partition>.ardamails.com.", and ResourceRecords containing "v=spf1 include:spf.mtasv.net ~all".
  2. Post-deploy — dig +short TXT {partition}.ardamails.com returns the SPF record string.

Method: Unit (Template matcher) + dig.

Procedure:

  1. Unit — assert a AWS::Route53::RecordSet with Type: "TXT", Name: "_dmarc.<partition>.ardamails.com.", and the value matching "v=DMARC1; p=quarantine; sp=quarantine; rua=mailto:dmarc-reports@arda.cards".
  2. Post-deploy — dig +short TXT _dmarc.{partition}.ardamails.com returns the DMARC record.

V-PART-007 — Partition-aware Postmark credential accessor

Section titled “V-PART-007 — Partition-aware Postmark credential accessor”

Method: Unit (injected mocks).

Procedure: in postmark-service.test.ts:

expect(postmarkCredentialOpReference("dev")).toBe("op://Arda-DevOAM/Postmark/credential");
expect(postmarkCredentialOpReference("stage")).toBe("op://Arda-StageOAM/Postmark/credential");
expect(postmarkCredentialOpReference("demo")).toBe("op://Arda-DemoOAM/Postmark/credential");
expect(postmarkCredentialOpReference("prod")).toBe("op://Arda-ProdOAM/Postmark/credential");

The function is pure; no CDK / network side-effects.


V-PART-008 — Per-partition Postmark Sender Signature

Section titled “V-PART-008 — Per-partition Postmark Sender Signature”

Method: Postmark Account API call (operator-driven, executed by Phase A’s register-partition-mail-signature.ts).

Procedure: after Phase A runs for the partition, query the Postmark Account API:

Terminal window
curl -H "X-Postmark-Account-Token: $token" \
https://api.postmarkapp.com/senders \
| jq '.SenderSignatures[] | select(.Name == "<partition>.ardamails.com")'

The response must include a matching SenderSignatures entry with Name: "<partition>.ardamails.com", DKIMVerified: true (after V-PART-009), and the correct partition Postmark account (PostmarkProd for prod / demo; PostmarkNonProd for dev / stage).


V-PART-009 — Sender Signature DKIM and Return-Path verified

Section titled “V-PART-009 — Sender Signature DKIM and Return-Path verified”

Method: Postmark Account API call.

Procedure: after Phase B’s cdk deploy for the partition AND DNS propagation:

Terminal window
curl -H "X-Postmark-Account-Token: $token" \
https://api.postmarkapp.com/senders/<signatureId>/verifydkim
curl -H "X-Postmark-Account-Token: $token" \
https://api.postmarkapp.com/senders/<signatureId>/verifyreturnpath

Both responses return 200 and contain DKIMVerified: true / ReturnPathVerified: true.


V-PART-010 — DKIM TXT + Return-Path CNAME records per partition

Section titled “V-PART-010 — DKIM TXT + Return-Path CNAME records per partition”

Method: Unit (Template matcher) + dig.

Procedure:

  1. Unit — in partition-email.test.ts, assert two AWS::Route53::RecordSet resources:
    • Type: "TXT", Name: "<selector>._domainkey.<partition>.ardamails.com." with the public DKIM key from cdk.context.json key postmark.<partition>.dkimKey.
    • Type: "CNAME", Name: "pm-bounces.<partition>.ardamails.com." with target <returnPathTarget> (typically pm.mtasv.net).
  2. Post-deploy — dig +short TXT <selector>._domainkey.<partition>.ardamails.com and dig +short CNAME pm-bounces.<partition>.ardamails.com return the expected values.

V-PART-011 — Per-partition Postmark account-token SM secret

Section titled “V-PART-011 — Per-partition Postmark account-token SM secret”

Method: Unit (Template matcher) + AWS CLI.

Procedure:

  1. Unit — in partition-email.test.ts:
    template.hasResourceProperties("AWS::SecretsManager::Secret", {
    Name: `${fqn}-I-EmailPostmarkAccountToken`,
    SecretString: { Ref: "PostmarkAccountToken" },
    });
    template.hasResource("AWS::SecretsManager::Secret", { DeletionPolicy: "Retain" });
    template.hasParameter("PostmarkAccountToken", { NoEcho: true });
  2. Post-deploy — aws secretsmanager describe-secret --secret-id <fqn>-I-EmailPostmarkAccountToken --profile <profile> returns a secret with DeletionPolicy: Retain and an AWSCURRENT versionId.

V-PART-012 — Postmark account-token SM secret ARN exported

Section titled “V-PART-012 — Postmark account-token SM secret ARN exported”

Method: Unit (Template matcher).

Procedure: in partition-email.test.tsfindOutputs("*", {...}) pattern (see V-PART-002 for the canonical shape and dual-emission discussion):

const outputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-EmailPostmarkAccountTokenArn` },
});
expect(Object.keys(outputs)).toHaveLength(1);

V-PART-014 — Per-partition encryption-key SM secret

Section titled “V-PART-014 — Per-partition encryption-key SM secret”

Method: Unit (Template matcher) + AWS CLI.

Procedure:

  1. Unit — in partition-email.test.ts:
    template.hasResourceProperties("AWS::SecretsManager::Secret", {
    Name: `${fqn}-I-EmailEncryptionKey`,
    GenerateSecretString: {
    PasswordLength: 64,
    ExcludeCharacters: '"@/\\',
    ExcludePunctuation: false,
    },
    });
    template.hasResource("AWS::SecretsManager::Secret", { DeletionPolicy: "Retain" });
  2. Post-deploy — aws secretsmanager describe-secret --secret-id <fqn>-I-EmailEncryptionKey --profile <profile> returns AWSCURRENT versionId and DeletionPolicy: Retain.

V-PART-015 — Encryption-key SM secret ARN exported

Section titled “V-PART-015 — Encryption-key SM secret ARN exported”

Method: Unit (Template matcher).

Procedure: in partition-email.test.tsfindOutputs("*", {...}) pattern (see V-PART-002):

const outputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-EmailEncryptionKeyArn` },
});
expect(Object.keys(outputs)).toHaveLength(1);

V-PART-016 — Encryption key amm.sh re-run is a no-op

Section titled “V-PART-016 — Encryption key amm.sh re-run is a no-op”

Method: AWS CLI (describe-secret versionId before/after).

Procedure:

  1. After the initial partition deploy, capture the encryption-key SM secret’s versionId: aws secretsmanager describe-secret --secret-id <fqn>-I-EmailEncryptionKey --query 'VersionIdsToStages' --profile <profile> > before.json.
  2. Re-run amm.sh for the same partition (no code changes; no 1P value changes).
  3. Re-capture: ... > after.json.
  4. Assert diff before.json after.json reports no changes — the AWSCURRENT versionId did not change.

Per REQ-PART-016: this catches accidental generateSecretString config drift in future PRs. Pairs with V-IAC-008’s pre-merge gate.


V-PART-017 — EmailDnsProvisioningRole instantiated per partition

Section titled “V-PART-017 — EmailDnsProvisioningRole instantiated per partition”

Method: Unit (Template matcher) + AWS CLI.

Procedure:

  1. Unit — in partition-email.test.ts:
    template.hasResourceProperties("AWS::IAM::Role", {
    AssumeRolePolicyDocument: Match.objectLike({
    Statement: [{
    Principal: { AWS: { "Fn::Sub": `arn:aws:iam::${account}:root` } },
    Condition: { ArnLike: { "aws:PrincipalArn": `arn:aws:iam::${account}:role/${fqn}-*` } },
    }],
    }),
    });
    template.hasResourceProperties("AWS::IAM::Policy", {
    PolicyDocument: Match.objectLike({
    Statement: Match.arrayWith([
    Match.objectLike({
    Action: Match.arrayEquals([
    "route53:ChangeResourceRecordSets",
    "route53:ListResourceRecordSets",
    "route53:ListHostedZonesByName",
    ]),
    }),
    ]),
    }),
    });
    // Negative: route53:GetChange must NOT be present.
  2. Negative-test for route53:GetChange: assert no Action element contains route53:GetChange anywhere in the role’s policy.
  3. Post-deploy — aws iam get-role --role-name <DnsRecordsRoleName> --profile <profile> returns the role with the expected trust policy.

V-PART-018 — DNS-records role ARN exported

Section titled “V-PART-018 — DNS-records role ARN exported”

Method: Unit (Template matcher).

Procedure: in partition-email.test.tsfindOutputs("*", {...}) pattern (see V-PART-002):

const outputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-EmailDnsProvisioningRoleArn` },
});
expect(Object.keys(outputs)).toHaveLength(1);

V-PART-019 — EmailEncryptionKeyFallbackRole per partition

Section titled “V-PART-019 — EmailEncryptionKeyFallbackRole per partition”

Method: Unit (Template matcher) + AWS CLI.

Procedure:

  1. Unit — in partition-email.test.ts:
    template.hasResourceProperties("AWS::IAM::Role", {
    AssumeRolePolicyDocument: Match.objectLike({/* same shape as V-PART-017 */}),
    });
    template.hasResourceProperties("AWS::IAM::Policy", {
    PolicyDocument: Match.objectLike({
    Statement: Match.arrayWith([
    Match.objectLike({
    Action: ["secretsmanager:GetSecretValue"],
    Resource: Match.stringLikeRegexp(`.*-I-EmailEncryptionKey.*`),
    }),
    ]),
    }),
    });
  2. Single-statement trust-policy regression check. The trust policy must contain exactly one statement whose ArnLike condition restricts assumption to the partition’s pod-role family. A separate test in partition-email.test.ts reaches into the synthesised AWS::IAM::Role resource’s AssumeRolePolicyDocument.Statement array and asserts length === 1 with the condition baked into the principal (via PrincipalWithConditions). Guards against the earlier bug shape where an unconditional AccountPrincipal trust statement plus an additive conditioned addStatements(...) call OR-evaluated to “anyone in the account”.
  3. Post-deploy — aws iam get-role --role-name <FallbackRoleName> --profile <profile> returns the role.

Method: Unit (Template matcher).

Procedure: in partition-email.test.tsfindOutputs("*", {...}) pattern (see V-PART-002):

const outputs = template.findOutputs("*", {
Export: { Name: `${publishingPrefix}-API-EmailEncryptionKeyFallbackRoleArn` },
});
expect(Object.keys(outputs)).toHaveLength(1);

V-IAC-001 — AllowCreatingNSRecordsRole generalized

Section titled “V-IAC-001 — AllowCreatingNSRecordsRole generalized”

Method: Unit (Template matcher; both trust-principal modes).

Procedure: in the construct’s test (allow-creating-ns-records-role.test.ts or its renamed sibling):

  1. Test mode A (legacy Lambda + OrgID): synthesize against a fixture and assert the trust policy uses Service: lambda.amazonaws.com + Condition: StringEquals.aws:PrincipalOrgID: <orgId>.
  2. Test mode B (Phase 4 account principal + ArnLike): synthesize against a fixture and assert the trust policy uses Principal: { AWS: <accountRoot> } + Condition: ArnLike.aws:PrincipalArn: <pattern>.
  3. Both modes produce the same Action / Resource statements (the construct’s permissions are unchanged).

V-IAC-002 — Root-account byte-equality (pre- and post-deploy)

Section titled “V-IAC-002 — Root-account byte-equality (pre- and post-deploy)”

Method: Unit (Template snapshot equality) + cdk diff against Root.

Procedure:

  1. Pre-merge unit gate — in root-dns-stack.test.ts:
    const template = Template.fromStack(rootStack);
    const baseline = JSON.parse(fs.readFileSync("root-dns-stack.baseline.json", "utf8"));
    expect(template.toJSON()).toEqual(baseline);
    The baseline JSON is checked into the repo at the path next to the test. The test fails closed if any Phase-4 (or post-Phase-4) PR alters the Root output.
  2. Post-merge operator gate (T-O2)cdk synth RootDnsStack from the merged main branch; aws cloudformation get-template --stack-name RootConfiguration --profile Admin-Alpha1 to capture the deployed template; diff of the two must be empty.

V-IAC-003 — partition-email stack composes correctly

Section titled “V-IAC-003 — partition-email stack composes correctly”

Method: Unit (Template matcher) + Unit (validateProps error paths) + synth-only smoke.

Procedure:

  1. Unit (composition) — partition-email.test.ts covers each sub-resource via the V-PART-NNN entries above; composition is implicitly tested because the same stack synthesis runs all sub-resource assertions.
  2. Unit (validateProps) — assert the static validateProps returns the expected Error[] on each known failure mode: invalid locator (via purpose.validatePurposeLocator), missing awsUtil.validateStackProps fields, malformed podRoleArnPattern, malformed DMARC mailbox, absent Postmark account reference. Construction with invalid props throws misc.MultiError before super().
  3. Unit (Built shape) — assert the constructed stack’s built field carries the expected typed members: partitionMailZone, emailEncryptionKeySecret, emailPostmarkAccountTokenSecret, emailDnsProvisioningRole, emailEncryptionKeyFallbackRole. Each is an interface type (IHostedZone, ISecret, IRole) — references, not concrete classes.
  4. Unit (ExportKeys ↔ export-name alignment) — assert every ExportKeys member ends with API and every produced export name contains -API-. The publish() regex enforces this at synth time; this test confirms the regex’s coverage.
  5. Synth-only smoke — npx cdk synth --app apps/Al1x/partition for each active partition produces a valid CloudFormation template; the CFN stack name in the output matches ${infrastructure}-${partition}-Email.

V-IAC-004 — apps/Al1x/partition.ts instantiates per partition

Section titled “V-IAC-004 — apps/Al1x/partition.ts instantiates per partition”

Method: Synth-only smoke per partition.

Procedure: npm run synth:named -- Alpha002/dev (and equivalent for Alpha002/stage, Alpha001/demo, Alpha001/prod) produces a valid template that includes Alpha00X-<partition>-Email in the stack listing. The partitions are iterated by buildPartition(); kyle is skipped silently because POSTMARK_ACCOUNT_FOR_PARTITION (derived from ENVIRONMENTS) returns undefined for partitions whose mail block is absent — no error path needed at the app layer.

A negative synth (no cdk.context.json entry for the partition) is also exercised: PartitionEmailStack falls back to the private PLACEHOLDER_CONTEXT and emits a PartitionEmailStackPlaceholderContext: "true" CfnOutput so the deployed stack flags the un-provisioned state explicitly. CI runs all four active partitions in this mode every PR build.


V-IAC-005 — Per-partition instance configurations

Section titled “V-IAC-005 — Per-partition instance configurations”

Method: Unit (config-shape assertions) + synth-only smoke.

Procedure:

  1. Unit — platforms.test.ts asserts that each active partition in ENVIRONMENTS carries a mail block with the expected postmarkAccount and credentialOpReference values; kyle carries no mail block (it is outside the Phase-4 set). The DMARC mailbox + SPF + DKIM record values are system-wide constants in ari-configuration.ts (DMARC_RECORD_VALUE, SPF_RECORD_VALUE), not per-partition fields — covered by partition-email.test.ts’s record-set assertions and re-asserted in ari-configuration.test.ts.
  2. Synth — see V-IAC-004.

V-IAC-006 — Stack composition is value-flowing only

Section titled “V-IAC-006 — Stack composition is value-flowing only”

Method: Repo-state grep (no env-var bridges) + Unit.

Procedure:

  1. Grep partition-email.ts (and its sub-construct invocations): no process.env.* reads, no fs.readFile, no env-var-bridge patterns.
  2. The composition uses Built value types passed as props between sub-constructs — verified by the construct’s typed signatures.

V-IAC-007 — Reserved-words list extended

Section titled “V-IAC-007 — Reserved-words list extended”

Method: Unit (reserved-words list assertion).

Procedure: in the existing reserved-words test:

expect(reservedWords).toContain("prod");
expect(reservedWords).toContain("demo");
expect(reservedWords).toContain("dev");
expect(reservedWords).toContain("stage");
expect(reservedWords).toContain("kyle");
expect(reservedWords).toContain("arda"); // Phase 3 baseline; still present

Additionally, any tenant-slug validation that consumes the registry must reject the partition names as tenant slugs.


V-IAC-008 — Encryption-key generation config locked at synth time

Section titled “V-IAC-008 — Encryption-key generation config locked at synth time”

Method: Unit (Template.hasResourceProperties against the CFN-native GenerateSecretString block).

Procedure: per DQ-R1-024 the EmailEncryptionKey is provisioned via a CFN-native AWS::SecretsManager::Secret with GenerateSecretString — no dedicated construct — so the test lives directly in partition-email.test.ts:

template.hasResourceProperties("AWS::SecretsManager::Secret", {
Name: "Alpha002-dev-I-EmailEncryptionKey",
GenerateSecretString: {
SecretStringTemplate: "{}",
GenerateStringKey: "key",
PasswordLength: 64,
ExcludePunctuation: true,
},
});

The shape is checked field-by-field so any drift in PasswordLength, GenerateStringKey, or ExcludePunctuation fails the test. CFN-native generation guarantees the versionId is immutable across re-deploy without a Custom Resource — V-PART-016 covers the runtime side.


V-CLI-001 — register-partition-mail-signature.ts entry script

Section titled “V-CLI-001 — register-partition-mail-signature.ts entry script”

Method: Unit (injected mocks) on the testable core; thin entry script delegates.

Procedure:

  1. Unit — in tools/lib/partition-mail-signature.test.ts (the entry script’s testable surface lives in tools/lib/partition-mail-signature.ts; tools/register-partition-mail-signature.ts is a ~30-line shim that wires production dependencies and delegates), with mocks for the Postmark client (postmarkRequest), the secret resolver, and the context-store writer:
    • Happy path: Alpha002 dev → list-domains returns empty → POST /domains registers dev.ardamails.comcdk.context.json is written under the namespaced key with the DKIM selector / public key / Return-Path target.
    • First-run path (per the corporate-cli v2.31.0 fix): the same happy-path Postmark response with DKIMHost: "" and DKIMTextValue: "" but populated DKIMPendingHost / DKIMPendingTextValue — the active-then-pending precedence helpers in tools/lib/postmark-client.ts (effectiveDkimHost, effectiveDkimTextValue) pick the pending values, and cdk.context.json lands with the correct selector + key.
    • Idempotent path: list-domains returns an existing entry for the zone → GET /domains/{id} fetches DKIM details → no POST /domains call.
    • No arguments → script emits the usage block to stderr → exit non-zero. Same for --help / -h.
    • Invalid <infrastructure> (e.g., Foo) → usage block on stderr + must be one of <derived list> error → exit non-zero. The infrastructure allow-list is derived from VALID_INFRASTRUCTURES in arda/platforms, which is itself derived from ENVIRONMENTS entries that contain at least one partition with a mail block.
    • Partition / infrastructure mismatch (e.g., Alpha001 dev) → usage block on stderr + a partition '<x>' does not belong to infrastructure '<y>' line → exit non-zero. Catches operator typos before any Postmark API call. Mapping derived from PARTITION_TO_INFRASTRUCTURE in arda/platforms.
    • Valid args but Postmark API failure → redacted error summary on stderr → exit non-zero, cdk.context.json unchanged.
    • --token-out <path> flag: when supplied, the resolved Postmark account token is written to the named file (mode 0600) so the calling shell (amm.sh) can read it for a subsequent CDK deploy without printing it on stdout. The test exercises a fake writer and asserts the token bytes are passed through.
    • Out-of-scope assertion: the test suite asserts no POST /servers call is made anywhere in the run (Sender Signature only — Postmark Servers are created at system Runtime by Tenant, not at Provisioning time).
  2. Usage parity with amm.sh: the script’s usage block names the same <infrastructure> <partition> positional shape as amm.sh line 140, so an operator who has invoked amm.sh recognises the convention.

Method: Unit (injected mocks; repeat invocation produces same result).

Procedure: in tools/lib/partition-mail-signature.test.ts:

  1. Mock the Postmark API to return an existing dev.ardamails.com domain in the GET /domains?count=500&offset=0 listing (simulating a prior run).
  2. Run registerPartitionMailSignature(...) with the mocked deps; assert the script calls GET /domains/{id} to fetch the existing domain’s DKIM details, never calls POST /domains (the create endpoint), and writes the existing values to cdk.context.json.
  3. Run again; assert the result is identical.

The endpoint is /domains (Postmark Sender Signatures registered at domain scope), not /servers (Postmark Servers) and not /senders (per-email Sender Signatures). See V-CLI-001 for the no POST /servers out-of-scope assertion.


V-CLI-003 — tools/lib/ helpers extracted and shared

Section titled “V-CLI-003 — tools/lib/ helpers extracted and shared”

Method: Unit (helpers tests) + grep (no inline reimplementation).

Procedure:

  1. Unit — tools/lib/*.test.ts covers each helper (Postmark client retry / backoff, op-resolver, redaction).
  2. Grep — grep -rn "PostmarkAccountAPI\|opRead" tools/ shows the relevant patterns appear only inside tools/lib/ and at call sites in corporate-cli.ts + register-partition-mail-signature.ts (not duplicated inline).

Method: Bash syntax check + manual operator dry-run; GHA-mask integration left to the first real CI execution.

Procedure:

  1. Static check: bash -n amm.sh returns zero. Manually inspecting the partition iteration body around the >>>>>>>>> Step ${step}.0.5: Partition mail Pre-Deploy marker, confirm the sequence is: mktempregister-partition-mail-signature.ts ... --token-out <tmpfile> → read the token via $(<"$tmpfile")rm -f "$tmpfile"::add-mask:: (when GITHUB_ACTIONS=true) → append --parameters …-Email:PostmarkAccountToken=… and --force to partition_cdk_arguments.
  2. Operator dry-run (pre-merge, judgement call per spec § T-O3): an operator may invoke ./amm.sh Alpha002 dev against the PR branch with a real Postmark token (not the prod one). Confirm the script reaches cdk deploy cleanly and that the token written to the temp file has the expected length.
  3. GHA mask integration (post-merge, first real CI run): observe a CI run of amm.sh and confirm the Postmark token does not appear unredacted anywhere in the workflow log. Automated test inside CI would require a real Postmark token at CI scope — out of scope for the unit-test suite; covered by the first scheduled deploy.

V-CLI-005 — Pre-Deploy failure semantics

Section titled “V-CLI-005 — Pre-Deploy failure semantics”

Method: Unit (injected mocks; failure paths).

Procedure: in tools/lib/partition-mail-signature.test.ts:

  1. Mock the Postmark API to return a 5xx; assert the script exits non-zero with a redacted error summary on stderr.
  2. Mock the secret resolver to throw; assert the script exits non-zero before any Postmark API call.
  3. Mock the writeContext dep to throw; assert the script exits non-zero. (The atomic .tmp + rename() strategy in src/main/cdk/utils/context-store.ts already prevents partial writes; that contract is exercised by context-store.test.ts.)
  4. Mock the Postmark response to come back with empty active and empty pending DKIM fields; assert effectiveDkimHost / effectiveDkimTextValue throw with the “empty DKIMHost AND DKIMPendingHost” / “empty DKIMTextValue AND DKIMPendingTextValue” messages.

V-OPS-001 — 1Password vault state per partition

Section titled “V-OPS-001 — 1Password vault state per partition”

Method: 1Password resolution (operator-driven).

Procedure: for each partition the operator is about to deploy, run op read "$(npx ts-node -e 'console.log(require(\"./platform/postmark-service\").postmarkCredentialOpReference(\"dev\"))')" (or equivalent) and assert the resolution returns a non-empty token. Operator records the check in the sign-off table.


V-OPS-002 — Operator AWS SSO credentials

Section titled “V-OPS-002 — Operator AWS SSO credentials”

Method: AWS CLI.

Procedure: for each partition the operator is about to deploy, run aws sts get-caller-identity --profile <profile> (Admin-Alpha1 for prod / demo; Alpha002-Admin for dev / stage) and assert the returned account ID matches the expected Infrastructure account.


V-OPS-003 — dmarc-reports@arda.cards mailbox healthy

Section titled “V-OPS-003 — dmarc-reports@arda.cards mailbox healthy”

Method: Manual / mailbox check.

Procedure: once before the first partition deploy, the operator confirms the dmarc-reports@arda.cards mailbox in Arda’s Google Workspace receives mail (a recent message exists, or a test message is sent and received). Operator records the check in the sign-off table.


V-OPS-004 — arda-nonprod account approval reply

Section titled “V-OPS-004 — arda-nonprod account approval reply”

Method: Manual (Postmark Compliance email).

Procedure: after the dev partition Sender Signature is verified (V-PART-009 for dev), the operator replies to Postmark Compliance ticket #11236089 citing the verified-domain evidence. Operator records the reply (date sent, content summary) in the sign-off table. Postmark’s response is monitored; if approval is granted, the operator records it. If Postmark requests additional evidence, the operator updates the rollout plan accordingly (see REQ-OPS-004 documented assumption).


Method: Manual / runbook.

Procedure: a sign-off table at the end of this verification doc (below) is populated as the rollout progresses — one row per partition (and one row per non-partition operator task: T-O1 pre-flight, T-O2 Root no-drift, T-O4 Postmark reply, T-O8 first drift run). Operator name, date, deviations, notes per row.


V-CI-001 — runtime-platform-drift workflow

Section titled “V-CI-001 — runtime-platform-drift workflow”

Method: YAML lint + workflow workflow_dispatch run.

Procedure:

  1. YAML lint — npx js-yaml infrastructure/.github/workflows/runtime-platform-drift.yml (or the repo’s equivalent linter) returns no errors.
  2. Manual trigger — gh workflow run runtime-platform-drift.yml runs to completion; the run’s logs match the expected per-partition probe shape.
  3. The workflow’s failure-issue labels match drift + runtime-platform.

Method: Unit (injected mocks) + synthetic-drift fixture.

Procedure:

  1. Unit — runtime-platform-drift.test.ts covers per-partition probes with mocks for Postmark, dig, AWS SDK. Happy path produces no drift; mocked drift produces the expected report.
  2. Synthetic fixture — run the driver against a fixture asset list where one partition has a deliberate mismatch (e.g., wrong DKIM selector); assert the report flags it and exit code is non-zero.

V-CI-003 — Shared drift utilities extracted

Section titled “V-CI-003 — Shared drift utilities extracted”

Method: Unit (helpers tests) + corporate-drift regression run.

Procedure:

  1. Unit — tools/lib/drift/*.test.ts covers each shared helper.
  2. Run corporate-drift.yml (manually via workflow_dispatch) against the live arda.ardamails.com Sender Signature post-extraction; assert the report shape is unchanged from pre-extraction baseline.

V-DOC-001 — secret-delivery-pattern.md content

Section titled “V-DOC-001 — secret-delivery-pattern.md content”

Method: make pr-checks + technical-writer review.

Procedure:

  1. make pr-checks passes on the documentation repo’s PR.
  2. The page’s frontmatter maturity is review (not draft).
  3. Technical-writer sub-agent review covers structure, clarity, internal consistency, link integrity, en_US locale, and adherence to the document-writing and path-conventions skills.

Method: make pr-checks + technical-writer review.

Procedure: same as V-DOC-001. At least one new page exists under current-system/runtime/ describing the partition mail topology; the page renders without broken links and passes the smoke tests.


Method: make pr-checks + technical-writer review.

Procedure: existing pages under current-system/oam/postmark-service/ are extended to reflect the multi-partition Sender Signature inventory; the per-partition deploy procedure invoking amm.sh is documented. make pr-checks passes.


V-DOC-004 — Encryption-key rotation runbook

Section titled “V-DOC-004 — Encryption-key rotation runbook”

Method: make pr-checks + technical-writer review.

Procedure: a new operator runbook (location pinned per REQ-DOC-004) covers the AWS-SM-native rotation flow per DQ-R1-019, the migration-completion verification query, and the SDK-fallback alarm playbook. Linked from operator-runbook.md. make pr-checks passes; the page’s frontmatter declares maturity: review.


Filled in as the rollout progresses. One row per operator task; the operator records deviations in the Deviations column and forward-pointers in Notes.

TaskRequirementOperatorDate (YYYY-MM-DD)DeviationsNotes
T-O1 pre-flight (dev)REQ-OPS-001, 002Miguel Pinilla2026-05-27noneSee execution log § dev / Pre-flight.
T-O2 Root no-drift verificationREQ-IAC-002Miguel Pinilla2026-05-27noneEmpty cdk diff on RootConfiguration post-Run-1 merge — preserved across all four partition deploys.
T-O3 deploy devREQ-PART-001..020 (dev)Miguel Pinilla2026-05-27noneAlpha002-dev-Email stack deployed; DKIM/Return-Path verified via Postmark API; six -API- exports present.
T-O4 arda-nonprod Postmark Compliance replyREQ-OPS-004Miguel Pinilla2026-05-27noneReply with dev.ardamails.com + stage.ardamails.com verified-domain evidence sent to ticket #11236089. Approved 2026-05-27 by Natalie K (Postmark Compliance) — account arda-nonprod now unlocked; on the free developer plan (100 test emails/month).
T-O1 pre-flight (stage)REQ-OPS-001, 002Miguel Pinilla2026-05-27noneSee execution log § stage / Pre-flight.
T-O5 deploy stageREQ-PART-001..020 (stage)Miguel Pinilla2026-05-27noneAlpha002-stage-Email stack deployed; DKIM/Return-Path verified on PostmarkNonProd.
T-O1 pre-flight (demo)REQ-OPS-001, 002Miguel Pinilla2026-05-27noneProfile switched to Admin-Alpha1 (Alpha001 partition).
T-O6 deploy demoREQ-PART-001..020 (demo)Miguel Pinilla2026-05-27noneAlpha001-demo-Email stack deployed; DKIM/Return-Path verified on PostmarkProd.
T-O1 pre-flight (prod)REQ-OPS-001, 002Miguel Pinilla2026-05-27noneProduction-deploy approval recorded in execution log before opening the entry.
T-O7 deploy prodREQ-PART-001..020 (prod)Miguel Pinilla2026-05-27noneAlpha001-prod-Email stack deployed; DKIM/Return-Path verified on PostmarkProd.
T-O8 first scheduled runtime-platform-drift runREQ-CI-001Miguel Pinilla2026-05-28noneAll-green across dev/stage/demo/prod after #466 (1Password integrationName length) and #475 (Postmark detail-endpoint DKIM/Return-Path) fixes. Run: 26608798192.
dmarc-reports@arda.cards mailbox health pre-flightREQ-OPS-003Miguel Pinilla2026-05-27noneMailbox confirmed receiving DMARC reports; re-checked at each partition’s pre-flight.

Copyright: (c) Arda Systems 2025-2026, All rights reserved