From c7075167a47c787acb594783e90d5d81a70424ea Mon Sep 17 00:00:00 2001 From: Mario Alberto Arce Date: Wed, 22 Jul 2026 20:00:49 -0600 Subject: [PATCH 1/5] feat(websample): reference the Features Framework and feature packages - Add project references to the Features engine and its abstractions - Add project references to the Cache feature and BitFaster provider - Add project references to the Sanitization feature and its abstractions --- samples/WebSample/WebSample.csproj | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/samples/WebSample/WebSample.csproj b/samples/WebSample/WebSample.csproj index ed3757b..01327e7 100644 --- a/samples/WebSample/WebSample.csproj +++ b/samples/WebSample/WebSample.csproj @@ -6,6 +6,13 @@ + + + + + + + From 919b746a2cb97a7979fe77714018b04b2b0fc34e Mon Sep 17 00:00:00 2001 From: Mario Alberto Arce Date: Wed, 22 Jul 2026 20:00:53 -0600 Subject: [PATCH 2/5] feat(websample): wire the Features Framework into the sample host - Register the Features Framework via auto discovery, opting in the Cache and Sanitization modules - Register the BitFaster cache provider so the cache demo has an active backend - Run the Features Framework pipeline hook after building the app - Map new demo endpoints for the cache and sanitization features --- .../Extensions/ServiceCollectionExtensions.cs | 28 ++++++++++++++++++- .../Extensions/WebApplicationExtensions.cs | 17 +++++++++++ samples/WebSample/Program.cs | 6 ++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/samples/WebSample/Extensions/ServiceCollectionExtensions.cs b/samples/WebSample/Extensions/ServiceCollectionExtensions.cs index 2bf27fd..2578390 100644 --- a/samples/WebSample/Extensions/ServiceCollectionExtensions.cs +++ b/samples/WebSample/Extensions/ServiceCollectionExtensions.cs @@ -1,3 +1,8 @@ +using PowerCSharp.Feature.Cache; +using PowerCSharp.Feature.Cache.BitFaster; +using PowerCSharp.Feature.Sanitization; +using PowerCSharp.Features; + namespace WebSample.Extensions; /// @@ -15,7 +20,7 @@ public static IServiceCollection AddSwaggerServices(this IServiceCollection serv services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new() { Title = "PowerCSharp Web Sample API", Version = "v1" }); - + // Include XML comments var xmlFile = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); @@ -24,4 +29,25 @@ public static IServiceCollection AddSwaggerServices(this IServiceCollection serv return services; } + + /// + /// Registers the PowerCSharp Features Framework via auto-discovery, opting in the Cache and + /// Sanitization feature modules. Also registers the BitFaster cache provider so the Cache demo + /// endpoint has an active backend rather than the NoOp floor. + /// + /// The IServiceCollection instance + /// The application configuration + public static IServiceCollection AddPowerCSharpFeatures(this IServiceCollection services, IConfiguration configuration) + { + services.AddPowerFeatures(configuration, options => + { + options.ScanAssemblies( + typeof(CacheFeatureModule).Assembly, + typeof(SanitizationFeatureModule).Assembly); + }); + + services.AddCacheBitFaster(configuration); + + return services; + } } diff --git a/samples/WebSample/Extensions/WebApplicationExtensions.cs b/samples/WebSample/Extensions/WebApplicationExtensions.cs index f19b965..5dd4b2a 100644 --- a/samples/WebSample/Extensions/WebApplicationExtensions.cs +++ b/samples/WebSample/Extensions/WebApplicationExtensions.cs @@ -1,5 +1,7 @@ +using PowerCSharp.Features; using WebSample.Samples.Core; using WebSample.Samples.Extensions; +using WebSample.Samples.Features; using WebSample.Samples.Helpers; using WebSample.Samples.Utilities; @@ -24,6 +26,17 @@ public static void UseSwaggerUI(this WebApplication app) }); } + /// + /// Runs the PowerCSharp Features Framework pipeline hook — resolves each enabled feature's + /// middleware (none, for Cache/Sanitization) and bridges the Sanitization engine's + /// configuration for non-DI call sites. + /// + /// The WebApplication instance + public static void UsePowerCSharpFeatures(this WebApplication app) + { + app.UsePowerFeatures(); + } + /// /// Maps all PowerCSharp demo endpoints using dedicated endpoint classes /// @@ -55,5 +68,9 @@ public static void MapPowerCSharpDemoEndpoints(this WebApplication app) app.MapGet("/demo/collection", CollectionSampleEndpoints.GetDemoData); app.MapGet("/demo/dictionary", DictionarySampleEndpoints.GetDemoData); app.MapGet("/demo/unix-timestamp", UnixTimestampSampleEndpoints.GetDemoData); + + // Features Framework Samples + app.MapGet("/demo/cache", CacheSampleEndpoints.GetDemoDataAsync); + app.MapGet("/demo/sanitization", SanitizationSampleEndpoints.GetDemoData); } } diff --git a/samples/WebSample/Program.cs b/samples/WebSample/Program.cs index 1a5b17c..56679e9 100644 --- a/samples/WebSample/Program.cs +++ b/samples/WebSample/Program.cs @@ -5,8 +5,14 @@ // Add Swagger services builder.Services.AddSwaggerServices(); +// Add the PowerCSharp Features Framework (Cache + Sanitization feature modules) +builder.Services.AddPowerCSharpFeatures(builder.Configuration); + var app = builder.Build(); +// Run the Features Framework pipeline hook (bridges the Sanitization engine's configuration) +app.UsePowerCSharpFeatures(); + // Map all PowerCSharp demo endpoints app.MapPowerCSharpDemoEndpoints(); From 2201c36e6268db5546beee1b49f954634a1497f7 Mon Sep 17 00:00:00 2001 From: Mario Alberto Arce Date: Wed, 22 Jul 2026 20:00:57 -0600 Subject: [PATCH 3/5] feat(websample): add cache feature demo endpoint - Demonstrate a cache miss followed by a set and hit round trip - Resolve the cache service via dependency injection --- .../Samples/Features/CacheSampleEndpoints.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 samples/WebSample/Samples/Features/CacheSampleEndpoints.cs diff --git a/samples/WebSample/Samples/Features/CacheSampleEndpoints.cs b/samples/WebSample/Samples/Features/CacheSampleEndpoints.cs new file mode 100644 index 0000000..d6cd91b --- /dev/null +++ b/samples/WebSample/Samples/Features/CacheSampleEndpoints.cs @@ -0,0 +1,39 @@ +using PowerCSharp.Feature.Cache.Abstractions; + +namespace WebSample.Samples.Features; + +/// +/// Sample endpoint demonstrating the Cache feature, resolved via the Features Framework +/// (PowerCSharp.Feature.Cache + PowerCSharp.Feature.Cache.BitFaster). +/// +public static class CacheSampleEndpoints +{ + private const string DemoKey = "websample:cache:demo"; + + /// + /// Gets cache demo data: a cache miss, a write, and the resulting hit, using the + /// DI-resolved (the active BitFaster provider, or NoOp if the + /// Cache feature is disabled via configuration). + /// + /// The cache service, injected by the Features Framework. + /// Demo results showing a cache miss followed by a set/hit round-trip. + public static async Task GetDemoDataAsync(ICacheService cache) + { + // Start from a clean slate so this endpoint is idempotent across repeated calls. + await cache.RemoveAsync(DemoKey); + + var missResult = await cache.GetWithResultAsync(DemoKey); + + var value = $"cached at {DateTimeOffset.UtcNow:O}"; + await cache.SetAsync(DemoKey, value, TimeSpan.FromMinutes(1)); + + var hitResult = await cache.GetWithResultAsync(DemoKey); + + return new + { + providerNote = "Backed by PowerCSharp.Feature.Cache.BitFaster; falls back to a NoOp cache if the Cache feature is disabled.", + beforeSet = new { hit = missResult.IsSuccess, value = missResult.Value }, + afterSet = new { hit = hitResult.IsSuccess, value = hitResult.Value, provider = hitResult.ProviderName } + }; + } +} From 087e301931f6e081cdf6fbfdb17fe548c67245d9 Mon Sep 17 00:00:00 2001 From: Mario Alberto Arce Date: Wed, 22 Jul 2026 20:01:01 -0600 Subject: [PATCH 4/5] feat(websample): add sanitization feature demo endpoint - Demonstrate log injection, file path traversal, sensitive data masking, and regex injection sanitization - Resolve the sanitization service via dependency injection --- .../Features/SanitizationSampleEndpoints.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 samples/WebSample/Samples/Features/SanitizationSampleEndpoints.cs diff --git a/samples/WebSample/Samples/Features/SanitizationSampleEndpoints.cs b/samples/WebSample/Samples/Features/SanitizationSampleEndpoints.cs new file mode 100644 index 0000000..7009a7d --- /dev/null +++ b/samples/WebSample/Samples/Features/SanitizationSampleEndpoints.cs @@ -0,0 +1,57 @@ +using PowerCSharp.Feature.Sanitization.Abstractions; + +namespace WebSample.Samples.Features; + +/// +/// Sample endpoint demonstrating the Sanitization feature, resolved via the Features Framework +/// (PowerCSharp.Feature.Sanitization). +/// +public static class SanitizationSampleEndpoints +{ + /// + /// Gets sanitization demo data covering all four concerns: log injection (CWE-117), + /// file-path traversal (CWE-22), sensitive-data masking (CWE-200), and regex-injection/ReDoS + /// validation (CWE-400/CWE-730), using the DI-resolved . + /// + /// The sanitization service, injected by the Features Framework. + /// Demo results for each sanitization concern. + public static object GetDemoData(ISanitizationService sanitizer) + { + const string maliciousLogInput = "user logged in\r\nADMIN: fake audit entry injected"; + const string maliciousPath = "../../etc/passwd"; + const string secretPayload = "password=SuperSecret123, token=abcdef0123456789"; + const string unsafeRegexPattern = "(a+)+$"; // classic catastrophic-backtracking shape + + var logResult = sanitizer.SanitizeForLogInjection(maliciousLogInput); + var pathResult = sanitizer.SanitizeForFilePath(maliciousPath); + var sensitiveResult = sanitizer.SanitizeForSensitiveData(secretPayload); + var regexResult = sanitizer.SanitizeForRegexInjection(unsafeRegexPattern); + + return new + { + note = "Falls back to a NoOp sanitizer (inputs pass through unchanged) if the Sanitization feature is disabled.", + logInjection = new + { + original = maliciousLogInput, + sanitized = logResult.SanitizedValue, + wasModified = logResult.WasModified + }, + filePathTraversal = new + { + original = maliciousPath, + wasRejected = pathResult.IsRejected + }, + sensitiveDataMasking = new + { + original = secretPayload, + masked = sensitiveResult.SanitizedValue, + wasModified = sensitiveResult.WasModified + }, + regexInjection = new + { + original = unsafeRegexPattern, + wasRejected = regexResult.IsRejected + } + }; + } +} From ce95a3bcd4e983ebf95d03dc9bc986d60366b444 Mon Sep 17 00:00:00 2001 From: Mario Alberto Arce Date: Wed, 22 Jul 2026 20:01:05 -0600 Subject: [PATCH 5/5] chore(websample): enable the cache and sanitization features - Add a PowerFeatures configuration section enabling both features - Configure the BitFaster provider and capacity for the cache demo --- samples/WebSample/appsettings.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/samples/WebSample/appsettings.json b/samples/WebSample/appsettings.json index 4d56694..e9990ae 100644 --- a/samples/WebSample/appsettings.json +++ b/samples/WebSample/appsettings.json @@ -5,5 +5,15 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "PowerFeatures": { + "Cache": { + "Enabled": true, + "Provider": "BitFaster", + "Capacity": 1000 + }, + "Sanitization": { + "Enabled": true + } + } }