Skip to content

feat: add connection create and update commands - #221

Open
qbalin wants to merge 3 commits into
mainfrom
devin/ent-6443-connection-create-update
Open

feat: add connection create and update commands#221
qbalin wants to merge 3 commits into
mainfrom
devin/ent-6443-connection-create-update

Conversation

@qbalin

Copy link
Copy Markdown

Summary

Adds workos connection create and workos connection update <id> for provisioning and migrating SSO connections via the Connections API, plus a connections alias for the resource (kept out of metric fragmentation via command-aliases.ts).

  • Body assembly: --data '<json>' and --file <path|-> (stdin) provide the raw request body; top-level flags --org/--organization-id, --name, --external-id, --type override/merge on top. Nested saml_options / oidc_options / attribute_maps are passed through the raw JSON body. Non-object JSON bodies are rejected with invalid_json_body (type-narrowed via an isJsonObject guard — no casts).
  • workos-api.ts: add PATCH to WorkOSRequestOptions['method'] and send JSON bodies for PATCH.
  • workos-client.ts: new connections.create(body) / connections.update(id, body) raw methods.
  • connection create requires organization_id; connection update rejects an empty body. Both support human and --json output and reuse the standard API-key resolution and error handling.

These endpoints are feature-gated server-side (connections-api-migrations-capabilities-api) and return 404 unless enabled for the team.

Part of https://linear.app/workos/issue/ENT-6443 — companion docs PR in workos/workos.

Test plan

  • bun run typecheck, bun run lint, bun run format:check, bun run build — clean.
  • bun run vitest run src/commands/connection.spec.ts src/lib/workos-api.spec.ts — new specs cover request construction, flag/JSON precedence, --file/stdin parsing, invalid JSON, empty update body, API errors, and JSON output mode.

Link to Devin session: https://app.devin.ai/sessions/9151860048f44f5084cd0fe314e8722c
Requested by: @qbalin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@qbalinqbalin self-assigned this Aug 14, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor
Original prompt from quentin.balin

Pick up this ticket. Ask any questions if need be: https://linear.app/workos/issue/ENT-6443/docs-cli-integration-workos-connections-create-update

@linear-code

Copy link
Copy Markdown

ENT-6443

@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-appsBot commented Aug 14, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds CLI commands for creating and updating SSO connections through the Connections API.

  • Registers connection create and connection update, with raw JSON/file input and top-level flag overrides.
  • Extends the API transport and client with PATCH-backed connection updates.
  • Adds the connections alias, static JSON help entries, documentation, and command/client tests.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

FilenameOverview
src/commands/connection.tsAdds request-body parsing, validation, and handlers for connection creation and updates.
src/lib/workos-api.tsExtends the shared API transport to accept PATCH and serialize PATCH request bodies.
src/lib/workos-client.tsAdds raw Connections API methods for creating and updating SSO connections.
src/bin.tsRegisters the new subcommands and the plural connection alias.
src/utils/help-json.tsMirrors the new connection commands in the static machine-readable help catalog.

Sequence Diagram

sequenceDiagram
participant User
participant CLI as connection command
participant Client as workos-client
participant Transport as workosRequest
participant API as WorkOS Connections API
User->>CLI: create/update flags or JSON
CLI->>CLI: parse and merge request body
CLI->>Client: connections.create/update
Client->>Transport: POST/PATCH request options
Transport->>API: authenticated JSON request
API-->>Transport: connection response
Transport-->>CLI: parsed connection
CLI-->>User: human or JSON output
Loading

Reviews (3): Last reviewed commit: "fix: use success envelope for connection..." | Re-trigger Greptile

greptile-apps[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment threadsrc/commands/connection.ts Outdated
Comment on lines +177 to +181
outputJson(connection);
return;
}
outputSuccess('Created connection', connection);
} catch (error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Machine-readable output for creating and updating connections omits the standard success wrapper

The newly created/updated connection is printed as a bare object (outputJson(connection) at src/commands/connection.ts:177-181) instead of the standard success envelope every other create/update command emits, so scripts and agents that read the status field get nothing back.
Impact: Automated callers parsing JSON output of these two commands see a different shape than for all other resource create/update commands and can mis-handle the result.

Why this deviates from the established output convention

CLAUDE.md requires new resource commands to follow the patterns in src/commands/organization.ts. There, create/update call outputSuccess('Created organization', org) (src/commands/organization.ts:34, src/commands/organization.ts:56), which in JSON mode produces { status: 'ok', message, data } (src/utils/output.ts:66-85). The same convention is used by role.ts (src/commands/role.ts:87, src/commands/role.ts:116) and by runConnectionDelete in this very file (src/commands/connection.ts:257). The new runConnectionCreate/runConnectionUpdate instead short-circuit with isJsonMode() + raw outputJson, matching only the get convention. Removing the isJsonMode() branch and calling outputSuccess alone yields both human and JSON output consistently (the new specs at src/commands/connection.spec.ts:288-302 would need to read output.data).

Suggested change
outputJson(connection);
return;
}
outputSuccess('Created connection',connection);
}catch(error){
outputSuccess('Created connection',connection);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 588ce9b — create/update now call outputSuccess(...) unconditionally, so JSON mode emits the standard { status: 'ok', message, data } envelope like the other resource create/update commands, and the specs assert on output.status/output.data.

Comment on lines +203 to +221
connections: {
async create(body: Record<string, unknown>) {
return workosRequest<SsoConnection>({
method: 'POST',
path: '/connections',
apiKey: key,
baseUrl: base,
body,
});
},
async update(id: string, body: Record<string, unknown>) {
return workosRequest<SsoConnection>({
method: 'PATCH',
path: `/connections/${encodeURIComponent(id)}`,
apiKey: key,
baseUrl: base,
body,
});
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 create/update return snake_case while get returns camelCase

connections.create/connections.update use the raw fetch wrapper and therefore return the API's snake_case shape (SsoConnection at src/lib/workos-client.ts:30-41), whereas runConnectionGet and runConnectionList return SDK-mapped camelCase objects (src/commands/connection.ts:220, src/commands/connection.ts:48-56). Consumers of --json output will see connection_type/organization_id from create/update but type/organizationId from get/list on the same resource. Worth confirming this is acceptable for agent tooling, or normalizing the raw response before printing.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accurate observation. This is deliberate: the pinned @workos-inc/node (8.13.0) has no createConnection/updateConnection, so these go through the raw transport, and I kept the API's snake_case shape in the output rather than hand-rolling a camelCase mapping. It's also symmetric with the input — --data/--file bodies are authored in the API's snake_case shape (matching the API reference docs), so the response echoes the same field names. If the SDK later ships these methods, switching to it would align create/update with get/list automatically. Happy to normalize now instead if consistency across subcommands matters more for agent tooling.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@qbalin