Documentation
fsds/identity-permission-discovery-fix.md
Plan: Fix Permission Discovery to Always Return 200 OK
Problem
When Identity queries components for permissions, some components don't have permission manifests. This causes:
- The
/.well-known/permissionsendpoint isn't mapped (line 397-400 in Extensions.cs returns early) - Component returns 404
- Identity logs warnings for each 404
- Red circles appear in Aspire dashboard
Solution
Every component must have a permission manifest (even if empty). When properly set up, all components return 200 OK with their permissions (or empty list).
Change 1: Always Map Permission Discovery Endpoint
File: strata/service-defaults/src/Acsis.Dynaplex.Strata.ServiceDefaults/Extensions.cs
Remove the early return at lines 397-400. Always map the endpoint - extract component name from assembly if no manifests found:
public static IEndpointRouteBuilder MapPermissionDiscoveryEndpoint(
this IEndpointRouteBuilder endpoints)
{
var assembly = Assembly.GetEntryAssembly();
var manifests = assembly?.GetTypes()
.Where(t => t.IsClass && t.IsSealed && t.IsAbstract)
.Select(t => t.GetProperty("Manifest", BindingFlags.Public | BindingFlags.Static))
.Where(p => p?.PropertyType == typeof(PermissionManifest))
.Select(p => p!.GetValue(null) as PermissionManifest)
.Where(m => m != null)
.Cast<PermissionManifest>()
.ToList() ?? new List<PermissionManifest>();
// Extract component name from assembly for fallback
var componentName = ExtractComponentName(assembly);
endpoints.MapGet("/.well-known/permissions", () =>
{
var allPermissions = manifests
.SelectMany(m => m!.GetAllPermissions())
.ToList();
return TypedResults.Ok(new PermissionDiscoveryResponse(
manifests.FirstOrDefault()?.Component ?? componentName,
DateTime.UtcNow,
allPermissions
));
})
.AllowAnonymous()
.ExcludeFromDescription();
return endpoints;
}
private static string ExtractComponentName(Assembly? assembly)
{
// Extract from assembly name like "Acsis.Dynaplex.Engines.Events" -> "events"
var assemblyName = assembly?.GetName().Name ?? "unknown";
var parts = assemblyName.Split('.');
return parts.Length >= 3 ? parts[2].ToLowerInvariant() : assemblyName.ToLowerInvariant();
}
Change 2: Add Missing Permission Manifests
Components queried by Identity that are missing permission manifests:
| Component | File to Create |
|---|---|
| transport | engines/transport/src/Acsis.Dynaplex.Engines.Transport/TransportPermissions.cs |
| workflow | engines/workflow/src/Acsis.Dynaplex.Engines.Workflow/WorkflowPermissions.cs |
| events | engines/events/src/Acsis.Dynaplex.Engines.Events/EventsPermissions.cs |
| core-data | engines/core-data/src/Acsis.Dynaplex.Engines.CoreData/CoreDataPermissions.cs |
| system-environment | engines/system-environment/src/Acsis.Dynaplex.Engines.SystemEnvironment/SystemEnvironmentPermissions.cs |
Each file follows the empty manifest pattern from BbuPermissions.cs:
using Acsis.Dynaplex;
namespace Acsis.Dynaplex.Engines.{ComponentName};
/// <summary>
/// Permission manifest for the {ComponentName} component.
/// </summary>
public static class {ComponentName}Permissions {
public static PermissionManifest Manifest { get; } = BuildManifest();
private static PermissionManifest BuildManifest() {
var manifest = new PermissionManifest("{component-name}");
// Add permissions here as needed
return manifest;
}
}
Summary
| Change | Files | Description |
|---|---|---|
| Always map endpoint | Extensions.cs | Remove early return, always respond with 200 OK |
| Add TransportPermissions.cs | transport | Empty permission manifest |
| Add WorkflowPermissions.cs | workflow | Empty permission manifest |
| Add EventsPermissions.cs | events | Empty permission manifest |
| Add CoreDataPermissions.cs | core-data | Empty permission manifest |
| Add SystemEnvironmentPermissions.cs | system-environment | Empty permission manifest |
Expected Outcome
- All components return 200 OK from
/.well-known/permissions - Components with no permissions return empty list
- Identity logs "Discovered 0 permissions from " at Info level
- No 404s, no warnings, no red circles in Aspire dashboard