Skip to content

Managed email domain deletion and Cloudflare DNS import UX#1442

Open
mantrakp04 wants to merge 2 commits into
devfrom
feat/managed-email-domain-delete-cloudflare-dns
Open

Managed email domain deletion and Cloudflare DNS import UX#1442
mantrakp04 wants to merge 2 commits into
devfrom
feat/managed-email-domain-delete-cloudflare-dns

Conversation

@mantrakp04
Copy link
Copy Markdown
Collaborator

@mantrakp04 mantrakp04 commented May 19, 2026

Summary

  • Add an admin-only delete endpoint and SDK method to remove managed email domains, with Resend/DNSimple cleanup and a guard against deleting domains currently in use for sending.
  • Add dashboard UI to remove unused managed domains (with confirmation) and improve the DNS setup step with Cloudflare detection, zone file download, and import instructions.
  • Add E2E coverage for delete auth, success, in-use rejection, post-switch deletion, and 404 cases.

Test plan

  • Run pnpm test run managed-email-onboarding
  • In dashboard email settings, add a managed domain and verify Cloudflare hint appears when NS records point to Cloudflare
  • Remove an unused managed domain and confirm it disappears from the list
  • Verify active (in-use) managed domains cannot be deleted until email provider is switched away

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Delete managed email domains from the dashboard with a confirmation flow and success notification
    • Cloudflare-aware domain setup: detection banner, quick links to Cloudflare DNS, downloadable import zone file, and import instructions
    • Prevent deletion when a domain is actively used for sending (clear error shown)
  • Tests

    • Added end-to-end coverage for the managed-domain delete scenarios (success, in-use conflict, auth/404 cases)

Review Change Stack

Let projects remove unused managed domains with upstream cleanup, and streamline Cloudflare NS record import during onboarding.

Co-authored-by: Cursor <[email protected]>
Copilot AI review requested due to automatic review settings May 19, 2026 23:19
@mantrakp04 mantrakp04 self-assigned this May 19, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment May 21, 2026 1:58am
stack-auth-mcp Ready Ready Preview, Comment May 21, 2026 1:58am
stack-auth-skills Ready Ready Preview, Comment May 21, 2026 1:58am
stack-backend Ready Ready Preview, Comment May 21, 2026 1:58am
stack-dashboard Ready Ready Preview, Comment May 21, 2026 1:58am
stack-demo Ready Ready Preview, Comment May 21, 2026 1:58am
stack-docs Ready Ready Preview, Comment May 21, 2026 1:58am
stack-preview-backend Ready Ready Preview, Comment May 21, 2026 1:58am
stack-preview-dashboard Ready Ready Preview, Comment May 21, 2026 1:58am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 252eab15-bc5a-41da-abe7-7f9cdd10ba4e

📥 Commits

Reviewing files that changed from the base of the PR and between d3caf61 and 0579159.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx

📝 Walkthrough

Walkthrough

End-to-end managed email domain deletion: DB helpers, backend deletion service (Resend + DNSimple cleanup), admin API and app mappings, dashboard Cloudflare detection and deletion UI, plus E2E tests covering success, conflicts, auth, and not-found cases.

Changes

Managed Email Domain Deletion

Layer / File(s) Summary
Database operations for managed domains
apps/backend/src/lib/managed-email-domains.tsx
Add deleteManagedEmailDomainById to delete a domain row and return the deleted entity or null; add countManagedEmailDomainsBySubdomainExcludingId to count active records for a subdomain excluding an ID.
Backend deletion service and DNSimple integration
apps/backend/src/lib/managed-email-onboarding.tsx
Import DB helpers; add deleteDnsimpleZoneByName to delete DNSimple zones (map 404 to not_found); implement and export deleteManagedEmailProvider that validates tenancy ownership, rejects if domain is in use, conditionally deletes Resend domain and DNSimple zone (only when no other subdomain references remain), then deletes the DB row.
API route and admin interface
apps/backend/src/app/api/latest/internal/emails/managed-onboarding/delete/route.tsx, packages/stack-shared/src/interface/admin-interface.ts, packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts, packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
Add authenticated admin POST route that validates resend_domain_id, calls deleteManagedEmailProvider, and returns { status }. Add deleteManagedEmailDomain to StackAdminInterface, implement mapping in admin app impl, and expose method on StackAdminApp interface.
DNS and Cloudflare detection helpers
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
Add DoH-based helpers to find authoritative zone apex and NS records, generate Cloudflare-importable zone files, and add CloudflareIcon plus effect/state to detect Cloudflare apex during setup stage.
Dialog styling and DNS records UI
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
Adjust dialog layout and DNS record table: update DialogContent overflow, refactor sender local part input for truncation/spacing, and improve DNS records grid alignment/truncation.
Domain deletion UI and confirmation
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
Add confirmDelete state, tooltip/title for list items, conditional trash button for non-active domains, and an ActionDialog that calls stackAdminApp.deleteManagedEmailDomain, shows success toast, and refreshes the list.
End-to-end test coverage
apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts
Add tests: client access rejection (401 INSUFFICIENT_ACCESS_TYPE); successful deletion of unused domain; conflict when domain is in use (409); deletion after switching away from managed email; and 404 for unknown domain.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • N2D4
  • nams1570

Poem

🐰 I nibbled through DNS and tidy rows,

Resend bid farewell where the wildwind blows,
DB cleared, Cloudflare waved from the sky,
A delete confirmed — hop, tests all fly! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding managed email domain deletion functionality and enhancing DNS import UX with Cloudflare support.
Description check ✅ Passed The description comprehensively covers the changes with a summary of key features, test plan with checkboxes, and context about the implementation approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/managed-email-domain-delete-cloudflare-dns

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds managed email domain deletion support end-to-end (backend endpoint + SDK + dashboard UX), plus Cloudflare-specific DNS setup affordances and E2E coverage to validate deletion behavior and authorization.

Changes:

  • Added an internal admin-only delete endpoint for managed email domains, including provider-side cleanup and “in-use” rejection.
  • Exposed the delete operation through the admin SDK/template layer and surfaced it in the dashboard UI with confirmation.
  • Improved DNS setup UX with Cloudflare detection, zone file download, and import instructions; added E2E tests for delete flows.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts Adds deleteManagedEmailDomain to the admin app interface.
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts Implements the new admin SDK method and maps parameters to the interface request payload.
packages/stack-shared/src/interface/admin-interface.ts Adds a StackAdminInterface method to call the internal delete endpoint.
apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts Adds E2E tests for auth, success, in-use rejection, post-switch deletion, and 404 deletion cases.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx Adds dashboard UI for deleting unused managed domains and Cloudflare DNS import UX.
apps/backend/src/lib/managed-email-onboarding.tsx Implements managed domain deletion logic with Resend/DNSimple cleanup and in-use guard.
apps/backend/src/lib/managed-email-domains.tsx Adds DB helpers to delete a managed domain row and count remaining references to a subdomain.
apps/backend/src/app/api/latest/internal/emails/managed-onboarding/delete/route.tsx Introduces the internal admin delete endpoint route.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/stack-shared/src/interface/admin-interface.ts
Comment thread packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR adds a managed email domain deletion feature end-to-end: an admin-only backend endpoint with Resend/DNSimple cleanup, an in-use guard, an SDK method, and a dashboard confirmation dialog — plus a Cloudflare detection UX with zone-file download and import instructions for the DNS setup step.

  • Backend delete flow (delete/route.tsx, managed-email-onboarding.tsx): the new deleteManagedEmailProvider function verifies tenancy ownership, blocks deletion of the currently-active sender, cleans up Resend and (conditionally) DNSimple resources before dropping the DB row, and is designed to be retryable on partial failure.
  • Dashboard UX (domain-settings.tsx): a trash button appears on unused domains, opens an ActionDialog for confirmation, and on success shows a toast and refreshes the list; stage 2 of the setup wizard now performs a client-side DoH NS lookup to detect Cloudflare and surfaces a banner with a deep link, zone-file download, and import instructions.
  • E2E tests (managed-email-onboarding.test.ts): five scenarios cover client auth rejection, clean delete, in-use 409 conflict, post-switch delete, and 404 for unknown domain.

Confidence Score: 5/5

Safe to merge; tenancy ownership is correctly enforced, the in-use guard prevents deleting active senders, and partial failures leave the system retryable.

The delete flow is well-structured with proper auth checks, a clear tenancy boundary, and retryable external-cleanup ordering. Two minor observations (a tiny TOCTOU window in shared-zone cleanup and the dialog not reflecting the async operation's actual completion) do not affect correctness in normal use.

The zone-cleanup section in managed-email-onboarding.tsx is worth a second look if cross-tenancy subdomain sharing becomes more common.

Important Files Changed

Filename Overview
apps/backend/src/app/api/latest/internal/emails/managed-onboarding/delete/route.tsx New admin-only POST route using SmartRouteHandler; validates admin auth, delegates to deleteManagedEmailProvider, and returns { status: "deleted" }.
apps/backend/src/lib/managed-email-onboarding.tsx Adds deleteManagedEmailProvider with in-use guard, Resend cleanup, conditional DNSimple zone cleanup, and DB deletion; a narrow TOCTOU window exists around zone cleanup when two tenancies share the same subdomain.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx Adds Cloudflare NS detection (DoH lookup), zone-file download, import popover, and a confirmation dialog for domain deletion; the delete dialog correctly uses runAsynchronouslyWithAlert.
apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts Adds five delete scenarios: client auth rejection, successful delete, in-use 409, post-switch delete, and 404 for unknown domain — comprehensive coverage of the new endpoint.
packages/stack-shared/src/interface/admin-interface.ts Adds deleteManagedEmailDomain method that POSTs to the new delete endpoint; straightforward plumbing consistent with adjacent methods.
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts Exposes deleteManagedEmailDomain as a public SDK method by delegating to _interface, translating camelCase ↔ snake_case consistently.
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts Adds deleteManagedEmailDomain to the StackAdminApp interface; signature matches implementation.

Sequence Diagram

sequenceDiagram
    participant Admin as Admin (Dashboard)
    participant API as DELETE /managed-onboarding/delete
    participant DB as Database
    participant Resend as Resend API
    participant DNS as DNSimple API

    Admin->>API: "POST { resend_domain_id }"
    API->>DB: getManagedEmailDomainByResendDomainId()
    DB-->>API: domain row (tenancyId, subdomain, senderLocalPart)
    API->>API: tenancy ownership check
    API->>API: isManagedEmailDomainInUseForTenancy()
    alt domain is in use
        API-->>Admin: 409 Cannot delete active domain
    else not in use
        API->>Resend: "DELETE /domains/{resendDomainId}"
        Resend-->>API: 200 or 404 (both OK)
        API->>DB: countManagedEmailDomainsBySubdomainExcludingId()
        DB-->>API: remaining count
        alt "remaining == 0"
            API->>DNS: "DELETE /zones/{subdomain}"
            DNS-->>API: deleted or not_found
        end
        API->>DB: deleteManagedEmailDomainById()
        DB-->>API: deleted row
        API-->>Admin: "200 { status: deleted }"
    end
Loading

Fix All in Claude Code Fix All in Cursor Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/backend/src/lib/managed-email-onboarding.tsx:711-720
**TOCTOU window in shared-zone cleanup**

Between `countManagedEmailDomainsBySubdomainExcludingId` returning 0 and `deleteDnsimpleZoneByName` completing, a concurrent `setupManagedEmailProvider` call for the same subdomain (from any tenancy) will reach `createOrReuseDnsimpleZone`, find the existing zone, and attach its new DB row to it. The deletion that follows then removes the zone from under the just-created row, leaving it with a valid DB record but a missing DNS zone. In practice two tenancies simultaneously racing a setup against a delete for the exact same subdomain is rare, but the broken state is silent — the new domain's status will never advance past `pending_dns`.

### Issue 2 of 2
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx:1186-1193
`runAsynchronouslyWithAlert` not awaited — dialog closes before the delete resolves.

`ActionDialog` does `await okButton.onClick?.()`. Because `onClick` fires `runAsynchronouslyWithAlert` without awaiting it, the outer promise resolves immediately and the dialog closes before the delete (or any error) has a chance to complete. Errors are still surfaced (good), but the "Remove" button shows no loading state, the dialog closes optimistically, and the domain remains in the list until `refreshDomains` eventually settles. Awaiting the call makes the dialog's built-in loading/disabled state cover the full operation.

```suggestion
          onClick: async () => {
            if (!confirmDelete) return;
            await runAsynchronouslyWithAlert(async () => {
              await stackAdminApp.deleteManagedEmailDomain({ resendDomainId: confirmDelete.domainId });
              toast({ title: "Domain removed", description: `${confirmDelete.senderLocalPart}@${confirmDelete.subdomain} was removed.`, variant: "success" });
              await refreshDomains();
            });
          },
```

Reviews (2): Last reviewed commit: "Refactor domain settings to improve subd..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts (1)

205-206: ⚡ Quick win

Replace fixed sleeps with condition-based polling to reduce E2E flakiness.

Line 205 and Line 243 use wait(1500) as a timing assumption for verification readiness. This can intermittently fail under slower CI timing; poll /check until "verified" with a bounded timeout instead.

♻️ Proposed fix
 import { wait } from "`@stackframe/stack-shared/dist/utils/promises`";
 import { describe } from "vitest";
 import { it } from "../../../../../helpers";
 import { Project, niceBackendFetch } from "../../../../backend-helpers";
 
+async function waitForManagedDomainVerified(domainId: string, subdomain: string, senderLocalPart: string) {
+  const timeoutAt = performance.now() + 10_000;
+  while (true) {
+    const checkResponse = await niceBackendFetch("/api/v1/internal/emails/managed-onboarding/check", {
+      method: "POST",
+      accessType: "admin",
+      body: {
+        domain_id: domainId,
+        subdomain,
+        sender_local_part: senderLocalPart,
+      },
+    });
+    if (checkResponse.body.status === "verified") return;
+    if (performance.now() > timeoutAt) {
+      throw new Error(`Timed out waiting for managed domain ${domainId} to become verified`);
+    }
+    await wait(250);
+  }
+}
+
 describe("managed email onboarding internal endpoints", () => {
 ...
-    await wait(1500);
+    await waitForManagedDomainVerified(setupResponse.body.domain_id, "mail.example.com", "noreply");
 ...
-    await wait(1500);
+    await waitForManagedDomainVerified(setupResponse.body.domain_id, "mail.example.com", "noreply");

Also applies to: 243-244

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts`
around lines 205 - 206, Replace the fixed wait(1500) sleeps used before
verification with a condition-based polling loop that repeatedly calls the
/check endpoint until it returns a response indicating "verified" or a bounded
timeout elapses; update the test that uses wait(1500) (and the other occurrence)
to poll at short intervals (e.g., 200–500ms) for a maximum duration (e.g., 10s),
assert success when the /check response contains "verified", and fail the test
if the timeout is reached—use the existing wait helper only for the poll
interval and keep the polling logic next to the verification steps so the test
no longer depends on a fixed sleep.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx (1)

326-341: ⚡ Quick win

Key the Cloudflare lookup off the subdomain, not the whole setup object.

Line 341 depends on setupState, so every setSetupState({ ...setupState, status }) during verification re-runs the same DoH lookup even though the queried domain did not change. That adds an extra third-party request to each verification click for no benefit.

♻️ Proposed fix
+  const setupSubdomain = setupState?.subdomain;
+
   useEffect(() => {
-    if (!props.open || stage !== 2 || !setupState) {
+    if (!props.open || stage !== 2 || setupSubdomain == null) {
       setCloudflareApex(null);
       return;
     }
     let cancelled = false;
     runAsynchronously(async () => {
-      const zone = await findZoneApex(setupState.subdomain);
+      const zone = await findZoneApex(setupSubdomain);
       if (cancelled || !zone) return;
       const usesCloudflare = zone.nameServers.some((n) => /(^|\.)cloudflare\.com$/i.test(n));
       if (usesCloudflare) setCloudflareApex(zone.apex);
     });
     return () => {
       cancelled = true;
     };
-  }, [props.open, stage, setupState]);
+  }, [props.open, stage, setupSubdomain]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
around lines 326 - 341, The effect that runs findZoneApex is being re-triggered
on every change to the entire setupState object; change its dependency to the
specific subdomain so the DoH lookup only runs when the queried domain changes:
in the useEffect that calls findZoneApex (and updates setCloudflareApex),
replace the dependency on setupState with the subdomain value (e.g.,
setupState?.subdomain) and guard the early-return checks against that subdomain
variable instead of the whole setupState to avoid unnecessary lookups when
setSetupState({...setupState, status}) is called.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/backend/src/lib/managed-email-domains.tsx`:
- Around line 244-249: The COUNT query in globalPrismaClient.$queryRaw against
"ManagedEmailDomain" counts archived/inactive rows, causing the deletion flow to
think a zone is still referenced; update the WHERE clause in that query (the one
using options.subdomain and options.excludeId) to exclude archived/inactive
records (for example add AND "archivedAt" IS NULL or AND "isArchived" = false
depending on the actual schema column used for soft-deletes) so only live
domains are counted; make sure to use the same archived/active column and
semantics used elsewhere in the codebase.

In `@apps/backend/src/lib/managed-email-onboarding.tsx`:
- Around line 720-729: The current "last reference" check uses
countManagedEmailDomainsBySubdomainExcludingId followed separately by
deleteDnsimpleZoneByName, which is racy; serialize cleanup for a given subdomain
by acquiring a per-subdomain critical section (e.g., a DB advisory lock or mutex
keyed by domain.subdomain) and perform the count-and-delete inside the same
transaction/locked section so the decision is atomic. Update the logic around
countManagedEmailDomainsBySubdomainExcludingId and deleteDnsimpleZoneByName (or
the caller createOrReuseDnsimpleZone flow) to: acquire lock for
domain.subdomain, re-check count (excluding the row being deleted) inside the
lock/transaction, call deleteDnsimpleZoneByName only if count === 0, then
release the lock; ensure lock acquisition/release errors are handled and do not
leave the zone orphaned.

In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx:
- Around line 1085-1093: The icon-only delete button (the button with
onClick={() => setConfirmDelete(d)} and the <Trash /> icon) lacks an accessible
name; add an explicit aria-label (for example aria-label={`Remove domain
${d.domain}` or a generic "Remove domain") on that button to provide a clear
label for screen readers while keeping the existing title; ensure the aria-label
text conveys the destructive action and identifies the domain when possible.

---

Nitpick comments:
In
`@apps/dashboard/src/app/`(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx:
- Around line 326-341: The effect that runs findZoneApex is being re-triggered
on every change to the entire setupState object; change its dependency to the
specific subdomain so the DoH lookup only runs when the queried domain changes:
in the useEffect that calls findZoneApex (and updates setCloudflareApex),
replace the dependency on setupState with the subdomain value (e.g.,
setupState?.subdomain) and guard the early-return checks against that subdomain
variable instead of the whole setupState to avoid unnecessary lookups when
setSetupState({...setupState, status}) is called.

In
`@apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts`:
- Around line 205-206: Replace the fixed wait(1500) sleeps used before
verification with a condition-based polling loop that repeatedly calls the
/check endpoint until it returns a response indicating "verified" or a bounded
timeout elapses; update the test that uses wait(1500) (and the other occurrence)
to poll at short intervals (e.g., 200–500ms) for a maximum duration (e.g., 10s),
assert success when the /check response contains "verified", and fail the test
if the timeout is reached—use the existing wait helper only for the poll
interval and keep the polling logic next to the verification steps so the test
no longer depends on a fixed sleep.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 535d9443-4e74-49ef-8313-e3dde8def862

📥 Commits

Reviewing files that changed from the base of the PR and between 0848a1a and d3caf61.

⛔ Files ignored due to path filters (1)
  • apps/dashboard/public/assets/cloudflare-import-dns.png is excluded by !**/*.png
📒 Files selected for processing (8)
  • apps/backend/src/app/api/latest/internal/emails/managed-onboarding/delete/route.tsx
  • apps/backend/src/lib/managed-email-domains.tsx
  • apps/backend/src/lib/managed-email-onboarding.tsx
  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/domain-settings.tsx
  • apps/e2e/tests/backend/endpoints/api/v1/internal/managed-email-onboarding.test.ts
  • packages/stack-shared/src/interface/admin-interface.ts
  • packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
  • packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts

Comment thread apps/backend/src/lib/managed-email-domains.tsx
Comment thread apps/backend/src/lib/managed-email-onboarding.tsx
…main removal feedback.

- Updated the `ManagedDomainSetupDialog` to use `setupState?.subdomain` for better clarity and reliability in Cloudflare DNS setup.
- Enhanced the domain removal button with an `aria-label` for improved accessibility.
- Wrapped the domain deletion process in `runAsynchronouslyWithAlert` to provide user feedback during the operation.
const responseBody = await response.text();
throw new StatusError(
502,
`DNSimple returned ${response.status} when deleting managed email zone ${zoneName}: ${responseBody.slice(0, 500)}`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should never ever return messages with internal information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants