Flow Studio
Tenant Isolation
Every workflow is owned by exactly one tenant. Cross-tenant access is architecturally impossible — TenantId is included in every database query and API check.
Isolation Rules
| Rule | Detail |
|---|---|
| Workflow ownership | Every Process has a TenantId set at creation — never null |
| Access queries | All Process_ProcessAccess lookups include WHERE TenantId = @tenantId |
| Cross-tenant sharing | Not supported — ActorId must belong to the same tenant |
| Tenant Admin | Has implicit Owner-level access to all workflows in their tenant (for audit) |
| Platform Admin | Read-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