Eigenverft.NetLib.Infrastructure 1.0.20264.60239-qa

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

🧱 Eigenverft.NetLib.Infrastructure

NuGet Version NuGet Downloads Build Status Targets License

Host-independent operational infrastructure for .NET applications and Generic Host-based services.

NetLib provides predictable writable storage plus safe loading, validation, protection, reload, and coordination of operational configuration. It keeps bad JSON candidates away from live settings, switches complete application-defined profiles, and supplies reusable certificate, diagnostics, and bootstrap primitives.


✨ At a glance

Capability Problem solved Starting point
Application directories Predictable writable storage below the executable AddDefaultDirectoryLayout()
SwitchableJson Last-known-good JSON loading and safe reloads AddSwitchableJsonFile(...)
Configuration Sets Coordinated multi-file profiles AddConfigurationSet(...)
Value preparation and protection Validate, transform, or protect persisted values before publication SwitchableJsonRegistrationOptions
Certificates and diagnostics Managed certificate recovery, configuration provenance, and bootstrap logging Public certificate and hosting helpers
Early host environment Resolve the host environment before Generic Host or ASP.NET Core builder creation StaticHostEnvironment.EnvironmentName

📦 Installation

dotnet add package Eigenverft.NetLib.Infrastructure

Or with the NuGet Package Manager:

Install-Package Eigenverft.NetLib.Infrastructure

🚀 Quick start

Create the host foundation

using Eigenverft.NetLib.Infrastructure.Hosting.DirectoryLayout;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder =
    HostApplicationBuilderFactory.CreateWithDefaultDirectory();
IAppDirectoryLayout directories = builder.GetDirectoryLayout();

string settingsDirectory =
    directories[DefaultDirectory.ApplicationSettings];

Console.WriteLine(settingsDirectory);

using IHost host = builder.Build();
await host.RunAsync();

Add last-known-good JSON reloads

using IHost host = builder.Build(); await host.RunAsync();


### Read the host environment before creating the builder

```csharp
using Eigenverft.NetLib.Infrastructure.Hosting;

string bootstrapSettings =
    $"BootstrapLogger.{StaticHostEnvironment.EnvironmentName}.json";

bool development = StaticHostEnvironment.IsDevelopment;
bool customQa = StaticHostEnvironment.IsEnvironment("QA");

StaticHostEnvironment supports both Generic Host and ASP.NET Core startup conventions. Precedence is process command-line arguments, then DOTNET_ENVIRONMENT, then ASPNETCORE_ENVIRONMENT, with Production as the default. A normal Generic Host application simply skips the ASP.NET Core fallback when that variable is absent. Custom environment names are preserved, and the value is captured once at first type initialization.

Add last-known-good JSON reloads

using Eigenverft.NetLib.Infrastructure.Hosting.Configuration.SwitchableJson;
using Eigenverft.NetLib.Infrastructure.Hosting.DirectoryLayout;
using Microsoft.Extensions.Hosting;

HostApplicationBuilder builder = HostApplicationBuilderFactory.CreateWithDefaultDirectory();
IAppDirectoryLayout directories = builder.GetDirectoryLayout();

string operationalSettings = Path.Combine(
    directories[DefaultDirectory.ApplicationSettings],
    "OperationalSettings.json");

builder.AddSwitchableJsonFile(
    name: "OperationalSettings",
    initialPath: operationalSettings,
    optional: false,
    reloadOnChange: true);

using IHost host = builder.Build();
await host.RunAsync();

The required initial file must exist. Invalid later edits are rejected and the previous configuration snapshot stays active.

Application directory layout

The standard layout is created directly below the executable directory:

<application>/
├─ AppLogs/
├─ AppData/
├─ AppState/
├─ AppProtectionKeys/
├─ AppCerts/
└─ AppSettings/

Each directory is created during registration and checked for write access, so path or permission problems fail early during startup.

The same layout is registered as IAppDirectoryLayout after Build(), so normal constructor injection works as expected:

public sealed class Worker(
    ILogger<Worker> logger,
    IAppDirectoryLayout directories) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "Using application data directory {Directory}",
            directories[DefaultDirectory.ApplicationData]);

        await Task.Delay(Timeout.Infinite, stoppingToken);
    }
}

🗂️ Override standard folder names

builder.AddDefaultDirectoryLayout(
    new Dictionary<DefaultDirectory, string>
    {
        [DefaultDirectory.ApplicationData] = "Data",
        [DefaultDirectory.ApplicationLogFiles] = "Logs",
    });

Unspecified standard directories retain their defaults.

🧩 Custom directory layouts

builder.AddDirectoryLayout(
    new Dictionary<string, string>
    {
        ["Cache"] = "cache",
        ["Imports"] = "incoming",
    });

string imports = builder.GetDirectoryLayout()["Imports"];

Folder mappings are intentionally direct children of the application root. Rooted paths, nested paths, and traversal patterns are rejected.

🔧 Without Generic Host

AppDirectoryLayout directories = AppDirectoryLayoutFactory.CreateDefault();

An explicit root can also be supplied to the factory for tools, tests, or custom bootstrap scenarios.

Safe operational configuration

SwitchableJson prepares a changed or alternative JSON file before publication and keeps the last-known-good snapshot when the candidate is missing, invalid, or rejected. Configuration Sets coordinate several switchable sources under one application-defined value, preventing related sources from silently using different profiles. Typical sets include operational modes, proxy behavior, build generations, feature collections, environments, and deployment lanes. Applications decide when to switch and may keep that choice transient or persist it as desired state.

Use case Example values Sources changed together
Reverse-proxy topology Primary, Canary, Failover Routes, clusters, and health policy
Operational observability Normal, Verbose, Incident Logging, diagnostics, and tracing
Traffic and download limits Restricted, Normal, Burst Rate limits, concurrency, bandwidth, and size limits
Resilience policy Normal, Degraded, Emergency Timeouts, retries, circuit breakers, and fallbacks
Feature or release set Stable, Preview, Rollback Features, endpoint exposure, and UI capabilities
Application availability Open, ReadOnly, Maintenance Endpoint access, write policy, jobs, and maintenance responses
Asset or content set Current, Campaign, Legacy Asset manifests, templates, branding, and content paths
Backend integration topology Primary, Secondary, Offline Service endpoints, queue targets, and credential references
Retention and data lifecycle Short, Standard, Archive Retention periods, cleanup windows, and archive policy
Capacity and performance Economy, Balanced, Peak Concurrency, batching, caching, and background-work limits

These are application-defined policies. Runtime switching requires reload-aware consumers; startup-fixed behavior should be controlled through the desired-state store with ConfigurationSetApplyMode.StartupOnly rather than a direct runtime switch.

For example, a reverse proxy can keep complete primary and failover generations side by side:

AppSettings/Routing/
├── Primary/Routes.json
├── Primary/Clusters.json
├── Failover/Routes.json
└── Failover/Clusters.json

Register both files as one choice so a bad route or cluster candidate cannot publish half a generation:

using Eigenverft.NetLib.Infrastructure.Hosting.Configuration.ConfigurationSets;
using Eigenverft.NetLib.Infrastructure.Hosting.Configuration.SwitchableJson;

string routingRoot = Path.Combine(
    directories[DefaultDirectory.ApplicationSettings],
    "Routing");

SwitchableJsonRegistrationOptions routingSourceOptions = new()
{
    // Follow valid edits within whichever routing generation is active.
    ReloadOnChange = true,
};

builder
    .AddConfigurationSet(
        // Logical identity used by runtime and desired-state operations.
        name: "RoutingProfile",
        // Start with AppSettings/Routing/Primary/*.json.
        initialValue: "Primary",
        // Permit a deliberate transition to the reviewed fallback generation.
        additionalAllowedValues: ["Failover"])
    .AddSwitchableJson(
        // Resolve <root>/<value>/<fileName> for both participants.
        rootPath: routingRoot,
        options: routingSourceOptions,
        fileNames: ["Routes.json", "Clusters.json"]);

Both candidates are prepared first; if either is missing or invalid, Primary remains active. Connect an admin UI or automation through an application-owned DI service:

using Eigenverft.NetLib.Infrastructure.Hosting.Configuration.ConfigurationSets;
using Eigenverft.NetLib.Infrastructure.Hosting.DirectoryLayout;
using Microsoft.Extensions.DependencyInjection;

string profileStateFile = Path.Combine(
    directories[DefaultDirectory.ApplicationState],
    "ConfigurationSets.json");

// Register persistent desired-state control in addition to ephemeral runtime control.
builder.AddConfigurationSetStateFile(path: profileStateFile);
builder.Services.AddSingleton<RoutingProfileService>();

public sealed class RoutingProfileService(
    IConfigurationSetManager configurationSets,
    IConfigurationSetDesiredStateStore desiredState)
{
    // Change only the running process.
    public bool TrySwitchCurrentProcess(
        string value,
        out ConfigurationSetSwitchResult? result) =>
        configurationSets.TrySwitchRuntime(
            setName: "RoutingProfile", value: value, result: out result);

    // Persist the operator's selection and honor the configured apply mode.
    public ConfigurationSetStateApplyResult SetDesiredProfile(string value) =>
        desiredState.TrySetDesiredValue(
            setName: "RoutingProfile", value: value);
}

The same service shape works for traffic limits, resilience, maintenance, feature, or logging profiles. An admin controller may inject it, display the active, desired, and allowed values from IConfigurationSetDesiredStateStore.GetDesiredStateStatus(), and translate a reviewed UI action into a switch. NetLib coordinates and reports the transition; the application remains responsible for authentication, authorization, and audit logging.

Preferred API

The public configuration surface is intentionally centered on developer-facing contracts and registration helpers:

  • builder.AddConfigurationSet(...) returns a ConfigurationSetRegistration for fluent startup binding. External runtime control uses IConfigurationSetManager.TrySwitchRuntime(...); set-specific control can use keyed IConfigurationSetCoordinator.TrySwitch(...).
  • builder.AddSwitchableJsonFile(...) registers a source; runtime control uses keyed ISwitchableJsonConfiguration. When ValueProtection is configured, matching clear-text values are protected before initial load and re-protected before observed runtime loads such as active-file reloads and source switches while the published configuration remains decoded. This is a load-bound, write-capable policy rather than a continuous watcher invariant, so matching clear text requires write access to the source file.
  • IConfigurationSetCoordinator.BindSwitchableJson(...) is an advanced binding API for already existing runtimes and is supported only for coordinators created by NetLib configuration-set registration; it is not the runtime switch API.
  • SwitchableJsonRegistrationOptions.CandidatePreparation accepts IJsonConfigurationSourcePreparation; common preparations come from JsonConfigurationCandidatePreparations.
  • ConfigurationValueCodecs provides the built-in persisted codecs. External adapters can compose a public ReversibleStringTransform with new ConfigurationValueCodec(...) and then use JsonConfigurationCandidatePreparations.Decode(...).
  • ConfigurationValueRecovery.RecoverProtectedValues(...) is an intentionally experimental recovery/debug helper that returns clear-text runtime values selected by registered NetLib ValueProtection rules. Copied configuration can be recovered elsewhere when the same non-host-bound protection context is available; unresolved protected envelopes throw with the configured codec name and guidance to run recovery on the original application server when host-bound state may be required. Using it requires explicit suppression of EVFRECOVERY001, and temporary recovery calls should be removed when finished.
  • ResetToMinimalConfigurationSources(...) and LogConfigurationResolution(...) are Generic Host configuration utilities and work through IHostApplicationBuilder.

Concrete coordinator, provider, runtime, pipeline, watcher, and persistence-format implementation types are intentionally internal. They are created and exposed through the public contracts above and are not required for normal consumer code.

Certificates

Eigenverft.NetLib.Infrastructure.Security.Certificates provides host-independent X.509 helpers:

  • SelfSignedCertificateFactory.Create(...) creates caller-owned self-signed certificates for TLS server/client, code-signing, and email-protection purposes using RSA or ECDSA profiles.
  • ManagedCertificateFile.LoadOrCreate(...) loads a managed PFX or returns a policy-controlled recovery certificate. CertificateRecoveryMode.PreserveExisting is the safe default and does not overwrite an existing unusable PFX.

The certificate APIs have no ASP.NET Core, Kestrel, SNI, configuration, or logging dependency.

Collection defaults and configuration overrides

The built-in configuration binder mutates initialized lists and dictionaries, so configured values normally append/merge with code defaults. NetLib provides one shared replacement layer instead of separate list/dictionary wrapper types:

using Eigenverft.NetLib.Infrastructure.Hosting.Configuration.CollectionOverrides;

configuration.GetSection("FilterOptions")
    .BindReplacingCollectionDefaults(options);

services
    .AddOptions<FilterOptions>()
    .BindReplacingCollectionDefaults("FilterOptions");

Missing list/dictionary keys keep code defaults. Present populated lists/dictionaries replace them. Present empty JSON arrays/objects clear initialized list/dictionary defaults. The native binder still performs the final binding and the native options integration still owns reload/change-token behavior; other collection shapes keep native binder semantics.

A5/A6 decision: NetLib does not recreate OptionsConfigOverridesDefaultsList<T> and OptionsConfigOverridesDefaultsDictionary<TKey,TValue>. Their shared intent is implemented once at the configuration-binding boundary.

IP normalization and CIDR matching

Eigenverft.NetLib.Infrastructure.Networking provides host-independent primitives:

  • IPAddress.Normalize() maps IPv4-mapped IPv6 to IPv4 and IPAddress.ToCanonicalString() produces stable canonical address text without IPv6 scope identifiers.
  • CidrNetwork.Parse(...) accepts convenience input such as 192.168.1.123/24, normalizes it to 192.168.1.0/24, and Contains(...) supports IPv4 and IPv6 matching.
  • IPAddress.Matches(...) keeps parsed-network caching and repeated IP/list match caching internally, including order-independent list keys, invalid-parse caching, and * match-all semantics.

These APIs have no ASP.NET dependency and are suitable for console apps, workers, desktop applications, and hosted services alike.

🎯 Target frameworks

The package ships dedicated assets for:

  • net8.0
  • net10.0

A .NET 9 consumer can use the compatible net8.0 asset.

📄 License

Licensed under the MIT License by Eigenverft.


Made with ❤️ by Eigenverft

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 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.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.20264.60239-qa 0 8/27/2026
1.0.20264.59777-qa 0 8/27/2026
1.0.20264.58155-qa 1 8/26/2026
1.0.20264.58123-qa 0 8/26/2026
1.0.20264.56966-qa 0 8/25/2026
1.0.20264.56956-qa 0 8/25/2026
1.0.20264.55738-qa 0 8/24/2026
1.0.20264.55730-qa 0 8/24/2026
1.0.20264.55715-qa 0 8/24/2026
1.0.20264.55655-qa 0 8/24/2026
1.0.20264.55529-qa 0 8/24/2026
1.0.20264.55515-qa 0 8/24/2026
1.0.20264.50793-qa 0 8/20/2026