Organizations
MapexOS is multi-tenant by design. An organization represents a real operational boundary: ownership, permissions, data retention, and event visibility are scoped by organization.
Applies to v1.0.0 — Hierarchical organizations with RBAC, scope propagation, and inheritance controls.
Organization hierarchy
Organizations form a hierarchical tree structure representing the physical and logical structure of a tenant's environment.
Organization types
| Type | Description | Depth |
|---|---|---|
| Vendor | Root organization (top-level tenant) | 0 |
| Customer | Client organization under a vendor | 1 |
| Site | Physical location | 2 |
| Building | Building within a site | 3 |
| Floor | Floor level within a building | 4 |
| Zone | Specific area within a floor | 5 |
Hierarchy example
Vendor: Acme Corp
└── Customer: Factory Alpha
├── Site: São Paulo Plant
│ └── Building: Main Warehouse
│ ├── Floor: Ground Floor
│ │ ├── Zone: Loading Dock
│ │ └── Zone: Storage Area
│ └── Floor: Second Floor
│ └── Zone: Office Area
└── Site: Rio de Janeiro Plant
└── Building: Distribution CenterIdentifiers: orgId vs pathKey
MapexOS uses two identifiers for organizations:
| Identifier | What it is | What it is used for |
|---|---|---|
orgId | Stable unique ID for the organization | CRUD operations, references from assets/memberships |
pathKey | Hierarchical position (path) | Descendant lookups, authorization scoping, and tree queries |
PathKey (hierarchical identification)
Each organization has a PathKey that represents its position in the hierarchy using a hierarchical path format (Base36 encoded for efficiency).
PathKey structure
000001 → Vendor (root)
000001/000001 → Customer (under Vendor)
000001/000001/0001 → Site (under Customer)
000001/000001/0001/0001 → Building (under Site)
000001/000001/0001/0001/0001 → Floor (under Building)
000001/000001/0001/0001/0001/01 → Zone (under Floor)Why PathKey matters
- Efficient range queries — Find all descendants using prefix matching (
pathKey LIKE '000001/000001/%') - No recursive joins — Fetch entire subtrees without recursion
- Audit visibility — Hierarchical context is visible in a single identifier
- Scalable — Performs well with deep hierarchies
In practice, pathKey is commonly used for:
- scoping “recursive” memberships
- enforcing inheritance boundaries
- filtering events/assets to a subtree
Access policies
Each organization defines an AccessPolicy that controls how permissions flow within the hierarchy.
AccessPolicy fields
| Field | Values | Description |
|---|---|---|
| RolePolicy | merge / strict | Controls whether the org accepts inherited permissions from parent nodes |
| DefaultScope | local / recursive | Default scope suggested by the UI when creating memberships |
RolePolicy behavior
| Value | Effect |
|---|---|
merge | Accepts inherited permissions from parent organizations |
strict | Blocks inheritance — only local memberships apply |
Example
Customer X (RolePolicy: merge)
├── Site SP (RolePolicy: merge)
│ └── Building A (RolePolicy: merge)
└── Site RJ (RolePolicy: strict) ← Blocks inheritance
└── Building B (RolePolicy: merge)If a user has recursive access at Customer X:
- Site SP — access granted (inherits from Customer X)
- Building A — access granted (inherits through Site SP)
- Site RJ — access denied (strict blocks inheritance)
- Building B — access denied (parent blocked inheritance)
DefaultScope
DefaultScope is a UX helper only. It pre-fills the scope when creating memberships. It does not change authorization logic.
Identity and access (IAM)
MapexOS uses a Role-Based Access Control (RBAC) model with hierarchical organization support.
Core entities
| Entity | Description |
|---|---|
| User | Individual identity that authenticates and operates the platform |
| Group | Collection of users — assign permissions to groups to simplify governance |
| Role | Reusable set of permissions (e.g., assets.read, rules.create) |
| Membership | Connects user/group + roles + organization + scope |
Memberships
A Membership is the glue that connects assignees, organizations, and roles.
Membership components
| Component | Description |
|---|---|
| Assignee | Who receives permissions (user or group) |
| Organization | Where permissions apply |
| Roles | What permissions are granted |
| Scope | How far permissions propagate |
Scope behavior
| Scope | Effect |
|---|---|
local | Permissions apply only to the specified organization |
recursive | Permissions apply to the org and all descendants |
Membership JSON example
{
"assigneeType": "user",
"assigneeId": "user123",
"orgId": "org111",
"roleIds": ["role789"],
"scope": "recursive"
}Permission inheritance
When checking whether a user can perform an action in an organization:
- Local user memberships — direct memberships at the target organization
- Local group memberships — memberships assigned to groups the user belongs to
- Inherited permissions — if
RolePolicy = merge, evaluate recursive memberships in ancestors
Recursive scope propagates only to descendants. It never crosses to sibling branches.
Inheritance flow
User wants to access Building A
│
▼
┌────────────────────────────────────┐
│ 1) Local user membership? │
└────────────────┬───────────────────┘
│
┌──────────┴──────────┐
│ NO │ YES
▼ ▼
┌─────────────────────┐ ✅ ACCESS GRANTED
│ 2) Local group │
│ membership? │
└──────────┬──────────┘
│
┌──────┴──────┐
│ NO │ YES
▼ ▼
┌─────────────────────┐ ✅ ACCESS GRANTED
│ 3) Org accepts │
│ inheritance? │
│ (RolePolicy=merge)│
└──────────┬──────────┘
│
┌──────┴──────┐
│ NO (strict) │ YES (merge)
▼ ▼
❌ ACCESS ┌─────────────────────┐
DENIED │ 4) Any ancestor has │
│ RECURSIVE │
│ membership? │
└──────────┬──────────┘
│
┌──────────┴──────────┐
│ NO │ YES
▼ ▼
❌ ACCESS ✅ ACCESS
DENIED GRANTEDCommon operations (enterprise patterns)
Create a new Site under a Customer
Use the Customer as the parent organization, then create a child org of type Site. The new Site inherits defaults (policy and visibility) from its parent.
Grant recursive access to an Operations team
Create a Group (e.g., ops) and assign a membership at the Customer or Site level with scope = recursive. This grants access to all descendants without duplicating memberships.
Isolate sensitive locations (strict boundary)
Set RolePolicy = strict on a Site or Building that must be isolated (e.g., clinics, restricted labs). This blocks inherited permissions from parent organizations.
Enterprise governance
Data isolation
- Tenants are isolated by the organization hierarchy.
- Users can only access organizations where they have memberships (direct or inherited).
- Subtree queries leverage
pathKeyto enforce boundaries efficiently.
Best practices
| Practice | Recommendation |
|---|---|
| Prefer groups | Use group-based memberships for enterprise clients |
| Avoid excessive recursion | Use recursive scope at the appropriate level (not always at root) |
| Use strict where required | Apply strict policy for hard isolation boundaries |
| Audit routinely | Review memberships and group composition periodically |
Next steps
- Roles & Permissions — Permission catalog and RBAC patterns
- Assets & Templates — Integration patterns and EVA fields
- Rules & Business Rules — Stateful automation and triggers
