Skip to content

feat(dns): live delegation checks, registrar-aware setup, and record presets#106

Merged
jamie-at-bunny merged 3 commits into
mainfrom
feat/dns-delegation-and-record-presets
Jun 30, 2026
Merged

feat(dns): live delegation checks, registrar-aware setup, and record presets#106
jamie-at-bunny merged 3 commits into
mainfrom
feat/dns-delegation-and-record-presets

Conversation

@jamie-at-bunny

Copy link
Copy Markdown
Member

feat(dns): live delegation checks, registrar-aware setup, and record presets

  • Add core/dns-nameservers.ts (checkDelegation/checkDelegations/expectedNameservers): resolve a domain's real registrar NS instead of trusting the API's NameserversDetected flag, which defaults to true on a freshly created zone
  • dns zones ns: confirm when delegated; otherwise show registrar-aware nameserver guidance (registrar named via RDAP in core/registrar.ts)
  • dns zones add: print setup steps after creating, and skip them when the registrar already points at bunny
  • dns zones list: live per-zone delegation column, and overwrite the NameserversDetected flag with the live value in JSON output
  • dns records preset: preset catalog (Google Workspace, Microsoft 365, Zoho, Mailgun, Resend, Proton, Bluesky, DMARC, CAA, no-email) with a summary, confirmation, and bulk write; also offered in the interactive records add wizard
  • core/format.ts: color table heads bunny orange in the bordered table output

@bogdan-at-bunny

Copy link
Copy Markdown

@codex review

@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0c35033

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@bunny.net/cli Patch
@bunny.net/cli-linux-x64 Patch
@bunny.net/cli-linux-arm64 Patch
@bunny.net/cli-darwin-x64 Patch
@bunny.net/cli-darwin-arm64 Patch
@bunny.net/cli-windows-x64 Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab92a48b5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/core/dns-nameservers.ts Outdated
Comment thread packages/cli/src/commands/dns/record/preset.ts Outdated
Comment thread packages/cli/src/commands/dns/zone/add.ts Outdated
Comment thread packages/cli/src/commands/dns/zone/list.ts Outdated
Comment on lines +26 to +33
const { value } = await prompts({
type: "text",
name: "value",
message: param.optional
? `${param.message} (blank to skip)`
: param.message,
initial: param.initial,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add flag equivalents for preset parameters

For named presets that need values, such as bluesky requiring a DID, this always reads the value with prompts and the command builder exposes no way to pass it as a flag. In non-interactive shells a fully specified invocation like bunny dns records preset bluesky example.com still blocks/fails before writing records, so add a scriptable parameter mechanism before falling back to prompts.

Useful? React with 👍 / 👎.

Comment on lines +69 to +73
if (detected) {
logger.success(
`Nameservers detected and pointing to Bunny DNS for ${zoneDomain}.`,
);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Keep nameserver output formats structured

For delegated zones, bunny dns zones ns example.com -o csv|table|markdown now emits a success sentence and returns, instead of honoring the requested non-JSON format with structured zone/nameserver data as this command did before. Any scripts consuming CSV/Markdown lose machine-readable output; keep the prose for text mode and render formatted rows for the other output formats.

Useful? React with 👍 / 👎.

Comment thread packages/cli/src/commands/dns/record/presets.ts Outdated
Comment thread packages/cli/src/core/dns-nameservers.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces bunny's NameserversDetected API flag (which defaults to true on new zones) with live DNS delegation checks across the DNS commands, adds a registrar name via RDAP lookup to the zone-add and nameservers outputs, and ships a dns records preset command with ten curated record sets.

  • Live delegation (core/dns-nameservers.ts): raw UDP NS query against the parent zone's authoritative servers with a bidirectional set match; bounded-concurrency checkDelegations limits fan-out for the zone list.
  • Preset catalog (record/presets.ts, record/preset.ts): ten presets with per-param prompts in interactive mode, --param key=value flags for non-interactive, a confirmation summary before write, and a clear partial-write error message if the API fails mid-sequence.
  • Registrar detection (core/registrar.ts): best-effort RDAP lookup at rdap.org (4s timeout, silently returns null on failure) used in zones add and zones nameservers.

Confidence Score: 5/5

Safe to merge; the new DNS delegation logic and preset catalog are well-tested and the two findings are defensive robustness improvements rather than present-defect blockers.

The hand-rolled DNS parser in decodeName lacks a guard against compression-pointer cycles, which could block the event loop on a crafted malformed packet — but in practice all queries go to TLD authoritative servers and the data is not attacker-controlled in normal CLI use. The non-interactive preset param strictness is a usability friction, not a data-loss issue. Both are straightforward to address. The previously-flagged issues (bidirectional NS set check, partial-write error reporting) are fully resolved.

packages/cli/src/core/dns-nameservers.ts (decodeName pointer-loop guard) and packages/cli/src/commands/dns/record/preset.ts (initial-value handling in non-interactive mode)

Important Files Changed

Filename Overview
packages/cli/src/core/dns-nameservers.ts New module for live NS delegation checks via raw UDP + fallback to dns.resolveNs; bidirectional set comparison correctly fixes the previously-flagged subset-only check. The hand-rolled DNS parser in decodeName has a compression-pointer loop guard gap.
packages/cli/src/commands/dns/record/preset.ts New preset apply/pick flow; partial-write issue from previous review is now addressed with a clear error showing how many records landed. Params with initial defaults but not marked optional fail in non-interactive mode.
packages/cli/src/commands/dns/record/presets.ts Pure preset catalog; record shapes, SPF includes, and provider-specific conventions all look correct.
packages/cli/src/core/registrar.ts Best-effort RDAP registrar name lookup with 4s timeout and full error swallowing; vcard fn parsing and legal-suffix trimming look correct.
packages/cli/src/commands/dns/zone/add.ts Post-create delegation check and registrar-aware next-steps printing; gracefully skips guidance when already delegated.
packages/cli/src/commands/dns/zone/list.ts Live per-zone delegation column via bounded-concurrency checkDelegations; JSON output correctly preserves API NameserversDetected on inconclusive checks.
packages/cli/src/commands/dns/zone/nameservers.ts Replaced static nameserver display with a live delegation check; text mode shows registrar-aware guidance, non-text modes stay machine-readable.
packages/cli/src/core/hostnames/bunny-dns.ts Switched delegated flag from NameserversDetected to a live checkDelegation call; tests updated with module mock to stay hermetic.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI
    participant BunnyAPI
    participant SystemDNS
    participant TLD_NS as TLD Nameserver (UDP)
    participant RDAP as rdap.org

    Note over CLI: dns zones add / dns zones ns / dns zones list

    CLI->>BunnyAPI: GET /dnszone (fetch zones)
    BunnyAPI-->>CLI: zones[]

    CLI->>SystemDNS: resolveNs(parent zone)
    SystemDNS-->>CLI: parent NS hosts

    CLI->>SystemDNS: resolve4(ns host)
    SystemDNS-->>CLI: IP addresses

    CLI->>TLD_NS: UDP NS query (non-recursive, EDNS0)
    TLD_NS-->>CLI: NS referral (authority section)

    alt referral readable
        CLI->>CLI: compare resolved vs expected (bidirectional)
    else referral unreadable
        CLI->>SystemDNS: resolveNs(domain) fallback
        SystemDNS-->>CLI: recursive NS answer
    end

    alt not yet delegated
        CLI->>RDAP: "GET /domain/{domain} (4s timeout)"
        RDAP-->>CLI: registrar name (or null)
        CLI->>CLI: print registrar-aware guidance
    else already delegated
        CLI->>CLI: print confirmation
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI
    participant BunnyAPI
    participant SystemDNS
    participant TLD_NS as TLD Nameserver (UDP)
    participant RDAP as rdap.org

    Note over CLI: dns zones add / dns zones ns / dns zones list

    CLI->>BunnyAPI: GET /dnszone (fetch zones)
    BunnyAPI-->>CLI: zones[]

    CLI->>SystemDNS: resolveNs(parent zone)
    SystemDNS-->>CLI: parent NS hosts

    CLI->>SystemDNS: resolve4(ns host)
    SystemDNS-->>CLI: IP addresses

    CLI->>TLD_NS: UDP NS query (non-recursive, EDNS0)
    TLD_NS-->>CLI: NS referral (authority section)

    alt referral readable
        CLI->>CLI: compare resolved vs expected (bidirectional)
    else referral unreadable
        CLI->>SystemDNS: resolveNs(domain) fallback
        SystemDNS-->>CLI: recursive NS answer
    end

    alt not yet delegated
        CLI->>RDAP: "GET /domain/{domain} (4s timeout)"
        RDAP-->>CLI: registrar name (or null)
        CLI->>CLI: print registrar-aware guidance
    else already delegated
        CLI->>CLI: print confirmation
    end
Loading

Reviews (2): Last reviewed commit: "updates" | Re-trigger Greptile

Comment thread packages/cli/src/core/dns-nameservers.ts Outdated
Comment thread packages/cli/src/commands/dns/record/preset.ts
@jamie-at-bunny jamie-at-bunny merged commit ff794c3 into main Jun 30, 2026
2 checks passed
@jamie-at-bunny jamie-at-bunny deleted the feat/dns-delegation-and-record-presets branch June 30, 2026 13:54
@github-actions github-actions Bot mentioned this pull request Jun 30, 2026
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