## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Connectors catalog lets people give agents tools or connect agents to conversations. > - GitHub put these two uses behind one card and an extra choice. > - People should choose the connection they need from the catalog. > - This pull request keeps GitHub for tools and adds GitHub Code Review Bot as a separate card. > - Each card opens its setup directly. Both use the existing connection code. ## Linked Issues or Issue Description **What existing behavior does this improve?** GitHub connector discovery and setup. **Current behavior** With chat connectors enabled, GitHub opens a menu that asks whether to use tools or create a bot. Saved tools and bots share the same catalog entry. **Proposed behavior** GitHub opens tool account access. GitHub Code Review Bot opens agent selection. Saved bots and drafts appear under the bot card. Chat-disabled instances show only GitHub tools. **Reason and benefit** The catalog names the two uses and removes an extra setup choice. The bot keeps the existing GitHub provider, credentials, endpoint IDs, setup steps, and runtime. **Additional context** Related work: https://github.com/paperclipai/paperclip/pull/12843 and https://github.com/paperclipai/paperclip/pull/14594 established GitHub account identity. This change preserves that tool flow. No duplicate catalog split was found. ## What Changed - Split the generated app definitions into GitHub tools and GitHub Code Review Bot. Reuse the existing GitHub logo and channel method. - Open bot setup directly, including old resume and reconnect links. - Put existing bot endpoints and drafts under the bot card. Hide duplicate internal chat applications. - Keep pasted GitHub URLs mapped to the tool connection. - Add seven Storybook states for the catalog, saved connections, disabled chat, both setup paths, mobile, and light mode. - Fix narrow-screen bot rows so the label cannot overlap status and setup actions. - Update catalog, route, browser, and API tests, plus the GitHub connector guide. ## Verification - [Hosted Storybook](https://d1p6rlowie26tp.cloudfront.net/storybook/branches/codex~2Fgithub-review-connection/?path=/story/connections-github-and-code-review-bot--catalog): seven states built from this branch. The deployment passed its public-file verification. - All GitHub checks pass on `d13a2cd53561645bb2a15c6f8e75a61a936d6459`. Two optional Storybook jobs skip under their normal trigger rules; the manual Storybook deployment passes. The branch has no merge conflicts. - Greptile: 5/5 on the current head, with no review comments or unresolved threads. - `pnpm -r typecheck`, `pnpm build`, `pnpm check:token-gates`, and `pnpm build-storybook` passed. The final Storybook fixture also passed UI typecheck and the hosted build. - Targeted catalog, URL matching, routing, grouping, brand, and chat UI contract tests passed. - GitHub provider browser tests: 2 passed. These cover direct tool setup and the bot setup and management lifecycle with provider responses mocked. - Embedded-browser test on an isolated local instance: opened both cards, selected an agent, saved a bot draft, and resumed the same endpoint under the bot card after a reload. - Storybook Tool Setup and Bot Setup assertions pass in the published preview. Chat Disabled assertions pass locally. Inspected mobile and light mode, including the draft-row layout and official GitHub marks. - Local full-suite limitation: `pnpm test:run` was not clean. A cross-company route assertion failed in the aggregate run and passed in isolation; a workspace-runtime test reached its 30-second hook timeout. Some isolated database reruns skipped when the embedded-PostgreSQL availability probe failed. The local aggregate was stopped after CI completed. The corresponding full CI suites pass all 360 tool-access tests and all 162 workspace-runtime tests. - No live GitHub authorization or installation was performed. The isolated instance correctly stopped at the cloud enrollment or public HTTPS prerequisites. ## Risks - Low scope: catalog presentation and routing change. There is no database migration or provider credential change. - Existing GitHub bot URLs now open bot setup directly. The tool route remains `/apps/connect?source=github`. - The bot remains behind the existing chat-connectors feature flag. Existing endpoints retain `provider: github`. - Channel applications are represented by endpoint rows. Regression tests cover legacy bot applications, tools, active bots, and drafts together. ## Model Used OpenAI GPT-6 through Codex, with reasoning, code execution, and embedded-browser tools. The exact deployed model ID, context window size, and reasoning setting are not exposed to this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
9.3 KiB
GitHub managed connection
GitHub is a Paperclip Cloud-managed GitHub App connection with an advanced PAT compatibility method. Cloud owns the fixed public OAuth callback and signed webhook inbox; provider tokens are sealed to the enrolled instance and stored only in its existing encrypted secret system.
Catalog entries
GitHub connects an account for repository tools, Git, and gh, and opens
Access → Connect directly. GitHub Code Review Bot connects one agent to a
GitHub App for pull-request reviews and mentions, and opens Choose agent directly.
The bot entry follows the Chat Connectors experimental setting.
Both entries reuse the existing GitHub integrations. Bot endpoints retain the
github provider identity and existing setup, reconnect, and management URLs;
saved bot connections and drafts appear under GitHub Code Review Bot. GitHub
repository and MCP URLs still resolve to the ordinary GitHub tool connection.
Self-hosted setup
The Access step uses Continue to open the local setup screen. Continue to GitHub on that screen starts the provider handoff. The first button does not imply that the browser is leaving Paperclip yet.
A self-hosted instance needs one Paperclip Cloud approval before its first managed connection. After approval, setup returns to step 2 and continues to GitHub without another instance approval or a service restart.
If an unapproved enrollment link expires, return to setup and select Continue. Paperclip asks the server for a valid link. The server reuses a live pending enrollment or replaces an expired one; this does not revoke or repeat an existing instance approval.
Identity resolution
Every MCP call, gh invocation, native Git operation, checkout, health check,
and webhook binding uses the same order:
- An active dedicated GitHub grant for the current agent.
- The active personal GitHub grant owned by the run's
responsibleUserId. - For automated work without a responsible user, a personal grant only when an existing standing delegation names the agent.
- Legacy
GH_TOKEN/GITHUB_TOKENonly when no managed GitHub connection is configured for the company.
An unavailable or ambiguous managed identity fails visibly. It never falls
through to another person, an organization credential, or a legacy token.
Agent grants are company-scoped, have exactly one subjectAgentId, cannot be
organization defaults, and are installed only for that agent.
The connection installation is the credential owner's consent boundary. A
personal setup may target every agent or a selected set, and runtime resolution
considers only an enabled, active connection installed for the current agent.
Within that boundary, Paperclip treats the run's server-resolved
responsibleUserId as its credential principal, including for automated work;
agents cannot choose or spoof this field. The owner must still be an active
non-viewer company member at each use. A standing delegation is needed only
when a run genuinely has no responsible user.
Credential lifecycle
The production, staging, and development GitHub Apps deliberately disable
user-to-server token expiration. The resulting long-lived access token is
checked with GitHub's /user endpoint every 30 days, together with installation
and repository summary refresh. Routine continuity requires no browser visit.
If GitHub returns an expiring access token and rotating refresh token instead, Paperclip stores both encrypted and:
- refreshes at least one hour before access expiry;
- forces a rotation at least every 30 days while the instance is active;
- serializes refresh through the existing database refresh lease and compare- and-swap update;
- atomically advances both secret values before clearing the lease;
- retries one forced refresh after a provider
401.
Only an unrecoverable provider invalidation marks a grant
needs_reauthorization. Installation removal or suspension is reported as an
installation-health failure, not as token expiry.
Repository access
OAuth completion verifies /user, every page of /user/installations, and every
page of each installation's accessible repositories. Setup remains incomplete
until at least one installation and repository are available. Paperclip stores
the authenticated username and a grant-scoped display snapshot containing only
repository IDs, full names, installation IDs, and private-repository flags. GitHub stays authoritative:
this snapshot never authorizes repository access.
The permissions page shows repositories across authorized accounts by default. Use the account filter and search to narrow the list. The list scrolls after about ten rows and marks known private repositories with a lock. Configure on GitHub opens the app account chooser so users can add or update organization access. Refresh access after changing the selection. Older snapshots omit the private flag until refreshed. If a legacy grant lacks its app chooser URL, Load GitHub configuration refreshes access and recovers the app slug from GitHub installation metadata. The page does not substitute a single-installation settings URL for the account chooser.
The permissions page shows the authenticated GitHub account and the complete accessible repository list. Refresh access reloads it from GitHub. Older grants and grants invalidated by newer installation lifecycle events prompt for a refresh instead of presenting a stale list. The page links to GitHub's installation management page. Selected repositories are recommended; all- repository access retains its warning.
Fresh local test-drives use production Paperclip Cloud. Instance enrollment
and provider enablement are separate: enrollment alone does not enable GitHub
OAuth. Production must advertise the github.code profile (see Cloud's
docs/github-connector-deploy-bootstrap.md). If it is unavailable, setup
preserves the sign-in intent and offers a retry instead of silently switching
to a personal access token. A successful retry preserves the chosen audience.
GitHub Actions tools
Managed and PAT connections request X-MCP-Toolsets: default,actions for MCP
discovery and invocation. GitHub's default catalog excludes Actions; granting
Actions permissions alone does not expose workflow tools. Existing connections
can use Refresh actions after upgrading to discover the added tools.
The normal catalog, access, approval, and quarantine rules still apply.
To dispatch an existing workflow, use actions_run_trigger with
method: "run_workflow", the repository owner and name, workflow_id, ref,
and any workflow inputs. The workflow must declare workflow_dispatch.
The GitHub App installation or fine-grained PAT needs Actions: Read and
write for the repository. App owners set that permission on the GitHub App
registration; installation owners must approve an increase before it takes
effect. Paperclip's action controls do not grant GitHub permissions.
The tool also supports rerunning and cancelling runs and deleting run logs.
It retains GitHub's destructive classification. Read tools include
actions_list, actions_get, and get_job_logs.
Provider references: MCP toolset configuration and workflow dispatch permissions.
Webhooks
Paperclip Cloud verifies X-Hub-Signature-256 against the exact bounded request
body before parsing, deduplicates by X-GitHub-Delivery, and persists a minimal
normalized event before returning 202. Raw webhook payloads are discarded.
When registering an active binding, Paperclip sends the current user token only
inside the signed, payload-bound broker request so Cloud can verify access to
that exact installation; Cloud neither logs nor persists that proof token.
Deliveries fan out independently to every enrolled instance bound to the GitHub
installation and are sealed to each instance's public key.
The instance polls with backoff, stores a company-scoped idempotency receipt, and acknowledges only successful applications. A merged pull request updates its matching external-object snapshot and immediately runs the existing merge- confirmation resolver. It wakes the assignee only when that interaction's continuation policy requests it; unrelated Paperclip issues are not closed. The periodic GitHub merge sweep remains the reconciliation fallback.
Installation lifecycle events refresh or invalidate installation summaries and remove obsolete Cloud bindings. Activity records contain event identifiers and outcomes but no webhook content. GitHub webhook content is never first-party telemetry.
Run projection
The resolved token is leased at run start as an audited class-3 secret and is projected only into the child process:
GH_TOKEN,GITHUB_TOKEN, and an internal credential-helper environment key;GIT_TERMINAL_PROMPT=0;- process-scoped
GIT_CONFIG_COUNT/KEY_n/VALUE_nentries that clear ambient helpers, install agithub.com-only helper, and rewrite GitHub SSH remotes to HTTPS; - author and committer identity using
<numeric-id>+<login>@users.noreply.github.com.
Tokens never appear in arguments, URLs, files, logs, events, or model context,
and the projection never replaces HOME.
Cloud deployment and exact GitHub App registration settings live in
paperclip-cloud/docs/github-connector-deploy-bootstrap.md.