Skip to main content

Permission Hierarchy (Fixed Backbone + Flex Tree)

MSK Core Concept β€” Permission Hierarchy

This page explains the "Permission Hierarchy" (Concept 1) among Multi-SaaS Kit's 6 core concepts.

Multi-SaaS Kit's permission system has three layers β€” a fixed backbone (separate tables) + a flex tree (organizations, unlimited depth) + a leaf (Member). The single source of truth for this decision is ADR-058.

One-line representation​

Platform > SaaS > Tenant > [ Org ... Org ] > Member
└──────── fixed backbone β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”” flex tree β”˜ β”” leaf β”˜
LevelNameLayerStored in
0Platform Adminfixed backbone(no FK β€” global)
1SaaS Adminfixed backbonesaas_products
2Tenant Adminfixed backbonetenants
3Organization Adminflex treeorganizations (org_level=3)
4Workspace Adminflex treeorganizations (org_level=4)
5Group Leaderflex treeorganizations (org_level=5)
6Memberleafusers.organization_id β†’ leaf node

1. Fixed Backbone​

The top three levels are a fixed structure, each with its own table.

  • Level 0 Platform β€” platform-global. Not tied to a specific tenant/SaaS.
  • Level 1 SaaS β€” saas_products. Product identity (pricing plan, feature flags, default theme, brand).
  • Level 2 Tenant β€” tenants. Customer organization = data isolation (RLS) boundary.

These three levels are always preserved regardless of multi-SaaS usage. (Even in a 1 project = 1 SaaS deployment, one saas_products row exists β€” ADR-029.)

2. Flex Tree​

Levels 3–5 are not separate tables; they are a self-referencing tree in the single organizations table.

ColumnRole
parent_idself reference (parent org)
pathMaterialized Path (e.g. /1/3/7)
depth0, 1, 2, … unlimited
org_level3–5 recommended label (any integer allowed; no behavioral effect)
typeheadquarters / branch / department / team, etc. (free)
  • Unlimited tree depth β€” arbitrary depth via the Materialized Path pattern.
  • Free mid-node insertion β€” inserting a parent/child org into an existing tree is cheap.
  • Nodes with the same org_level may exist at multiple depths in the tree.

3. Leaf​

  • Level 6 Member β€” users.organization_id points to a leaf node of the tree.

⭐ users.level (fixed 0–6) vs tree depth (unlimited) β€” independent concepts​

The most common misconception is to read the system as a "fixed 7-level tree". Precisely:

  • The 0–6 classification of users.level is fixed (used by permission checks like hasLevelAtLeast()).
  • The actual operational org tree depth is unlimited, and org_level is merely a recommended label attached to a node.
  • That is, "permission classification (7 kinds)" and "org tree depth" are two independent concepts. What grows without limit is the number/depth of org nodes, not the number of permission Levels.

Minimal operating scenarios​

ScenarioStructureusers.organization_idSuitable domain
Simple SaaSPlatform > SaaS > Tenant > MemberNULLB2C, personal
Standard SaaS (recommended default)Platform > SaaS > Tenant > Org₁ > MemberOrg₁.idgeneral B2B
Complex orgPlatform > SaaS > Tenant > Org₁ > Orgβ‚‚ > … > Memberleaf node identerprise/group

A new project's (make create) default seed creates 5 demo accounts at Levels 0/1/2/3/6. Level 4 (Workspace) and 5 (Group) nodes are added by the operator when the org tree is expanded.