Phase 3 -- Corporate Updates -- Verification
Verification catalogue for Phase 3. Each V-CORP-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 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). - Unit (Jest + injected mocks) —
npx jest <path>; the test injects mocks for external dependencies (Postmark client, 1Password SDK, filesystem,dig) and exercises code paths. - Synth-only smoke —
npx cdk synth --app <app>; asserts the App synthesizes without errors against a fixture context. cdk diffagainst deployed — compares the synthesized template to the deployed CloudFormation stack; passes when expected diffs are present and unexpected diffs are absent.digquery — DNS resolution from a controlled host; asserts record presence, type, value, TTL.- Postmark Account API call —
curl -X GET https://api.postmarkapp.com/...; asserts the response shape and content. - 1Password SDK resolution —
op read 'op://...'(DesktopAuth) or SDK-equivalent; asserts the reference resolves. ghCLI assertion —gh issue list --label drift; asserts the workflow’s issue-on-failure behavior.- 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 Phase C) and written into the long-lived runbook at
process/sre/runbooks/postmark-domain-verification.mdduring Phase D. - Smoke-send / E2E — send a test email; assert
Authentication-Resultsheaders at the recipient.
Tests prefixed V-CORP-NNN and V-IAC-NNN mostly run via Jest unit tests in infrastructure; tests prefixed V-OPS-NNN and V-DOC-NNN are method-mixed.
Traceability table
Section titled “Traceability table”| V-test | Requirement | Method | Status |
|---|---|---|---|
V-CORP-001 | REQ-CORP-001 | Unit (Template matcher) + cdk diff | pending |
V-CORP-002 | REQ-CORP-002 | Unit (Template matcher) | pending |
V-CORP-003 | REQ-CORP-003 | Unit (Template matcher) + dig | pending |
V-CORP-004 | REQ-CORP-004 | Unit (Template matcher) + dig | pending |
V-CORP-005 | REQ-CORP-005 | Unit (Template matcher) + dig | pending |
V-CORP-006 | REQ-CORP-006 | Postmark API call | pending |
V-CORP-007 | REQ-CORP-007 | Postmark API call | pending |
V-CORP-008 | REQ-CORP-008 | Unit (Template matcher) + dig | pending |
V-CORP-009 | REQ-CORP-009 | Postmark API call | pending |
V-CORP-010 | REQ-CORP-010 | 1Password SDK resolution + Postmark API call | pending |
V-IAC-001 | REQ-IAC-001 | Unit (injected mocks) | pending |
V-IAC-002 | REQ-IAC-002 | Repo-state grep + Unit (Template matcher) | pending |
V-IAC-003 | REQ-IAC-003 | Unit (Template matcher) | pending |
V-IAC-004 | REQ-IAC-004 | Unit (Template matcher) | pending |
V-IAC-005 | REQ-IAC-005 | Synth-only smoke | pending |
V-IAC-006 | REQ-IAC-006 | Repo-state grep | pending |
V-IAC-007 | REQ-IAC-007 | Unit (assertion on constant) | pending |
V-IAC-008 | REQ-IAC-008 | Repo-state grep + Unit | pending |
V-CLI-001 | REQ-CLI-001 | --help smoke + Unit (injected mocks) | pending |
V-CLI-002 | REQ-CLI-002 | Unit (injected mocks) | pending |
V-CLI-003 | REQ-CLI-003 | Unit (injected mocks) | pending |
V-CLI-004 | REQ-CLI-004 | Unit (injected mocks) | pending |
V-CLI-005 | REQ-CLI-005 | Unit (injected mocks) + Repo-state grep | pending |
V-CLI-006 | REQ-CLI-006 | Unit (injected mocks) | pending |
V-CLI-007 | REQ-CLI-007 | Unit (injected mocks; log capture) | pending |
V-CLI-008 | REQ-CLI-008 | Unit (injected mocks) + Manual (post-deploy) | pending |
V-OPS-001 | REQ-OPS-001 | Manual (test-mail send to mailbox) | satisfied (2026-05-09) |
V-OPS-002 | REQ-OPS-002 | CLI-output capture + Manual | pending |
V-OPS-003 | REQ-OPS-003 | Repo-state grep | pending |
V-OPS-004 | REQ-OPS-004 | Smoke-send / E2E | pending |
V-CI-001 | REQ-CI-001 | Repo-state grep + workflow-YAML lint | pending |
V-CI-002 | REQ-CI-002 | Unit (injected mocks) | pending |
V-CI-003 | REQ-CI-003 | gh CLI assertion (manual smoke after first failure-trigger) | pending |
V-CI-004 | REQ-CI-004 | Unit (Jest) | pending |
V-DOC-001 | REQ-DOC-001 | make pr-checks (link check) | pending |
V-DOC-002 | REQ-DOC-002 | Repo-state grep | pending |
V-DOC-003 | REQ-DOC-003 | make pr-checks (link check) | pending |
V-DOC-004 | REQ-DOC-004 | Repo-state grep | pending |
V-test details
Section titled “V-test details”V-CORP-001 — arda.ardamails.com hosted zone is declared
Section titled “V-CORP-001 — arda.ardamails.com hosted zone is declared”Method: Unit (Template matcher) + cdk diff against deployed.
Procedure:
-
Unit — in
corporate-mail-dns.test.ts:template.hasResourceProperties("AWS::Route53::HostedZone", {Name: "arda.ardamails.com.",});template.hasResource("AWS::Route53::HostedZone", {DeletionPolicy: "Retain",UpdateReplacePolicy: "Retain",}); -
Post-deploy —
cdk diff apps/Corporate/against deployed reports zero differences for the zone resource.
V-CORP-002 — arda.ardamails.com zone ID is exported
Section titled “V-CORP-002 — arda.ardamails.com zone ID is exported”Method: Unit (Template matcher).
Procedure: in corporate-mail-dns.test.ts:
template.hasOutput("ardaCorporateMailZone", { Export: { Name: "arda-corporate-mail-zone" },});V-CORP-003 — NS-delegation record for arda is written via CR
Section titled “V-CORP-003 — NS-delegation record for arda is written via CR”Method: Unit (Template matcher) + post-deploy dig.
Procedure:
- Unit — assert the
WriteNSRecordsToUpstreamDnsLambda +Custom::WriteNSRecordsToUpstreamDnsare present, and the CR’s properties includesubdomain: "arda"and anameServersreference to the Corporate zone’shostedZoneNameServerstoken. - Post-deploy —
dig +short NS arda.ardamails.comreturns the four AWS-assigned name-servers of the Corporate zone (verifies the NS record set is in place at the parent).
V-CORP-004 — SPF record at Corporate zone apex
Section titled “V-CORP-004 — SPF record at Corporate zone apex”Method: Unit (Template matcher) + post-deploy dig.
Procedure:
- Unit — a TXT record with
Name: "arda.ardamails.com."andResourceRecords: ['"v=spf1 include:spf.mtasv.net ~all"']is present. - Post-deploy —
dig +short TXT arda.ardamails.comincludes the SPF string.
V-CORP-005 — DMARC record at Corporate zone
Section titled “V-CORP-005 — DMARC record at Corporate zone”Method: Unit (Template matcher) + post-deploy dig.
Procedure:
- Unit — a TXT record with
Name: "_dmarc.arda.ardamails.com."includesp=quarantine,sp=quarantine,rua=mailto:dmarc-reports@arda.cards. Alignment tags (adkim,aspf) are absent — relaxed alignment is the documented initial posture. - Post-deploy —
dig +short TXT _dmarc.arda.ardamails.comreturns the DMARC string.
V-CORP-006 — Postmark Sender Signature exists for arda.ardamails.com
Section titled “V-CORP-006 — Postmark Sender Signature exists for arda.ardamails.com”Method: Postmark Account API call.
Procedure: from a workstation authenticated with the PostmarkProd account token (resolved from 1Password):
curl -H "X-Postmark-Account-Token: $TOKEN" \ "https://api.postmarkapp.com/domains?Name=arda.ardamails.com"Asserts the response contains exactly one entry with Name: "arda.ardamails.com".
V-CORP-007 — DKIM and Return-Path are API-verified
Section titled “V-CORP-007 — DKIM and Return-Path are API-verified”Method: Postmark Account API call.
Procedure: after Phase B deploys the DNS records, invoke:
curl -X PUT -H "X-Postmark-Account-Token: $TOKEN" \ "https://api.postmarkapp.com/domains/<id>/verifyDkim"curl -X PUT -H "X-Postmark-Account-Token: $TOKEN" \ "https://api.postmarkapp.com/domains/<id>/verifyReturnPath"Each response should report DKIMVerified: true and ReturnPathDomainVerified: true respectively. corporate-cli verify automates this.
V-CORP-008 — Free Kanban Tool DNS records published
Section titled “V-CORP-008 — Free Kanban Tool DNS records published”Method: Unit (Template matcher) + post-deploy dig.
Procedure:
- Unit — in
free-kanban-tool-mail-dns.test.ts, assert the DKIM TXT record at<selector>._domainkey.freekanban.arda.ardamails.comand the Return-Path CNAME atpm-bounces.freekanban.arda.ardamails.com→pm.mtasv.netare present. - Post-deploy —
dig +short TXT <selector>._domainkey.freekanban.arda.ardamails.comreturns the DKIM key;dig +short CNAME pm-bounces.freekanban.arda.ardamails.comreturnspm.mtasv.net..
V-CORP-009 — Free Kanban Tool Postmark server exists
Section titled “V-CORP-009 — Free Kanban Tool Postmark server exists”Method: Postmark Account API call.
Procedure: list servers in PostmarkProd:
curl -H "X-Postmark-Account-Token: $TOKEN" \ "https://api.postmarkapp.com/servers?count=500"Assert the response includes a server matching the Free Kanban Tool’s configured name (from instances/Corporate/free-kanban-tool.ts).
V-CORP-010 — Free Kanban server token resolves
Section titled “V-CORP-010 — Free Kanban server token resolves”Method: 1Password SDK resolution + Postmark API call.
Procedure:
-
From an operator workstation authenticated with DesktopAuth (or via service-account token scoped to
Arda-CorporateOAM):op read 'op://Arda-CorporateOAM/Free-Kanban-Generator-Postmark-Server/credential'Returns a non-empty string.
-
Use the returned token to authenticate against the Postmark Server API:
curl -H "X-Postmark-Server-Token: $RESOLVED" \"https://api.postmarkapp.com/server"Returns the server metadata; status
200. -
The CI service-account token (
OP_SERVICE_ACCOUNT_TOKEN) does not resolve this reference (vault is out of its scope); a separate test asserts the failure mode.
V-IAC-001 — Postmark thin-wrapper constructs exist
Section titled “V-IAC-001 — Postmark thin-wrapper constructs exist”Method: Unit (injected mocks).
Procedure: npx jest src/main/cdk/platform/constructs/postmark/. The tests:
- Inject a mock Postmark client.
- Configure the construct with a fixture
Configuration. - Assert the
Builtinterface is populated correctly whencdk.context.jsoncarries the corresponding keys. - Assert idempotent behavior: running twice with the same context yields the same
Builtand does not double-call the API.
V-IAC-002 — DnsZone rename and caller migration
Section titled “V-IAC-002 — DnsZone rename and caller migration”Method: Repo-state grep + Unit (Template matcher) for callers.
Procedure:
grep -rn "Route53HostedZone\|route-53-hosted-zone" src/ tools/ apps/returns zero matches.- For each app that previously called
Route53HostedZone, the synthesized template is identical to the pre-rename baseline (template-diff vs. checkpoint).
V-IAC-003 — DnsEmailRecords construct exists
Section titled “V-IAC-003 — DnsEmailRecords construct exists”Method: Unit (Template matcher).
Procedure: npx jest src/main/cdk/constructs/xgress/dns-email-records.test.ts. Tests assert the construct synthesizes correctly: TXT and CNAME records with the configured names, types, values, TTLs.
V-IAC-004 — Corporate stacks exist and compose correctly
Section titled “V-IAC-004 — Corporate stacks exist and compose correctly”Method: Unit (Template matcher).
Procedure: npx jest src/main/cdk/stacks/corporate/. The tests cover both stacks:
CorporateMailDns: zone, NS-write CR, SPF, DMARC, retention policies, exports.FreeKanbanToolMailDns: DKIM TXT, Return-Path CNAME, no inter-construct circular dependency.
V-IAC-005 — Corporate App synthesizes
Section titled “V-IAC-005 — Corporate App synthesizes”Method: Synth-only smoke.
Procedure: npx cdk synth --app "npx ts-node src/main/cdk/tools/cdk-corporate.ts" (or via the ci-corporate-check.js CI step) runs to completion against a fixture cdk.context.json. The CI matrix exercises this on every PR.
V-IAC-006 — instances/Corporate/free-kanban-tool.ts exists and is imported
Section titled “V-IAC-006 — instances/Corporate/free-kanban-tool.ts exists and is imported”Method: Repo-state grep.
Procedure:
git ls-files src/main/cdk/instances/Corporate/free-kanban-tool.tsreturns the path.grep -rn "instances/Corporate/corporate" src/main/cdk/tools/cdk-corporate.tsreturns at least one match (the instance import in the entry script).
V-IAC-007 — Reserved-words list extended
Section titled “V-IAC-007 — Reserved-words list extended”Method: Unit (assertion on constant).
Procedure: in ari-configuration.test.ts:
expect(MAIL_RESERVED_SLUGS_AT_MAIL_ROOT).toContain("arda");If a partition-zone slug-validation function consumes the constant, a separate test asserts that the validator rejects arda and accepts unrelated slugs.
V-IAC-008 — FREE_KANBAN_POSTMARK_ITEM reference reintroduced
Section titled “V-IAC-008 — FREE_KANBAN_POSTMARK_ITEM reference reintroduced”Method: Repo-state grep + Unit.
Procedure:
grep -n "FREE_KANBAN_POSTMARK_ITEM" src/main/cdk/platform/one-password.tsreturns the export declaration.- The declaration’s fields match
vault: "Arda-CorporateOAM",title: "Free-Kanban-Generator-Postmark-Server",primaryField: "credential", and the canonicalop://...reference (asserted by a unit test). tools/drift-check.test.ts— the count test moves from 3 to 4 items.
V-CLI-001 — Two-phase CLI shape
Section titled “V-CLI-001 — Two-phase CLI shape”Method: --help smoke + Unit (injected mocks).
Procedure:
corporate-cli --helplistsprepareanddeploysubcommands.- Unit — the
preparesubcommand exits cleanly when injected with mocks for the Postmark client, 1Password SDK, and filesystem.
V-CLI-002 — Phase A is idempotent
Section titled “V-CLI-002 — Phase A is idempotent”Method: Unit (injected mocks).
Procedure: invoke prepare twice with the same inputs against a mock backend that is initially empty. After the first invocation, the mock is populated; after the second invocation, the mock state is unchanged (no duplicate Sender Signature, no duplicate server, no duplicate 1P item, cdk.context.json content identical).
V-CLI-003 — Phase A conflict-check
Section titled “V-CLI-003 — Phase A conflict-check”Method: Unit (injected mocks).
Procedure:
- Pre-populate the mock Postmark backend with a Sender Signature whose name matches the asset’s configured zone but whose ID differs from any reconciliation target. Invoke
prepare. The CLI exits non-zero with a message naming the colliding entity. - Repeat for a colliding Postmark server.
- Repeat for a colliding 1Password item.
V-CLI-004 — Server-token write ordering
Section titled “V-CLI-004 — Server-token write ordering”Method: Unit (injected mocks).
Procedure:
- Inject a mock 1Password SDK that fails the write N times then succeeds. Phase A succeeds after the retries; the token is written once (no duplicate writes).
- Inject a mock 1Password SDK that fails permanently. Phase A exits non-zero with a redacted summary;
cdk.context.jsonis not written (verify by checking the filesystem mock).
V-CLI-005 — cdk.context.json public-values only
Section titled “V-CLI-005 — cdk.context.json public-values only”Method: Unit (injected mocks) + Repo-state grep.
Procedure:
- Unit — after a successful Phase A invocation, the mock filesystem’s
cdk.context.jsoncontains keyspostmark.<asset>.serverId,dkimSelector,dkimKey,returnPathTargetand noserverToken-shaped key. - Repo grep —
grep -rn "serverToken" tools/corporate-cli.tsconfirms no token is written to context anywhere in the CLI source. (The token may flow through process-local secret buffer, distinct from any persistent file.)
V-CLI-006 — API-driven verification
Section titled “V-CLI-006 — API-driven verification”Method: Unit (injected mocks).
Procedure: invoke a verification subcommand (corporate-cli verify <asset> if exposed, or the verification step embedded in prepare). Assert the mock Postmark client receives verifyDkim and verifyReturnPath calls (not just getDomain reads).
V-CLI-008 — verify subcommand
Section titled “V-CLI-008 — verify subcommand”Method: Unit (injected mocks) + Manual (post-deploy).
Procedure:
- Unit —
corporate-cli verify free-kanbaninvoked against a mock Postmark backend that returnsverified: truefor both DKIM and Return-Path; assert the CLI exits 0 and reports verified status. Repeat forverified: false; assert non-zero exit and a clear message. - Manual (Task O3) — after deploy, the operator runs
corporate-cli verify free-kanbanagainst PostmarkProd; the response confirms verified status for both DKIM and Return-Path onarda.ardamails.com. Captured in operator notes.
V-CLI-007 — Structured logging with redaction
Section titled “V-CLI-007 — Structured logging with redaction”Method: Unit (injected mocks; log capture).
Procedure:
- Capture the CLI’s stdout during a Phase A run. Each line parses as JSON.
- Inject a known token shape (Postmark UUID-prefixed token) into the input. Confirm it does not appear in the captured output (redacted to
***). - Repeat for 1Password service-account token and GitHub PAT shapes.
V-OPS-001 — DMARC-reports mailbox reachable
Section titled “V-OPS-001 — DMARC-reports mailbox reachable”Method: Manual (test-mail send to mailbox).
Status: satisfied — dmarc-reports@arda.cards was confirmed reachable on 2026-05-09. The
mailbox is live in Arda’s Google Workspace. This prerequisite is cleared ahead of Phase B deploy.
Procedure: send a test email to dmarc-reports@arda.cards from any external account. Confirm receipt within 2 minutes. Captured in operator notes during Task O3 and surfaced in the long-lived runbook (Task D2) at process/sre/runbooks/postmark-domain-verification.md.
V-OPS-002 — Sandbox-to-live status surfaced by CLI
Section titled “V-OPS-002 — Sandbox-to-live status surfaced by CLI”Method: CLI-output capture + Manual.
Procedure:
- Run
corporate-cli prepare free-kanbanthrough to server creation. Confirm the structured log output includes aserver-delivery-typeevent after the server-creation step:infolevel withdeliveryType: "Live"if the server will deliver real mail.warnlevel withdeliveryType: "Sandbox"(or"unknown") if the server is in sandbox. The event is derived fromGET /servers/{id}on the just-created server. Note: Postmark has no account-level sandbox endpoint (GET /redirects to the marketing site;GET /accountreturns 404);DeliveryTypeon the individual server is the only correct API-surface indicator.
- If sandbox: operator submits the approval request via the Postmark Console; captures the date submitted in the operator companion. Approval landing is asynchronous.
V-OPS-003 — Operator runbook authored post-deploy
Section titled “V-OPS-003 — Operator runbook authored post-deploy”Method: Repo-state grep + Manual.
Procedure: by the end of Phase D’s Task D2, the file process/sre/runbooks/postmark-domain-verification.md exists in the documentation repository, with valid Starlight frontmatter (title, tags, domain, maturity, author) and prose covering at minimum: the verifyDkim / verifyReturnPath invocation pattern, the sandbox-to-live approval step (when applicable), the end-to-end smoke-send procedure, and the dmarc-reports@arda.cards mailbox prerequisite. The runbook reflects the actual deploy experience captured in Task O3’s operator notes (not the pre-deploy guess). The file passes make pr-checks link integrity and the documentation-quality-review pass per spec § 1.6.
V-OPS-004 — Smoke send passes authentication
Section titled “V-OPS-004 — Smoke send passes authentication”Method: Smoke-send / E2E.
Procedure:
- From the Free Kanban Tool’s send path, dispatch one test email to a non-owner mailbox (e.g., a personal Gmail account).
- Inspect the recipient’s
Authentication-Resultsheader. Required:dkim=pass header.d=arda.ardamails.com,spf=pass smtp.mailfrom=...arda.ardamails.com,dmarc=pass. - Capture the header text in the operator companion.
V-CI-001 — corporate-drift.yml exists and is scheduled
Section titled “V-CI-001 — corporate-drift.yml exists and is scheduled”Method: Repo-state grep + workflow-YAML lint.
Procedure:
git ls-files .github/workflows/corporate-drift.ymlreturns the path.gh workflow list(inArda-cards/infrastructure) shows the workflow as enabled with the configured schedule.- Manual
workflow_dispatchsmoke run succeeds (post-deploy).
V-CI-002 — Drift driver enumerates instances/Corporate/
Section titled “V-CI-002 — Drift driver enumerates instances/Corporate/”Method: Unit (injected mocks).
Procedure: in corporate-drift.test.ts:
- Inject a fixture
instances/Corporate/containing two assets (e.g.,free-kanban-tooland a fake sibling). - Run the driver with mock Postmark /
dig/ 1Password. - Assert two asset checks are exercised (the driver enumerates by directory listing or by an explicit registry).
V-CI-003 — Drift workflow opens issue on failure
Section titled “V-CI-003 — Drift workflow opens issue on failure”Method: gh CLI assertion (manual smoke after first failure-trigger).
Procedure: cause an intentional drift (e.g., delete a DNS record manually in a NonProd zone, or simulate via fixture). Trigger the workflow. Assert gh issue list --label drift,corporate includes a new issue authored within the workflow run’s timeframe. Capture the issue URL in the operator companion.
V-CI-004 — Drift-check extended
Section titled “V-CI-004 — Drift-check extended”Method: Unit (Jest).
Procedure: npx jest tools/drift-check.test.ts. The count test asserts ALL_OP_ITEMS.length === 4. The OP_SERVICE_ACCOUNT_TOKEN-scoped resolution test continues to assert only the three Phase-1-resolvable items.
V-DOC-001 — Phase 3 planning artifacts published
Section titled “V-DOC-001 — Phase 3 planning artifacts published”Method: make pr-checks (link check).
Procedure:
- The five Pass-2 documents plus
analysis.mdare present underroadmap/in-progress/email-integration/3-corporate-updates/. make test-links(called bymake pr-checks) reports zero broken links from the Phase 3 docs.- The Pass-2 documents are linked from
phases.mdPhase 3 section.
V-DOC-002 — DQ-R1-009..016 published
Section titled “V-DOC-002 — DQ-R1-009..016 published”Method: Repo-state grep.
Procedure: grep -n "^### DQ-R1-00[9]\|^### DQ-R1-01[0-6]" decision-log.md returns 8 matches (one per decision-section heading). The decision-table at the top contains rows for each. The Summary table at the bottom contains rows for each.
V-DOC-003 — Documentation pages published by content type
Section titled “V-DOC-003 — Documentation pages published by content type”Method: make pr-checks (link check).
Procedure:
- New pages exist under
current-system/oam/andcurrent-system/runtime/perREQ-DOC-003. make test-linksreports zero broken links from the new pages.make test-smokePlaywright tests still pass.
V-DOC-004 — Operator companion published
Section titled “V-DOC-004 — Operator companion published”Method: Repo-state grep.
Procedure: identical procedure to V-OPS-003. (The two Vs cross-reference because the companion is both an operator-prerequisite outcome and a documentation deliverable.)
References
Section titled “References”requirements.md— numbered requirements.specification.md— task contract.exports.md— downstream contracts.plan/task-plan.md— execution plan.../decision-log.md— decisions including newDQ-R1-009..016.
Copyright: © Arda Systems 2025-2026, All rights reserved