From 028bc2fdf6fd2e8cfabcb63aaae962fb29eac1a2 Mon Sep 17 00:00:00 2001 From: Heimdall Date: Wed, 11 Nov 2026 11:17:25 +0000 Subject: [PATCH] Registration: sign-up form with proof-of-work and a no-JS time-lock fallback (#56) --- docs/oidc-issuer.md | 2 +- docs/registration-gates.md | 78 +- .../Configuration/RegistrationOptions.cs | 14 +- .../Features/ConceptVotes/CastRequestGuard.cs | 29 - .../Membership/BifrostIdentityService.cs | 49 +- .../Registration/NativeRegistration.cs | 123 +++ .../RegistrationChallengeService.cs | 105 +- .../Features/Registration/RegistrationPage.cs | 176 ++++ .../Registration/RegistrationRateLimit.cs | 19 +- .../Features/Shared/RequestOriginGuard.cs | 41 + .../Shared/StartupConfigurationValidator.cs | 13 + src/Bifrost.Web/Pages/Mill/Vote.cshtml.cs | 4 +- src/Bifrost.Web/Program.cs | 189 +++- .../Fixtures/registration-page-harness.cjs | 64 ++ .../RegistrationFormTests.cs | 897 ++++++++++++++++++ .../RegistrationGateTests.cs | 6 +- 16 files changed, 1681 insertions(+), 128 deletions(-) delete mode 100644 src/Bifrost.Web/Features/ConceptVotes/CastRequestGuard.cs create mode 100644 src/Bifrost.Web/Features/Registration/NativeRegistration.cs create mode 100644 src/Bifrost.Web/Features/Registration/RegistrationPage.cs create mode 100644 src/Bifrost.Web/Features/Shared/RequestOriginGuard.cs create mode 100644 tests/Bifrost.Web.Tests/Fixtures/registration-page-harness.cjs create mode 100644 tests/Bifrost.Web.Tests/RegistrationFormTests.cs diff --git a/docs/oidc-issuer.md b/docs/oidc-issuer.md index 06dff5f..d6cb22d 100644 --- a/docs/oidc-issuer.md +++ b/docs/oidc-issuer.md @@ -59,7 +59,7 @@ There are no development or ephemeral keys in the host. Key files are provisione | `preferred_username` | `NormalizedBifrostIdentity` (minted once; there is no rename path) | | `name` | `DisplayName`, else `BifrostIdentity` | -No e-mail, no Heimdall id, no GitHub id, and no membership detail leaves Bifrost. +No e-mail, no Heimdall id, no GitHub id, and no membership detail leaves Bifrost. A native account's verified address, once that is built, stays inside Bifrost as sign-in recovery and is never a claim (`registration-gates.md`, Email verification). ## Who may sign in diff --git a/docs/registration-gates.md b/docs/registration-gates.md index 1b9278a..87f5db0 100644 --- a/docs/registration-gates.md +++ b/docs/registration-gates.md @@ -41,10 +41,39 @@ server verifies the protection, the expiry and the hash, and spends the id once. (`Bifrost:Registration:Limits`, 10 per minute by default, IPv6 by /64, over budget is 429 with Retry-After). An attacker with many addresses can still fill the set; that is the accepted bound, the same as oidc-issuer.md. -Not built: the sign-up form. No registration page exists today; the endpoint is the contract and the only client is a -script. The form (solving in a worker, a `