Problem
completeGitHubWebOAuth/createSessionFromGitHubToken (src/auth/github-oauth.ts) and the device-flow poll path fetch a real GitHub user-to-server token during login, use it exactly once (GET https://api.github.com/user, to verify identity), and then discard it — createSessionForGitHubUser never receives or stores the raw token, only the resulting login/scopes/metadata. loopover-mcp login (packages/loopover-mcp/bin/loopover-mcp.js) only persists the loopover-minted opaque session token locally, never a GitHub-API-usable one. Confirmed via the GitHub App's Permissions tab (Loopover ORB, App ID 4139483) that Contents/Pull requests/Issues/Checks/Workflows are already Read & write, so the token this flow could produce is already capable of everything AMS needs — the gap is purely that it's thrown away.
Area
src/auth/github-oauth.ts, src/auth/security.ts (createSessionForGitHubUser, session storage), the auth session D1 table/schema.
Proposal
Persist the raw GitHub user-to-server token, encrypted at rest, associated with the session record — not in plaintext in the same row as everything else. Expose it via a new session-scoped endpoint (e.g. POST /v1/auth/github/token or similar, gated by the same session bearer auth every other authenticated route already requires) that returns the current live GitHub token for the calling session, for a CLI/AMS process to fetch on demand rather than needing it baked into the session payload returned at login time.
Concrete requirements:
- Encrypt the token at rest (this repo already has secret-handling conventions elsewhere — reuse them, don't invent a new encryption scheme).
- Never log the raw token — audit events, error messages, and telemetry must follow the same "no credential material" discipline already enforced for wallet/hotkey material elsewhere in this codebase.
revokeSession (already exists) must also invalidate/delete the stored GitHub token, not just the loopover session.
- The new token-retrieval endpoint must not be reachable by the static "mcp"/"api" shared-secret identities — session-only.
Deliverables
Resources
src/auth/github-oauth.ts (completeGitHubWebOAuth, createSessionFromGitHubToken)
src/auth/security.ts (createSessionForGitHubUser, revokeSession)
packages/loopover-mcp/bin/loopover-mcp.js:2698 (login), the device-flow poll path
Boundaries
This is the foundational piece the rest of this milestone depends on — #[refresh issue] and #[CLI issue] are both blocked by this. Security-sensitive: touches live credential storage for existing users. Maintainer-only for now.
maintainer-only — assigned JSONbored.
Problem
completeGitHubWebOAuth/createSessionFromGitHubToken(src/auth/github-oauth.ts) and the device-flow poll path fetch a real GitHub user-to-server token during login, use it exactly once (GET https://api.github.com/user, to verify identity), and then discard it —createSessionForGitHubUsernever receives or stores the raw token, only the resultinglogin/scopes/metadata.loopover-mcp login(packages/loopover-mcp/bin/loopover-mcp.js) only persists the loopover-minted opaque session token locally, never a GitHub-API-usable one. Confirmed via the GitHub App's Permissions tab (Loopover ORB, App ID 4139483) that Contents/Pull requests/Issues/Checks/Workflows are already Read & write, so the token this flow could produce is already capable of everything AMS needs — the gap is purely that it's thrown away.Area
src/auth/github-oauth.ts,src/auth/security.ts(createSessionForGitHubUser, session storage), the auth session D1 table/schema.Proposal
Persist the raw GitHub user-to-server token, encrypted at rest, associated with the session record — not in plaintext in the same row as everything else. Expose it via a new session-scoped endpoint (e.g.
POST /v1/auth/github/tokenor similar, gated by the same session bearer auth every other authenticated route already requires) that returns the current live GitHub token for the calling session, for a CLI/AMS process to fetch on demand rather than needing it baked into the session payload returned at login time.Concrete requirements:
revokeSession(already exists) must also invalidate/delete the stored GitHub token, not just the loopover session.Deliverables
revokeSession/logout deletes the stored tokenResources
src/auth/github-oauth.ts(completeGitHubWebOAuth,createSessionFromGitHubToken)src/auth/security.ts(createSessionForGitHubUser,revokeSession)packages/loopover-mcp/bin/loopover-mcp.js:2698(login), the device-flow poll pathBoundaries
This is the foundational piece the rest of this milestone depends on — #[refresh issue] and #[CLI issue] are both blocked by this. Security-sensitive: touches live credential storage for existing users. Maintainer-only for now.
maintainer-only — assigned JSONbored.