BackendWorkspaces & Teams
Overview
Multi-tenancy with workspaces, teams, and role-based access.
HyperSaaS uses workspace-based multi-tenancy. Every resource (chats, documents, knowledge bases) belongs to a workspace. Users access workspaces through memberships.
Core Models
Workspace
class Workspace(BaseModel):
id = models.UUIDField(primary_key=True)
name = models.CharField(max_length=200, default="Default Workspace")
slug = models.SlugField(max_length=255, unique=True) # Auto-generated
owner = models.ForeignKey(User, on_delete=models.CASCADE)
members = models.ManyToManyField(User, through="WorkspaceMembership")
status = models.CharField(choices=[ACTIVE, ARCHIVED])
subscription = models.ForeignKey(Subscription, null=True, blank=True)WorkspaceMembership
class WorkspaceMembership(BaseModel):
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
role = models.CharField(choices=ROLE_CHOICES, default="member")
# unique_together = ("workspace", "user")Team
Teams are sub-groups within a workspace for fine-grained access control:
class Team(BaseModel):
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=150)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
members = models.ManyToManyField(User, through="TeamMembership")Folder
Folders organize resources within a workspace:
class Folder(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
type = models.CharField(max_length=50, null=True) # 'chat', 'file', 'prompt', 'agent'Roles
| Role | Capabilities |
|---|---|
admin | Full read/write, manage members, delete workspace resources |
member | Read access, create own resources, limited write |
The workspace owner always has admin-level access.
Data Isolation
Every workspace-scoped API endpoint:
- Extracts
workspace_pkfrom the URL - Verifies the user is a member of that workspace
- Filters all queries to that workspace
# Example: Chat sessions are always scoped to a workspace
GET /api/workspaces/{workspace_id}/chats/