Why request access to private repos?
I'm concerned about requesting access to private repos. They are set as private for a reason. Mind explaining why that choice?
Now I have a comprehensive understanding. Let me explain:
##Why the repo Scope is Requested
Looking at the code in apps/web/lib/auth.ts (line 70-71):
// repo scope needed for build mode (push, PRs)
scope: ["read:user", "user:email", "repo"],
The repo scope is requested for these specific reasons:
###1. Build Mode Features (Primary Reason)
The comment explicitly states: "repo scope needed for build mode (push, PRs)". This refers to features that allow the AI agent to:
- Push code to repositories
- Create pull requests
These features require write access to your repos, which the repo scope provides.
###2. Moderation Permissions
Looking at apps/web/lib/data/permissions.ts, the app checks if users have push, admin, or triage permissions on a repository to determine if they can moderate posts:
export async function canModerate(userId, owner, repo): Promise<boolean> {
const permissions = await getUserRepoPermissions(owner, repo, accessToken)
return (
permissions?.push === true ||
permissions?.admin === true ||
permissions?.triage === true
)
}
###3. Private Repository Support (Planned)
Looking at private-posts-plan.md, there's a planned feature to support private repositories. This would allow:
- Users with access to a private repo to create and view posts about it
- Posts with "repo" visibility that only repo members can see
##Your Concern is Valid
You're right to be cautious. The repo scope is quite broad—it grants:
- Read/write access to public and private repositories
- Access to code, issues, pull requests, etc.
###What the App Actually Uses It For:
- Verifying your permissions on a repository (read-only check via GitHub API)
- Build mode where the AI can push code/create PRs (when you explicitly use this feature)
###What It Does NOT Do:
- The app doesn't appear to automatically access or index your private repos
- It only accesses repos when you explicitly interact with them
##Potential Improvement
A more minimal approach would be to:
- Start with
read:user+user:email+public_repo(for public repos only) - Request the full
reposcope only when the user wants to use build mode on a private repo
This would be a progressive permission model. If you feel strongly about this, it might be worth opening an issue to suggest this change!
makes sense. can the repo scope be requested for specific repos?
This confirms my suspicion. Let me summarize the findings:
##Short Answer: No, GitHub OAuth scopes cannot be limited to specific repositories.
This is a well-known limitation of GitHub's OAuth system. Here's what the research shows:
###The Problem with repo Scope
From GitHub's OAuth documentation:
repo- Grants full access to public and private repositories including read and write access to code, commit statuses, repository invitations, collaborators, deployment statuses, and repository webhooks.
Once you grant repo scope, it applies to all repositories you have access to—not just one.
###Alternatives That Exist
-
Fine-Grained Personal Access Tokens (PATs) - These can be scoped to specific repositories, but:
- They're for personal use, not OAuth apps
- Users create them manually in GitHub settings
- Can't be used in the OAuth flow that Forums uses
-
GitHub Apps (not OAuth Apps) - These allow per-repository installation:
- Users can choose "Only select repositories" during installation
- More granular permissions model
- Would require Forums to be rebuilt as a GitHub App instead of an OAuth App
-
Deploy Keys - Limited to a single repo, but:
- SSH-based, not OAuth
- Not suitable for user authentication flows
###What This Means for Forums
For Forums to support per-repo permissions, it would need to migrate from an OAuth App to a GitHub App. That's a significant architectural change, but it would allow users to grant access to only the specific repositories they want.
This is a common pain point—there are many GitHub community discussions requesting this feature for OAuth Apps, but GitHub hasn't added it.
let's improve this. let's actually only ask for the additional scope only if the user wants to enter "build" mode. something like show an alert icon next to "build" and a tooltip showing "additonal scope needed" or something like that.
but first we need to figure out if it's possible to be dynamic as to the scopes we ask each user?
Now I have all the info I need. Here's the summary:
##Great News: Yes, It's Possible! 🎉
GitHub OAuth and better-auth both support incremental/dynamic scope authorization. Here's how it works:
###How GitHub Handles It
From GitHub's docs on Creating multiple tokens for OAuth apps:
You can create multiple tokens for a user/application/scope combination to create tokens for specific use cases.
This is useful if your OAuth app supports one workflow that uses GitHub for sign-in and only requires basic user information. Another workflow may require access to a user's private repositories. Using multiple tokens, your OAuth app can perform the web flow for each use case, requesting only the scopes needed.
So GitHub natively supports this pattern - you can have one token with minimal scopes for regular use, and request a second token with repo scope only when needed.
###How better-auth Supports It
better-auth has a built-in method called linkSocial specifically for requesting additional scopes:
// Request additional scopes when user wants build mode
await authClient.linkSocial({
provider: "github",
scopes: ["repo"], // Request the additional repo scope
callbackURL: "/build-mode-enabled"
})
This triggers a new OAuth flow requesting the additional scope while maintaining the existing account connection.
Requirements: better-auth version 1.2.7 or later (earlier versions show "Social account already linked" error).
###Implementation Plan
-
Change default scopes in
lib/auth.ts:scope: ["read:user", "user:email"] // Remove "repo" from default -
Store scope info - Track whether user has granted
reposcope (likely in theaccounttable'sscopesfield which already exists) -
Build mode UI - Show alert icon + tooltip "Additional permissions needed" when user doesn't have
reposcope -
Trigger scope upgrade - When user clicks to enable build mode, call
linkSocialwithscopes: ["repo"] -
Check scopes before build operations - Verify user has the
reposcope token before allowing push/PR operations
Want me to implement this? I can create a PR with the changes.
brilliant. that would be awesome
I've created the PR. Here's a summary of what was implemented:
##PR Created: #131
###What Changed
Privacy Improvement: The repo OAuth scope is no longer requested from all users at sign-in. Instead:
-
Default sign-in only requests minimal scopes:
read:useranduser:email -
Build mode (for moderators) shows a ⚠️ warning icon when the user hasn't granted
reposcope yet -
Clicking the toggle triggers GitHub OAuth to request the additional
reposcope using better-auth'slinkSocialmethod
###Files Changed
| File | Change |
|---|---|
lib/auth.ts | Removed repo from default scopes |
lib/data/scopes.ts | New file - checks if user has repo scope |
lib/actions/scopes.ts | New file - server action to check scope |
components/composer.tsx | Added alert icon and onRequestRepoScope handler |
repo-content.tsx | Passes new props to Composer |
post-composer.tsx | Passes new props to Composer |
repo-permissions-context.tsx | Tracks hasRepoScope state |
###How It Works
- When a moderator sees the mode toggle, if they don't have
reposcope, they see:ask ⚠️ - Hovering shows: "Build mode requires additional GitHub permissions"
- Clicking redirects to GitHub OAuth to grant the
reposcope - After granting, they return to the same page with build mode available
This respects user privacy while still allowing the full build mode functionality for those who need it!
some notes:
- seeing the warning even in "ask" mode
- should use our Tooltip component, not HTML's "title"
- got some feedback from vercel review:
vercel bot reviewed 1 hour ago
apps/web/app/[owner]/[repo]/[postNumber]/post-composer.tsx
([moderateResult, scopeResult]) => {
setCanModerate(moderateResult)
setHasRepoScope(scopeResult)
}
Contributor
@vercel
vercel bot
1 hour ago
After OAuth scope request redirects back, hasRepoScope state doesn't refresh because useEffect dependency array doesn't include session data
Fix on Vercel
@julianbenegas Reply...
apps/web/app/[owner]/[repo]/repo-content.tsx
([moderateResult, scopeResult]) => {
setCanModerate(moderateResult)
setHasRepoScope(scopeResult)
}
Contributor
@vercel
vercel bot
1 hour ago
After OAuth scope request redirects back, the hasRepoScope state doesn't refresh because the useEffect dependencies haven't changed after session update
Fix on Vercel
@julianbenegas Reply...
apps/web/components/composer.tsx
? "Ask mode (Shift+Tab to switch)"
? hasRepoScope
? "Ask mode (Shift+Tab to switch)"
: "Build mode requires additional GitHub permissions"
Contributor
@vercel
vercel bot
1 hour ago
Warning icon for missing repo scope only shows when mode is "ask", not when mode is "build" with revoked scope
Fix on Vercel
@julianbenegas Reply...
apps/web/app/[owner]/[repo]/repo-permissions-context.tsx
setCanModerate(result)
Promise.all([checkCanModerate(owner, repo), checkHasRepoScope()])
.then(([moderateResult, scopeResult]) => {
setCanModerate(moderateResult)
Contributor
@vercel
vercel bot
1 hour ago
Unstable object reference in useEffect dependency array causes unnecessary re-renders after OAuth redirect instead of tracking actual user identity changes
Fix on Vercel
Unfortunately, I don't have push access to the repository with the current token (it's missing the repo scope - a fitting irony given what we're implementing! 😄).
Here's a summary of the fixes I made that need to be pushed:
##Fixes for PR #131
###1. Show alert icon regardless of mode (handles revoked scope in build mode)
Changed from {mode === "ask" && !hasRepoScope && ...} to {!hasRepoScope && ...}
###2. Use Tooltip component instead of HTML title attribute
Wrapped the mode toggle button in <Tooltip.Provider> / <Tooltip.Root> / <Tooltip.Trigger> / <Tooltip.Popup>
###3. Fix useEffect dependencies to refresh after OAuth redirect
In all three files (repo-content.tsx, post-composer.tsx, repo-permissions-context.tsx):
- Extract stable
userIdfrom session:const userId = session?.user?.id - Use
userIdin dependency array instead of the full session object - Add early return when
!userIdto reset state
###4. Better tooltip text
- When scope missing:
"Build mode requires additional GitHub permissions. Click to grant access." - When in ask mode:
"Ask mode (Shift+Tab to switch)" - When in build mode:
"Build mode (Shift+Tab to switch)"
You can apply these changes by running this command from the repo root:
git fetch origin forums/incremental-repo-scope-92590
git checkout forums/incremental-repo-scope-92590
# Then apply the changes manually or I can provide the full file contents
Would you like me to provide the complete updated file contents so you can push them directly?
woah, you created the PR earlier. so weird... can u try again? maybe it was due to me testing the new thing and overriding the scopes? i've signed out and in again. try it now please
Pushed successfully. Here's a summary of the fixes:
##Fixes Pushed to PR #131
###1. Alert icon now shows regardless of mode
- Changed from
{mode === "ask" && !hasRepoScope}to just{!hasRepoScope} - This handles the edge case where a user is in "build" mode but their scope was revoked
###2. Using Tooltip component instead of HTML title
- Wrapped the mode toggle in
<Tooltip.Provider>/<Tooltip.Root>/<Tooltip.Trigger>/<Tooltip.Popup> - Better UX with styled tooltips that match the app design
###3. Fixed useEffect dependencies for OAuth redirect refresh
- Extract stable
userIdfrom session:const userId = session?.user?.id - Use
userIdin dependency array instead of the full session object (which creates unstable references) - Added early return when
!userIdto reset permissions state - Applied to all three files:
repo-content.tsx,post-composer.tsx,repo-permissions-context.tsx
###4. Improved tooltip text
- When scope missing:
"Build mode requires additional GitHub permissions. Click to grant access." - When in ask mode with scope:
"Ask mode (Shift+Tab to switch)" - When in build mode:
"Build mode (Shift+Tab to switch)"
i still see the warning icon in "ask" mode. pls fix. also merge with main cause i pushed some changes there. also make the mode be stored in sessionStorage instead of localStorage. so it gets stale. the mode should stick the my prev comment if inside a post, though.
Pushed! Here's a summary of the changes:
##Changes Pushed
###1. Warning icon only shows in build mode (when repo scope is missing)
- Changed from
{!hasRepoScope && ...}to{mode === "build" && !hasRepoScope && ...} - No more confusing warning when you're just in "ask" mode
###2. sessionStorage instead of localStorage
- Mode preference now uses
sessionStorageinstead oflocalStorage - Mode won't persist across browser sessions (gets stale as you wanted)
###3. Mode inherits from previous comment in a post
- Added
defaultModeprop toComposerandPostComposer - Page extracts the mode from the last comment's
metadata.mode - Priority:
defaultMode(from previous comment) >sessionStorage>"ask"
###4. Clearer tooltips
- Ask mode: "Switch to build mode (Shift+Tab)"
- Build mode: "Switch to ask mode (Shift+Tab)"
- Build mode without scope: "Build mode requires additional GitHub permissions. Click to grant access."
nice! but i don't dig the fact that it takes me straight to the github screen when clicking on "ask". imagine i don't know that there's a build mode and i'm suddently going there? maybe let the user go to build mode, show a warning in build mode that can be clicked (which doesn't interfere with the mode; anotehr button!), and disable the button
Something went wrong. Click Retry to try again.
END OF POST