Cohesive.Identity is a semantic layer for defining the identity architecture of a system before binding it to a particular authentication provider, HTTP framework, authorization middleware, or storage engine.
It models identity as part of the system definition: principals, scopes, grants, permissions, capabilities, and effective scope selection become explicit semantic data that can be interpreted by APIs, storage repositories, process runtimes, presentation layers, and infrastructure adapters.
The result is an identity model that works for simple single-tenant products and for multi-tenant or multi-scope platforms where users, service accounts, system jobs, resources, and workflows operate across different tenants, workspaces, organizations, environments, or domains.

- Why It Exists
- Core Model
- Single-Tenant And Multi-Tenant Systems
- Identity Providers And Runtime Adapters
- First-Class Cohesive.Api Integration
- First-Class Cohesive.Storage Integration
- Identity As A Semantic Boundary
- References
Why It Exists
Most identity stacks are excellent at authentication, but they tend to push product authorization into application-specific glue code:
- a JWT proves who the caller is;
- route handlers manually extract a tenant id;
- services manually check membership;
- storage code separately decides which partition to use;
- generated API clients separately learn which endpoints need tenant context.
Cohesive.Identity treats those decisions as one semantic model. External identity providers still authenticate the principal, but Cohesive resolves what that principal means inside the product: which scopes are visible, which capabilities are granted, which scope is selected for this operation, and where scoped data should be placed.
Core Model
Cohesive.Identity is centered on a small set of concepts.
Principal
A principal is the actor known to the product: a user, service account, system account, or anonymous caller. The principal may be resolved from a Microsoft Entra subject, an Okta subject, an Auth0 subject, an email claim, a client id, or a local bootstrap account.
var actor = new PrincipalRef(
Id: "user_01J4M0ZJ9JKR3YJX3P3J5M82ZC",
Kind: PrincipalKind.User,
DisplayName: "Ada Lovelace"
);Scope
A scope is the semantic boundary where access and placement are interpreted. A scope can represent a tenant in a SaaS system, a workspace in a collaboration product, an organization in an enterprise deployment, a region, an environment, or a system-wide domain.
Scopes may also carry physical placement metadata, such as a storage partition key.
var tenant = new ScopeRef(
Id: "tenant-acme",
Kind: "shipping.tenant",
DisplayName: "Acme Logistics",
PartitionKey: "pk_acme"
);Grant
A grant connects a principal to a scope with a set of capability identifiers. Capabilities are product-level permission atoms such as shipment.read, shipment.dispatch, workflow.cancel, or admin.users.manage.
var grant = new IdentityScopeGrant(
Grantee: actor,
Scope: tenant,
Capabilities:
[
"shipment.read",
"shipment.dispatch",
"workflow.status.read"
],
Source: "tenant-membership"
);Effective Scope
The effective scope is the scope selection for one operation. It can be a single selected scope, several explicitly requested scopes, all scopes accessible to the principal, or a trusted system scope.
var identity = new IdentityContext(
Actor: actor,
EffectiveScope: new(
Scopes: [tenant],
Mode: ScopeSelectionMode.Single,
Source: ScopeSelectionSource.RequestHeader),
Grants: [grant]
);
var context = OperationContext.Create()
.WithIdentityContext(identity);Single-Tenant And Multi-Tenant Systems
In a single-tenant deployment, Cohesive.Identity can resolve one ambient or default scope and keep the rest of the application scoped without scattering tenant-specific conditionals through the codebase.
In a multi-tenant or multi-scope system, the same model supports:
- tenant, workspace, organization, or environment scopes;
- parent-child scope relationships;
- default scope resolution;
- explicitly selected scope ids from headers, route values, query parameters, request bodies, or token claims;
- multi-scope operations over all accessible scopes or a filtered requested set;
- service-account and system-account operations;
- delegated or async work that preserves actor, subject, and initiator identity.
This matters for products that start single-tenant and later become SaaS, as well as for enterprise products where one user may operate across several tenants or workspaces in the same request.
Identity Providers And Runtime Adapters
Cohesive.Identity does not replace Microsoft.Identity, ASP.NET authentication, Okta, Auth0, or another OpenID Connect provider. Those systems authenticate credentials and produce a host principal. Cohesive.Identity consumes that principal and resolves product semantics from it.
The ASP.NET adapter enriches OperationContext from the current HttpContext, reads requested scope selections, and enforces API scope policy metadata. The claims helpers understand standard OAuth scope claims, Microsoft Entra role and scope claim shapes, subject claims, email-like claims, and OAuth client id claims.
The same resolver shape can be used with Okta, Auth0, or any other OIDC provider because the adapter boundary is a ClaimsPrincipal. Provider-specific identity is normalized into local lookup keys such as subject, email, client id, or principal id, then resolved through an IIdentityDirectory.
First-Class Cohesive.Api Integration
Cohesive.Api operations can declare their scope requirements as API metadata. That metadata is projected into concrete transports and enforced by adapters.
For example, an operation can require a single tenant from a header, filter a query to all accessible tenants, or derive a tenant from a resource id in the route.
Once the policy is declared, API definitions carry the scope semantics with them.
Transport projections can then generate OpenAPI extensions, typed clients, frontend request metadata, and server-side endpoint metadata from the same declaration. The ASP.NET adapter reads that metadata, resolves the requested scope, and checks it against the identity's accessible grants.
First-Class Cohesive.Storage Integration
Identity is also a placement model.
Because ScopeRef can carry a PartitionKey, storage repositories can place scoped data according to the identity architecture rather than duplicating tenant-partition logic in every repository or handler. This allows a semantic tenant id to be distinct from a physical partition key while still keeping writes and point reads efficient.
This integration gives storage adapters enough semantic information to:
- write observations into a tenant, workspace, or organization partition;
- resolve exact partition keys for point reads when the request has one effective scope;
- keep system jobs and process runtimes scoped without bypassing placement policy;
- distinguish logical scope ids from physical storage partition keys;
- preserve multi-tenant rules across storage backends.
Identity As A Semantic Boundary
Cohesive.Identity keeps authentication, authorization, API routing, storage placement, and workflow execution connected through one semantic identity context.
That context can be interpreted differently by different infrastructure:
- ASP.NET uses it to enrich request operation context and enforce API policies.
- Microsoft.Identity, Okta, Auth0, and other identity providers feed it through normalized claims.
- Cohesive.Api uses it to declare scoped endpoints and generate transport metadata.
- Cohesive.Storage uses it to place scoped records and optimize point reads.
- Cohesive.Processes can use it to preserve actor, initiator, scope, and capability context across durable or ephemeral workflows.
- Cohesive.Presentation can use API scope metadata to project scope-aware actions and request clients.
The identity model therefore remains product-owned and portable. Infrastructure authenticates, transports, stores, and executes; Cohesive.Identity defines what identity means.