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 | pending |
V-PART-002 | REQ-PART-002 | Unit (Template matcher) | pending |
V-PART-003 | REQ-PART-003 | Unit (Template matcher) + dig | pending |
V-PART-004 | REQ-PART-004 | Unit (Template matcher) + dig | pending |
V-PART-005 | REQ-PART-005 | Unit (Template matcher) + dig | pending |
V-PART-007 | REQ-PART-007 | Unit (injected mocks) | pending |
V-PART-008 | REQ-PART-008 | Postmark Account API call | pending |
V-PART-009 | REQ-PART-009 | Postmark Account API call | pending |
V-PART-010 | REQ-PART-010 | Unit (Template matcher) + dig | pending |
V-PART-011 | REQ-PART-011 | Unit (Template matcher) + AWS CLI | pending |
V-PART-012 | REQ-PART-012 | Unit (Template matcher) | pending |
V-PART-014 | REQ-PART-014 | Unit (Template matcher) + AWS CLI | pending |
V-PART-015 | REQ-PART-015 | Unit (Template matcher) | pending |
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 | pending |
V-PART-018 | REQ-PART-018 | Unit (Template matcher) | pending |
V-PART-019 | REQ-PART-019 | Unit (Template matcher) + AWS CLI | pending |
V-PART-020 | REQ-PART-020 | Unit (Template matcher) | pending |
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) | pending |
V-IAC-002 | REQ-IAC-002 | Unit (Template snapshot equality) + cdk diff against Root | pending |
V-IAC-003 | REQ-IAC-003 | Unit (Template matcher) + synth-only smoke | pending |
V-IAC-004 | REQ-IAC-004 | Synth-only smoke per partition | pending |
V-IAC-005 | REQ-IAC-005 | Unit (config-shape assertions) + synth-only smoke | pending |
V-IAC-006 | REQ-IAC-006 | Repo-state grep (no env-var bridges) + Unit | pending |
V-IAC-007 | REQ-IAC-007 | Unit (reserved-words list assertion) | pending |
V-IAC-008 | REQ-IAC-008 | Unit (idempotent re-synth) + Template snapshot | pending |
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 | pending |
V-CLI-002 | REQ-CLI-002 | Unit (injected mocks; repeat invocation produces same result) | pending |
V-CLI-003 | REQ-CLI-003 | Unit (helpers tests) + grep (no inline reimplementation) | pending |
V-CLI-004 | REQ-CLI-004 | Bash dry-run + GHA mask integration test | pending |
V-CLI-005 | REQ-CLI-005 | Unit (injected mocks; failure paths) | pending |
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 | pending |
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 | pending |
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.*`),}),]),}),}); - 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: npx cdk synth --app apps/Al1x/partition --context partition=dev (and equivalent for stage, demo, prod) produces a valid template for each. kyle is excluded — synth either errors with a clear “kyle is suspended” message or skips kyle gracefully (matches the instance-config decision).
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 — for each of the four config files (
Alpha001/prod.ts,Alpha001/demo.ts,Alpha002/dev.ts,Alpha002/stage.ts), assert the config object has the expected shape: Postmark account ref matches the partition’s account, sub-zone name matches<partition>.ardamails.com, DMARC mailbox isdmarc-reports@arda.cards. - 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 construct test locks generation config
Section titled “V-IAC-008 — Encryption-key construct test locks generation config”Method: Unit (idempotent re-synth) + Template snapshot.
Procedure: in the encryption-key construct’s test:
- Synthesize the construct (within
partition-email.test.ts) and capture theAWS::SecretsManager::Secretresource’sGenerateSecretStringblock. - Re-synthesize against the same fixture inputs and assert the second template equals the first (idempotent re-synth invariant).
- Optionally, assert the
GenerateSecretStringshape against a small snapshot fixture so any field change triggers a test failure.
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) + bash sub-process invocation.
Procedure:
- Unit — in
register-partition-mail-signature.test.ts, with mocks for the Postmark client,opresolver, and filesystem:- Happy path:
Alpha002 dev→ Sender Signature registration succeeds →cdk.context.jsonis written with the expected keys → exit 0. - 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 + a clear “must be Alpha001 or Alpha002” error → exit non-zero. SandboxKyle002as<infrastructure>→ rejected with a PDEV-438 reference → exit non-zero.- 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.) - Valid args but Postmark API failure → redacted error summary on stderr → exit non-zero,
cdk.context.jsonunchanged.
- Happy path:
- Integration smoke —
bash -c 'npx ts-node tools/register-partition-mail-signature.ts Alpha002 dev'against fixtures runs end-to-end without error. - Usage parity with
amm.sh: the script’s usage output uses the same shape asamm.shline 140 (Usage: ./amm.sh [...] <infrastructure> (<partition>)) so an operator who has invokedamm.shrecognises the convention.
V-CLI-002 — Phase A idempotency
Section titled “V-CLI-002 — Phase A idempotency”Method: Unit (injected mocks; repeat invocation produces same result).
Procedure: in register-partition-mail-signature.test.ts:
- Mock the Postmark API to return an existing
dev.ardamails.comSender Signature on the first call (simulating a prior run). - Run the script; assert it skips creation (no
POST /senderscall) and writes the existing values tocdk.context.json. - Run again; assert the result is identical.
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 dry-run + GHA mask integration test.
Procedure:
- Bash dry-run — invoke
amm.shwith the partition-mail step against a fixture partition; assert the emitted commands includeop read,::add-mask::,npx ts-node tools/register-partition-mail-signature.ts, andcdk deploy ... --parameters PostmarkAccountToken=. - GHA mask integration — run
amm.shinside a GHA-emulating environment (e.g., setGITHUB_ACTIONS=true); assert the Postmark token does not appear unredacted in stdout / stderr.
V-CLI-005 — Phase A failure semantics
Section titled “V-CLI-005 — Phase A failure semantics”Method: Unit (injected mocks; failure paths).
Procedure: in register-partition-mail-signature.test.ts:
- Mock the Postmark API to return a 503; assert the script exits non-zero with a redacted error summary on stderr.
- Mock the op-resolver to throw; assert the script exits non-zero before any Postmark API call.
- Mock the filesystem write to fail; assert the script exits non-zero and does not partially write
cdk.context.json.
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 | ||||
| T-O2 Root no-drift verification | REQ-IAC-002 | ||||
T-O3 deploy dev | REQ-PART-001..020 (dev) | ||||
T-O4 arda-nonprod Postmark Compliance reply | REQ-OPS-004 | ||||
T-O1 pre-flight (stage) | REQ-OPS-001, 002 | ||||
T-O5 deploy stage | REQ-PART-001..020 (stage) | ||||
T-O1 pre-flight (demo) | REQ-OPS-001, 002 | ||||
T-O6 deploy demo | REQ-PART-001..020 (demo) | ||||
T-O1 pre-flight (prod) | REQ-OPS-001, 002 | ||||
T-O7 deploy prod | REQ-PART-001..020 (prod) | ||||
T-O8 first scheduled runtime-platform-drift run | REQ-CI-001 | ||||
dmarc-reports@arda.cards mailbox health pre-flight | REQ-OPS-003 |
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