Repository navigation
feat(sdk): connectors on create, connectors and images lists - #18
Merged
Merged
Conversation
Adds `connectors=` on docks.create and `DockInfo.connectors`, `client.connectors.list/connect/disconnect`, `client.images.list`, and typed DockError subclasses for connector_not_connected, connector_admin_only, image_unknown and image_unavailable. Bumps SCENARIOS_REF to 05d0182 and maps the new ops in the scenario runner. Closes #17 Refs usedock/dock#59 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Disconnecting a connector that is not connected answers 404 connector_not_found; the JS and Go SDKs expose that code, so Python gets a typed subclass too. Also fix the admin wording: connecting needs an organization admin, not a workspace admin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parnexcodes
commented
Oct 11, 2026
parnexcodes
left a comment
Member
Author
There was a problem hiding this comment.
Review: feat(sdk): connectors on create, connectors and images lists (dock-python#18)
Verdict: SHIP
Reviewed together with usedock/dock-js#13, #18 and usedock/dock-go#14, against usedock/dock 05d0182 (connectors controller/service/verify, images controller/service, dock-view allowlist, create/branch DTOs, sdk-scenarios ops.yaml and the list-connectors / list-images scenarios).
Verified against the API:
- Paths and methods match
connectors.controller.tsandimages.controller.ts: GET/v1/workspaces/{id}/connectors, PUT/DELETE/v1/workspaces/{id}/connectors/{kind}with body{token}, GET/v1/images. Workspace id and kind are path-escaped in all three SDKs. - Disconnect returns
{kind, status: 'not_connected'}; connect returns the connector view. Field mapping is right (sizeMiBmaps tosizeMiB/size_mib/SizeMiB;accountLabel,oauthAvailable,readOnly,updatedAt). connectorsis in thedockViewallowlist and onCreateDockDto.BranchDockDtodoes not accept it (a branch inherits the source's connectors), and none of the SDKs add it to branch, which is correct.- The token is only sent in the PUT body. It is never in a path, a repr, a log line, or an error message, and the server never echoes it back.
- The changes only add things: new services, optional fields and new error types or constants. That makes this a minor release.
- Cross-language: the same nouns and verbs in all three (
connectors.list/connect/disconnect,images.list,connectorson create and on the Dock object). oauthStart is in ops.yaml, but it is a browser redirect flow, and no SDK exposes it. That is consistent and fine. - Error codes: JS exported
connector_not_found(404 on disconnect of a kind that is not connected) but Python and Go did not. I aligned them: PythonConnectorNotFoundError, GoCodeConnectorNotFound, each with a test.
Blocking
None.
Fixed in this review (35d21d0)
src/usedock/errors.py: there was no typed error forconnector_not_found. Disconnecting a kind that is not connected raised a plainDockError, while JS and Go name the code. I addedConnectorNotFoundError, exported it, and addedtest_disconnect_not_connected_raises_connector_not_found.README.mdand theConnectorAdminOnlyErrordocstring said "workspace admins". The API checks the organizationadminrole, and members who connect getforbidden, notconnector_admin_only. I corrected the wording.
Non-blocking
DockInfogainedconnectorsbeforeraw. Anyone who buildsDockInfo(...)positionally all the way torawwould break, but these are response models and that use is unlikely.connectcan also fail withconnector_token_invalid(400) andconnector_unreachable(502). None of the three SDKs type these codes, so the SDKs stay consistent. Adding them is a possible follow-up across all three.
Checks
ruff check ./ruff format --check .: passmypy: passpytest(scenarios at 05d0182): 91 passed / 9 skipped (live and CI only)- CI on 35d21d0: test (3.9, 3.13), gitleaks and cla all green
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Closes #17
What
client.docks.create(connectors=[...])andDockInfo.connectors.client.connectors.list(workspace_id),.connect(workspace_id, kind, token),.disconnect(workspace_id, kind), returningConnector,ConnectorandConnectorState.client.images.list()returningImage(name, description, arch, size_mib, contents, available).ConnectorNotConnectedError,ConnectorAdminOnlyError,ImageUnknownError,ImageUnavailableError, all subclasses ofDockError(existingexcept DockErrorand.codekeep working).SCENARIOS_REFbumped to 05d0182f83f3f7675567cc812c7801659f9cd3b6; the scenario runner mapsimages.listandconnectors.*, and the fake server accepts PUT.Why
usedock/dock shipped connectors and the Dockyard catalog; the SDK had no way to use them. Refs usedock/dock#59.
How to verify
Local results: 91 passed, 9 skipped (live scenarios, need a real API); ruff, ruff format and mypy clean. The offline
list-connectorsandlist-imagesscenarios pass. New unit tests cover request shape, models and typed errors.Risk
Low and additive. Error classes subclass
DockError, so existing handling is unchanged.connectors.oauthStartis intentionally not exposed.branchdoes not takeconnectors(the API op does not list it).🤖 Generated with Claude Code