TenantUser
Junction entity representing the membership relationship between a user and a tenant workspace, enabling users to access and switch between multiple isolated tenant environments. This entity is the cornerstone of multi-tenant user management, tracking user membership status, invitation workflow, tenant-specific user attributes, and access periods. It enables scenarios where users work across multiple client tenants (consultants, agencies), collaborate with partner organizations, or manage multiple workspaces. The entity supports invitation-based onboarding, role designations per tenant (owner, member, guest), tenant switching in the UI, and complete membership lifecycle from invitation through active membership to removal. It serves as the authorization boundary for tenant-scoped data access and the foundation for tenant isolation in B2B SaaS platforms, enterprise systems, and collaborative applications.
Properties
| Property | Type | Mode | Description | Required |
|---|---|---|---|---|
| user | User | stored | Reference to the User who is a member of this tenant | Required |
| tenant | Tenant | stored | Reference to the Tenant that this user belongs to | Required |
| membershipStatus | string | stored | Current status of the user's membership in this tenant Values: Example: | Required |
| joinedAt | datetime | stored | Date/time when the user joined or was added to this tenant Example: | Required |
| invitedBy | User | stored | Reference to the User who invited this user to the tenant | Optional |
| invitedAt | datetime | stored | Date/time when the invitation was sent Example: | Optional |
| invitationAcceptedAt | datetime | stored | Date/time when the user accepted the invitation Example: | Optional |
| isOwner | boolean | stored | Whether this user is an owner/administrator of the tenant with full administrative privileges Example: | Optional |
| isPrimary | boolean | stored | Whether this is the user's primary/default tenant workspace Example: | Optional |
| displayName | string | stored | Tenant-specific display name for this user (may differ from Person name for privacy or branding) Example: | Optional |
| position | string | stored | User's position or job title within this tenant Example: | Optional |
| department | string | stored | Department or division within the tenant Example: | Optional |
| metadata | json | stored | Tenant-specific metadata for this user (e.g., employee ID, cost center, custom fields) Example: | Optional |
| leftAt | datetime | stored | Date/time when the user left or was removed from the tenant | Optional |
| leftReason | string | stored | Reason for leaving the tenant | Optional |
| isActive | boolean | calculated | Whether this membership is currently active (status is active and not left) | Optional |
| daysSinceJoined | number | calculated | Number of days since the user joined this tenant | Optional |
| isInvitationPending | boolean | calculated | Whether the invitation is still pending acceptance | Optional |
Examples
Example 1
{
"@type": "TenantUser",
"user": {
"@type": "User",
"username": "john.doe"
},
"tenant": {
"@type": "Tenant",
"slug": "acme-corp",
"name": "ACME Corporation"
},
"membershipStatus": "active",
"joinedAt": "2023-06-01T12:00:00Z",
"isOwner": true,
"isPrimary": true,
"displayName": "John Doe",
"position": "CEO",
"department": "Executive"
}Example 2
{
"@type": "TenantUser",
"user": {
"@type": "User",
"username": "jane.smith"
},
"tenant": {
"@type": "Tenant",
"slug": "acme-corp",
"name": "ACME Corporation"
},
"membershipStatus": "active",
"joinedAt": "2024-03-15T09:00:00Z",
"invitedBy": {
"@type": "User",
"username": "john.doe"
},
"invitedAt": "2024-03-10T10:00:00Z",
"invitationAcceptedAt": "2024-03-15T09:00:00Z",
"isOwner": false,
"isPrimary": true,
"displayName": "Jane Smith",
"position": "Sales Manager",
"department": "Sales",
"metadata": {
"employeeId": "EMP-00234",
"costCenter": "CC-SALES-001"
}
}Example 3
{
"@type": "TenantUser",
"user": {
"@type": "User",
"username": "bob.wilson"
},
"tenant": {
"@type": "Tenant",
"slug": "techstart",
"name": "TechStart Inc"
},
"membershipStatus": "invited",
"invitedBy": {
"@type": "User",
"username": "admin"
},
"invitedAt": "2024-11-20T10:00:00Z",
"isOwner": false,
"isPrimary": false,
"position": "Consultant"
}Example 4
{
"@type": "TenantUser",
"user": {
"@type": "User",
"username": "john.doe"
},
"tenant": {
"@type": "Tenant",
"slug": "consulting-partners",
"name": "Consulting Partners LLC"
},
"membershipStatus": "active",
"joinedAt": "2024-09-01T09:00:00Z",
"isOwner": false,
"isPrimary": false,
"displayName": "John Doe (Advisor)",
"position": "Strategic Advisor",
"metadata": {
"partTime": true,
"hoursPerWeek": 10
}
}