Project · ASP.NET companions
Verify tenant variation and private bypass
Use eight independent checks to keep tenant-specific public keys distinct and private calculations uncached.
All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.
Program.cs
VariationChecks.Run();
Domain/PublicCatalogCache.cs
public sealed record CatalogKey(string Tenant, string Topic);
public sealed class PublicCatalogCache {
private readonly Dictionary<CatalogKey, int> items = new();
private int generation;
public int Count => items.Count;
public int Public(string tenant, string topic) {
if (string.IsNullOrWhiteSpace(tenant) || string.IsNullOrWhiteSpace(topic)) throw new ArgumentException("Both key dimensions are required");
var key = new CatalogKey(tenant, topic);
if (!items.TryGetValue(key, out int value)) items[key] = value = ++generation;
return value;
}
public int Private() => ++generation;
public void Clear() => items.Clear();
}
Checks/VariationChecks.cs
public static class VariationChecks {
public static void Run() {
var cache = new PublicCatalogCache(); int checks = 0;
void Check(bool condition) { if (!condition) throw new Exception("Independent variation expectation failed"); checks++; }
int first = cache.Public("alpha", "csharp"); Check(first == 1);
Check(cache.Public("alpha", "csharp") == first);
Check(cache.Public("beta", "csharp") == 2);
Check(cache.Public("alpha", "dotnet") == 3);
Check(cache.Private() == 4 && cache.Private() == 5 && cache.Count == 3);
try { cache.Public("", "csharp"); throw new Exception("Invalid key accepted"); } catch (ArgumentException) { checks++; }
cache.Clear(); Check(cache.Count == 0);
Check(cache.Public("alpha", "csharp") == 6);
Console.WriteLine("variation checks:" + checks); Console.WriteLine("cache:domain only");
}
}
PublicVariation.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>