Skip to content

Members

A project has members, and a member has one of three roles — the smallest set a QA team actually distinguishes, taken from Testomat.io’s project roles with the company layer left out:

RoleMay
ownereverything — and alone: invite, change roles, remove, rename the project
membereverything else: cases, suites, runs, plans, settings, tokens
readerlook. Every write is refused at the boundary, before a handler runs

The person who creates a project is its owner. Their default project is theirs the same way.

Settings → Members, the Invite form — an address and a role. Or:

POST /v1/members { "email": "[email protected]", "role": "member" } → 201

Two outcomes, told apart by kind in the answer:

  • member — the address already has a Plune account: they are in at once, and the answer is their row.
  • invitation — nobody has signed in with that address yet: a row waits on the Pending list, a mail says where to sign in, and the sign-in itself turns the invitation into a membership with the role it was sent with. No token travels in the mail: the magic link is the proof, and the invitation is what lets the address ask for one.

The address is lower-cased before it is compared or stored. Inviting the same address twice, or one already in, answers 409; so does a project at its member limit (200).

GET /v1/members → 200 { members: […], invitations: […] }
PATCH /v1/members/{userId} { "role": "reader" } → 200 owner only
DELETE /v1/members/{userId} → 204 owner, or yourself
DELETE /v1/invitations/{id} → 204 owner only

Any member may read the list — it is how a member finds out who to ask for a role. The menu on a row (owners) offers Make owner · Make member · Make read-only and Remove from project; a member’s own row carries Leave instead. Somebody removed keeps nothing and loses nothing of the project’s: a case they wrote is the project’s, not theirs.

A reader cannot leave: the read-only rule has no exceptions, and leaving is a write. An owner removes them, or makes them a member first.

A reader reads every route a member reads and is answered 403 { "error": "read-only member" } on every POST, PATCH and DELETE in the project. The dashboard says so once, on every screen: a banner under the top bar — You can view everything in Project and change nothing — rather than a greyed button here and a working one there. Make member on the Members screen lifts it (Testomat’s «grant write access»).

A reader cannot mint a token either — minting is a write — so a read-only member reads reports in the dashboard, not through the CLI; see Projects.

Every change of who is in the project lands in the project’s audit feed as an update of the project entity, the address as the field: added [email protected] as member, invited … as reader, olena@…: member → owner, removed …, … left, revoked the invitation of …. Who did it and when are the feed’s own columns.

A person is their address until they give themselves a name — Settings → General, «Your name»:

PATCH /v1/me { "name": "Olena Kovalenko" } → 200 session only, like the tokens
GET /v1/me → 200 { …, "name": "Olena Kovalenko" }

One to 100 characters, trimmed; null clears it and the address stands in again. The name is what every screen shows where a row names somebody — the Members list, the avatar’s initials in the top bar, and the three records that now carry an actor:

RecordFieldSet when
a casecreatedByPOST /v1/test-cases, and a duplicate — the caller, never the body
a runcreatedBythe first shard that created it — POST /v1/runs on either road, a plan’s launch, a Cairn ingest; a joining shard is not the creator
a resultexecutedBya source: manual result — whoever submitted it, then whoever last corrected it; a reporter’s result names nobody

Each is a userId; the dashboard resolves them through GET /v1/members, which is why a reader may read that list. The case page says created by Olena Kovalenko under the head, the run page Launched by Olena Kovalenko in the run’s line, and a mark on the «To run» list reads by Olena Kovalenko · 2 minutes ago. Somebody without a name shows as the local part of their address.

Assigning a case to somebody: Cases → Assignee. Saying something about a case, beside it: Cases → Comments. Notifications about either are not here yet.