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:

  1. The /.well-known/permissions endpoint isn't mapped (line 397-400 in Extensions.cs returns early)
  2. Component returns 404
  3. Identity logs warnings for each 404
  4. 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