diff --git a/src/apps/Elsa.ModularServer.Web/Program.cs b/src/apps/Elsa.ModularServer.Web/Program.cs
index 0b1248f4f..bdc52921a 100644
--- a/src/apps/Elsa.ModularServer.Web/Program.cs
+++ b/src/apps/Elsa.ModularServer.Web/Program.cs
@@ -35,6 +35,7 @@ var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
configuration.AddJsonFile(configuration["Elsa:PlatformIntegration:ShellOverlayPath"] ?? "platform-shell-overrides.json", optional: true, reloadOnChange: false);
+services.AddRoleManagementE2EFixtures(configuration);
var serviceVersion = typeof(Program).Assembly.GetName().Version?.ToString();
builder.Logging.AddOpenTelemetry(logging =>
diff --git a/src/apps/Elsa.ModularServer.Web/RoleManagementE2EFixtures.cs b/src/apps/Elsa.ModularServer.Web/RoleManagementE2EFixtures.cs
new file mode 100644
index 000000000..bc3eac891
--- /dev/null
+++ b/src/apps/Elsa.ModularServer.Web/RoleManagementE2EFixtures.cs
@@ -0,0 +1,46 @@
+using Elsa.Permissions;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Elsa.ModularServer.Web;
+
+/// Opt-in services used by the Elsa Studio role-management acceptance harness.
+public static class RoleManagementE2EFixtureServiceCollectionExtensions
+{
+ /// Configuration switch that enables the role-management catalog fixture.
+ public const string IncludeUnverifiedPermissionDescriptorKey = "RoleManagementE2EFixtures:IncludeUnverifiedPermissionDescriptor";
+
+ ///
+ /// Adds the deterministic role-management fixture when explicitly enabled by the host configuration.
+ /// The default path is intentionally a no-op so ordinary sample and production hosts do not change.
+ ///
+ public static IServiceCollection AddRoleManagementE2EFixtures(this IServiceCollection services, IConfiguration configuration)
+ {
+ if (configuration.GetValue(IncludeUnverifiedPermissionDescriptorKey))
+ services.AddSingleton(RoleManagementE2EFixturePermissionDescriptorProvider.Instance);
+
+ return services;
+ }
+}
+
+/// Provides the one unverified descriptor needed by the role-management acceptance harness.
+///
+/// This is a value type on purpose: the shell descriptor scanner discovers class-based module providers, while
+/// this provider is registered only through the explicit opt-in above. It therefore cannot leak into the normal
+/// catalog merely because the host assembly is loaded.
+///
+internal readonly struct RoleManagementE2EFixturePermissionDescriptorProvider : IPermissionDescriptorProvider
+{
+ public static RoleManagementE2EFixturePermissionDescriptorProvider Instance => new();
+
+ public IEnumerable GetDescriptors() =>
+ [
+ new(
+ "e2e/role-management/unverified",
+ [Authorization.CoreVerbs.View],
+ "E2E unverified permission",
+ "Fixture-only permission descriptor for role-management acceptance testing.",
+ "E2E fixtures",
+ Verified: false)
+ ];
+}
diff --git a/test/integration/Elsa.Hosts.SmokeTests/RoleManagementE2EFixtureTests.cs b/test/integration/Elsa.Hosts.SmokeTests/RoleManagementE2EFixtureTests.cs
new file mode 100644
index 000000000..b7112cfd4
--- /dev/null
+++ b/test/integration/Elsa.Hosts.SmokeTests/RoleManagementE2EFixtureTests.cs
@@ -0,0 +1,49 @@
+using Elsa.Authorization;
+using Elsa.ModularServer.Web;
+using Elsa.Permissions;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Elsa.Hosts.SmokeTests;
+
+public class RoleManagementE2EFixtureTests
+{
+ [Fact]
+ public void DisabledConfigurationLeavesServicesUnchanged()
+ {
+ var services = new ServiceCollection();
+ services.AddSingleton();
+ var before = services.ToArray();
+
+ services.AddRoleManagementE2EFixtures(new ConfigurationBuilder().Build());
+
+ Assert.Equal(before, services);
+ Assert.DoesNotContain(services, x => x.ServiceType == typeof(IPermissionDescriptorProvider));
+ }
+
+ [Fact]
+ public void EnabledConfigurationContributesOneUnverifiedDescriptor()
+ {
+ var configuration = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary
+ {
+ [RoleManagementE2EFixtureServiceCollectionExtensions.IncludeUnverifiedPermissionDescriptorKey] = "true"
+ })
+ .Build();
+ var services = new ServiceCollection();
+
+ services.AddRoleManagementE2EFixtures(configuration);
+
+ using var serviceProvider = services.BuildServiceProvider();
+ var providers = serviceProvider.GetServices().ToArray();
+ var descriptors = providers.SelectMany(x => x.GetDescriptors()).ToArray();
+
+ Assert.Single(providers);
+ var descriptor = Assert.Single(descriptors);
+ Assert.Equal("e2e/role-management/unverified", descriptor.Resource);
+ Assert.False(descriptor.Verified);
+ Assert.Equal([CoreVerbs.View], descriptor.SupportedVerbs);
+ }
+
+ private sealed class ExistingService;
+}