openova/core/pkg/dynadot-client
e3mrah cd6b2555a0
fix(pdm/dynadot): remove fictional ResponseHeader wrapper from api3.json adapter (#939) (#948)
Dynadot's real api3.json response places ResponseCode + Status + Error
DIRECTLY under each <Command>Response envelope; there is no nested
`ResponseHeader` object — the prior decode shape was a misread of the
docs that survived because every test fixture used the same fictional
shape.

Live capture (2026-05-05, omani.works domain_info success):
  {"DomainInfoResponse":{"ResponseCode":0,"Status":"success",
   "DomainInfo":{...}}}

Live capture (error envelope):
  {"DomainInfoResponse":{"ResponseCode":"-1","Status":"error",
   "Error":"could not find domain in your account"}}

Note: ResponseCode is JSON int 0 on success but JSON string "-1" on
error. Switched to json.Number so both shapes round-trip without an
Unmarshal failure, and added codeIsZero() to normalise comparison.

What's fixed in this commit:

- core/pool-domain-manager/internal/registrar/dynadot:
  ValidateToken / SetNameservers / GetNameservers / GetGlueRecord /
  RegisterGlueRecord (all five command paths) now decode against the
  real shape. Tightened classifyDynadotError so "could not find domain
  in your account" maps to ErrDomainNotInAccount before the auth
  matcher (which would otherwise grab on the substring "auth").

- core/pkg/dynadot-client: GetDomainInfo (was the last set_dns2 sibling
  still using the wrapper) aligned with the rest of the client.

- products/catalyst/bootstrap/api/internal/dynadot: AddRecord rebound
  to SetDnsResponse (not the SetDns2Response key it never returned)
  with code+status at the top — fixes the silent-success-on-failure
  loophole the catalyst-api was hitting.

Tests use real api3.json fixture shapes; new regression coverage for:
  - ResponseCode=int 0 w/o Status field (Dynadot omits Status sometimes)
  - "could not find domain in your account" → ErrDomainNotInAccount
  - "needs to be registered with an ip address" set_ns rejection (#900)

Verified via live integration call against api.dynadot.com:
  - ValidateToken(omani.works)  -> success
  - ValidateToken(google.com)   -> ErrDomainNotInAccount
  - GetNameservers(omani.works) -> ["ns1.openova.io","ns2.openova.io"]

Refs #939, #170, #900, #825.

Co-authored-by: hatiyildiz <269457768+hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 15:11:39 +04:00
..
client_test.go fix(pdm/dynadot): remove fictional ResponseHeader wrapper from api3.json adapter (#939) (#948) 2026-05-05 15:11:39 +04:00
client.go fix(pdm/dynadot): remove fictional ResponseHeader wrapper from api3.json adapter (#939) (#948) 2026-05-05 15:11:39 +04:00
doc.go feat(dns): cert-manager-dynadot-webhook for DNS-01 wildcard TLS (closes #159) (#291) 2026-04-30 19:37:47 +04:00
go.mod feat(dns): cert-manager-dynadot-webhook for DNS-01 wildcard TLS (closes #159) (#291) 2026-04-30 19:37:47 +04:00
managed.go feat(dns): cert-manager-dynadot-webhook for DNS-01 wildcard TLS (closes #159) (#291) 2026-04-30 19:37:47 +04:00