OpenApiFeatureFlags.AspNetCore 0.2.0

dotnet add package OpenApiFeatureFlags.AspNetCore --version 0.2.0
                    
NuGet\Install-Package OpenApiFeatureFlags.AspNetCore -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OpenApiFeatureFlags.AspNetCore" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenApiFeatureFlags.AspNetCore" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="OpenApiFeatureFlags.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OpenApiFeatureFlags.AspNetCore --version 0.2.0
                    
#r "nuget: OpenApiFeatureFlags.AspNetCore, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OpenApiFeatureFlags.AspNetCore@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OpenApiFeatureFlags.AspNetCore&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=OpenApiFeatureFlags.AspNetCore&version=0.2.0
                    
Install as a Cake Tool

OpenApiFeatureFlags

Feature flags for OpenAPI documents.

CI CodeQL NuGet License: MIT

Mark the endpoint, action, property or parameter with [OpenApiFeatureFlag] and it only appears in the generated document once the flag is enabled — using the same flags the runtime already reads.

[OpenApiFeatureFlag("NewCheckout")]
[HttpPost("checkout")]
public IActionResult Checkout() => Ok();

With NewCheckout off, /api/orders/checkout is not in swagger.json. With it on, it is. No restart, no rebuild, no conditional compilation.

Multi-targets net8.0, net9.0 and net10.0. Both document engines are supported — Swashbuckle, and the built-in Microsoft.AspNetCore.OpenApi through a net10.0-only package — and flags can come from Microsoft.FeatureManagement, the CNCF OpenFeature standard, or your own IFeatureFlagSource.


The problem this solves

A document is generated from the code, so it describes every endpoint the code declares. A feature toggle only gates runtime behaviour. The result is customers reading documented API surface they cannot use — and, once the document is published, a support conversation about an endpoint that "exists" but does not work.

Installation

dotnet add package OpenApiFeatureFlags.Swashbuckle
dotnet add package OpenApiFeatureFlags.FeatureManagement

That is the whole install for a Swashbuckle API reading flags through Microsoft's feature management: OpenApiFeatureFlags and OpenApiFeatureFlags.Abstractions arrive as dependencies. Swap the second line for OpenApiFeatureFlags.OpenFeature to read flags through the CNCF OpenFeature standard, or leave it out if you are implementing IFeatureFlagSource yourself.

Package What it is for
OpenApiFeatureFlags Core: the planner and the service registration.
OpenApiFeatureFlags.Swashbuckle Swashbuckle filter set. Add this if you use AddSwaggerGen.
OpenApiFeatureFlags.AspNetCore Transformer set for the built-in Microsoft.AspNetCore.OpenApi. Add this if you use AddOpenApi. net10.0 only, and it cannot share an application with the Swashbuckle adapter.
OpenApiFeatureFlags.FeatureManagement Reads flags from Microsoft's IFeatureManager.
OpenApiFeatureFlags.OpenFeature Reads flags through the CNCF OpenFeature standard.
OpenApiFeatureFlags.Abstractions Attribute and contracts only. Reference this from assemblies that must not take a dependency on Swashbuckle or a flag library.

Quickstart

1. Register the services

builder.Services.AddOpenApiFeatureFlagsWithFeatureManagement();

builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "1.0" });

    // Register this LAST. See "Filter ordering" below.
    options.AddOpenApiFeatureFlagFilters();
});

AddOpenApiFeatureFlagsWithFeatureManagement() is one call that registers your existing Microsoft.FeatureManagement setup and points OpenApiFeatureFlags at it. Already using feature management? Chain instead:

builder.Services
    .AddOpenApiFeatureFlags(options => options.Mode = DocumentMode.Annotate)
    .AddFeatureManagementFlagSource();

Bringing your own flag store? Implement one interface and register it:

public sealed class MyFlagSource(IMyToggleStore store) : IFeatureFlagSource
{
    public bool IsEnabled(string flagName) => store.IsOn(flagName);
}

builder.Services.AddOpenApiFeatureFlags(new MyFlagSource(store));

Azure App Configuration needs no adapter of its own. It is a configuration source that feeds Microsoft.FeatureManagement, and OpenApiFeatureFlags.FeatureManagement reads through IFeatureManager, so the wiring above is the whole integration — plus the three lines that add the store. See docs/azure-app-configuration.md.

2. Mark what is gated

[ApiController]
[Route("api/orders")]
public sealed class OrdersController : ControllerBase
{
    [HttpGet("{id}")]
    public Order Get(string id) => _orders.Find(id);

    [OpenApiFeatureFlag("NewCheckout")]                  // gates this operation
    [HttpPost("checkout")]
    public IActionResult Checkout() => Ok();

    [HttpGet("search")]
    public IActionResult Search(
        [OpenApiFeatureFlag("InternalSearch")] string? scope) => Ok();   // gates one parameter
}

public sealed class Order
{
    public string? Id { get; set; }

    [OpenApiFeatureFlag("LoyaltyProgram")]               // gates one response property
    public int LoyaltyPoints { get; set; }
}

The attribute works on a controller, an action, a model property or a parameter. Two attributes on one target are ANDed: the element is documented only when every flag is enabled.

Doc comments become descriptions, and you cannot put an attribute on half a sentence. Wrap gated prose in <gate> instead:

/// <summary>
/// The order total.
/// <gate flag="LoyaltyProgram">Points are shown in <c>loyaltyPoints</c>.</gate>
/// </summary>
public decimal Total { get; set; }

3. Done

Nothing else. The document is regenerated on every request, so flipping a flag changes the published document without a restart.

Modes

Mode Behaviour
Remove (default) Gated elements are hidden — removed from the document.
Annotate Gated elements stay, tagged with x-feature-flag, so a portal can filter them.
Include The library does nothing; the full document is published.

Annotate publishes your flag names — on each gated operation, and as a document-level list. On a document that anyone can read, that discloses which features exist, including ones you have not released. Use it for internal or authenticated audiences; use Remove for public documents. See docs/security.md.

See docs/modes.md for output samples.

What this library does not do

It never changes runtime behaviour. Hiding an operation from the document leaves the endpoint routeable; hiding a property leaves it serialised. A documentation decision must not silently become a behaviour change, and this is the one rule the design refuses to bend. Runtime gating stays in your application code.

So do not use it to protect an endpoint. Gating makes unreleased surface less discoverable; it is not an access control, and it cannot unpublish a document that has already been served. Authentication and authorization belong where they always did. docs/security.md sets out what this library does and does not do to your security posture, including its availability trade-offs.

Guarantees worth knowing

  • Fail closed. If a flag cannot be resolved, the element is hidden rather than leaked.
  • Fail loudly instead of quietly deleting. Failing closed is only safe while your flag store answers. If a document contains gated elements and no flag could be read, the library throws FeatureFlagSourceUnavailableException rather than publishing a document that is silently missing released endpoints. Turn it off with CanaryEnabled = false if you accept that risk.
  • Invisible when unused. With no attributes applied, the produced document is byte-identical to one generated without the library. There is a regression test that asserts exactly this.

Filter ordering

Swashbuckle applies filters in registration order, and this matters:

  • Call AddOpenApiFeatureFlagFilters() after your own filters and document processors. A processor that clears and rebuilds Paths would otherwise put removed operations back, and one that rebuilds Tags would put removed tags back.

The registration order inside AddOpenApiFeatureFlagFilters is deliberate and documented in the method's XML docs.

Documentation

Project

  • CONTRIBUTING.md — build and test commands, and the two rules a pull request is most likely to trip over.
  • SECURITY.md — how to report a vulnerability privately. Please do not open a public issue for one.
  • CODE_OF_CONDUCT.md — how people are expected to treat each other here.
  • CHANGELOG.md — what changed, and when.

Author

Dogukan Demir — @dogukandemir

Licence

MIT.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 46 9/30/2026