MaleusMaleus

Identity, permissions, and multi-tenant isolation

Understand sessions, SSO, RBAC, contextual controls, least-privilege keys, and data isolation.

In the appApplication · Users and SSOUpdated September 19, 2026
On this page

The foundation separates four questions that are often conflated: who is calling, which action is requested, in which tenant, and on which project or record. A request must pass these checks before reaching the use case.

Authenticate a person or a system

The browser flow uses short-lived access tokens and refresh tokens stored server-side. Refresh tokens can be revoked and are associated with the session context. Passwords are hashed with Argon2, repeated failures can temporarily lock an account, and verification time is equalized to limit user enumeration.

The same foundation supports OIDC or SAML SSO providers. Their availability does not mean a provider is already configured: metadata, certificates, claims, and login policy remain client-specific.

The login flow can offer local credentials and SSO in the same interface.

For a machine integration, an API key carries a list of allowed actions. It can therefore receive a subset of its creator's permissions and can optionally be limited to a project.

Name actions with capabilities

A capability describes an action, such as users:list or documents:upload. A role groups exact capabilities or patterns. A group grants one or more roles to its members.

ElementRole in the decision
IdentityPerson, API key, or agent behind the request.
CapabilityAction requested by the route.
RoleSet of capabilities needed for a use case.
GroupCollective assignment of roles and projects.
ContextTenant, project, principal type, and any business scope.

Built-in roles cover administration and standard use. Tenant-specific roles and groups can extend this foundation when the application exposes the corresponding screens.

Add contextual ABAC-style rules

RBAC answers, "Can this role perform this action?" Some decisions also require, "On which resource?" The project access guard then combines several attributes: current tenant, groups, accessible projects, key scope, agent project, and principal type.

A business repository can add a dynamic predicate, such as "only records for which the user is responsible." This extension is intentionally local to the domain. The foundation does not claim to provide a universal ABAC policy engine.

Isolate tenants and projects

The tenantId is propagated in the request context. Tenant-aware repositories require it in their operations and add it to SQL clauses. Project permissions are layered on top of this first boundary.

This mechanism greatly reduces the risk that an identifier valid in one tenant grants access to the same identifier in another. API tests systematically include cross-tenant attempts, including for ad hoc queries that do not go through a tenant-aware repository.

A verifiable decision

A useful security matrix covers at least:

  • person, API key, and agent;
  • allowed role and denied role;
  • current tenant and external tenant;
  • accessible project and inaccessible project;
  • allowed action and out-of-scope action.

This matrix becomes a test plan, not merely an architecture convention.