feat: v1 surface parity — connections.get, authed session read, webhook endpoints, key rotation (0.2.0) - #1
Merged
Conversation
…ok endpoints, key rotation (0.2.0)
… now reaches the authed arm and 401s
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
dodomain-sdkup to the API's current/v1surface. Every callable RESToperation now has a method, sync and async. Nothing was removed and no existing
return value changed shape, so 0.1.0 → 0.2.0 is a drop-in upgrade.
Verified against three sources, not one: the route handlers on
dodomain@origin/main,packages/core/src/schemas.ts, and the live OpenAPI document athttps://dodomain.io/docs/openapi.json.
What ships
connections.get(id)GET /v1/connections/{id}sessions.get(session_id)GET /v1/sessions/{id}(the authed arm)webhook_endpoints.list()GET /v1/webhook-endpointswebhook_endpoints.create(url=…)POST /v1/webhook-endpointswebhook_endpoints.update(id, url=…)PATCH /v1/webhook-endpoints/{id}webhook_endpoints.delete(id)DELETE /v1/webhook-endpoints/{id}webhook_endpoints.rotate_secret(id)POST /v1/webhook-endpoints/{id}/rotate-secretwebhook_endpoints.get(id)list, see below)keys.rotate()POST /v1/keys/rotatePlus additive fields the API grew after 0.1.0:
Connection.record_fqdns,Session.records,Session.warnings; andPermissionError_.secret_key_requiredso the secret-key-only 403 is distinguishable from a missing OAuth scope.
Three findings worth a reviewer's eye
1.
webhook_endpoints.gethas no route behind it. The spec has noGET /v1/webhook-endpoints/{id}— only the collection,PATCH,DELETEandrotate-secret. Rather than skip the method or fake a request,getreads theapp's own list and picks the id out, and says so in three places: the docstring,
a
status_code == 0on theNotFoundErrorit raises (no 404 came from theserver), and a test named for it. The semantics are faithful — the list contains
exactly this app's endpoints, so an id missing from it is either someone else's
or nobody's, which is precisely what the API refuses to distinguish. If the
Node SDK ships a
gethere, the two should agree on this; flagging for parity.2. The two session read arms answer different shapes, and the difference is
easy to get wrong.
sessions.getreturns composed records —type/host/fqdnwith no
value(zComposedRecordpicks only two fields off the recordschema) — plus
appId,connectionIdand a server-derivedexpired, and noreturnUrl. That is a newIntegratorSessionmodel, not a reuse ofPublicSession. Handing add_sess_token togetwould succeed server-sideand answer the public shape, then fail deep in the parser on a missing
appId,so the SDK refuses a token up front and points at
retrieve.3. Two README claims were false and are corrected here. The webhook section
still described the pre-cutover
{event, data}body — the envelope has been{id, type, occurredAt, data}+ a deprecatedeventalias since 2026-08-06, anda reader following the old text would have built the wrong parser. And it stated
that doDomain publishes no OpenAPI document; it does.
verify_webhookitselfneeded no change: it was wire-format agnostic by design, which is exactly why it
survived the cutover.
Evidence
ruff check·ruff format --check·ty check— clean.pytest— 329 passed, coverage 99.20% (gate is 90%).gained a structural check that the two clients expose the same resource tree,
so a method added to one and forgotten on the other now fails immediately
rather than waiting for someone to remember a parametrized case.
records/recordFqdnsexisted still parses, while a field present with thewrong type fails loudly.
401onapp.dodomain.io— a route that did not exist would answer404.connections.get(compared againstthe list element), the endpoint list (asserting no secret is ever on a read
surface), and a 401 probe of the secret-key-only routes.
keys.rotate()is deliberately never called live. Rotation has no gracewindow, so a real call would invalidate the very
DODOMAIN_SECRET_KEYthe CIe2e job authenticates with — the response is the only copy of the replacement and
nothing in the suite could store it. Same reasoning keeps endpoint writes out
of prod. Both are fully covered against
respx, and what the e2e proves insteadis that the routes are deployed and reject a bad credential.
Not published to PyPI by this PR.