You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hub needs a way to represent a person independently of GitHub, Entra, or any future sign-in provider. Before adding sign-in, membership, or roles, Hub must be able to map a verified external identity to one Hub user and safely record which authentication configuration is active. This changeset adds that small persistence foundation, following the architecture in github/replica-internal#48.
What changes
This changeset introduces four records:
A Hub user is the provider-neutral identity used by Hub.
An external identity links one immutable provider identity, such as a GitHub numeric user ID, to exactly one Hub user.
An authentication provider revision records the fingerprint of a validated provider configuration and which revision is selected. Provider credentials and configuration values are not stored here.
A security audit records a small, typed description of identity changes without storing tokens, secrets, or raw provider data.
The first Prisma migration creates these records and enforces their uniqueness, ownership, and immutability rules in PostgreSQL. Database tests install the committed migration so they exercise the same constraints that a running Hub will use.
Identity creation and provider-revision changes are atomic with their success audits. If concurrent requests race, the kernel retries a small fixed number of times and converges on the existing identity or provider revision instead of creating conflicting records. Provider validation and other network work happen before the database transaction.
This PR does not let anyone sign in yet. It does not add Hub sessions, membership or admission, OAuth or OIDC routes, product authorization, GitHub repository synchronization, publishing, or UI. Those capabilities build on this foundation in later changesets.
Storybook screenshots
No Storybook screenshots are required because this change does not alter UI or stories.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved critical validation gaps allow credentials to be persisted, generated identity mappings to be overridden, and provider settings to be stored with mismatched digests.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Valid multibyte identity tuples can exceed PostgreSQL’s B-tree entry limit and roll back creation, while copied transaction runners prevent race tests from validating production isolation and conflict handling.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Identity fields still accept NULs and lone surrogates, risking database failures and wrong-user resolution, while credential-filtering, retry-exhaustion, and final-audit rollback tests remain incomplete.
No open issues 🎉
4 previously missed issues
In code that hasn't changed since last review
Reject NUL characters and lone surrogates in issuer and subject
issuer and subject accept NUL characters and lone UTF-16 surrogates. NUL causes database failures, while UTF-8 encoding maps distinct subjects such as x\uD800 and x\uDC00 to identical bytes, risking resolution to the wrong user. Reject both at this boundary and test those rejections while still allowing valid surrogate pairs.
Test rollback when the final success-audit write fails
The rollback tests stop before the success-audit write, so they do not cover failure at the final step of either transaction. Add migration-backed cases through the production runners that fail this audit and verify that new state rolls back, any previous provider selection is preserved, and exactly one terminal failure audit is added. Same gap in hub/server/domains/identity/validate-and-persist-provider-revision/index.ts:123.
Test provider revision retry exhaustion and failure audit
No provider-revision test exhausts the retry budget, so neither the ProviderRevisionConflictError conversion nor the terminal persist_failed audit with reason retry_exhausted is covered. Add a database case whose transaction always throws IdentityTransactionConflictError, and assert three attempts, that error type, exactly one failure audit with the expected reason, and no new revision.
Test credential rejection and safe metadata acceptance
The utility's tests cover size, type, and depth limits but never exercise credential-shaped values or secret-bearing keys. Add representative rejection cases and acceptance cases for ordinary issuer URLs and safe metadata such as tokenEndpoint, so changes to these checks cannot silently expose credentials or block valid audits.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Issuer and subject parsing accepts U+0000, which PostgreSQL cannot store, causing both the identity transaction and its failure audit to fail without leaving an audit record.
thrownewError("JSON values cannot contain credential or key material.")
}
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
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.
Why
Hub needs a way to represent a person independently of GitHub, Entra, or any future sign-in provider. Before adding sign-in, membership, or roles, Hub must be able to map a verified external identity to one Hub user and safely record which authentication configuration is active. This changeset adds that small persistence foundation, following the architecture in github/replica-internal#48.
What changes
This changeset introduces four records:
The first Prisma migration creates these records and enforces their uniqueness, ownership, and immutability rules in PostgreSQL. Database tests install the committed migration so they exercise the same constraints that a running Hub will use.
Identity creation and provider-revision changes are atomic with their success audits. If concurrent requests race, the kernel retries a small fixed number of times and converges on the existing identity or provider revision instead of creating conflicting records. Provider validation and other network work happen before the database transaction.
This PR does not let anyone sign in yet. It does not add Hub sessions, membership or admission, OAuth or OIDC routes, product authorization, GitHub repository synchronization, publishing, or UI. Those capabilities build on this foundation in later changesets.
Storybook screenshots
No Storybook screenshots are required because this change does not alter UI or stories.