Skip to content

Phase 2 -- Root Updates -- Specification

The contract for Phase 2 implementation. Each task lists its scope, file targets, and a STOP point where the implementer pauses for review before proceeding.

This specification is derived from requirements.md and analysis.md. The verification regime is in verification.md. The cross-phase exports Phase 2 produces are catalogued in exports.md.

  • typescript-coding skill — TypeScript style for the renamed stack and the new instances/Root/dns.ts file.
  • cdk-infrastructure skill — CDK construct conventions and the CFN stack-name immutability rule.
  • unit-tests-infra skill — CDK Template-matcher unit tests.

The CDK id argument passed to the RootDnsStack constructor must remain the literal string "RootConfiguration". Any change to that argument forces CloudFormation to delete and recreate the stack, destroying the production hosted zones and the IAM role every partition’s NS-delegation pattern depends on. An inline source-code comment immediately above the constructor call documents the constraint. This rule is restated for emphasis in ../phases.md § Phase 2 and is the highest-risk concern in this phase.

Per requirements.md § Out of scope of Phase 2:

  • The NS-delegation entry for arda.ardamails.com — written by Phase 3 (Corporate).
  • The arda reserved-words update — belongs to Phase 3.
  • Per-partition mail sub-zones and their NS delegations — belong to Phase 4.
  • Tightening of AllowCreatingNSRecordsRole.allowedParentHostedZoneIds — not part of this project.
  • Extraction of the IAM role to a RootSecurityStack — settled by DQ-013.

Task 1: Rename apps/rootConfiguration/ to apps/Root/

Section titled “Task 1: Rename apps/rootConfiguration/ to apps/Root/”

Goal: align the app folder name with the rev1 PascalCase instance-group convention without disturbing the deployed CFN stack.

Scope:

  1. Rename the folder src/main/cdk/apps/rootConfiguration/ to src/main/cdk/apps/Root/. Use git mv so history is preserved.
  2. Rewrite any in-repo imports that reference the old path. Since the files inside (r53-zones.ts, live-url.ts) are CDK app entry points, expect zero or very few such imports; check exhaustively with grep -rn "apps/rootConfiguration" before declaring done.
  3. Do not edit the file contents of r53-zones.ts or live-url.ts in this task; that’s Task 2.

File targets:

  • Move: src/main/cdk/apps/rootConfiguration/{r53-zones,live-url}.tssrc/main/cdk/apps/Root/{r53-zones,live-url}.ts.

STOP — review after Task 1: confirm git status shows only the rename (no file-content modifications). npm run build should still succeed at this point because the stack class is still named RootConfigurationStack; only the entry-file path has moved.


Task 2: Rename RootConfigurationStackRootDnsStack and update entry points

Section titled “Task 2: Rename RootConfigurationStack → RootDnsStack and update entry points”

Goal: align the stack class with its actual concern (DNS) while preserving the published CFN stack name.

Scope:

  1. Rename src/main/cdk/stacks/root/root-configuration-stack.ts to src/main/cdk/stacks/root/root-dns-stack.ts (use git mv).

  2. Inside the file, rename the class RootConfigurationStack to RootDnsStack. Update the constructor’s docstring if it names the old class.

  3. Update apps/Root/r53-zones.ts (and apps/Root/live-url.ts if it instantiates the stack):

    • Update the import path to the new file name.

    • Update the type / class reference to RootDnsStack.

    • Leave the third positional argument as "RootConfiguration" (this is the CDK id that becomes the CFN stack name). Add an inline single-line comment immediately above the call that reads exactly:

      // CFN stack name MUST remain "RootConfiguration" -- changing it would
      // force CloudFormation to delete and recreate the stack.
  4. Update any other in-repo imports of RootConfigurationStack or the old file path.

File targets:

  • Move + edit: src/main/cdk/stacks/root/root-configuration-stack.tsroot-dns-stack.ts (with class rename).
  • Edit: src/main/cdk/apps/Root/r53-zones.ts (import path, class name, inline comment).
  • Edit: src/main/cdk/apps/Root/live-url.ts (only if it imports the stack class; review first).

STOP — review after Task 2: a fresh cdk synth of apps/Root/ against a non-prod environment must produce a CloudFormation template whose top-level StackName (or AWS metadata) reads RootConfiguration. npm run build and npm run lint must pass.


Task 3: Add instances/Root/dns.ts declarative configuration

Section titled “Task 3: Add instances/Root/dns.ts declarative configuration”

Goal: crystallise the rev1 declarative instances/<InstanceGroup>/<asset>.ts convention for the Root instance group.

Scope:

  1. Create src/main/cdk/instances/Root/ directory.
  2. Create src/main/cdk/instances/Root/dns.ts exporting:
    • The set of zone-name constants the Root app declares (app.arda.cards, io.arda.cards, auth.arda.cards, assets.arda.cards, ardamails.com). Reuse the prefixes from platform/ari-configuration.ts for the arda.cards family.
    • An expectedExports object naming the CloudFormation export names this instance produces (matching RootDnsStack.exportDefinition).
  3. Update apps/Root/r53-zones.ts to import from instances/Root/dns.ts instead of using inline literals (where the declarative pattern dictates — this may be minimal in Phase 2 if the existing app file doesn’t have many literals to extract; do not refactor beyond what’s needed to make instances/Root/dns.ts the source of truth for the new ardamails.com zone).

File targets:

  • New: src/main/cdk/instances/Root/dns.ts.
  • Edit: src/main/cdk/apps/Root/r53-zones.ts (limited; primarily to thread the ardamails.com zone through from the declarative config).

STOP — review after Task 3: npm run build and npm test pass. cdk synth for apps/Root/ produces the expected resource set (existing zones + new ardamails.com zone).


Task 4: Add ardamails.com PublicHostedZone and its export

Section titled “Task 4: Add ardamails.com PublicHostedZone and its export”

Goal: declare the mail-root hosted zone in the Root account and expose its zone ID to downstream stacks.

Scope:

  1. In RootDnsStack, instantiate a new r53.PublicHostedZone(this, "ArdamailsZone", { zoneName: "ardamails.com" }).
  2. Extend the stack’s Built interface with a new ardamailsZone: string field (the zone ID).
  3. Extend the stack’s exportDefinition with a new ardamailsZone entry whose exportName is "arda-ardamails-zone" and whose description is "The Hosted Zone Id for the ardamails.com mail-root zone".
  4. Wire the new field into the publish() method.
  5. Confirm via cdk synth that the resulting template includes a AWS::Route53::HostedZone for ardamails.com. and an AWS::CloudFormation::Output for arda-ardamails-zone.

File targets:

  • Edit: src/main/cdk/stacks/root/root-dns-stack.ts.

STOP — review after Task 4: cdk diff against the deployed Root stack shows only an additive Outputs.ardaArdamailsZone and an additive Resources.ArdamailsZone. No deletions or replacements of existing resources.


Task 5: Update deploy-root.sh for the renamed app folder

Section titled “Task 5: Update deploy-root.sh for the renamed app folder”

Goal: keep the deploy entry point working after the rename.

Scope:

  1. In deploy-root.sh line 56, change src/main/cdk/apps/rootConfiguration/r53-zones.ts to src/main/cdk/apps/Root/r53-zones.ts. Path-only edit; no other change to the script.

File targets:

  • Edit: deploy-root.sh.

STOP — review after Task 5: a dry-run invocation (npx cdk synth ... substituting the same --app argument the script uses) succeeds.


Goal: align the project-level documentation with the Phase 2 / Phase 3 ownership split for cross-zone NS delegations.

Scope:

  1. In ../phases.md:
    • Phase 2 deliverables table: remove the row “NS-delegation for arda.ardamails.com”. Replace with a row “ardamails.com zone declaration” pointing at RootDnsStack. Drop the “gated to fire only when Phase 3 has provisioned the Corporate zone” language.
    • Phase 2 exit criteria: remove the parenthetical “(after Phase 3 lands the zone — this exit criterion gates the joint state, but Phase 2 itself only adds the forward declaration)”. The dig assertion belongs to Phase 3.
    • Phase 3 deliverables table: add a new row “NS-delegation for arda.ardamails.com written into ardamails.com via WriteNSRecordsToUpstreamDns (Corporate stack)” so the ownership is explicit.
  2. In ../decision-log.md:
    • Add the row DQ-R1-006 to the decision table.
    • Add the section ### DQ-R1-006: Locus of Cross-Zone NS-Delegation Writes under the Round R1-Phase1 heading (or a Round R1-Phase2 heading if cleaner — author’s discretion at write time, with a brief rationale in the section).
    • Add the entry to the Summary table at the bottom.

File targets:

  • Edit: documentation/src/content/docs/roadmap/in-progress/email-integration/phases.md.
  • Edit: documentation/src/content/docs/roadmap/in-progress/email-integration/decision-log.md.

STOP — review after Task 6: make pr-checks passes.


Goal: every PR to a protected branch carries a CHANGELOG.md entry.

Scope:

  1. Documentation repo: add an entry under a new [0.30.0] heading with ### Added listing the five Phase 2 planning artefacts, the phases.md patch, and the DQ-R1-006 decision-log entry.
  2. Infrastructure repo (when implementation lands): add an entry under a new [2.29.0] heading with ### Changed listing the renames and ### Added listing the ardamails.com zone + new export. The infrastructure CHANGELOG entry is not part of the documentation PR; it lands with the Phase 2 implementation PR.

File targets:

  • Edit: documentation/CHANGELOG.md (this PR).
  • Edit (later): infrastructure/CHANGELOG.md (Phase 2 implementation PR).

Tasks 1 through 5 land on the infrastructure side and are executed in order. Each Task’s STOP point gates entry to the next. Task 6 lands on the documentation side; Task 6 may be performed in parallel with Tasks 1-5 because the patch is text-only and does not depend on the implementation. Task 7 (CHANGELOG) is the last action before opening either PR.

A single-engineer execution can complete the work; if the team chooses to parallelise, the natural split is along repository boundaries (one agent on infrastructure for Tasks 1-5, one on documentation for Task 6).

Restated for clarity; identical to requirements.md § Out of scope of Phase 2.

  • NS-delegation entry for arda.ardamails.com.
  • Reserving arda in the reserved-words list.
  • Per-partition mail sub-zones.
  • Tightening allowedParentHostedZoneIds.
  • Extraction of the IAM role.

Phase 2 has no open questions on the date this specification is written. The decision that resolved the Phase 2 / Phase 3 ownership split is captured in DQ-R1-006.

If implementation surfaces an OQ, record it here with a recommendation, then resolve to a DQ-R1-NNN entry in decision-log.md per the convention introduced in architecture-overview.md § 10.

#QuestionOptionsRecommendationDecision
(none open)