Repository navigation
Conversation
GitHub login admits an invitation by comparing lower(users.email) with the
lower-cased verified GitHub emails, and `facility instance bootstrap`
stores the owner email in lower case. POST /v1/members instead looked the
invited address up with an exact, case-sensitive match and stored it as
typed. Re-inviting someone as "Jane@Example.com" after "jane@example.com"
therefore created a second user with a second membership instead of
updating the existing one, and while neither account was linked to GitHub
that person's login failed with identity_conflict ("Multiple Facility users
match verified GitHub emails").
Normalize the invited address the same way login does, look it up with
lower(email), and store new invitations in lower case.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
POST /v1/memberslooks up the invited user witheq(users.email, body.email)(case-sensitive) and stores the email exactly as typed. GitHub sign-in (routes/auth.ts) admits invitations by comparinglower(users.email)with lower-cased verified emails, andfacility instance bootstraplower-cases the owner email.Failure scenario: an admin invites
jane@acme.com, then re-invitesJane@Acme.comto change her role. A secondusersrow and membership are created instead of updating the first. If Jane has not signed in yet, her GitHub sign-in then fails with403 identity_conflict("Multiple Facility users match verified GitHub emails"); if she has, the role change silently lands on an orphan account.Fix
Export the existing
normalizedEmailfromauth/identity-provider.tsso invitations use the same normalization as sign-in: the lookup islower(users.email) = normalized, and new invitations are stored lower-cased.Tests
test/identity-provider.test.ts:it.eachcase fornormalizedEmail.test/member-invite-email.integration.test.ts(new): a re-invite in different case updates the same user (oneusersrow, new role); a legacy mixed-case row is still matched; a new invitation is stored lower-cased.Commands run
biome check(2.5.2) on the changed files: clean. Vitest/tsc not run locally (no Postgres/Docker test stack here); relying on CI.