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>