# Workspace

> Manage members and invitations for the active organization.

**Workspace** is organization-level administration. Open it from the header link **Workspace** (default: **Members**).

## Workspace side rail

The left **Workspace** rail lists Members, Invitations, User groups, Custom fields, and Activity. On desktop you can collapse it to an icon-only mini-rail; the organization avatar or initial stays visible in the header. Hover or focus an icon to read its label in a tooltip. Collapse state is saved per browser and is independent from project or user rails.

## Members (`/workspace/members`)

The screen matches the Invitations visual system: a mono **workspace / members** breadcrumb, page title, role-explainer description, and an **Invite members** action that opens the invite dialog in place (no export control).

Owners and admins can:

- Search members by name or email from the shared filter bar's search slot (server-side, case-insensitive, debounced)
- Add a **Role** filter from **Add filter** — a multi-select chip over Owner, Admin, Member, and Viewer. Selected roles are OR-ed (`role=admin,owner`); search and the role chip combine with AND logic server-side. Filter state lives in the URL and any change resets to page 1
- Add a **Status** filter from **Add filter** to list only **Active** or only **Deactivated** members (`status=deactivated`). Without it, every member is listed
- Review table columns: **Member** (profile photo when uploaded, otherwise initials avatar; display name from profile or email; full email; **You** badge on your row), **Role** (chip), **Status** (**Active** or **Deactivated**), **In organization since** (absolute date plus relative subline), **Actions**
- Change a member's role from the row's **More actions** menu → **Edit** → **Access** (`PATCH /api/v1/orgs/:orgUlid/members/:userUlid`). The owner role is not assigned this way — see [Transfer ownership](#transfer-ownership)
- **Deactivate** a member from the row's **More actions** menu → **Deactivate**, then confirm (`POST /api/v1/orgs/:orgUlid/members/:userUlid/deactivate`). A deactivated member loses access at once: in the web app, through API keys, and through connected apps (OAuth and MCP). They take no seat, but keep their role, project access, groups, and the name on everything they created. Their assignments on open runs and their reviewer slots on open reviews are cleared, because that work cannot progress without them. Their API tokens and connected apps for this organization are revoked.
- **Reactivate** a deactivated member from the same menu (`POST …/reactivate`). Reactivation takes a free seat: when none is free, it is refused with `409 seat_limit_exceeded`. It does not restore the revoked API tokens or connected apps, so the member creates new tokens and authorizes those apps again.

A deactivated member's row offers no role change, and the owner cannot be deactivated.

On a narrow (phone-width) screen the table becomes a card list: each member presents as its own card, showing the same role chip, status, and join date, with the role-change control and the deactivate or reactivate action still available on the card. Every search, filter, and action you have on a wider screen is still there — only the layout changes. At tablet width and above the list is the table described above.

You cannot deactivate or demote yourself. The sole owner cannot be demoted (the API returns `409 last_owner` if violated), so the owner steps down by transferring ownership. Promoting a viewer to a paid role is refused with `409 seat_limit_exceeded` once the organization is at its seat limit. On Pro a viewer never takes a seat; on Free every viewer does. Demoting or deactivating a member frees a seat for the next invite, promotion, or reactivation.

**Managed by your identity provider.** When your identity provider manages a member's role, the member shows the **Managed by your identity provider** chip. While strict mode is on in SCIM settings, the member's **Access** control is disabled and shows why. A role change sent through the API is refused with `409` and the message "This member's role is managed by your identity provider. Change it there, or turn off strict mode in SCIM settings." The owner is never locked, and members your identity provider does not manage are never affected. For how roles are set, see the _SCIM provisioning_ guide.

A custom role that a SCIM group maps to cannot be deleted. Probara refuses the deletion with `409` and the message "This role is mapped to a SCIM group. Change that group's role in SCIM settings first."

### Transfer ownership

An organization has exactly one owner. Only the owner can hand the organization to another member:

1. Open the member's row **More actions** menu and choose **Edit**.
2. Set **Access** to **Owner**. A warning appears in the dialog: the member gets full control of the organization, including billing and deleting it, and you become an **Admin**.
3. Confirm with **Transfer ownership**.

Both changes happen together, and the activity log records both role changes. You cannot undo the transfer yourself: only the new owner can transfer ownership back. A viewer who becomes the owner needs a free seat (`409 seat_limit_exceeded` otherwise). Integrators use `POST /api/v1/orgs/:orgUlid/ownership-transfer` with `{ "userUlid": "…" }`, or the MCP tool `transfer_org_ownership`; `PATCH …/members/:userUlid` refuses `role: "owner"` with `422 validation_failed`.

## Invitations (`/workspace/invitations`)

The screen matches the product mock: a mono **workspace / invitations** breadcrumb (no separate page title), a **New invitation** action that opens a modal (rather than an inline form on the page), and the list of invitations sent. Its shared filter bar offers a **search** input (invitee email, server-side and debounced) plus **Status** and **Role** chips from **Add filter** — each a multi-select writing comma-separated params (`status=pending,expired`). Values OR within a chip and AND across the search and both chips; any change resets to page 1. The list's filters do not affect the invite modal.

The **New invitation** modal has two tabs, **Single** and **Bulk**, each with its own **Access** checkbox:

- **Single** sends one invitation: enter an invitee email and role (`admin`, `member`, or `viewer` — not owner) and select **Invite**. The invitee receives an email with a link `/invite/:token`.
- **Bulk** sends up to 50 invitations at once under one shared role: paste addresses separated by newlines, commas, or semicolons, and a counter under the field reports how many distinct addresses will actually be submitted (blank lines and case-different repeats don't count twice). If every address is created, the modal closes; if any address is refused, the modal stays open, lists each refused address next to its own reason (already invited, already a member, or not a valid address), and keeps only the refused addresses in the field so a corrected resubmission can't duplicate an invitation that was already created. A refusal that applies to the whole list (for example, hitting your organization's seat limit) is stated once and is never attributed to a single address.
- **Access**: check it to grant the invitee — or, on the Bulk tab, every address in the list — access to every private project **once they accept** the invitation; the grant replays at acceptance, it is not immediate. For the `owner` and `admin` roles the checkbox is shown **disabled**, with a note explaining that role already reaches every project, so checking it would grant nothing.

Owners and admins can also:

1. Review the list's columns: **Invitee** (the invited email, with "Invited by" and the inviter's name below it), **Status**, **Role**, **Sent** and **Expires** (the date with how long ago or how soon below it; **Expires** shows a dash once an invitation is accepted or revoked).
2. For **pending** rows, use icon actions to **Resend** (`POST /api/orgs/:orgUlid/invitations/:invitationUlid/resend`, rotates the one-time token and sends mail again) or **Revoke** (`DELETE` on the invitation).

A **pending** row whose email could not be delivered shows a caution indicator next to its status: **Undeliverable — invite a different address** means the recipient's mail provider permanently rejected the address (a bounce or a spam report) — inviting a different address is the only way forward. **Delivery failed — you can resend it** means delivery was retried and did not succeed for another reason — resending may work. Either way, the invitation itself stays **Pending**; it is not automatically revoked. The indicator can take a short time to appear after you send or resend the invite (delivery happens after the request completes) and survives a page reload.

On a narrow (phone-width) screen the invitation list becomes a card list: each invitation presents as its own card, showing the same email, status, role, inviter, sent, and expires values, with resend/revoke still available on **pending** cards. At tablet width and above the list is the table described above.

Status labels are short (**Pending**, **Expired**, etc.).

Limits: one pending invite per email per org; up to 50 pending invitations per organization; invitations expire after seven days.

## User groups (`/workspace/groups`)

Groups let owners and admins organize members into collections they can manage together — a name,
an optional description, and a member roster. A group can be given access to projects from its
**Projects** tab: every member of the group then reaches those projects.

A group your identity provider manages shows the **Managed by your identity provider** label. Its name
and members are read-only in Probara; its description and project access stay editable. See
[SCIM provisioning](https://docs.probara.net/en/guides/scim-provisioning/#groups).

The list matches the workspace visual system: a **Title** column showing the group's name with its
description on a subordinate second line (omitted entirely for a description-less group), **Users**
and **Projects** counts, and a **New group** header action. A single free-text search box (no filter
chips — a group has no categorical field to chip yet) searches both the name and the description,
server-side, and travels in the URL.

Owners and admins can:

1. Create a group from **New group**: a name (required, unique in the organization), an optional
   description, and an optional members field — a searchable multiselect showing each organization
   member's avatar, letting you seed the group's initial roster in the same step instead of adding
   members one by one afterward. This field only appears on create; editing a group's name or
   description later does not offer it — use the detail screen's **Add member**/**Remove from
   group** actions to manage membership after creation.
2. Rename a group or edit its description from the row menu's **Rename** action — one dialog, the same
   form used to create.
3. Delete a group from the row menu's **Delete** action. A group with members is deleted along with
   its membership rows in one step; there is no requirement to empty it first.
4. Open a group to reach its detail screen at `/workspace/groups/{groupUlid}`, addressed by the
   group's ULID (not a slug) so renaming never breaks a bookmarked link.

The detail screen shows the group's name and description with the same rename/delete actions, and two
tabs:

- **Members** — the group's roster: avatar, name and email, role chip, position title, and a per-row
  **Remove from group** action with a confirmation naming the person. An **Add member** action offers
  only organization members not already in the group.
- **Projects** — a finished-looking, inert placeholder for the group-based project access this
  release does not yet ship.

On a narrow (phone-width) screen both the list and the Members register become card lists, with every
action persistently visible (never hover-only). At tablet width the row actions consolidate into a
single menu; at desktop and above the full row is visible.

Members with role **member** or **viewer** see a permission message in place of the register on both
screens; the rail entry itself stays visible to every member regardless of role.

## Settings (`/workspace/settings`)

Owners only. **General** holds the organization name. **Security** has **Require two-factor authentication**: while it is on, members whose account has no two-factor authentication cannot open the organization until they turn it on (see [Organizations that require 2FA](https://docs.probara.net/en/guides/authentication/#organizations-that-require-2fa)). API keys and MCP clients are not affected. To turn it on, your own account needs two-factor authentication first. The danger zone holds [organization deletion](https://docs.probara.net/en/guides/delete-organization/).

## Custom fields (`/workspace/custom-fields`)

Owners and admins define organization-wide metadata fields (system and custom) and which projects each field applies to. See the dedicated guide: [Custom fields (Workspace)](https://docs.probara.net/en/guides/workspace-custom-fields/).

## Attachments (`/workspace/attachments`)

Every member can monitor storage usage and browse every file the organization has uploaded, across all attachment surfaces. Owners and admins can additionally select files and bulk-delete them. See the dedicated guide: [Attachments (Workspace)](https://docs.probara.net/en/guides/attachments/).

## Activity (`/workspace/activity`)

Owners and admins can review an append-only feed of domain changes (projects, cases, members, invitations, API tokens, and more). See [Workspace activity](https://docs.probara.net/en/guides/workspace/activity/) in the product docs site for details.
