Documentation Index
Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
Use this file to discover all available pages before exploring further.
WorkspaceGroupMembership represents a single person’s membership within a workspace group, capturing the lifecycle from invitation through acceptance or revocation. It associates a People record with a WorkspaceGroup, carries the assigned role, invitation token, and status, and is soft-deleted on revocation so the audit trail is preserved. A partial unique index on (person_pk, workspace_group_pk) WHERE deleted_at IS NULL enforces the idempotent-invite guard at the schema level: at most one live membership per person-group pair, while allowing revoke-then-re-invite semantics.
| Naming | Value |
|---|
| Object | WorkspaceGroupMembership |
Resource type (JSON:API type) | people |
| Collection / records root | — (not a records root) |
| REST base | /v1/workspace-group-memberships |
| Entity class | WorkspaceGroupMembership |
Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.
API operations
| Operation | Method & path | Status |
|---|
| List | GET /v1/workspace-group-memberships | 🟡 Planned |
| Retrieve | GET /v1/workspace-group-memberships/{id} | 🟡 Planned |
| Create | POST /v1/workspace-group-memberships | 🟡 Planned |
| Update | PATCH /v1/workspace-group-memberships/{id} | 🟡 Planned |
| Delete | DELETE /v1/workspace-group-memberships/{id} | 🟡 Planned |
Data model
Attributes
| Field | Type | Required | Constraints | Allowed values | Description |
|---|
| workspace_group_membership_id | string (UUID) | ✅ Yes | unique; generated by gen_random_uuid() at row creation | any valid UUID v4 | Public stable identifier for the membership. Exposed as the JSON:API resource id. Never changes after creation. |
| membership_role | string (enum) | ✅ Yes | NOT NULL; DB default ‘member’ | owner | admin | member | guest | The role assigned to the person within the group. Set at invitation time. Changeable via PATCH /v1/workspace-groups/memberships/:membership_id by an owner or admin. |
| status | string (enum) | ✅ Yes | NOT NULL; DB default ‘pending’ | pending | active | Lifecycle state of the membership. Starts as ‘pending’ on invitation; flips to ‘active’ when the invitee accepts via POST …/accept. |
| invite_token | string (UUID) | null | ⚪ No | unique; nullable | any valid UUID v4, or null | One-time cryptographic token sent to the invitee. Cleared (set to null) or consumed when the invitation is accepted. The accept endpoint validates this token; the membership_id alone is not sufficient proof. |
| is_default | boolean | ✅ Yes | NOT NULL; DB default false | true | false | Marks whether this membership is the person’s default group membership for the workspace. Used to determine the group selected by default in UI contexts. DB-defaulted to false. |
| created_at | 🔒 system — datetime | ✅ Yes | NOT NULL | ISO 8601 datetime | Timestamp of row creation. Set once by the onCreate MikroORM hook; never updated. |
| updated_at | 🔒 system — datetime | null | ⚪ No | nullable | ISO 8601 datetime, or null | Timestamp of the most recent mutation. Set by onCreate and refreshed by onUpdate hooks. |
| deleted_at | 🔒 system — datetime | null | ⚪ No | nullable | ISO 8601 datetime, or null | Soft-delete timestamp. Set when a membership is revoked. A non-null value excludes the row from active queries and from the partial unique index on (person_pk, workspace_group_pk), allowing revoke-then-re-invite. |
Relationships
| Name | Type | Required | Description |
|---|
| person | to-one (ManyToOne) | Yes — NOT NULL FK | The People record being granted membership in the group. FK: workspace_group_memberships.person_pk → peoples.pk (ON DELETE RESTRICT by default). |
| workspace_group | to-one (ManyToOne) | Yes — NOT NULL FK | The WorkspaceGroup this membership belongs to. FK: workspace_group_memberships.workspace_group_pk → workspace_groups.pk (ON DELETE RESTRICT by default). |
| invited_by | to-one (ManyToOne, nullable) | No — nullable FK | The People record of the actor who issued the invitation. Nullable; SET NULL on delete of the inviter. Null for system-created memberships. |
System-computed
- workspace_group_membership_id — generated by gen_random_uuid() at INSERT; unique constraint enforced at the DB level
- created_at — set once by MikroORM onCreate hook (new Date()); never overwritten
- updated_at — set by onCreate hook and refreshed on every UPDATE by onUpdate hook
- deleted_at — set to current timestamp by the revocation path (WorkspaceGroupService.revokeMembership); NULL for live rows
- Partial unique index workspace_group_memberships_person_group_active_unique on (person_pk, workspace_group_pk) WHERE deleted_at IS NULL — enforced at the schema level; the service’s idempotent-invite guard relies on this index to prevent duplicate pending/active memberships
- invite_token — generated as a UUID by the service’s invite flow (WorkspaceGroupService.inviteToGroup); consumed/cleared on accept; the token is the cryptographic proof validated by the accept endpoint rather than the membership_id alone
- status transitions — ‘pending’ on creation (DB default); ‘active’ set by the service on a successful acceptInvite call; no direct user-patch path for status
Example
{
"data": {
"type": "workspace-group-membership",
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"attributes": {
"membership_role": "member",
"status": "active",
"invite_token": null,
"is_default": false,
"created_at": "2026-05-29T10:15:00.000Z",
"updated_at": "2026-05-30T08:22:00.000Z"
},
"relationships": {
"person": {
"data": { "type": "people", "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901" }
},
"workspace_group": {
"data": { "type": "workspace-group", "id": "c3d4e5f6-a7b8-9012-cdef-123456789012" }
},
"invited_by": {
"data": { "type": "people", "id": "d4e5f6a7-b8c9-0123-defa-234567890123" }
}
}
}
}
Source: apps/api/src/database/entities/WorkspaceGroupMembership.ts · domain: workspace · tier: Platform