Skip to content

feat: Add native group authorization - #136

Merged
gjtorikian merged 8 commits into
workos:mainfrom
SamyPesse:codex/group-authorization
Oct 15, 2026
Merged

gjtorikian merged 8 commits into
workos:mainfrom
SamyPesse:codex/group-authorization

Conversation

@SamyPesse

@SamyPesse SamyPesse commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Native AuthKit group role assignments are missing from the emulator, so apps using group permissions cannot exercise their authorization flows locally. This adds group assignment create/list/get/delete endpoints, role-and-resource criteria removal for group and direct grants, and the Node SDK's resource PATCH paths.

Checks, effective permissions, resource discovery, and assignment listings resolve current group memberships and resource ancestors through the existing stored roles and resources. Deleting members or groups revokes their derived grants; deleting roles, resources, or organizations cleans up group grants, including grants scoped to the organization itself. Derived role assignments use stable role_assignment_ IDs across membership and resource listings. No assignment webhooks or delayed reconciliation are simulated. Bulk group replacement and resource-type configuration remain outside this subset.

The supported-feature matrix and README describe the added behavior and limits. This is based on the latest upstream main and contains no request-budget changes from #133.

Validation:

  • All 1,348 upstream tests pass, including four focused HTTP flows for group access/revocation, direct/group criteria removals, group deletion, and resource PATCH paths.
  • Build, type checks, lint, formatting, Node compatibility smoke, and package validation pass.
  • All 18 organization and group HTTP tests also pass against OpenKnowledge Compute's installed patched @workos/emulate@0.14.0; its nine changed authorization runtime/type files match this branch's build byte for byte.

API references: group role assignments and criteria removal.

@greptile-apps

greptile-apps Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The PR appears safe to merge, with the previous member-removal issue fixed.

Summary

Adds native group role assignments and includes their grants in permission checks and assignment lists.

  • Apps can assign, view, and remove roles for AuthKit groups.
  • Group role grants give current members access to scoped resources.
  • Callers can remove role grants by role and resource.
  • Resource updates accept the Node SDK's PATCH paths.
  • Deleting a group, role, or resource clears its group grants.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Membership[Organization membership] --> Links[Current group links]
  Links --> Group[Group]
  Group --> Grants[Group role assignments]
  Grants --> Roles[Stored roles and permissions]
  Grants --> Scope[Resource and its ancestors]
  Roles --> Checks[Permission checks and lists]
  Scope --> Checks
Loading

Reviews (6) · Last reviewed commit: "fix(seed): link a membership to a seeded..." · Reviewed by Greptile

Comment thread src/workos/routes/authorization-resources.ts Outdated
Comment thread src/workos/routes/organizations.ts
Comment thread src/workos/routes/authorization-checks.ts Outdated
SamyPesse and others added 3 commits October 12, 2026 19:27
The emulator's group grants diverged from the pinned spec (0.98.0) and
from production in ways SDK fixtures and id-matching consumers would
trip over:

- Criteria DELETE on /authorization/groups/{id}/role_assignments always
  answered 204. The spec says "Returns 404 when no matching active
  assignment is found", and production resolves the slug first
  (group-role-assignments.orchestrator.ts:199 throws
  RoleNotFoundException) before group-role-assignments.service.ts:395
  throws GroupRoleAssignmentNotFoundException on `affected === 0`.
- The duplicate 409 used an invented code. The spec's const, and the
  controller at authorization-group-role-assignments.controller.ts
  lines 271/331/462, is `duplicate_group_role_assignment`.
- Ids were minted with a literal `gra` outside ID_PREFIXES, so the
  prefix conformance test never saw the spec's `gra_01HXYZ…` example.
- An omitted resource was stored as nulls, but the spec requires
  `resource.id`, `external_id` and `resource_type_slug` as strings:
  production's resolveResource (orchestrator lines 238-281) maps an
  omitted selector to findOrCreateOrganizationResource. Group grants
  are therefore always resource-scoped, and the organization rename
  sync must refresh their denormalized `resource_external_id` too.

The direct membership criteria DELETE gains the same 404 for an unknown
slug (organization-membership-user-roles-orchestrator.ts:2433) but keeps
204 when nothing matches, because production's removeSubResourceScopedRole
(lines 2387-2393) and removeRoleFromAllUserRolesForLockedMembership
(line 1282) are no-ops there.

Moving the formatter into helpers.ts and registering
`group_role_assignment` in OBJECT_SCHEMA_MAP puts the shape under the
spec-conformance harness, which is what would have caught the nulls.
Comment thread src/workos/routes/authorization-checks.ts Outdated
Comment thread src/workos/routes/authorization-checks.ts
…each group once

Removal by criteria on a membership resolved the slug to a role but then
matched assignments by slug, so when an organization role shadows an
environment role of the same slug both grants went, taking the
environment role's permissions with them. Match the resolved role's id,
as the group route already does.

A seed that repeats a member email links the membership to the same
group more than once, and each link re-expanded the group's grants under
the same derived id. With limit=1 the cursor then pointed at the first
copy forever. Expand each group once per membership.
Comment thread src/workos/routes/authorization-checks.ts
A seed that names the same member email twice created two links to the
same membership. Removing the member then deleted only one of them, so
the member kept the group's permissions. Link once at seed time, which
is also what the POST route already does, and drop the per-request
guard that worked around the duplicates when deriving role assignments.
@gjtorikian
gjtorikian merged commit dcf3719 into workos:main Oct 15, 2026
10 checks passed
@gjtorikian

Copy link
Copy Markdown
Collaborator

thanks!

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