HyperSaaS
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

RoleCapabilities
adminFull read/write, manage members, delete workspace resources
memberRead access, create own resources, limited write

The workspace owner always has admin-level access.

Data Isolation

Every workspace-scoped API endpoint:

  1. Extracts workspace_pk from the URL
  2. Verifies the user is a member of that workspace
  3. Filters all queries to that workspace
# Example: Chat sessions are always scoped to a workspace
GET /api/workspaces/{workspace_id}/chats/

On this page