Skip to content

feat(roles): manage roles, permissions, mappings and organization roles - #341

Merged
Bccorb merged 1 commit into
mainfrom
feat/roles-and-permissions
Nov 6, 2026
Merged

Bccorb merged 1 commit into
mainfrom
feat/roles-and-permissions

Conversation

@Bccorb

@Bccorb Bccorb commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

What

Adds /roles (Roles in the sidebar), which makes the v0.23 access model manageable in the console:

  • Permissions: list, create, edit description, delete. A refused delete names the roles still granting it.
  • Organization roles: list, create with permissions, edit description, edit mapping, delete. Built-ins offer no delete. A refused delete gives the holder count.
  • Instance roles: list and edit mapping only. They stay defined in available_roles, and the page links to System configuration.
  • The page says that a change reaches a user when their next access token is issued, and that an instance admin and an organization admin never share a grant. The mapping dialog repeats the second point for the role being edited.
  • A 404 on these routes shows "Needs Seamless Auth API v0.23" with no retries.

Organization members:

  • The role picker now uses the organization role catalogue, not instance roles. On an API without the catalogue it falls back to what it offered before.
  • A role the member holds outside the catalogue stays visible, selected and retained.
  • 400 and 403 refusals name the roles, and the dialog stays open.

Supporting changes:

  • @seamless-auth/types 0.34 to 0.38, with fixtures updated for oidc_cli_client_id and sessionExchangeEnabled.
  • New audit events get categories and labels, including a Roles and Permissions filter. session_exchange* goes under Session Tokens.
  • ApiError.details carries the API's details.
  • Table row actions take an optional hidden.
  • useRoles takes enabled.
  • Removing an instance role in System now warns that its mappings go too.

Before this works behind a server adapter

seamless-auth-server's bundled manifest comes from API 0.21.0 and does not list these routes. A standalone console behind that adapter will show the "needs v0.23" state even on API v0.23, until the manifest is synced and released. The message mentions the adapter for this reason.

What was run

  • npm run lint, npm run typecheck, npm run format:check, npm run build: pass
  • npm test: 108 files, 803 tests pass
  • npm run test:e2e: 203 pass, against the repo's mocked backend, including the new e2e/tests/roles.spec.ts
  • npm run check:types-current: pass

In a browser (Chromium through Playwright), against the API worktree for #576 and #577 on a scratch Postgres:

  • Created permissions and an organization role, and edited mappings, including on a role named Legacy Role, whose name has a space.
  • Saw the real 409s for a permission still granted and a role still held.
  • Saw the real 400 by deleting a permission while the mapping dialog was open.
  • Assigned a catalogue role to a member holding Legacy Role. The database row kept it.
  • A read-only admin saw no write controls.
  • A session with no fresh step-up sent no write and got the enrol-a-factor toast. The API answered step_up_required to the same write sent directly.

What was not run

  • The real adapter. A scratch proxy stood in for it, injecting a bearer token minted directly for test accounts, so sign-in was not exercised.
  • A completed passkey or TOTP step-up against the real API. The "fresh" session had its step-up time set in the database. The ceremony itself is unchanged existing code.
  • An actual older API. The 404 state was checked in the browser by intercepting the routes: 2 requests in 6 seconds, one per route, and the member picker fell back.
  • The member 403 from the real API. An instance admin:write, which the admin route requires, passes that check, so it is only covered by mocks.
  • A small copy change after the browser run (an action label and a toast sentence). Tests were rerun after it. The browser run was not repeated.
  • Dark mode and the other themes. The page only uses existing tokens.

Noticed, not changed

  • useUpdateSystemConfig does not invalidate ["roles"].
  • handleRemoveMember in Organizations.tsx has no canWrite guard, and handleAddMember checks it twice.
  • The global query retry still retries 404s. The new hooks opt out on their own.
  • The console has no controls for sessionExchangeEnabled or oidc_cli_client_id, both new in the types.

Closes #297

Add a Roles page for the permission catalogue, the organization role
catalogue, and what each instance and organization role grants. Writes ask
for step-up, refusals name what stood in the way, and an API older than
v0.23 gets an upgrade message rather than retries.

Organization member roles now come from the catalogue, keeping a legacy role
a member already holds. Bump @seamless-auth/types to 0.38 and categorize the
new audit events.

Closes #297
@Bccorb Bccorb added this to the v0.23 milestone Nov 6, 2026
@Bccorb
Bccorb merged commit f2d95b1 into main Nov 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: manage roles and permissions in the console

1 participant