Skip to content

Orgs

Purpose

The orgs app defines the multi-tenant foundation of the platform.

It is responsible for:

  • modeling organizations (internal and customer)
  • structuring organizations in a hierarchical tree
  • managing user membership and roles within organizations
  • separating internal workforce users from customer users
  • enabling organization-level configuration and branding
  • enforcing tenant isolation and access control boundaries

Every other domain (projects, servicereports, inventory, accounts, etc.) relies on orgs to determine who can access what within which organization.


Key concepts

Organization

A tenant in the system. Can be: - internal (your company structure) - customer (external client organization)

Organizations are arranged in a tree (MPTT): - parent → child inheritance - used for settings and branding fallback


OrgMembership

Defines a user’s role inside an internal organization.

Key roles: - owner - admin - manager - engineer - viewer

This is the primary authorization layer across the backend.


CustomerMembership

Separate membership model for customer users.

Why separate? - avoids mixing internal roles with customer roles - enforces clean boundary between tenants

Roles: - customer_admin - customer_user


Links an internal org to a customer org.

Used for: - portal access - controlled cross-tenant visibility - project/customer sharing


Org-scoped requests

Most APIs rely on a current organization context (typically via headers):

  • X-ORG-ID
  • X-ORG-SLUG

This ensures: - correct tenant isolation - consistent permission checks


Effective settings & branding

Organizations support inherited configuration:

  • parent org defines defaults
  • child org overrides selectively

Used for: - branding (logos, colors) - document generation (PDF identity) - feature flags or org-level config


Entry points

URLs

Main endpoints include:

  • /orgs/me/ → list user organizations
  • /orgs/members/ → members of current org

Future endpoints may include: - org detail/update - membership management - customer linking APIs


Admin

Django admin is typically used for:

  • managing organizations and hierarchy
  • correcting memberships
  • inspecting historical changes (via simple_history)

Tasks

Currently: - no dedicated Celery tasks in orgs

(Tasks exist in accounts, e.g. invites/emails)


Signals

No explicit signals in this app currently.

(Unlike accounts, which auto-creates profile/settings/schedule)


Dependencies

Depends on

  • accounts → user model
  • core → permissions (e.g. HasCurrentOrg)
  • django-mptt → tree structure
  • django-simple-history → audit tracking

Used by

  • projects → org-scoped projects
  • servicereports → org-scoped reports
  • inventory → org-scoped stock
  • teams → org-based grouping
  • accounts → membership + access control
  • portal → customer org access

The orgs app is a central dependency for almost all backend domains.


Operational notes

Known pitfalls

1. Missing org context

Many endpoints require a current org.

If headers are missing: - requests may fail with 403 or 400 - or behave unpredictably


2. Role vs permission confusion

Permissions are role-based, not user-based.

Avoid: - hardcoding user checks - bypassing OrgMembership

Always: - resolve permissions via membership role


3. Owner safety constraints

Certain operations must never leave an org without an owner.

Examples: - demoting the last owner - deactivating the last owner

These rules must always be enforced in services.


4. Internal vs customer separation

Never mix: - OrgMembership (internal) - CustomerMembership (external)

This is a critical security boundary.


5. Tree inheritance complexity

Settings and branding are inherited:

  • debugging issues may require checking parent orgs
  • overrides may not behave as expected if hierarchy is deep

Performance considerations

1. Membership queries

Common pattern:

OrgMembership.objects.filter(user=user, is_active=True)

Should be: • indexed • often prefetched when used in bulk


2. Organization tree queries

MPTT operations: • get_ancestors() • get_descendants()

Can be expensive if misused.


3. Branding resolution

effective_branding() merges: • model fields • inherited JSON settings

Avoid calling this repeatedly in loops without caching.


4. Member listing

Endpoints like: • /orgs/members/

Should use: • select_related("user")

to avoid N+1 queries.


Architecture overview

Summary

The orgs app is the backbone of tenancy and authorization.

It ensures: • users belong to the correct organizations • roles are enforced consistently • data stays isolated per tenant • customer access is controlled and explicit

If orgs breaks, everything breaks — which is why: • services are strongly tested • permissions are centralized • role logic is carefully enforced