From 74edb30a2db8d034da6a3bd8d0ca5ec9b197d135 Mon Sep 17 00:00:00 2001 From: Heimdall Date: Wed, 11 Nov 2026 10:15:45 +0000 Subject: [PATCH] Test the IPv6 /64 and mapped-IPv4 keying of the registration budget Co-Authored-By: Claude Sonnet 5.5 --- .../RegistrationLimitTests.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/Bifrost.Web.Tests/RegistrationLimitTests.cs b/tests/Bifrost.Web.Tests/RegistrationLimitTests.cs index 84940f7..cbda9c4 100644 --- a/tests/Bifrost.Web.Tests/RegistrationLimitTests.cs +++ b/tests/Bifrost.Web.Tests/RegistrationLimitTests.cs @@ -163,6 +163,34 @@ public sealed class RegistrationBudgetTests(RegistrationBudgetFactory factory) : Assert.Equal(HttpStatusCode.OK, other.StatusCode); } + [Fact] + public async Task An_IPv6_caller_owns_its_slash_64_and_a_mapped_IPv4_shares_its_IPv4_key() + { + using var client = factory.CreateClient(); + string[] sameSlash64 = ["2001:db8:1:2::1", "2001:db8:1:2::2", "2001:db8:1:2:aaaa::3", "2001:db8:1:2:ffff:ffff:ffff:ffff", "2001:db8:1:2::5"]; + var statuses = new List(); + foreach (var peer in sameSlash64) + { + using var response = await ChallengeAsync(client, peer); + statuses.Add(response.StatusCode); + } + + Assert.Equal( + [HttpStatusCode.OK, HttpStatusCode.OK, HttpStatusCode.OK, HttpStatusCode.TooManyRequests, HttpStatusCode.TooManyRequests], + statuses); + using var otherSlash64 = await ChallengeAsync(client, "2001:db8:1:3::1"); + Assert.Equal(HttpStatusCode.OK, otherSlash64.StatusCode); + + for (var i = 0; i < 3; i++) + { + using var ok = await ChallengeAsync(client, "203.0.113.50"); + Assert.Equal(HttpStatusCode.OK, ok.StatusCode); + } + + using var mapped = await ChallengeAsync(client, "::ffff:203.0.113.50"); + Assert.Equal(HttpStatusCode.TooManyRequests, mapped.StatusCode); + } + [Fact] public async Task Challenge_and_register_spend_one_budget_and_a_refused_register_creates_nothing() {