Skip to content

feat(pipes): organization-owned connected accounts - #177

Open
dkarten wants to merge 5 commits into
workos:mainfrom
dkarten:org-connected-accounts
Open

dkarten wants to merge 5 commits into
workos:mainfrom
dkarten:org-connected-accounts

Conversation

@dkarten

@dkarten dkarten commented Oct 29, 2026

Copy link
Copy Markdown

Summary

  • Add support for the spec's GET|POST|PUT|DELETE /organizations/{organization_id}/connected_accounts/{slug}.
  • An organization holds one account per provider, with user_id: null, apart from any accounts its members hold. POST and PUT take the acting member in user_id, who must be an active member of the organization.
  • Accounts report established_by_user_id: the member who imported an organization's account, or who was seeded as establishing it. It is null on a user's own account, and becomes null when that member is deleted.
  • Deleting an organization deletes its accounts and its members' accounts scoped to it, and each emits pipes.connected_account.disconnected. Before, the members' scoped accounts were left behind.
  • The connectedAccounts seed takes owner: organization, with email optional to name who established the account.
  • The organization POST and PUT read the account after awaiting the body, so two overlapping imports give one 201 and one 409.
  • Shared helpers:
    • insertConnectedAccount replaces the insert that the user import and the seed each spelled out
    • importedFields builds the fields an import takes from its body, and updateAccount is the PUT both paths use.
  • docs/behavior.md under "Pipes / Connected Apps", and docs/seeding.md describe the updated behaviors.

Behaviour

Request Outcome
Organization POST or PUT without user_id 422
Organization POST or PUT whose user_id is not an active member 403
Organization POST when the organization already has an account for the provider 409 conflict

Boundary

  • When the establishing member's membership ends, the account is not invalidated.
  • The multiple-connections contract (connection_intent, connected_account_id, supports_multiple_connections) is not supported.

Verification

Full suite: 1908 pass, 0 fail. bun run typecheck, bun run lint, bun run fmt:check and bun run gen:supported are clean. New tests in connected-accounts.spec.ts cover the four verbs, membership, overlapping imports, the organization-delete cascade, the establisher after a user delete, and seeding and its validation.

Resolves part of #176 .

dkarten and others added 5 commits October 29, 2026 09:51
Serve GET, POST, PUT and DELETE on /organizations/{organization_id}/connected_accounts/{slug}.
An organization holds one account per provider with user_id null, apart from any its members
hold. Import and update name the acting member in user_id, who must be an active member.

Accounts now report established_by_user_id, cleared when that user is deleted. Deleting an
organization deletes its accounts and its members' accounts scoped to it. The connectedAccounts
seed takes owner: organization.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Describe the organization-owned rules in prose, as the other behavior sections do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
An overlapping import otherwise misses the other's write and both answer 201. Cover the members'
scoped accounts in the organization-delete cascade test, and say plainly that ending a membership
does not clear credentials, unlike production.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
As CLAUDE.md asks, and cite production's invalidation when the establishing member leaves.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@greptile-apps

greptile-apps Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

Adds organization-owned connected accounts alongside user-owned accounts.

  • Organizations can keep one connected account for each provider.
  • Seed files can create organization-owned connected accounts.
  • Deleting an organization now removes its connected accounts.

No actionable issues were found. Tests were inspected, not run.

Explicit boundaries from dkarten: invalidating accounts when the establishing member’s membership ends is deferred. The multiple-connections contract is also deferred.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Organization POST or PUT] --> B[Read request body]
  B --> C[Find organization and account]
  C --> D{Acting user is an active member?}
  D -->|No| E[Reject request]
  D -->|Yes| F[Import or update organization account]
  F --> G[Return account without tokens]
  H[Delete organization] --> I[Delete organization-owned and member-scoped accounts]
  I --> J[Emit disconnected events]
  K[Delete establishing user] --> L[Clear established_by_user_id]
  L --> M[Keep organization account]
Loading

Reviews (1) · Last reviewed commit: "docs(pipes): list the organization-owned..." · Reviewed by Greptile

Sign up for free to 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