From acd03524ecaea5ddcdbb0b27d066eff6c9ab3232 Mon Sep 17 00:00:00 2001 From: Hermes Date: Thu, 29 Oct 2026 22:04:47 -0700 Subject: [PATCH] =?UTF-8?q?[grade=3DB=20urn:ump:wokpmecjfauc7jvnxyyyu4fq3z?= =?UTF-8?q?kkvwge455a5mxlmi3pdzkfdw3a]=20fix(DC-171):=20AXFR=20dig=20args?= =?UTF-8?q?=20to=20documented=20order=20(zone=20before=20type)=20=E2=80=94?= =?UTF-8?q?=20deploy-judge=20blocker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploy gate dc-prod-deploy-dc171 (grade D, urn:ump:iesjvepuqb5poim7wu22ff4jtd5vhpw2lotfhogljemsw2h4y6vq) blocked the cutover: listRecords built 'dig @srv -p port AXFR zone', but dig's documented positional contract is [name] [type]. BIND 9.18 accepts either order (live-checked), so the bug was invisible on this host's dig; older 9.11-9.16 on other distros follow the documented order. Fixed to 'zone AXFR', test asserts the production argv, and the corrected code path was LIVE-VERIFIED against a real DNS server: actual AXFR of zone 'sami' via the adapter itself — 48 records parsed (SOA/A/NS), zero mocked pieces. Parity suite: 24/24. --- dashcaddy-api/__tests__/dns/dns-provider-parity.test.js | 5 +++-- dashcaddy-api/src/dns/dns-providers/rfc2136.js | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dashcaddy-api/__tests__/dns/dns-provider-parity.test.js b/dashcaddy-api/__tests__/dns/dns-provider-parity.test.js index acb51c2..6970f31 100644 --- a/dashcaddy-api/__tests__/dns/dns-provider-parity.test.js +++ b/dashcaddy-api/__tests__/dns/dns-provider-parity.test.js @@ -183,8 +183,9 @@ describe('RFC2136 listRecords via AXFR (BIND 9 parity, DC-171)', () => { const [, args] = execFile.mock.calls[0]; expect(args[0]).toBe('@192.0.2.10'); expect(args.slice(1, 3)).toEqual(['-p', '53']); - expect(args[3]).toBe('AXFR'); - expect(args[4]).toBe('other.example.com.'); + // dig's documented positional contract: [name] [type] — zone before AXFR + expect(args[3]).toBe('other.example.com.'); + expect(args[4]).toBe('AXFR'); expect(args.slice(5)).toContain('+onesoa'); const kIdx = args.indexOf('-k'); expect(kIdx).toBeGreaterThan(-1); diff --git a/dashcaddy-api/src/dns/dns-providers/rfc2136.js b/dashcaddy-api/src/dns/dns-providers/rfc2136.js index 3f1ccc2..39bf823 100644 --- a/dashcaddy-api/src/dns/dns-providers/rfc2136.js +++ b/dashcaddy-api/src/dns/dns-providers/rfc2136.js @@ -337,10 +337,13 @@ class RFC2136Provider extends BaseDNSProvider { if (!effectiveZone) throw new Error('Missing required config: zone'); const fqdnZone = this._ensureFqdn(effectiveZone); + // dig positional contract is `dig [@server] [name] [type]` — zone name + // FIRST, then the AXFR request type (BIND 9.18 happens to accept either + // order, but 9.11-9.16 on older distros follow the documented order). const args = [ `@${this.server}`, '-p', String(this.port), - 'AXFR', fqdnZone, + fqdnZone, 'AXFR', '+nocomments', '+onesoa', '+nostats', '+time=10', '+tries=1', ];