Files
PaperClipAI/doc/connections/GITHUB.md
T
DottaandPaperclip ed2c22ea8c feat(connections): simplify dedicated GitHub App setup (#15416)
## Thinking Path

> - Paperclip manages agent work and the tools each agent can use.
> - GitHub bots need their own App identity and restricted repository
access.
> - Manual App configuration and repeated setup gates make that
connection hard to finish.
> - GitHub can create an App from a manifest, but people must approve
creation and repository access.
> - Each Paperclip stack should own configuration, credentials,
signature verification, and task admission.
> - This change uses Cloud as an encrypted callback and event gateway,
then completes setup in the stack.
> - GitHub review bots have their own experimental setting. Chat
connector opt-in does not control them.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Dedicated GitHub App setup, bot settings, and task-scoped GitHub
replies.

**Current behavior**

Users must configure an App, copy credentials, repeat repository
selection, and complete manual verification gates. Review settings are
hard to scan. Mentions in descriptions can be missed, and automatic
completion text can produce an extra GitHub comment.

**Proposed behavior**

Choose an agent and connect GitHub under a personal account or
organization. GitHub asks for creation and installation consent.
Paperclip resumes the same draft, stores secrets locally, imports
access, verifies delivery, and opens Settings. Each accepted request has
one editable App-owned comment for progress and results. Review
assessments produce deterministic checks for the reviewed commit.

**Breaking changes**

GitHub bots require their own default-off experimental opt-in. The
setup-method and delegated-agent screens are removed. Per-person
automatic-run flags remain readable but are replaced by author filters.
Existing connections, direct webhooks, saved restrictions, and manual
existing-App recovery remain supported.

Companion gateway:
https://github.com/paperclipai/paperclip-cloud/pull/688 (merged). The
roadmap and related PRs were checked; no duplicate dedicated-App wizard
was found.

## What Changed

- Add an independent **GitHub review bots** setting across the catalog,
routes, identity admission, and task controls. Existing bots continue
running when the UI setting is off.
- Replace setup with Choose agent and Connect GitHub. Support personal
and organization owners, inline low-trust conversion, saved drafts,
known organization suggestions, automatic completion, and same-App
recovery.
- Keep manifests, OAuth PKCE, credential exchange, vault storage,
installation verification, and original webhook-signature validation in
the stack. Use the Cloud sealed gateway for public callbacks and
outbound local delivery.
- Add resumable owner metadata in migration 0323. Retry a failed
registration renewal through the same durable replacement rather than
creating another App route.
- Support authorized mentions in issue and PR bodies, comments, inline
comments, and review summaries. Preserve attachments, edited-source
identity, duplicate protection, and lifecycle invalidation. Filter
requests explicitly addressed to another connected bot.
- Give agents task-scoped review, comment, and update tools. Update one
working comment through progress and final output. Close coalesced
requests and recover delayed acknowledgements, including deleted earlier
working comments. Preserve automatic replies for legacy connections
without saved review configuration. Preserve partial publication
evidence and quarantine uncertain automatic fallbacks without blocking
Board messages or questions.
- Reorganize Settings and Access with rich slash-skill instructions,
numeric passing scores, clear automation controls, formal-review
tooltips, member and contributor sections, and verified App branding
links. Preserve invalid score drafts and automation choices across tabs.
- Paginate repositories in 20-row batches with search and a true
connection-wide toggle. Batch verification at GitHub's 500-ID token
limit. Keep saved repository overrides while hiding their editor.
- Give each review a detail URL that remains usable beyond the newest
100 records. Synchronize the manager OpenAPI contracts and add recovery,
authorization, UI, and browser regressions.
- Reconcile the current master branch and retain its agent avatar,
feature catalog, and extracted heartbeat preparation code. Preserve a
saved test-drive port and recover from an occupied high port.

## Verification

- Focused UI, independent experimental-setting, and CLI tests: 199
passed.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates`
passed. The broad local Vitest attempt was interrupted after resource
timeouts and stale expectations; the affected regressions passed focused
reruns. The latest-head full CI matrix passed, including all browser
shards, server/chat suites, builds, typechecking, canary packaging, and
Docker context integrity. A Docker Hub 429 required a CI retry; it
passed without changing the code.
- Final review repairs: 127 attachment/event tests and server typecheck
passed. All 13 final integration regressions passed under the normal CI
timeout, covering legacy reply compatibility, deleted coalesced
comments, inline-only review completion, progress edits, and native
final recovery. Restart-safe description/review attachments passed the
attachment suite.
- Final regressions: four reply/lifecycle tests, both native GitHub wait
tests, 171 feature-gate/reply-contract tests, the routed review preview,
and five scheduler/reply regressions passed. The final fixture repair
also passed all six setup-continuation cases and all three complete
chat-test shards in CI, covering terminal receipts and retries under the
normal CI timeout. One loaded-host receipt run exceeded its local
timeout; the exact case passed in an isolated rerun and the complete CI
shard.
- GitHub integration tests cover personal and organization setup, retry
recovery, edited mentions, attachment provenance, coalesced requests,
delayed acknowledgements, partial review writes, old review URLs, and
company boundaries.
- Browser qualification: both GitHub journeys, all five provider
setup/management journeys, and the GitHub uncertain-send recovery
journey passed. GitHub setup, reconnect, and task replies run with chat
disabled; chat enabled alone cannot expose GitHub bots. The disposable
qualification database was removed after testing.
- Earlier live qualification verified App-owned issue replies, native
slash-skill invocation, progress comment edits, and a 5/5 PR review with
a passing current-head check in the dedicated permissions-smoke
repository. These live checks did not use personal credentials as bot
execution authority.

## Risks

- Deploy the merged Cloud gateway protocol before the stack update. Each
callback and encrypted event must retain the original instance and
tenant binding.
- Migration 0323 uses idempotent column additions for test installations
that already applied the earlier draft migration number.
- A verified connection does not prove runtime isolation or a completed
review. Runtime checks remain separate.
- Required merge checks must be configured in GitHub. A passing numeric
score does not formally approve a PR; approval and request-changes tools
remain opt-in.
- Existing-App credentials cannot silently renew an uncertain manifest
exchange. Recovery preserves the existing App, draft, connection, and
agent.
- Repository changes save immediately. Global toggles affect all
currently available repositories, including unloaded rows, without
granting new installation access.
- A failed or uncertain tool write suppresses automatic fallback text;
the governed outbox retains its evidence. Deleted or replaced response
comments are not recreated through a personal credential fallback.
- GitHub logo upload remains an optional human action in GitHub App
settings. Runtime provisioning, delegated setup, screenshot publication,
and production push delivery remain deferred.

## Model Used

OpenAI Codex, based on GPT-6, with tool use and code execution. The
exact runtime model identifier and context size are not exposed in 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 references)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (focused suites; complete
test matrix is checked in CI)
- [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>
2026-10-09 17:01:20 -05:00

17 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 Settings → Experimental → GitHub review bots (enableGitHubReviewBots), which defaults to off. It is independent of Chat connectors: enabling one does not enable the other. Turning off the GitHub setting hides setup and management; existing bots keep running.

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.

Bot instructions and triggers

Bot Settings uses the shared Markdown editor for common and event-specific instructions. Type / and select a company skill to insert a saved skill link. Common instructions accompany every admitted GitHub task; event-specific instructions accompany that event. Selected skills are materialized for the run and explicitly invoked by the native Runner, subject to existing tool and isolation restrictions. The admitted configuration snapshot determines skill selection for each wake, including queued events. GitHub messages, repository content and other companies' skills cannot assign skills to the run.

Authorized @mentions remain available when Run automatically is on or off. The switch in Settings reveals the PR and issue event checkboxes. Access lists company members and external contributors separately. Author include/exclude filters in Settings control whose activity starts automatic work; there is no per-person automatic-run switch. Automatic events still require an authorized author and an enabled event. Legacy people[].automaticReviews values are accepted but ignored. External contributors additionally need Allow automatic runs for external contributors. Their restricted guest profile and sponsor requirements are unchanged.

The passing-score number field accepts a whole number from 1 to 5, defaulting to 5. Paperclip publishes a successful Paperclip Review check only after a complete assessment of the current commit meets the threshold; lower scores fail and incomplete assessments require action. To block merging, separately require this check from the dedicated App in GitHub branch protection or a ruleset. A new head commit needs its own check. Report-only mode publishes a neutral conclusion, which GitHub can accept for a required check; it does not enforce a score requirement. A passing score does not formally approve a PR. Approvals and change requests contains those optional agent permissions. Scheduling filters, ignored files, and inline-comment options have separate disclosures. The header shows the App identity, copyable mention, avatar download, and GitHub branding settings.

Self-hosted setup

The setup screen states the default access in one line, with Change for other choices. Continue to GitHub on that screen starts the provider handoff.

A self-hosted instance needs one Paperclip Cloud approval before its first managed connection. After approval, setup returns to the connect screen 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:

  1. An active dedicated GitHub grant for the current agent.
  2. The active personal GitHub grant owned by the run's responsibleUserId.
  3. For automated work without a responsible user, a personal grant only when an existing standing delegation names the agent.
  4. Legacy GH_TOKEN/GITHUB_TOKEN only 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

For the shared GitHub account connector, 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.

Dedicated agent Apps

The bot wizard uses Cloud gateway protocol version 2. The stack builds the private manifest for a personal account or organization. GitHub still asks the user to confirm creation and repository installation. The stack exchanges the returned manifest code directly with GitHub and stores every App secret in its vault, including the private key, client secret, and webhook verifier.

Cloud stores only opaque, instance-bound callback routes and encrypted callback claims. It does not exchange codes, track App or installation identity, store GitHub secrets, or interpret bot events. It forwards original webhook bytes, provider headers, and signature in an envelope sealed to the stack before writing the inbox. The stack decrypts and authenticates those bytes through its existing durable ingress. Only that local check can verify a connection or admit work. Shared-App account connectors keep the behavior described above.

Unverified gateway traffic has request, byte, pending-queue, retention and wake limits. Its transport deduplication includes the body and signature, so a forged request cannot occupy a real delivery's identifier. A ping received before its verifier reaches the vault remains queued for retry. Malformed and forged traffic is discarded after local verification. Installation returns only request a state refresh; the stack queries GitHub to establish installation authority.

OAuth state, PKCE, consent, repository discovery, recovery and lifecycle changes also stay in the stack. Interrupted single-use manifest exchanges require recovery of the existing App instead of a second creation. Direct webhook and manual existing-App recovery remain available. Connecting does not prove that an agent runtime can execute a review.

One editable response per request

After accepting authorized GitHub work, Paperclip posts Working on this… before starting the agent. Issue and PR discussion comments use the same GitHub comment API; inline-review conversations receive an inline reply. Description mentions and automatic tasks also receive a working comment. No new eyes reaction is added; cleanup still handles receipts created by older versions.

The agent's update_comment tool edits the current request's working comment. It takes a body and a stable idempotency key, with no caller-selected comment ID or destination. Instructions encourage brief, factual progress updates during longer work. Distinct updates use distinct keys; retries reuse the same key. Progress does not complete an assessment or change a review check.

The comment tool replaces that same comment with the final answer. submit_review replaces it with the allowed review summary; checks, inline findings and explicitly permitted formal reviews remain separate. Corrected assessments can update the summary again. Delayed progress cannot overwrite a final answer. Native final text stays in Paperclip and creates no extra comment. Legacy connections without a saved review configuration retain automatic run progress and final replies until upgraded to this tool-owned response model.

Receipts are bound to the company, App, task, accepted request and original runtime generation. The existing publication lease serializes edits, and App-owned markers recover uncertain creation without posting duplicates. Deleted or no-longer-owned comments are not recreated or edited. Coalesced runs settle a deleted earlier working comment without blocking the current response, review findings, or check publication. Failed runs update the same comment when no final reply is confirmed or unresolved. A run that ends without a final reply clears a remaining working state honestly. Repository restrictions, person authorization and governed tool checks remain in effect for edits. Existing disabled or quarantined tools stay disabled. Existing native sessions refresh incompatible tool checkpoints so the agent can see update_comment. The same Paperclip task and saved history remain.

Explicit bot mentions and subscriptions

Issue and PR descriptions, discussion comments, inline comments, and review summaries retain uploaded attachment references when they mention the bot. Private images use the exact unchanged source's authenticated GitHub rendering; repository/thread identity and body hashes remain bound across restarts. Signed image URLs and credentials are never added to durable attachment descriptors.

A manual message naming another connected GitHub bot in the same company does not wake this bot through its thread subscription. Paperclip filters that delivery before creating task work or adding an acknowledgement. Explicitly mentioning both bots allows both to receive the request, subject to their normal authorization and repository checks.

Unaddressed follow-ups, human mentions and unknown handles retain the existing subscription behavior. The routing rule does not change automatic issue or PR event policies. Archived bots and identities from other companies or providers are excluded from the routing lookup.

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_n entries that clear ambient helpers, install a github.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.