paperclip/server/src
Dotta 5da6499860
fix(connections): reuse one-time cloud enrollment (#12891)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Managed connections let agents use provider credentials without
exposing those credentials to the control plane UI
> - A self-hosted instance must first establish a trusted credential
destination with Paperclip Cloud
> - The GitHub connection flow repeated that trust decision before
provider consent
> - The local setup route also lost step 2 after enrollment and could
display the PAT identity defaults before enrollment
> - This pull request makes enrollment a one-time instance decision and
sends later provider starts directly to provider consent
> - The benefit is a shorter flow with one clear Paperclip approval and
no required service restart

## Linked Issues or Issue Description

Refs #12843.

Companion Cloud change:
[paperclipai/paperclip-cloud#391](https://github.com/paperclipai/paperclip-cloud/pull/391).

## What Changed

- Made `stage=setup` authoritative during initial route hydration and
enrollment return.
- Added a contained one-time enrollment screen with provider-specific
copy.
- Accepted a provider `authorizationUrl` from Paperclip Cloud only when
it matches the exact GitHub or Google OAuth endpoint.
- Preferred the direct provider URL while retaining the legacy
confirmation URL fallback.
- Preserved the company-bound identity and agent-access draft across the
full-page enrollment callback, including cold company-context hydration.
- Kept GitHub defaulted to “My GitHub account” and “Any agent,”
including before Cloud advertises the managed method.
- Updated GitHub identity and agent-access copy for responsible-person
and dedicated-agent behavior.
- Labeled the provider action “Continue to GitHub.”
- Added parser, routing, cold-hydration, access-restoration, visibility,
fallback, defaults, and copy tests.

## Verification

- `pnpm exec vitest run
server/src/services/paperclip-cloud-connector.test.ts
ui/src/pages/apps/AppsConnect.test.tsx` (114 tests passed)
- `pnpm check:token-gates`
- `pnpm -r typecheck`
- `pnpm build`
- Live browser proof used a new data directory on `127.0.0.1:3117` and
the exact Cloud PR revision on staging.
- The fresh flow selected “My GitHub account” and “Any agent,” showed
one enrollment approval, returned to local step 2, and connected GitHub
without a second Paperclip confirmation or login.
- The connected screen showed one selected repository, a long-lived
token, installation metadata, a successful access refresh, and healthy
webhook delivery.
- Gmail on the same instance went directly to Google consent without
another Paperclip approval.
- Restarting the same data directory preserved enrollment. A second new
data directory required exactly one new approval.
- A final fresh-data-dir rerun selected a dedicated GitHub identity for
Ada before enrollment, approved the instance once, returned to step 2,
retained Ada after a Back check, connected directly through GitHub, and
finished with “Used only by Ada,” one selected repository, and a
long-lived token.
- Port 3100 remained untouched throughout the proof.

## Risks

- The new Cloud field is additive and restricted to the exact GitHub and
Google OAuth origins and paths, with no embedded credentials or URL
fragment.
- An older Cloud response still works through `confirmationUrl`.
- A self-hosted instance still requires one signed Cloud enrollment.
Managed Cloud instances do not render the enrollment screen.
- Provider authentication and consent remain mandatory after instance
enrollment.
- No schema migration is included in this pull request.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

OpenAI Codex, `gpt-5.6-sol`, extended reasoning, tool use, code
execution, browser control, and multi-file repository editing. The
context window size was not provided.

## 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
2026-09-05 08:42:20 -05:00
..
__tests__ fix(runner): restore multi-turn remote sessions (#12840) 2026-09-05 06:25:06 -05:00
adapters fix(security): harden privileged server boundaries (#12776) 2026-09-03 14:15:32 -05:00
auth feat(runner): add Codex-native application integration (#12591) 2026-08-31 14:38:38 -05:00
built-ins/agents Remove cheap model profiles (#12683) 2026-09-01 14:57:38 -05:00
http fix(server): raise company import zip upload limit to 1 GB and make it operator-configurable (#11184) 2026-08-10 12:47:03 -07:00
lib perf(server): reduce issue detail request overhead (#10414) 2026-08-11 14:39:23 -04:00
middleware fix(server): honor proxy trust for forwarded host (#12832) 2026-09-04 10:02:28 -05:00
onboarding-assets fix: reliably show plans in the Plan pane and restore sticky plan confirmation CTAs (#10930) 2026-08-05 19:32:07 -07:00
realtime feat(runner): add remote execution substrate (#12638) 2026-09-01 01:29:06 -05:00
routes feat(connections): add durable GitHub identities and webhooks (#12843) 2026-09-04 18:02:52 -05:00
secrets feat(secrets): write through external values and deep-link details (#10196) 2026-07-27 19:08:07 -05:00
services fix(connections): reuse one-time cloud enrollment (#12891) 2026-09-05 08:42:20 -05:00
storage feat(run-logs): durable run-log store via object-storage mirror (#8984) 2026-07-14 15:45:39 -07:00
types feat(mcp) [split 3/8]: add tool access policy core (#9558) 2026-07-14 14:22:39 -05:00
vendor/paperclip-runner fix(runner): restore multi-turn remote sessions (#12840) 2026-09-05 06:25:06 -05:00
agent-auth-jwt.ts fix(server): align agent run JWT default TTL with documented 48h default (#10176) 2026-08-12 16:44:20 -07:00
app.ts fix(runner): stabilize local paid E2E recovery (#12836) 2026-09-04 11:16:20 -05:00
attachment-types.ts Remove the company brand color and per-company attachment limit (#12291) 2026-08-27 12:11:05 -07:00
board-claim.ts [codex] Add agent permissions and controls plan (#6386) 2026-05-22 08:12:52 -05:00
build-commit.ts fix(server): preserve source SHA without Git metadata (#9638) 2026-07-15 20:03:52 -05:00
build-version.ts fix(server): stamp the real build version into images instead of the package.json placeholder (#10257) 2026-07-25 10:06:28 -07:00
config-file.ts fix(config): preserve extensions and guard invalid repairs (#11005) 2026-08-07 00:41:19 -05:00
config.ts feat(apps): improve gateway and workspace connection UX (#12340) 2026-08-29 12:08:32 -05:00
db-errors.ts fix(issues): make DELETE /api/issues/:id succeed for issues with dependents (#11331) 2026-08-13 12:02:15 -07:00
dev-native-runner-status.ts feat(runner): integrate Codex native execution (#12616) 2026-08-31 22:51:17 -05:00
dev-runner-worktree.ts feat(workspaces): sign the workspace login handoff and gate readiness (#11671) 2026-08-19 02:37:02 -05:00
dev-server-status.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
dev-watch-ignore.ts fix(server): ignore sibling worktrees in dev watch (#11074) 2026-08-07 18:30:16 -07:00
embedded-postgres-supervisor.ts fix(workspaces): recover degraded runtime databases (#11651) 2026-08-18 17:40:54 -05:00
errors.ts feat(artifacts): bridge Markdown work products into the document review surface (#11822) 2026-08-20 17:28:01 -07:00
first-admin-claim.ts [codex] Add private browser first-admin claim flow (#6755) 2026-05-27 21:15:01 -10:00
home-paths.ts feat(server): thread plural referenced-project workspaces through run prep (#10448) 2026-07-29 14:27:05 -07:00
index.ts feat(connections): add durable GitHub identities and webhooks (#12843) 2026-09-04 18:02:52 -05:00
instrumentation.test.ts fix(server): export manual OpenTelemetry spans (#10565) 2026-07-31 12:47:57 -07:00
instrumentation.ts fix(observability): pin the Sentry browser SDK and gate the optional Sentry server peer on the exact version (#12270) 2026-08-27 07:20:03 -07:00
log-redaction.ts Sync/master post pap1497 followups 2026 04 15 (#3779) 2026-04-15 21:13:56 -05:00
paths.ts feat(cli): add client commands and home-based local runtime defaults 2026-02-20 07:10:58 -06:00
peer-version-check.ts fix(observability): pin the Sentry browser SDK and gate the optional Sentry server peer on the exact version (#12270) 2026-08-27 07:20:03 -07:00
redaction.ts fix(runner): restore multi-turn remote sessions (#12840) 2026-09-05 06:25:06 -05:00
runtime-api.ts Prefer loopback runtime API URL for local agents (#5102) 2026-06-20 14:03:21 -07:00
runtime-tools-token.test.ts feat(connections): add self-serve intent runtime (#12345) 2026-08-29 12:08:34 -05:00
runtime-tools-token.ts feat(connections): add self-serve intent runtime (#12345) 2026-08-29 12:08:34 -05:00
sentry-dsn.ts feat(server): split the Sentry DSN into front-end and backend variables (#12678) 2026-09-01 11:02:04 -07:00
sentry.ts feat(server): split the Sentry DSN into front-end and backend variables (#12678) 2026-09-01 11:02:04 -07:00
server-info.ts fix(server): preserve source SHA without Git metadata (#9638) 2026-07-15 20:03:52 -05:00
shutdown.test.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
shutdown.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
startup-banner.ts fix(security): route paperclipai CLI guidance through safe npx form (CWE-78) (#11400) 2026-08-14 22:11:16 -07:00
startup-recovery-state.ts fix(runner): recover native sessions across restarts (#12845) 2026-09-04 15:03:53 -05:00
startup-refusals.ts fix(server): stop paging Sentry for supervised boot races in managed cloud (#12772) 2026-09-03 10:02:42 -07:00
static-index-html.ts [codex] Bundle local branch fixes from PAP-10032 (#6604) 2026-05-25 07:25:26 -05:00
static-ui-cache.ts fix(ui): keep the installed service worker fresh on parked tabs (#12198) 2026-08-25 16:12:02 -07:00
telemetry.ts fix: add periodic flush and graceful shutdown for server-side telemetry 2026-04-02 10:47:29 -05:00
ui-branding.ts Ensure worktree execution starts only after activation (#9374) 2026-07-10 16:11:26 -05:00
url-utils.test.ts fix(runtime): only rewrite base-URL port for loopback hosts (#10258) 2026-08-13 09:47:13 -07:00
url-utils.ts fix(runtime): only rewrite base-URL port for loopback hosts (#10258) 2026-08-13 09:47:13 -07:00
version.ts fix(server): stamp the real build version into images instead of the package.json placeholder (#10257) 2026-07-25 10:06:28 -07:00
vite-html-renderer.ts fix(runner): stabilize local paid E2E recovery (#12836) 2026-09-04 11:16:20 -05:00
worktree-config.ts feat(apps): consolidate connector management (#12684) 2026-09-01 14:55:35 -05:00
worktree-seed-manifest.ts feat(workspaces): sign the workspace login handoff and gate readiness (#11671) 2026-08-19 02:37:02 -05:00