Skip to content

Mount IT contacts on the Organizations service - #110

Merged
jonatascastro12 merged 2 commits into
mainfrom
devin/1787249011-it-contacts-naming
Aug 24, 2026
Merged

Mount IT contacts on the Organizations service#110
jonatascastro12 merged 2 commits into
mainfrom
devin/1787249011-it-contacts-naming

Conversation

@jonatascastro12

@jonatascastro12 jonatascastro12 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds SDK generation policy for the org-scoped IT Contacts endpoints, which currently resolve to a OrganizationsItContacts service with path-derived names (listOrganizationItContacts, etc.).

// mount-rules.ts
OrganizationsItContacts: 'Organizations',

// operation-hints.ts
'GET /organizations/{organization_id}/it_contacts': { name: 'list_it_contacts' },
// ... create/delete/invite/revoke

Resulting surface (per review discussion — IT contacts stay a subresource of organization, matching the API): workos.organizations.listItContacts({ organizationId }), createItContact, deleteItContact, inviteItContact, revokeItContact.

npm run sdk:resolve shows all five operations resolving to Organizations with those names. Node SDK side: workos/workos-node#1681.

Link to Devin session: https://app.devin.ai/sessions/2633e183d1b146d6a18a87e0e1b9c42b
Requested by: @jonatascastro12

Default resolution produced organizationsItContacts.listOrganizationItContacts and
createItContactInvite. Mount the OrganizationsItContacts tag on ItContacts and name
the operations after the resource/action, matching Groups. No SDK has generated IT
Contacts yet, so no compat baseline is affected.

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

Copy link
Copy Markdown
Contributor
Original prompt from jonatas

Please work on ticket "Add IT Contacts API to Node SDK" (ENT-6867)

@playbook:playbook-b0d9a34380374c3e903d900d340d8da7

@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

@devin-ai-integration devin-ai-integration Bot 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: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds generation policy for organization-scoped IT Contacts.

  • Maps the OrganizationsItContacts source service to the Organizations mount.
  • Adds explicit SDK-facing names for listing, creating, deleting, inviting, and revoking IT contacts.

Confidence Score: 5/5

The PR appears safe to merge because no eligible blocking failure remains from the available previous-review context.

No blocking failure remains.

Important Files Changed

Filename Overview
src/policy/mount-rules.ts Adds an exact mount rule mapping the IT Contacts source service to Organizations.
src/policy/operation-hints.ts Adds explicit operation names for all five organization-scoped IT Contacts endpoints.

Reviews (2): Last reviewed commit: "Mount IT contacts on Organizations" | Re-trigger Greptile

Comment thread src/policy/mount-rules.ts Outdated
Comment on lines +57 to +58
// Org-scoped IT contacts -> ItContacts (own service, like Groups)
OrganizationsItContacts: 'ItContacts',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do we want this as a top-level mount if we created this as a subresource? Should we create it as a top-level resource in the API instead?

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.

This mount only changes the generated SDK surface, not the API — the HTTP paths stay /organizations/{organization_id}/it_contacts either way.

Precedent for keeping it top-level: Groups is exactly the same shape (/organizations/{organizationId}/groups, .../groups/{groupId}/organization-memberships) and is mounted as its own Groups service, with organizationId passed as an option — workos.groups.listGroups({ organizationId }). Org API keys and authorized applications go the other way (mounted onto ApiKeys / Organizations), which is why the policy needs an explicit rule here. IT contacts have their own object type (it_contact), their own lifecycle and their own actions (invite/revoke), so they read more like Groups than like organizations.listAuthorizedApplications, and mounting them on Organizations would give workos.organizations.listItContacts(...) alongside unrelated org CRUD. jonatas confirmed workos.itContacts.* as the desired surface.

Making it a top-level resource in the API (/it_contacts?organization_id=...) is a bigger, separate call — it would break the shipped endpoints, and no SDK exposes them yet so nothing forces it now. Happy to switch this to Organizations (or hold pending an API change) if you'd rather; that's just editing these two policy entries and regenerating workos/workos-node#1681.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

More-so what I'm saying is it seems like we want it to be both a top-level resource and a sub-resource, but feels like we should choose one.

@jonatascastro12 jonatascastro12 Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah... It needs to be a subresource of organization.

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.

Got it — the inconsistency you're pointing at is real: API says subresource, this policy says top-level.

Two consistent options:

  1. Keep the API as-is and mount on Organizationsworkos.organizations.listItContacts({ organizationId }). Two-line change here plus a regen of feat: Add IT Contacts API workos-node#1681.
  2. Make it top-level in the API too (/it_contacts with organization_id) and keep this mount. That's a breaking change to already-shipped endpoints, so it needs its own decision — though no SDK exposes IT contacts yet, so the blast radius is limited to direct API users.

Worth noting Groups sits in the same "inconsistent" spot today (/organizations/{organizationId}/groups mounted as top-level Groups), so option 1 makes IT contacts stricter than the closest existing precedent. I don't have a stake either way — @jonatascastro12 asked for workos.itContacts.*, so I'll follow whichever you two land on. Tell me which and I'll push it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Keep the API as-is and mount on Organizations

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.

Done — option 1 is pushed here (OrganizationsItContacts: 'Organizations', commit 7739c4b), and workos/workos-node#1681 now exposes workos.organizations.listItContacts/createItContact/deleteItContact/inviteItContact/revokeItContact({ organizationId, ... }). CI green on both.

IT contacts are a subresource of organization in the API, so keep the SDK
surface consistent: workos.organizations.listItContacts(...).

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
},
'POST /organizations/{organization_id}/it_contacts/{contact_id}/revoke': {
name: 'revoke_it_contact',
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Based on the change above, what do the SDK methods end up looking like?

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.

Node (other langs get the same names in their own casing):

await workos.organizations.listItContacts({ organizationId });
await workos.organizations.createItContact({ organizationId, email });
await workos.organizations.deleteItContact({ organizationId, contactId });
await workos.organizations.inviteItContact({ organizationId, contactId, intents: ['sso'] });
await workos.organizations.revokeItContact({ organizationId, contactId });

Without the hints they'd be workos.organizationsItContacts.listOrganizationItContacts(...) etc. See workos/workos-node#1681 for the actual implementation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do we do for organization domains currently?

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.

Organization domains are the other shape: the API itself is top-level, not nested — POST /organization_domains (with organization_id in the body), GET|DELETE /organization_domains/{id}, POST /organization_domains/{id}/verify — so they need no mount rule or hints, and the SDK gets workos.organizationDomains.createOrganizationDomain({ organizationId, domain }) / getOrganizationDomain(id) / verifyOrganizationDomain(id) / deleteOrganizationDomain(id).

IT contacts can't follow that without changing the shipped API paths, which is the option we ruled out above. The closest nested precedent is Groups (/organizations/{organizationId}/groups), which is mounted top-level as workos.groups.* — this PR deliberately doesn't follow that one per jonatas' call to keep the SDK consistent with the API hierarchy.

@devin-ai-integration devin-ai-integration Bot changed the title Mount IT contacts on their own ItContacts service Mount IT contacts on the Organizations service Aug 24, 2026
@jonatascastro12
jonatascastro12 merged commit 7ae2ea4 into main Aug 24, 2026
6 checks passed
@jonatascastro12
jonatascastro12 deleted the devin/1787249011-it-contacts-naming branch August 24, 2026 15:12
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.

2 participants