Repository navigation
app-v1 Issue #3: GitHub App OAuth + NextAuth 登录链路 #164
Copy link
Copy link
Closed
Labels
acceptedAccepted for development (Module 4 trigger)Accepted for development (Module 4 trigger)accepted-by-claudeClaude self-acceptance after clarify loop (Module 4 trigger, distinct from maintainer accepted)Claude self-acceptance after clarify loop (Module 4 trigger, distinct from maintainer accepted)enhancementNew feature or requestNew feature or requestsize:MOne moduleOne modulestage:failedA module failed; needs maintainer triageA module failed; needs maintainer triagetest:retry-2Auto-retry 2/3: re-running Module 4 with test feedbackAuto-retry 2/3: re-running Module 4 with test feedbacktriageNewly opened; awaiting triage botNewly opened; awaiting triage botverify:retry-1Verify retry 1/3: self-verify failed, re-running Module 4 to fixVerify retry 1/3: self-verify failed, re-running Module 4 to fix
Description
Background
App v1 Issue #3 — 在 #162 Postgres schema 基础上加 GitHub App OAuth + NextAuth.js 登录链路(PRD docs/prd-app-v1.md §4.1 + §7 Day 0-30 第 4 项 + US-001)。这是后续 webhook (#4) / 仪表盘 (#6) 的鉴权地基 — 没有 session 就无法做 tenant 隔离 (S8)。
GitHub App 已注册(App ID 4331480, Client ID Iv23li3dWlH3ZoRIIKtW, slug gitautodev),5 个凭证已存为 repo secrets:APP_ID, APP_CLIENT_ID, APP_CLIENT_SECRET, APP_PRIVATE_KEY, WEBHOOK_SECRET。本 Issue 只用其中 APP_CLIENT_ID + APP_CLIENT_SECRET。
Context budget paths
允许 AI 读写:
app/src/auth/(新建 config.ts + route handler)app/src/app/api/auth/(NextAuth route handler)app/src/app/login/(登录页)app/src/app/dashboard/(最小 dashboard 占位,验证 session 能用)app/src/lib/github-app.ts(GitHub App installation_token helpers,为 feat(#3): Add CONTRIBUTING.md with local-poll setup steps #4 准备)app/src/middleware.ts(受保护路由)app/package.json(加依赖)app/.env.example(加新 env 变量)app/next.config.mjs(如需)docs/app-architecture.md(更新 §4.1 鉴权段引用实际文件)
禁止扫:py/、rust/、.github/workflows/ 非 app-ci、.github/actions/、scripts/。
Files + lines
app/package.json(MODIFY)
- 新增 deps:
next-auth@^4.24.7(已有,确认)@auth/core@^0.37.0(NextAuth v4 新 peer)jose@^5.9.0(JWT 签名/验签 — GitHub App installation_token JWT 用)
- 不加 prisma / 老的 next-auth v5 beta
app/src/auth/config.ts(NEW)
- 导出
authOptions: NextAuthOptions - provider:
GitHubProvider({ clientId, clientSecret, authorization: { params: { scope: 'read:user user:email repo' } } }) - callback URL 由 NextAuth 自动生成
/api/auth/callback/github - adapter: 不用(v1 简化 — 用户表暂用 Postgres
tenants表,但 v1 OAuth 只放 session,不写 tenants 行;那留给 webhook installation 事件 feat(#3): Add CONTRIBUTING.md with local-poll setup steps #4 落表) - session strategy:
"jwt"(无 session DB 表,简化) - jwt
secret:process.env.NEXTAUTH_SECRET - callbacks:
jwt({ token, profile }):profile 是 GitHub user info;token.githubId = profile.id; token.githubLogin = profile.loginsession({ session, token }):把 githubId/githubLogin 注入 session.user
- 加
'server-only'顶部 import
app/src/app/api/auth/[...nextauth]/route.ts(NEW)
- Next.js App Router 标准写法:
import NextAuth from "next-auth"; import { authOptions } from "@/auth/config"; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
app/src/auth/with-app-installer.ts(NEW,GitHub App helpers)
getAppInstallationsForUser(accessToken: string): Promise<{id:number, account:{login:string, type:string}}[]>— 调用GET /user/installations(GitHub App 用户级 token 才能 list)getAppInstallationToken(installationId: number): Promise<string>— 用 APP_PRIVATE_KEY 签 JWT → POST /app/installations/{id}/access_tokens → 缓存到 50 分钟(S11)signAppJwt(): string— APP_ID + APP_PRIVATE_KEY → RS256 JWT,9 分钟有效期- 不实现 installation_events webhook(留给 feat(#3): Add CONTRIBUTING.md with local-poll setup steps #4)
app/src/lib/github-app-jwt.ts(NEW)
- 用
jose签 GitHub App JWT:import { SignJWT, importPKCS8 } from "jose";
- 私钥从
process.env.APP_PRIVATE_KEY读(PEM 文本,不是 base64 — secret 管理用 base64 存储,运行时 base64 decode → PEM) - 缓存
importPKCS8结果避免每次重算
app/src/middleware.ts(NEW)
- Next.js middleware 保护
/dashboard/*+/settings/* - 未登录 → 重定向
/login?callbackUrl=<original> - 用
next-auth的getToken({ req })读 JWT,不查 DB
app/src/app/login/page.tsx(NEW)
- 简单 client component:一个 "Sign in with GitHub" 按钮 →
signIn("github", { callbackUrl: "/dashboard" }) - 引导文案说明会请求
reposcope
app/src/app/dashboard/page.tsx(NEW,最小占位)
- 服务端组件,读
getServerSession() - 显示
欢迎, {session.user.name}+GitHub ID: {session.user.githubId} - 列出该用户的 App installations(调用
getAppInstallationsForUser(session.accessToken))— 没安装则显示 install URLhttps://github.com/apps/gitautodev/installations/new - 不做完整仪表盘 UI(留给 Bug: Login button does not respond to clicks on Safari 18.2 #6)
app/.env.example(MODIFY)
- 加:
NEXTAUTH_URL=http://localhost:3000(开发环境)NEXTAUTH_SECRET=(注释:openssl rand -base64 32)APP_ID=(注释:from GitHub App settings)APP_CLIENT_ID=APP_CLIENT_SECRET=APP_PRIVATE_KEY=(注释:base64-encoded PEM,base64 -i app.private-key.pem)
app/src/app/page.tsx(MODIFY)
- 把 disabled "Sign in with GitHub" 按钮改成
<Link href="/login">或直接signIn调用
docs/app-architecture.md(MODIFY)
- §4.1 鉴权段加:
NextAuth GitHubProvider → /api/auth/* → JWT session → middleware 守护 /dashboard - 引用实际文件路径
app/src/auth/config.ts
Acceptance criteria
-
pnpm install && pnpm lint && pnpm typecheck && pnpm build在app/下全部成功(无 NEXTAUTH_SECRET 也能跑 build) -
/login页面渲染,有 "Sign in with GitHub" 按钮 - 点按钮重定向到 GitHub OAuth 授权页(需要 APP_CLIENT_ID/SECRET env 配置后真实跑通,CI 不验证)
- 回调
/api/auth/callback/github走通后写入 JWT cookienext-auth.session-token -
/dashboard服务端组件能读 session,显示 GitHub login - 未登录访问
/dashboard被中间件拦截重定向/login?callbackUrl=/dashboard -
app/src/auth/config.ts用next-authGitHubProvider,scope 含repo -
app/src/lib/github-app-jwt.ts用jose签 RS256 JWT,9 分钟有效期 -
app/src/auth/with-app-installer.ts的getAppInstallationToken缓存 token ≤ 50 分钟(S11) - 不打印任何 token / secret / cookie 值到日志(S4)
-
.env.example新增 6 个 env 变量占位(NEXTAUTH_URL/SECRET + APP_ID/CLIENT_ID/CLIENT_SECRET/PRIVATE_KEY) -
docs/app-architecture.md§4.1 鉴权段引用实际文件路径 - CI 跑通:app-ci workflow lint + typecheck + build 全绿
Context / non-goals
- 不实现 OAuth callback 后落表
tenants(v1 简化,session-only;tenants 行在 webhook installation 事件 feat(#3): Add CONTRIBUTING.md with local-poll setup steps #4 时落) - 不实现多 installation 切换 UI(v1 单 user 单 installation 简化 — PRD R7;多 installation 留 v2)
- 不实现 BYOK 配置页(make the app faster #8)
- 不实现 webhook installation 事件(feat(#3): Add CONTRIBUTING.md with local-poll setup steps #4)
- 不接 Stripe(Add dark mode toggle to navbar #10)
- 不做完整仪表盘(Bug: Login button does not respond to clicks on Safari 18.2 #6)— dashboard 页只显示 session + installations list
- 不在 CI 测真实 GitHub OAuth(需要真实 APP_CLIENT_ID/SECRET + 浏览器交互;CI 只验证编译过 + 中间件逻辑单元测试)
- session strategy 选
jwt而非database— 避免引入sessions表 + adapter 复杂度(v2 多 installation 时再评估迁移到 database strategy) - 不实现 refresh token 续期(GitHub OAuth token 不会过期,除非用户手动撤销;v2 评估用 GitHub App refresh flow)
References
docs/prd-app-v1.md§4.1(分层 — NextAuth 是 API Routes 层的鉴权 gate)docs/prd-app-v1.mdUS-001(验收标准对齐)docs/prd-app-v1.md§6 S11(installation_token 缓存 ≤ 50 分钟)- NextAuth.js v4 docs: https://next-auth.js.org/providers/github
- GitHub App JWT 文档: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
jose库 docs: https://github.com/panva/jose- 现有
app/package.json([app-v1] Postgres schema + Drizzle ORM(5 张表 + migration + db client) #162 已装 next-auth@4.24.7)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
acceptedAccepted for development (Module 4 trigger)Accepted for development (Module 4 trigger)accepted-by-claudeClaude self-acceptance after clarify loop (Module 4 trigger, distinct from maintainer accepted)Claude self-acceptance after clarify loop (Module 4 trigger, distinct from maintainer accepted)enhancementNew feature or requestNew feature or requestsize:MOne moduleOne modulestage:failedA module failed; needs maintainer triageA module failed; needs maintainer triagetest:retry-2Auto-retry 2/3: re-running Module 4 with test feedbackAuto-retry 2/3: re-running Module 4 with test feedbacktriageNewly opened; awaiting triage botNewly opened; awaiting triage botverify:retry-1Verify retry 1/3: self-verify failed, re-running Module 4 to fixVerify retry 1/3: self-verify failed, re-running Module 4 to fix
Activity
github-actions commentedon Jul 18, 2026
Triage: Accepted ✅
This is a well-specified feature request for app-v1 Issue #3 — GitHub App OAuth + NextAuth login pipeline. The issue has clear context budget paths, per-file specs, and detailed acceptance criteria. No clarification needed.
Summary of understood scope
app/src/auth/config.ts) — NextAuth with GitHubProvider, JWT session strategy, githubId/githubLogin in token+session callbacksapp/src/app/api/auth/[...nextauth]/route.ts) — standard App Router catch-allapp/src/auth/with-app-installer.ts,app/src/lib/github-app-jwt.ts) — installation listing, JWT signing (RS256, 9min expiry), token caching (≤50min per S11)app/src/middleware.ts) — protects/dashboard/*+/settings/*, redirects unauthenticated to/loginapp/src/app/login/page.tsx) — "Sign in with GitHub" button withreposcopeapp/src/app/dashboard/page.tsx) — server component showing session + installations listapp/.env.example,app/package.json,app/src/app/page.tsx,docs/app-architecture.md) — 6 new env vars, next-auth/jose deps, updated homepage link, architecture doc updateNon-goals are explicitly called out (no tenants table write, no webhook installation handling, no BYOK, no Stripe, no full dashboard). Session strategy is JWT (no DB adapter). The
app/directory CI (lint + typecheck + build) must pass.Moving into the pipeline.
github-actions commentedon Jul 18, 2026
Triage: Accepted ✅
This is a well-specified feature request for app-v1 Issue #3 — GitHub App OAuth + NextAuth login pipeline. The issue has clear context budget paths, per-file specs, and detailed acceptance criteria. No clarification needed.
Summary of understood scope
app/src/auth/config.ts) — NextAuth with GitHubProvider, JWT session strategy, githubId/githubLogin in token+session callbacksapp/src/app/api/auth/[...nextauth]/route.ts) — standard App Router catch-allapp/src/auth/with-app-installer.ts,app/src/lib/github-app-jwt.ts) — installation listing, JWT signing (RS256, 9min expiry), token caching (≤50min per S11)app/src/middleware.ts) — protects/dashboard/*+/settings/*, redirects unauthenticated to/loginapp/src/app/login/page.tsx) — "Sign in with GitHub" button withreposcopeapp/src/app/dashboard/page.tsx) — server component showing session + installations listapp/.env.example,app/package.json,app/src/app/page.tsx,docs/app-architecture.md) — 6 new env vars, next-auth/jose deps, updated homepage link, architecture doc updateNon-goals are explicitly called out (no tenants table write, no webhook installation handling, no BYOK, no Stripe, no full dashboard). Session strategy is JWT (no DB adapter). The
app/directory CI (lint + typecheck + build) must pass.Moving into the pipeline.
akushonkamen commentedon Jul 18, 2026
🤖 Claude self-acceptance (M8 workload=standard).
accepted-by-claudeapplied — Module 4 develop-gate will pick this up. Maintainer may override withrejected.akushonkamen commentedon Jul 18, 2026
🚀 Development branch pushed:
claude/issue-164-app-v1-issue-3-github-app-oauth-nextauth@b67caa09a7ff. PR: #167akushonkamen commentedon Jul 18, 2026
🔄 Verify retry 1/3
code-generate.yml will auto-trigger on the
verify:retry-1label,fetch this comment as the prior-verify-report, and re-run Module 4 to
address the verify failure.
github-actions commentedon Jul 18, 2026
🤖 AI Initial Review:
postedThe AI has posted an initial review as a PR comment. This is an
advisory review only — AI does NOT approve. A CODEOWNER must
perform the final human review and approve (PRD §6).
Next: Module 9 (merge queue) triggers on approved + green checks.
14 remaining items
akushonkamen commentedon Jul 18, 2026
✅ Verify passed — Module 6 (test) engaged. PR: #167
feat(app): GitHub App OAuth + NextAuth login (Issue #164)
docs(app-architecture): add auth flow file references to §4.1
github-actions commentedon Jul 18, 2026
❌ Test:
failedTest framework: NONE
This project has no test framework installed (no jest/vitest/mocha in devDependencies), no test config (no jest.config.* / vitest.config.), and no test files (.test.*, .spec.) anywhere in the codebase. The
app/package.jsonhas notestscript.Existing CI checks (run as surrogate "tests")
These are build-time checks, not acceptance tests — they verify the code compiles and lints, but exercise none of the Issue #3 runtime behaviour (OAuth flow, middleware redirect, JWT signing, session injection, API call caching).
Acceptance criteria coverage
Summary
Zero test coverage for all 13 acceptance criteria. 0/13 covered by automated tests. The project needs at least a test framework (vitest or jest) and unit/integration tests for the NextAuth config, middleware, JWT helper, installation token cache, and page rendering.
akushonkamen commentedon Jul 18, 2026
🔄 Auto-retry 2/3
Failure summary (prior Module 6 run)
Test framework: NONE
This project has no test framework installed (no jest/vitest/mocha in devDependencies), no test config (no jest.config.* / vitest.config.), and no test files (.test.*, .spec.) anywhere in the codebase. The
app/package.jsonhas notestscript.Existing CI checks (run as surrogate "tests")
code-generate.yml will auto-trigger on the
test:retry-2label,fetch this comment as the prior-test-report, and re-run Module 4 to
fix the failure.
github-actions commentedon Jul 18, 2026