Skip to content

Evaluate replacing the vendored spec + codegen with the official name.com Core SDK #40

Description

@patramsey

name.com now publishes an official Go SDK for the Core API:
https://github.com/namedotcom/core-api-go (MIT, Fern-generated, v1.33.2).
It did not exist when this CLI was built, which is why internal/api/gen exists
at all. It is worth evaluating whether adopting it lets us delete most of that.

What it could replace

Today With the SDK
internal/api/gen/zz_generated.go — 23,381 generated lines github.com/namedotcom/core-api-go
namecom.api.yaml vendored spec + make verify-spec SHA pin upstream's problem
scripts/spec_to_30.py — the OpenAPI 3.1 → 3.0 preprocessor gone
make generate + oapi-codegen gone
retry/backoff in internal/api/transport.go built in (exponential, configurable limit, default 2)
parseError() in internal/api/apierror.go core.APIError, errors.As-compatible

The preprocessor is the part worth highlighting. It exists solely because
oapi-codegen v2.4.x lacks OpenAPI 3.1 support, and it carries three documented
workarounds: nullable type: [T, null] unions, bare - type: null oneOf
members, and 33 *Response schema names renamed to *ResponseSchema to avoid
colliding with generated operation wrappers. All of that is scaffolding for a
problem the SDK does not have.

It should also retire the "Key generated type gotchas" section of CLAUDE.md
Record.Ttl being int64 while body Ttl is *int64, Record.Type being
*string while create/update need a gen.DNSCreateRecordBodyType(str) cast,
DomainResponsePayload.Locked being a bool alias rather than *bool. Those
are artifacts of our codegen path, and every one of them is a place a
contributor has to be told something non-obvious.

Endpoint coverage looks complete

The SDK's service packages line up with our command groups, with room to spare:

domains  dns  dnssecs  emailforwardings  urlforwardings  vanitynameservers
transfers  orders  refunds  contactverification  tldpricing  premiumdomains
accountinfo  domaininfo  accounts  webhooknotifications

webhooknotifications, premiumdomains, and accounts are endpoints we do not
currently surface. Coverage still needs verifying call-by-call against what
cmd/ actually invokes — this list is a directory listing, not a guarantee.

What does not come for free

These are the reasons this is an evaluation issue and not a straightforward
swap. Each needs an answer before committing.

  1. Client-side rate limiting. We run a x/time/rate limiter at 10 req/s
    with burst 5 in internal/api/transport.go. The SDK documents retries but
    not rate limiting. Probably preserved by passing our own instrumented
    *http.Client via option.WithHTTPClient — needs confirming.

  2. Idempotency-key gating on POST retries. Our transport retries a POST
    only when X-Idempotency-Key is set, which is what keeps a retried
    registration from becoming two registrations. The SDK's legacy retry
    profile retries 408/429/5XX; we need to know whether it applies that to
    unsafe methods, and whether --idempotency-key can be threaded through. This
    is the highest-stakes item on the list — getting it wrong costs real money.

  3. Auth shape. We set an Authorization header directly (client.go:134)
    and deliberately let namecom api --header 'Authorization: …' override it.
    The SDK exposes option.WithBasicAuth(username, password) and
    option.WithToken. Need to confirm which one name.com Core expects and that
    the escape hatch survives.

  4. Flags that reach into the transport. --base-url maps cleanly onto
    option.WithBaseURL, and --sandbox onto the SDK's environments. --debug
    / --debug-file and the User-Agent both live in our http.Client, so they
    ride along with item 1.

  5. namecom api raw passthrough. cmd/apicmd uses Client.HTTPClient()
    directly and does not care about generated types. It needs whatever
    configured *http.Client we end up with, not the typed surface.

Risk

The SDK is new — repo created 2026-07-02, last pushed 2026-08-18. One star,
and Fern regenerates it, so expect version churn and the possibility of
breaking changes between minor tags. Dependencies are light (google/uuid,
testify) and go.mod declares go 1.22, so nothing conflicts with our
1.26.6 toolchain. MIT on both sides.

Worth weighing against the status quo, which is not free either: we currently
own a spec pin, a Python preprocessor, and a codegen step that no upstream
maintains for us.

Suggested first step

Spike one command group — dns is a good candidate, since it exercises reads,
the read-modify-write update path, and typed enums — against the SDK on a
branch, without deleting anything. That answers items 1–3 concretely and gives
a real diff to judge the ergonomics from, before committing to a migration that
touches every command.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgoPull requests that update go code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions