Portal Community

Isolation Rules

RuleDetail
Workflow ownershipEvery Process has a TenantId set at creation — never null
Access queriesAll Process_ProcessAccess lookups include WHERE TenantId = @tenantId
Cross-tenant sharingNot supported — ActorId must belong to the same tenant
Tenant AdminHas implicit Owner-level access to all workflows in their tenant (for audit)
Platform AdminRead-only access to all tenants for support; audited separately

TenantId Propagation

TenantId flows from the JWT claim through the entire stack:

1

JWT Authentication

JWT contains tenant_id claim. ASP.NET authentication middleware extracts it and stores in ClaimsPrincipal.

2

ITenantContext

Scoped service ITenantContext.TenantId is populated from the claim. All services inject ITenantContext — never accept TenantId from the request body.

3

Repository Queries

All ProcessRepository methods include .Where(p => p.TenantId == _tenantContext.TenantId) — data from other tenants is never returned.

Never trust client-supplied TenantId: API clients cannot override TenantId. It is always derived from the authenticated JWT. Any attempt to access another tenant's workflow with a manipulated processId returns 404 (not 403 — revealing that the resource exists in another tenant is itself a security risk).

Tenant Admin Access

// Tenant admin check in IProcessAccessChecker
private bool IsTenantAdmin(string userId)
{
    return _iamService.HasRoleAsync(userId, WellKnownRoles.TenantAdmin);
}

// In CanViewAsync:
if (await IsTenantAdmin(userId)) return true;  // admin bypasses per-workflow policy