@@ -331,22 +331,40 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
331331 t . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName )
332332 ) ;
333333
334- // Get the source code of the assembly as will be used to check Power FX Namespaces
335334 var code = DecompileModuleToCSharp ( assembly ) ;
336335
337336 foreach ( TypeDefinition type in module . GetAllTypes ( ) )
338337 {
339- // Provider types: pass-through (no namespace validation). Keep existing behavior.
340- if ( type . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Providers . ITestWebProvider ) . FullName )
338+ bool isProviderLike =
339+ type . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Providers . ITestWebProvider ) . FullName )
341340 || type . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Users . IUserManager ) . FullName )
342- || type . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName ) )
341+ || type . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName ) ;
342+
343+ if ( isProviderLike )
343344 {
345+ if ( CheckPropertyArrayContainsValue ( type , "Namespaces" , out var declaredNamespaces ) && declaredNamespaces ? . Length > 0 )
346+ {
347+ foreach ( var ns in declaredNamespaces )
348+ {
349+ // Inline IsNamespaceAllowed logic
350+ var effectiveAllows = settings . AllowPowerFxNamespaces . Where ( a => ! string . IsNullOrEmpty ( a ) ) . ToList ( ) ;
351+ var effectiveDenies = settings . DenyPowerFxNamespaces . Where ( d => ! string . IsNullOrEmpty ( d ) ) . ToList ( ) ;
352+
353+ bool denied = effectiveDenies . Any ( d => Regex . IsMatch ( ns , WildcardToRegex ( d ) ) ) ;
354+ bool allowed = ( effectiveAllows . Count == 0 ) || effectiveAllows . Any ( a => Regex . IsMatch ( ns , WildcardToRegex ( a ) ) ) || ns == NAMESPACE_TEST_ENGINE ;
355+
356+ if ( denied || ! allowed )
357+ {
358+ Logger ? . LogInformation ( $ "Namespace { ns } not permitted for provider/user/auth type { type . Name } .") ;
359+ return false ;
360+ }
361+ }
362+ }
344363 continue ;
345364 }
346365
347366 if ( type . BaseType != null && type . BaseType . Name == "ReflectionFunction" )
348367 {
349- // Always allow PauseFunction (legacy behavior). It will register at root.
350368 if ( type . Name == "PauseFunction" )
351369 {
352370 Logger ? . LogInformation ( "Skipping namespace validation for PauseFunction (explicitly allowed)." ) ;
@@ -389,7 +407,7 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
389407 var allowList = settings . AllowPowerFxNamespaces . ToList ( ) ;
390408 if ( assemblyHasProvider && ! allowList . Contains ( NAMESPACE_PREVIEW ) )
391409 {
392- allowList . Add ( NAMESPACE_PREVIEW ) ; // preserve previous provider behavior
410+ allowList . Add ( NAMESPACE_PREVIEW ) ;
393411 }
394412
395413 if ( settings . DenyPowerFxNamespaces . Contains ( fxNamespace ) )
@@ -411,7 +429,6 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
411429
412430 if ( type . BaseType != null && type . BaseType . Name == "ReflectionAction" )
413431 {
414- // Actions now use same namespace validation as functions (AllowActionsInRoot removed).
415432 var constructors = type . GetConstructors ( ) ;
416433 if ( constructors . Count ( ) == 0 )
417434 {
0 commit comments