# Workspace activity

> Organization-wide audit feed for owners and admins.

The **Activity** tab (`/workspace/activity`) shows an append-only feed of meaningful changes in the active organization: who did what, on which entity, and when.

## Who can see it

Only **owners** and **admins** can open the feed. Members and viewers see the standard permission message and the API returns `403`.

## What is recorded

Each successful domain mutation emits one event per HTTP request, for example:

- Projects, suites, and test cases (create, update, move, archive, delete)
- Custom fields and bundled test-case edits (one `test_case.updated` when a PATCH changes fields, steps, parameters, or values together). A change to a case's parameters or excluded combinations is listed in the event's details, such as **Parameter added**, **Parameter removed**, or **Excluded combinations**
- Shared parameters: created, updated, or deleted. A case that a shared parameter change reaches is recorded as changed through that shared parameter. See [Parameterized test cases](https://docs.probara.net/en/guides/parameterized-test-cases/#shared-parameters)
- Members deactivated or reactivated, and members who leave (a deactivated or departed member's open work is unassigned from them), invitations, API tokens, and connected apps (OAuth and MCP) revoked when a member is deactivated or leaves
- Single sign-on: connection created, updated, or deleted; connection tested; enforcement turned on or off; the sign-in policy changed (automatically adding new sign-ins or the default role); owner emergency access used; verified domains claimed, verified, unverified after a lapse, or removed; members who joined through single sign-on; and existing accounts linked to a single sign-on identity
- SCIM provisioning: SCIM turned on or off, SCIM tokens created, revoked, or expired, people provisioned, changed, deactivated, reactivated or deleted through SCIM (a role change made by SCIM shows the previous and the new role), SCIM role settings changed (role source, strict mode, default group), and group role mappings changed
- **Test runs** — create, update, close (including automatic close once every case has a result), abort, delete, clone ("Run again"), add/remove cases, mark cases and steps, assignees, retries, and actual-result text edits

Events older than your plan's [history retention window](https://docs.probara.net/en/guides/test-runs/#data-retention) are deleted automatically.

## Filtering the feed

Use **Add filter** above the timeline to narrow the organization feed:

- **Actor** filters to events performed by one organization member. Events whose
  user was later deleted remain in the feed, but they do not match a member
  actor filter.
- **Entity type** filters by the kind of object that changed, such as project,
  test run, defect, custom field, member, invitation, or API token. Select more
  than one entity type to OR them together.

Filters are reflected in the URL, so owners and admins can share a narrowed
activity view. Changing filters reloads the feed from the newest matching event;
use **Clear filters** to return to the full timeline.

### Run activity in the feed

Run events use snapshotted labels so the timeline stays readable even if a case is renamed or deleted later.

| What happened                       | What you see                                                                                                                                                                                                       |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Run created                         | Case count plus optional environment, default assignee, and milestone                                                                                                                                              |
| Run updated                         | Collapsible diff for name, description, default assignee, environment, or milestone                                                                                                                                |
| Run closed                          | Final scorecard (passed / failed / blocked / skipped / untested counts, total duration, projected pass/fail). Renders the same whether the run closed automatically (every case got a result) or via **Complete**. |
| Run deleted                         | Run name (plain text, no link), final scorecard, and whether it was open or closed at deletion                                                                                                                     |
| Actual result edited                | Step context with `from → to` text diff on the live execution path                                                                                                                                                 |
| Run cloned ("Run again")            | Source run name and the new run's name/label                                                                                                                                                                       |
| Cases added                         | How many cases were appended (up to 20 named in the payload)                                                                                                                                                       |
| Case marked                         | Linked case label (`PROJECT-42 · Title`), status chip from → to, optional elapsed time                                                                                                                             |
| Step marked                         | Case link, step position/action, status chip, case-level status after the mark                                                                                                                                     |
| Case assigned                       | Who assigned whom (including auto-assign on open vs manual patch)                                                                                                                                                  |
| Case retried                        | Prior status reset to untested and elapsed time cleared when applicable                                                                                                                                            |
| Case removed                        | Case identity and status at removal                                                                                                                                                                                |
| Bulk mark / assign / retry / remove | One row per gesture with count, first few case IDs, and an expandable per-case diff (status chips, assignee transitions, or removal status)                                                                        |
| Bulk submit result                  | One row per gesture: status, count, first few case IDs, and an expandable per-case status diff (same shape as bulk mark) — split time and any attached defect are not shown in the diff itself                     |

When the run still exists, the run name on a case event opens the run execution view at that case, and on a case marked event at the attempt it recorded. Deleted runs fall back to plain text labels.

## Activity inside a run

Each run execution view (`/projects/{project}/runs/{run}`) includes an **Activity** tab next to **Test cases**. It shows the same day-grouped timeline and diff primitives as the workspace feed, but scoped to that run only.

| Surface                | Who can open it                            | API                                       |
| ---------------------- | ------------------------------------------ | ----------------------------------------- |
| Workspace **Activity** | Owners and admins                          | `GET /api/v1/orgs/{orgUlid}/audit-events` |
| Run **Activity** tab   | Any role that can read the run (`viewer`+) | `GET /api/v1/runs/{runUlid}/audit-events` |

The tab persists in the URL as `?tab=activity` so deep links and the browser back button restore the selection. On a closed run the **Test cases** tab is read-only, but **Activity** continues to show the full history. Run links inside the tab are omitted because you are already inside that run.

## Timeline layout

The feed is a **day-grouped timeline**:

- Events are grouped under sticky day headers (**Today**, **Yesterday**, or an absolute date) with a per-day count.
- A vertical rail connects round actor avatars within each day.
- Each avatar shows a small **action-type badge** (create, update, move, or delete) derived from the event action.

Use the footer (`showing N events · load more`) to page through older entries. Appending a page does not duplicate a day header when new events belong to a day already on screen.

## Change details (diff)

Events of type `*.updated`, `*.moved`, and `member.role_changed` carry a structured diff that describes **which fields changed** and **what they changed to**:

- **All changes** (including a single field) appear in one collapsible group labeled with a zero-padded count and the word **change** or **changes** by count (e.g. `01 change`, `03 changes`). Expand it to see each changed field by name, then its previous value, an arrow, and its new value. In longer text, such as a description, the words that changed are highlighted on each side.
- **Null values** render as **Not set**.
- **Long values:** strings are truncated to 240 characters and a **See more** button reveals the full snapshot saved at the moment of the change.
- **Case steps:** when a consolidated save changes steps, the feed shows a **detailed per-step diff** inside the same change group — one row per touched step with a verdict (**Added**, **Removed**, **Modified**, **Reordered**), field-level `from → to` lines for action/data/expected (same layout and **See more** truncation as scalar fields), position moves, and image add/remove by filename. Historical events may still show the legacy count-only row (`Steps: 3 → 5`). If more than 20 steps change at once, the first 20 rows appear plus a summary line for the rest (totals by verdict stay accurate).
- **Custom field definitions:** `custom_field.updated` records every mutable part of the definition — scalar properties (`title`, `placeholder`, **Required**, default value) as `from → to` rows, plus phrase-style lines for **project visibility** (shown in all projects, switched to specific projects, **no projects** (same copy as the custom-fields table) when scope is left empty, or added/removed per project with snapshotted project names) and **option list** edits (added, removed, renamed options with snapshotted names). Pure option reorder still uses the separate `custom_field.options_reordered` action without option lines. Field and reference names are snapshots from emission time, even if later renamed or deleted.
- **Milestone, environment, and defect edits:** `milestone.updated`, `environment.updated`, and `defect.updated` carry the same field-level diff as other updates. A milestone shows name, description, dates (start, due, and forecast), and **parent milestone** by name; status changes — a manual edit or automatic completion — record the status `from → to`. An environment shows name, slug, description, URL, and the **Default** flag. A defect shows its **assignee** and **milestone** by name. These reference fields render the human-readable label snapshotted at the moment of the change, never the internal id.

Non-update events (`*.created`, `*.deleted`, `*.archived`, `*.restored`) keep showing their descriptive template without a change group.

## Comments and review notes

Comments on test cases, review requests, and defects show the comment text as a quote under the event line, not inside it. When a comment is deleted, its text stays in the quote, struck through, so the record shows what was removed.

A review decision that carries a note (approve, **Request changes**, or decline) quotes the note the same way. A **Request changes** note has an amber bar.

## Actor types

| Actor     | How it appears                                                                                                                         |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| User      | Round initials avatar and display name or email local-part                                                                             |
| App token | The app's logo, the app name and the token name, such as **JUnit XML · nightly-ci** ([app tokens](https://docs.probara.net/en/guides/integrations/junit-xml/)) |
| System    | Neutral icon and label “System”                                                                                                        |

An action taken with one of your personal [API tokens](https://docs.probara.net/en/guides/user-profile/#api-tokens) shows you, exactly like an action taken in the app, with **From an API token** at the end of the event line.

If a user or app token is deleted later, older events stay in the feed with “Deleted user” / “Deleted token”.

## Related API

Integrators can read the same data with `GET /api/v1/orgs/{orgUlid}/audit-events`. See [Audit events API](https://docs.probara.net/en/developers/api/audit-events/).
