Organization hierarchy
An Instance contains top-level Organizations. An Organization can contain one level of SubOrg; each organization remains a policy, membership, branding, RBAC, and isolation boundary.
An OrgUnit is a department or team inside one Organization. It never changes TenantContext, issuer, token claims, or the one-level SubOrg limit.
- OrgUnit trees support a maximum depth of eight.
- Each member can have one primary OrgUnit and additional placements.
- The nearest active manager in the OrgUnit ancestor chain is the first access-request approver candidate.
Projects and access policy
Projects group applications and authorization roles. The per-project access_policy controls only same-organization users without an effective UserGrant; cross-organization ProjectGrant authorization is unaffected.
| Project policy | Same-organization behavior | Self-service path |
|---|---|---|
| Open | Allowed without a UserGrant. | No access request is needed. |
| Restricted | Denied; an administrator grants access directly. | No self-service request is available. |
| Approval required | Denied until an AccessRequest is approved. | The user submits an access request. |
Access request lifecycle
AccessRequest moves from pending to approved, denied, cancelled, or expired. Every outcome is terminal, and pending requests expire lazily after 14 days.
Approval creates a traceable UserGrant in the same transaction. The requester cannot approve their own request; resolution falls through from the OrgUnit manager to project and organization managers.
| Method | Path | Purpose | Required scope |
|---|---|---|---|
GET, POST |
/auth/access-requests |
Create and list the current user’s requests. | session |
POST |
/auth/access-requests/:id/cancel |
Cancel the current user’s pending request. | session |
GET |
/auth/access-approvals |
List requests awaiting the current user’s approval. | session |
POST |
/auth/access-approvals/:id/{approve|deny} |
Approve or deny a pending request assigned to the current user. | session |
GET |
/v1/organizations/:orgId/access-requests |
List requests inside one organization. | access-requests:read |
GET |
/v1/organizations/:orgId/units |
Read the organization unit tree. | org-units:read |
POST, PATCH, DELETE, PUT |
/v1/organizations/:orgId/units/* |
Create, update, move, archive, and manage members of units. | org-units:write |
Security boundaries
- Every OrgUnit and AccessRequest query is scoped by
tenant_idandorg_id. Cross-organization or cross-tenant identifiers return 404 without revealing existence. - Membership and project access are separate: invitations join an Organization, while AccessRequest grants an existing active member access to one Project.
- SCIM provisions users and memberships but does not map directory groups to OrgUnits or Project roles in the current implementation.
- The Management API uses cursor pagination and shared API-key or organization-manager guards. It does not reuse end-user business routes.