CSealTest 1.0.2

dotnet add package CSealTest --version 1.0.2
                    
NuGet\Install-Package CSealTest -Version 1.0.2
                    
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="CSealTest" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CSealTest" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="CSealTest" />
                    
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 CSealTest --version 1.0.2
                    
#r "nuget: CSealTest, 1.0.2"
                    
#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 CSealTest@1.0.2
                    
#: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=CSealTest&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=CSealTest&version=1.0.2
                    
Install as a Cake Tool

ConfigSeal

Strict startup configuration validation for ASP.NET Core. The FluentValidation for configuration.


The Problem

Configuration errors are silent killers. Your app starts fine, then crashes in production because App:PaymentApiKey was never set, Database:MaxPoolSize is 0, or a developer accidentally committed localhost as the API base URL.

.NET's built-in IOptions<T> binding gives you type safety, but no enforcement. Missing values stay null. Invalid values go unnoticed. Secrets get left as placeholders.

ConfigSeal catches all of this at startup, before your app serves a single request.


What It Looks Like

// Program.cs
var guard = builder.Services.AddConfigSeal(builder.Configuration, builder.Environment);

guard.Bind<AppOptions>("App")
    .Require(x => x.ApiKey)
    .Validate(x => x.Timeout > 0)
    .ValidateEnvironment();

guard.Bind<DatabaseOptions>("Database")
    .Require(x => x.ConnectionString)
    .Validate(x => x.MaxPoolSize is > 0 and <= 500, "MaxPoolSize must be 1–500.");

guard.ValidateAll(); // throws if anything is wrong — app will not start

On failure, instead of a cryptic NullReferenceException at runtime, you get:

╔══════════════════════════════════════════════════════════════╗
║           ConfigSeal: Configuration Sealed — Startup Blocked        ║
╠══════════════════════════════════════════════════════════════╣
║  ✗ [Critical] App.ApiKey
║      → Required configuration value is missing or empty.
║      💡 Generate via: openssl rand -hex 32
║  ✗ [Error] Database.MaxPoolSize
║      → Value 0 is outside the allowed range [1, 500].
╠══════════════════════════════════════════════════════════════╣
║  2 validation error(s) must be resolved before startup.
╚══════════════════════════════════════════════════════════════╝

Features

Attribute-Based Validation

Decorate your options classes — no extra registration needed:

public class AppOptions
{
    [RequiredConfig(Hint = "Generate via: openssl rand -hex 32")]
    [SecretConfig(MinLength = 32)]
    public string? ApiKey { get; set; }

    [RangeConfig(1, 300)]
    public int TimeoutSeconds { get; set; }

    [AllowedValues("Strict", "Relaxed", "Off")]
    public string? CorsPolicy { get; set; }

    [RegexConfig(@"^https://", ErrorMessage = "BaseUrl must use HTTPS.")]
    public string? BaseUrl { get; set; }
}
Attribute What it enforces
[RequiredConfig] Non-null, non-empty value
[SecretConfig(MinLength)] Exists, meets length, not a placeholder (CHANGEME, TODO, etc.)
[RangeConfig(min, max)] Numeric value within bounds
[AllowedValues("a","b")] Value must match one of the allowed strings
[RegexConfig(pattern)] Value matches the regex
[EnvironmentOnly("Production")] Only validated in specified environments

Fluent Validation

For logic that spans multiple properties or needs runtime context:

guard.Bind<CacheOptions>("Cache")
    .Validate(x => !(x.UseMemoryCache && x.UseRedis),
              "Cannot enable both MemoryCache and Redis simultaneously.")
    .Validate(x => x.ExpiryMinutes,
              v => v is > 0 and <= 1440,
              "Cache expiry must be between 1 minute and 24 hours.");

Environment Safety Checks

.ValidateEnvironment() fails startup if production config contains development defaults: localhost, 127.0.0.1, development, debug, ::1, etc.

Secret Validation

[SecretConfig] catches the most common secrets-in-production mistakes:

  • Missing entirely → Critical
  • Looks like a placeholder (CHANGEME, your_secret_here, <replace_me>) → Critical
  • Too short for the context → Warning

All Failures at Once

ConfigSeal collects every problem before throwing. You see the full picture on the first failed deploy, not one error at a time.

Custom Validators

Plug in reusable cross-cutting validation:

public class ConnectionStringValidator : IConfigValidator
{
    public void Validate(object options, ValidationContext context)
    {
        if (options is DatabaseOptions db)
            if (!db.ConnectionString?.Contains("Encrypt=True") ?? true)
                context.AddWarning("ConnectionString",
                    "Connection string does not enforce encryption.",
                    "Add 'Encrypt=True' for production.");
    }
}

guard.Bind<DatabaseOptions>("Database")
    .WithValidator(new ConnectionStringValidator());

Installation

dotnet add package ConfigSeal

Targets net8.0. Depends only on Microsoft.Extensions.* abstractions — no heavy third-party dependencies.


Publishing a Release

Releases are fully automated via GitHub Actions. The publish job runs only on version tags and requires the build-and-test job to pass first.

One-time setup

Add your NuGet API key as a repository secret:

  1. Go to nuget.org → Account → API Keys → Create
  2. In your GitHub repo → Settings → Secrets and variables → Actions → New repository secret
  3. Name: NUGET_API_KEY, value: your key

Releasing

# Bump the version in src/ConfigSeal/ConfigSeal.csproj first, then:
git tag v1.2.3
git push origin v1.2.3

The CI pipeline will:

  1. Build and run all tests (blocks publish on failure)
  2. Pack ConfigSeal.1.2.3.nupkg using the tag as the version
  3. Push to nuget.org
  4. Create a GitHub Release with auto-generated notes and the .nupkg attached

The tag version and the <Version> in the .csproj can differ — the tag always wins at publish time. Keep them in sync to avoid confusion.

Versioning

This project follows Semantic Versioning:

Change Version bump
Breaking API change MAJOR — e.g. v2.0.0
New backward-compatible feature MINOR — e.g. v1.1.0
Bug fix / internal change PATCH — e.g. v1.0.1

See CHANGELOG.md for the full release history.


Why ConfigSeal?

Every ASP.NET Core app uses configuration. Very few apps validate it rigorously. The ones that do write the same if (string.IsNullOrEmpty(...)) throw boilerplate in every project.

ConfigSeal makes thorough configuration validation the default, not the exception.


License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.0.2 113 3/29/2026