Repository navigation
Conversation
A personal token saved in Settings -> Credentials had no account data. So engrams did not know whose token it was (for GitHub: the login). A connector can now declare `userCredential.token.identity`: one bounded "who am I" request to one of its hosts. The orchestrator sends it with the token in `PutCredentialRequest.identity`. The coordinator runs it with the token before the seal, and keeps the display and workspace names. The account id stays empty, so a later OAuth connect to a different account still replaces the token. If the provider refuses the token, the token is not saved, and the route returns 400 with a plain message. GitHub declares `GET /user` -> `login`. The parse of the probe moves out of `parseOauth` into shared helpers, so the OAuth metadata probe and the token identity probe use one validation. The credentials form now shows the server's message instead of the status line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Mine" shows only pull requests whose author is the reader's GitHub login, as their connected GitHub credential names it. It uses the existing server author filter, and hides the Author filter while it is on. The rail uses the same per-browser choice, so the switcher and the ledger list the same pull requests. If GitHub is not connected, or the token was saved before engrams recorded the login, "Mine" says how to fix it instead of showing an empty list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RFC 6749 token endpoints answer in JSON, but GitHub answers in form
encoding unless the request asks for JSON. The coordinator could then not
read a GitHub token response ("token response was not JSON"). The token
request (code exchange, refresh, and server-side grants) now sends
`Accept: application/json`. This does not change the result for providers
that already answer in JSON.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A member could only paste a personal access token for GitHub. Now a member can click Connect in Settings -> Credentials and authorize the org's GitHub App to act as them. The user token has the App's permissions, limited to the member's own access. It expires after eight hours and the coordinator refreshes it, as it does for other personal OAuth credentials. - The `github_app` mint kind gets two optional fields, `client_id` and `client_secret`: the App's OAuth client. The admin enters them in the same GitHub setup form. Minting does not use them. - A mint connector has no org OAuth facet to reuse, so its `userCredential.oauth` is now a complete authorization-code flow of its own (`oauthFacet`). Its token URL may be on an acquisition host: GitHub exchanges codes on github.com, and adding github.com to `hosts` would open it to session injection. A personal flow can name no scopes, because GitHub ignores scopes for App user tokens. - GitHub's flow asks `GET /user` for the account: `id` is the account id and `login` the name, so the Reviews "Mine" filter works after connect. - Settings -> Credentials offers Connect only when the org has the app's client id and secret. Without them the button could only fail. - The GitHub setup panel shows the callback URL to set on the App, and the App manifest sets it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The GitHub guide gets the optional fifth setup step (the App's callback URL and OAuth client), the two ways a person connects their own GitHub account, and the Mine selection on the Reviews page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The identity probe of a pasted token reported every failure as "probe_failed", and the route answered each one with 400 "Check the token". A GitHub outage or a 5xx then told the user that the token was bad. The probe now reports HTTP 401 and 403 as "probe_rejected". The route answers a refusal with 400 and tells the user to check the token. It answers any other probe failure with 503 and tells the user to try again. The token is not saved in either case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # orchestrator/src/__tests__/me-oauth.test.ts
GitHub answers a dead refresh token with HTTP 200 and the error code "bad_refresh_token", not the RFC's "invalid_grant". The token grant reported that as "exchange_failed", which the refresh sweep treats as transient. A GitHub App user credential whose refresh token expired or was revoked then stayed "connected": the sweep retried each minute, and sessions got an expired token with no reconnect prompt. The grant now reports "bad_refresh_token" as "invalid_grant". The sweep marks the credential broken, and keeps the existing check that reloads the winner when a concurrent refresh moved the row version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nikhilunni
enabled stacked auto-merge
November 4, 2026 15:28
nikhilunni
previously approved these changes
Nov 4, 2026
nikhilunni
disabled stacked auto-merge
November 4, 2026 20:37
github-merge-queue
Bot
removed this pull request from the merge queue because a pull request earlier in the stack was removed
Nov 4, 2026
Contributor
Author
|
@engrams-agent Are you able to fix the merge conflicts? |
# Conflicts: # orchestrator/src/__tests__/connectors.test.ts # orchestrator/src/__tests__/me-oauth.test.ts # orchestrator/src/connectors/oauth-spec.ts # orchestrator/src/connectors/registry.ts # orchestrator/src/routes/me.ts
akwirick
enabled stacked auto-merge
November 10, 2026 19:39
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.
Stacked on #1719. Review and merge #1719 first; GitHub then changes this PR's base to
main.Summary
A member can now click Connect for GitHub in Settings → Credentials and authorize the org's GitHub App to act as them. They do not have to create or paste a personal access token. After connect, engrams knows their GitHub login, so the Reviews "Mine" filter from #1719 works at once.
Accept: application/json. This does not change the result for providers that already answer in JSON.github_appmint kind gets two optional fields,client_idandclient_secret: the App's OAuth client. The admin enters them in the same GitHub setup form. Minting does not use them.userCredential.oauthis now a complete authorization-code flow of its own (oauthFacet). This replaces the parse error "user-to-server OAuth is not implemented".github.com. Addinggithub.comtohostswould open it to session injection. The org facet keeps the strict rule.GET /user:idbecomes the account id andloginthe display name.callback_urls.What sessions get
A profile that acts as the launching person now uses the App user token when the person connected with OAuth. That token has the App's permissions, limited to the person's own access, and does not carry the permissions of a token the person made by hand. GitHub App user tokens expire after 8 hours. The coordinator refreshes them on the same path that refreshes the other personal OAuth credentials.
Upgrade notes
<origin>/api/v1/integrations/github/oauth/callback, generate a client secret, and enter the Client ID and client secret in the optional fields. An App made from the old manifest does not have the callback URL yet.Test plan
oauth_redirect: the token request sendsAccept: application/json.oauth_user_credentialspasses.engram-git-github: the descriptor test pins the two optional fields.cargo fmt --check,clippy -D warningsandhakari generate --diffpass. Innextest --no-fail-fast, 3223 of 3226 tests pass. The 3 that fail (engram-harness-codexdynamic-tool tests,engram-uffd-handlerstalled_alt_source_…) also fail on the base commit in my environment.true, a non-code grant, or a token host outside the declared hosts), GitHub authorize and callback through the personal flow, and Connect only when both client secrets are set. In the full suite, 2434 tests pass.connector-facetsfailed once on a 5.5 s timeout and passes alone.lib/githubSetup,components/integrationsandcomponents/settingspnpm build(leak and style lint, astro check)🤖 Generated with Claude Code