Skip to content

docs(api): document registerDomain's idempotent reclaim behavior - #981

Open
AmirF194 wants to merge 1 commit into
tokencanopy:mainfrom
AmirF194:fix/824-registerdomain-idempotency-docs
Open

docs(api): document registerDomain's idempotent reclaim behavior#981
AmirF194 wants to merge 1 commit into
tokencanopy:mainfrom
AmirF194:fix/824-registerdomain-idempotency-docs

Conversation

@AmirF194

@AmirF194 AmirF194 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

registerDomain has always returned 201 with the existing row when a caller re-registers a domain their own account already owns (#819's plan-cap exemption depends on this). That behavior was undocumented everywhere except a code comment, and one design doc stated the opposite: that a retry always 409s. This PR documents the real behavior and corrects the false premise.

Client surface checklist

  • OpenAPI spec + generated types refreshed (make spec then make generate-sdk)
  • TypeScript SDK regenerated (docstring only, no behavior change)
  • Python SDK regenerated (docstring only, no behavior change)
  • Everything else in the template checklist doesn't apply: no handler, migration, CLI, or MCP change.

What changed

  • Added a Description to the registerDomain operation (internal/httpapi/domains.go), matching its listDomains/deleteDomain/verifyDomain siblings, which already had one.
  • Regenerated api/openapi.yaml and both generated SDK bases from it.
  • Added one sentence to docs/api.md's domains section.
  • Corrected docs/design/api-v1-redesign.md, which twice said a register_domain retry is "a 409, never a duplicate." It reclaims the existing row with 201.

Explicitly not changing

The 201 status code itself stays as is. /v1 is frozen at v1.5.0, so 201 -> 200 would be a breaking response-success-status-removed change under the compat gate, and the Python SDK's generated client only deserializes '201' for this operation, so 200 would silently return None to callers. This PR is documentation only.

Verification

  • go test ./internal/httpapi/... green, including the two existing tests that already pin this behavior (TestRegisterDomainAtCapAllowsReclaimOfOwnedDomain, TestRegisterDomainAtCapStillReturnsConflictForAnotherAccountsDomain).
  • make spec-check and make openapi-compat-check (against upstream main) both clean: no drift, no breaking changes.
  • make generate-sdk-check's normalization tests and scripts/check-sdk-operation-coverage.py both pass; the only generated-code diff is the new description string in the domains API docstrings.
  • go build ./..., go vet ./internal/httpapi/..., and gofmt are clean. Did not run the full DB-backed integration/e2e suites, since nothing here touches runtime behavior.

Fixes #824

registerDomain has always returned 201 with the existing row when the
caller re-registers a domain it already owns (tokencanopy#819 depends on this),
but the operation carried no description, unlike its listDomains,
deleteDomain, and verifyDomain siblings, and
docs/design/api-v1-redesign.md stated the opposite: that a retry
always 409s. A caller reading only the spec could not tell whether a
retry was safe, and a caller reading the design doc was told it was
not idempotent.

Add a Description to the registerDomain operation, regenerate
api/openapi.yaml and the two generated SDK bases, add one line to
docs/api.md, and correct the two design-doc lines that asserted the
409 premise. Purely additive; the 201 status code itself is
intentionally unchanged (frozen at v1.5.0, and the Python SDK's
generated client only maps '201').

Fixes tokencanopy#824
@AmirF194
AmirF194 requested a review from jiashuoz as a code owner September 1, 2026 12:29
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.

docs/api: POST /v1/domains idempotency is undocumented, and a design doc asserts the opposite

1 participant