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.
Verification methods used
Section titled “Verification methods used”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,Propertiesfields,Outputs, retention policies). Used heavily for stack-level assertions onpartition-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 forregister-partition-mail-signature.ts, drift driver, helpers intools/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 smoke —
npx cdk synth --app <app>; asserts the App synthesizes without errors against a fixture context for all four active partitions. cdk diffagainst 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).digquery — DNS resolution from a controlled host (or@8.8.8.8for public-resolver semantics); asserts record presence, type, value, TTL.- Postmark Account API call —
curl -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 resolution —
op read 'op://...'(or SDK-equivalent); asserts the reference resolves to a non-empty value. - AWS CLI / SDK call —
aws secretsmanager describe-secret,aws iam get-role,aws cloudformation get-template,aws sts get-caller-identity; asserts resource state. ghCLI assertion —gh issue list --label drift,gh workflow run; asserts the workflow’s issue-on-failure behavior and triggers.- Repo-state grep / lint —
grep -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.
Traceability table
Section titled “Traceability table”Per-partition deliverables (PART)
Section titled “Per-partition deliverables (PART)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-PART-001 | REQ-PART-001 | Unit (Template matcher) + cdk diff per-partition | complete (Run-2 unit; cdk diff post-deploy) |
V-PART-002 | REQ-PART-002 | Unit (Template matcher) | complete (Run-2) |
V-PART-003 | REQ-PART-003 | Unit (Template matcher) + dig | complete (Run-3 cascade dig + Template matcher) |
V-PART-004 | REQ-PART-004 | Unit (Template matcher) + dig | complete (Run-3 cascade dig + Template matcher) |
V-PART-005 | REQ-PART-005 | Unit (Template matcher) + dig | complete (Run-3 cascade dig + Template matcher) |
V-PART-007 | REQ-PART-007 | Unit (injected mocks) | complete (Run-1) |
V-PART-008 | REQ-PART-008 | Postmark Account API call | complete (Run-3 cascade; Postmark API verify-domain) |
V-PART-009 | REQ-PART-009 | Postmark Account API call | complete (Run-3 cascade; Postmark API verifyDkim + verifyReturnPath) |
V-PART-010 | REQ-PART-010 | Unit (Template matcher) + dig | complete (Run-2 unit; dig post-deploy) |
V-PART-011 | REQ-PART-011 | Unit (Template matcher) + AWS CLI | complete (Run-2 unit; AWS CLI post-deploy) |
V-PART-012 | REQ-PART-012 | Unit (Template matcher) | complete (Run-2) |
V-PART-014 | REQ-PART-014 | Unit (Template matcher) + AWS CLI | complete (Run-2 unit; AWS CLI post-deploy) |
V-PART-015 | REQ-PART-015 | Unit (Template matcher) | complete (Run-2) |
V-PART-016 | REQ-PART-016 | AWS CLI (describe-secret versionId before/after) | pending |
V-PART-017 | REQ-PART-017 | Unit (Template matcher) + AWS CLI | complete (Run-2 unit; AWS CLI post-deploy) |
V-PART-018 | REQ-PART-018 | Unit (Template matcher) | complete (Run-2) |
V-PART-019 | REQ-PART-019 | Unit (Template matcher) + AWS CLI | complete (Run-2 unit; AWS CLI post-deploy) |
V-PART-020 | REQ-PART-020 | Unit (Template matcher) | complete (Run-2) |
IaC hygiene (IAC)
Section titled “IaC hygiene (IAC)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-IAC-001 | REQ-IAC-001 | Unit (Template matcher; both trust-principal modes) | complete (Run-1) |
V-IAC-002 | REQ-IAC-002 | Unit (Template snapshot equality) + cdk diff against Root | partial (unit gate: Run-1; operator T-O2 gate: post-merge) |
V-IAC-003 | REQ-IAC-003 | Unit (Template matcher) + synth-only smoke | complete (Run-2) |
V-IAC-004 | REQ-IAC-004 | Synth-only smoke per partition | complete (Run-2) |
V-IAC-005 | REQ-IAC-005 | Unit (config-shape assertions) + synth-only smoke | complete (Run-2) |
V-IAC-006 | REQ-IAC-006 | Repo-state grep (no env-var bridges) + Unit | complete (Run-2) |
V-IAC-007 | REQ-IAC-007 | Unit (reserved-words list assertion) | complete (Run-1) |
V-IAC-008 | REQ-IAC-008 | Unit (idempotent re-synth) + Template snapshot | complete (Run-2) |
Operator entry-points (CLI)
Section titled “Operator entry-points (CLI)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-CLI-001 | REQ-CLI-001 | Unit (injected mocks) + bash sub-process invocation | complete (Run-2) |
V-CLI-002 | REQ-CLI-002 | Unit (injected mocks; repeat invocation produces same result) | complete (Run-2) |
V-CLI-003 | REQ-CLI-003 | Unit (helpers tests) + grep (no inline reimplementation) | complete (Run-1) |
V-CLI-004 | REQ-CLI-004 | Bash dry-run + GHA mask integration test | partial (Run-2 static; CI mask post-deploy) |
V-CLI-005 | REQ-CLI-005 | Unit (injected mocks; failure paths) | complete (Run-2) |
Operator prerequisites and post-deploy verification (OPS)
Section titled “Operator prerequisites and post-deploy verification (OPS)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-OPS-001 | REQ-OPS-001 | 1Password resolution (operator-driven) | pending |
V-OPS-002 | REQ-OPS-002 | AWS CLI (sts get-caller-identity) | pending |
V-OPS-003 | REQ-OPS-003 | Manual / mailbox check | pending |
V-OPS-004 | REQ-OPS-004 | Manual (Postmark Compliance email) | pending |
V-OPS-005 | REQ-OPS-005 | Manual / runbook | complete |
CI workflows (CI)
Section titled “CI workflows (CI)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-CI-001 | REQ-CI-001 | YAML lint + workflow workflow_dispatch run | complete |
V-CI-002 | REQ-CI-002 | Unit (injected mocks) + synthetic-drift fixture | pending |
V-CI-003 | REQ-CI-003 | Unit (helpers tests) + corporate-drift regression run | pending |
Documentation (DOC)
Section titled “Documentation (DOC)”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-DOC-001 | REQ-DOC-001 | make pr-checks + technical-writer review | pending |
V-DOC-002 | REQ-DOC-002 | make pr-checks + technical-writer review | pending |
V-DOC-003 | REQ-DOC-003 | make pr-checks + technical-writer review | pending |
V-DOC-004 | REQ-DOC-004 | make pr-checks + technical-writer review | pending |
V-test details
Section titled “V-test details”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:
- Unit — in
partition-email.test.ts, for each fixture partition (prod,demo,dev,stage), use the canonicalhasResourcepartial-match shape from cdk-infrastructure.md § 7:template.hasResource("AWS::Route53::HostedZone", {Properties: {Name: `${partition}.ardamails.com.`,},DeletionPolicy: "Retain",UpdateReplacePolicy: "Retain",});hasResourcepartial-matches viaMatch.objectLikeby default, so this single call covers both the property check and the retention-policy check (no need for a separatehasResourcePropertiescall). - Post-deploy —
cdk diffper 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:
- Unit — in
partition-email.test.ts: assert theWriteNSRecordsToUpstreamDnsCustom Resource is declared withsubdomain: <partition>and references the zone’shostedZoneNameServerstoken. - Post-deploy —
dig NS {partition}.ardamails.com @8.8.8.8returns 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:
- Unit — assert a
AWS::Route53::RecordSetwithType: "TXT",Name: "<partition>.ardamails.com.", andResourceRecordscontaining"v=spf1 include:spf.mtasv.net ~all". - Post-deploy —
dig +short TXT {partition}.ardamails.comreturns the SPF record string.
V-PART-005 — DMARC record per partition
Section titled “V-PART-005 — DMARC record per partition”Method: Unit (Template matcher) + dig.
Procedure:
- Unit — assert a
AWS::Route53::RecordSetwithType: "TXT",Name: "_dmarc.<partition>.ardamails.com.", and the value matching"v=DMARC1; p=quarantine; sp=quarantine; rua=mailto:dmarc-reports@arda.cards". - Post-deploy —
dig +short TXT _dmarc.{partition}.ardamails.comreturns 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:
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:
curl -H "X-Postmark-Account-Token: $token" \ https://api.postmarkapp.com/senders/<signatureId>/verifydkimcurl -H "X-Postmark-Account-Token: $token" \ https://api.postmarkapp.com/senders/<signatureId>/verifyreturnpathBoth 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:
- Unit — in
partition-email.test.ts, assert twoAWS::Route53::RecordSetresources:Type: "TXT",Name: "<selector>._domainkey.<partition>.ardamails.com."with the public DKIM key fromcdk.context.jsonkeypostmark.<partition>.dkimKey.Type: "CNAME",Name: "pm-bounces.<partition>.ardamails.com."with target<returnPathTarget>(typicallypm.mtasv.net).
- Post-deploy —
dig +short TXT <selector>._domainkey.<partition>.ardamails.comanddig +short CNAME pm-bounces.<partition>.ardamails.comreturn 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:
- 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 }); - Post-deploy —
aws secretsmanager describe-secret --secret-id <fqn>-I-EmailPostmarkAccountToken --profile <profile>returns a secret withDeletionPolicy: Retainand anAWSCURRENTversionId.
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.ts — findOutputs("*", {...}) 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:
- 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" }); - Post-deploy —
aws secretsmanager describe-secret --secret-id <fqn>-I-EmailEncryptionKey --profile <profile>returnsAWSCURRENTversionId andDeletionPolicy: 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.ts — findOutputs("*", {...}) 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:
- 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. - Re-run
amm.shfor the same partition (no code changes; no 1P value changes). - Re-capture:
... > after.json. - Assert
diff before.json after.jsonreports no changes — theAWSCURRENTversionId 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:
- 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. - Negative-test for
route53:GetChange: assert no Action element containsroute53:GetChangeanywhere in the role’s policy. - 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.ts — findOutputs("*", {...}) 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:
- 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.*`),}),]),}),}); - 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.tsreaches into the synthesisedAWS::IAM::Roleresource’sAssumeRolePolicyDocument.Statementarray and assertslength === 1with the condition baked into the principal (viaPrincipalWithConditions). Guards against the earlier bug shape where an unconditionalAccountPrincipaltrust statement plus an additive conditionedaddStatements(...)call OR-evaluated to “anyone in the account”. - Post-deploy —
aws iam get-role --role-name <FallbackRoleName> --profile <profile>returns the role.
V-PART-020 — Fallback role ARN exported
Section titled “V-PART-020 — Fallback role ARN exported”Method: Unit (Template matcher).
Procedure: in partition-email.test.ts — findOutputs("*", {...}) 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):
- 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>. - 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>. - 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:
- Pre-merge unit gate — in
root-dns-stack.test.ts: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.const template = Template.fromStack(rootStack);const baseline = JSON.parse(fs.readFileSync("root-dns-stack.baseline.json", "utf8"));expect(template.toJSON()).toEqual(baseline); - Post-merge operator gate (T-O2) —
cdk synthRootDnsStackfrom the mergedmainbranch;aws cloudformation get-template --stack-name RootConfiguration --profile Admin-Alpha1to capture the deployed template;diffof 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:
- Unit (composition) —
partition-email.test.tscovers each sub-resource via the V-PART-NNN entries above; composition is implicitly tested because the same stack synthesis runs all sub-resource assertions. - Unit (
validateProps) — assert the staticvalidatePropsreturns the expectedError[]on each known failure mode: invalidlocator(viapurpose.validatePurposeLocator), missingawsUtil.validateStackPropsfields, malformedpodRoleArnPattern, malformed DMARC mailbox, absent Postmark account reference. Construction with invalid props throwsmisc.MultiErrorbeforesuper(). - Unit (
Builtshape) — assert the constructed stack’sbuiltfield carries the expected typed members:partitionMailZone,emailEncryptionKeySecret,emailPostmarkAccountTokenSecret,emailDnsProvisioningRole,emailEncryptionKeyFallbackRole. Each is an interface type (IHostedZone,ISecret,IRole) — references, not concrete classes. - Unit (
ExportKeys↔ export-name alignment) — assert everyExportKeysmember ends withAPIand every produced export name contains-API-. Thepublish()regex enforces this at synth time; this test confirms the regex’s coverage. - Synth-only smoke —
npx cdk synth --app apps/Al1x/partitionfor 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:
- Unit —
platforms.test.tsasserts that each active partition inENVIRONMENTScarries amailblock with the expectedpostmarkAccountandcredentialOpReferencevalues;kylecarries nomailblock (it is outside the Phase-4 set). The DMARC mailbox + SPF + DKIM record values are system-wide constants inari-configuration.ts(DMARC_RECORD_VALUE,SPF_RECORD_VALUE), not per-partition fields — covered bypartition-email.test.ts’s record-set assertions and re-asserted inari-configuration.test.ts. - 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:
- Grep
partition-email.ts(and its sub-construct invocations): noprocess.env.*reads, nofs.readFile, no env-var-bridge patterns. - The composition uses
Builtvalue 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 presentAdditionally, 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:
- Unit — in
tools/lib/partition-mail-signature.test.ts(the entry script’s testable surface lives intools/lib/partition-mail-signature.ts;tools/register-partition-mail-signature.tsis 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 /domainsregistersdev.ardamails.com→cdk.context.jsonis 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: ""andDKIMTextValue: ""but populatedDKIMPendingHost/DKIMPendingTextValue— the active-then-pending precedence helpers intools/lib/postmark-client.ts(effectiveDkimHost,effectiveDkimTextValue) pick the pending values, andcdk.context.jsonlands with the correct selector + key. - Idempotent path: list-domains returns an existing entry for the zone →
GET /domains/{id}fetches DKIM details → noPOST /domainscall. - 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 fromVALID_INFRASTRUCTURESinarda/platforms, which is itself derived fromENVIRONMENTSentries that contain at least one partition with amailblock. - Partition / infrastructure mismatch (e.g.,
Alpha001 dev) → usage block on stderr + apartition '<x>' does not belong to infrastructure '<y>'line → exit non-zero. Catches operator typos before any Postmark API call. Mapping derived fromPARTITION_TO_INFRASTRUCTUREinarda/platforms. - Valid args but Postmark API failure → redacted error summary on stderr → exit non-zero,
cdk.context.jsonunchanged. --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 /serverscall is made anywhere in the run (Sender Signature only — Postmark Servers are created at system Runtime by Tenant, not at Provisioning time).
- Happy path:
- Usage parity with
amm.sh: the script’s usage block names the same<infrastructure> <partition>positional shape asamm.shline 140, so an operator who has invokedamm.shrecognises the convention.
V-CLI-002 — Pre-Deploy idempotency
Section titled “V-CLI-002 — Pre-Deploy idempotency”Method: Unit (injected mocks; repeat invocation produces same result).
Procedure: in tools/lib/partition-mail-signature.test.ts:
- Mock the Postmark API to return an existing
dev.ardamails.comdomain in theGET /domains?count=500&offset=0listing (simulating a prior run). - Run
registerPartitionMailSignature(...)with the mocked deps; assert the script callsGET /domains/{id}to fetch the existing domain’s DKIM details, never callsPOST /domains(the create endpoint), and writes the existing values tocdk.context.json. - 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:
- Unit —
tools/lib/*.test.tscovers each helper (Postmark client retry / backoff, op-resolver, redaction). - Grep —
grep -rn "PostmarkAccountAPI\|opRead" tools/shows the relevant patterns appear only insidetools/lib/and at call sites incorporate-cli.ts+register-partition-mail-signature.ts(not duplicated inline).
V-CLI-004 — amm.sh partition-mail step
Section titled “V-CLI-004 — amm.sh partition-mail step”Method: Bash syntax check + manual operator dry-run; GHA-mask integration left to the first real CI execution.
Procedure:
- Static check:
bash -n amm.shreturns zero. Manually inspecting the partition iteration body around the>>>>>>>>> Step ${step}.0.5: Partition mail Pre-Deploymarker, confirm the sequence is:mktemp→register-partition-mail-signature.ts ... --token-out <tmpfile>→ read the token via$(<"$tmpfile")→rm -f "$tmpfile"→::add-mask::(whenGITHUB_ACTIONS=true) → append--parameters …-Email:PostmarkAccountToken=…and--forcetopartition_cdk_arguments. - Operator dry-run (pre-merge, judgement call per spec § T-O3): an operator may invoke
./amm.sh Alpha002 devagainst the PR branch with a real Postmark token (not the prod one). Confirm the script reachescdk deploycleanly and that the token written to the temp file has the expected length. - GHA mask integration (post-merge, first real CI run): observe a CI run of
amm.shand 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:
- Mock the Postmark API to return a 5xx; assert the script exits non-zero with a redacted error summary on stderr.
- Mock the secret resolver to throw; assert the script exits non-zero before any Postmark API call.
- Mock the
writeContextdep to throw; assert the script exits non-zero. (The atomic.tmp+rename()strategy insrc/main/cdk/utils/context-store.tsalready prevents partial writes; that contract is exercised bycontext-store.test.ts.) - Mock the Postmark response to come back with empty active and empty pending DKIM fields; assert
effectiveDkimHost/effectiveDkimTextValuethrow 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).
V-OPS-005 — Operator sign-off table
Section titled “V-OPS-005 — Operator sign-off table”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:
- YAML lint —
npx js-yaml infrastructure/.github/workflows/runtime-platform-drift.yml(or the repo’s equivalent linter) returns no errors. - Manual trigger —
gh workflow run runtime-platform-drift.ymlruns to completion; the run’s logs match the expected per-partition probe shape. - The workflow’s failure-issue labels match
drift+runtime-platform.
V-CI-002 — Drift driver script
Section titled “V-CI-002 — Drift driver script”Method: Unit (injected mocks) + synthetic-drift fixture.
Procedure:
- Unit —
runtime-platform-drift.test.tscovers per-partition probes with mocks for Postmark,dig, AWS SDK. Happy path produces no drift; mocked drift produces the expected report. - 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:
- Unit —
tools/lib/drift/*.test.tscovers each shared helper. - Run
corporate-drift.yml(manually viaworkflow_dispatch) against the livearda.ardamails.comSender 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:
make pr-checkspasses on the documentation repo’s PR.- The page’s frontmatter
maturityisreview(notdraft). - Technical-writer sub-agent review covers structure, clarity, internal consistency, link integrity, en_US locale, and adherence to the
document-writingandpath-conventionsskills.
V-DOC-002 — Per-partition mail pages
Section titled “V-DOC-002 — Per-partition mail pages”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.
V-DOC-003 — Postmark-service updates
Section titled “V-DOC-003 — Postmark-service updates”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.
Operator sign-off
Section titled “Operator sign-off”Filled in as the rollout progresses. One row per operator task; the operator records deviations in the Deviations column and forward-pointers in Notes.
| Task | Requirement | Operator | Date (YYYY-MM-DD) | Deviations | Notes |
|---|---|---|---|---|---|
T-O1 pre-flight (dev) | REQ-OPS-001, 002 | Miguel Pinilla | 2026-05-27 | none | See execution log § dev / Pre-flight. |
| T-O2 Root no-drift verification | REQ-IAC-002 | Miguel Pinilla | 2026-05-27 | none | Empty cdk diff on RootConfiguration post-Run-1 merge — preserved across all four partition deploys. |
T-O3 deploy dev | REQ-PART-001..020 (dev) | Miguel Pinilla | 2026-05-27 | none | Alpha002-dev-Email stack deployed; DKIM/Return-Path verified via Postmark API; six -API- exports present. |
T-O4 arda-nonprod Postmark Compliance reply | REQ-OPS-004 | Miguel Pinilla | 2026-05-27 | none | Reply 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, 002 | Miguel Pinilla | 2026-05-27 | none | See execution log § stage / Pre-flight. |
T-O5 deploy stage | REQ-PART-001..020 (stage) | Miguel Pinilla | 2026-05-27 | none | Alpha002-stage-Email stack deployed; DKIM/Return-Path verified on PostmarkNonProd. |
T-O1 pre-flight (demo) | REQ-OPS-001, 002 | Miguel Pinilla | 2026-05-27 | none | Profile switched to Admin-Alpha1 (Alpha001 partition). |
T-O6 deploy demo | REQ-PART-001..020 (demo) | Miguel Pinilla | 2026-05-27 | none | Alpha001-demo-Email stack deployed; DKIM/Return-Path verified on PostmarkProd. |
T-O1 pre-flight (prod) | REQ-OPS-001, 002 | Miguel Pinilla | 2026-05-27 | none | Production-deploy approval recorded in execution log before opening the entry. |
T-O7 deploy prod | REQ-PART-001..020 (prod) | Miguel Pinilla | 2026-05-27 | none | Alpha001-prod-Email stack deployed; DKIM/Return-Path verified on PostmarkProd. |
T-O8 first scheduled runtime-platform-drift run | REQ-CI-001 | Miguel Pinilla | 2026-05-28 | none | All-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-flight | REQ-OPS-003 | Miguel Pinilla | 2026-05-27 | none | Mailbox confirmed receiving DMARC reports; re-checked at each partition’s pre-flight. |
References
Section titled “References”requirements.md— numbered requirements.specification.md— implementation tasks (T-NNN) and STOP gates.analysis.md— Capability decomposition; Implementation Groups; readiness criteria.exports.md— cross-phase contracts.../../decision-log.md— DQ-R1-017..023 + pre-design follow-ups.email-server-key-encryption.md— encryption-key lifecycle invariants.- Phase 3 analogue:
3-corporate-updates/verification.md.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved