Files
PaperClipAI/server
DottaandPaperclip 3475e33fc7 fix(connector): isolate broker enrollment targets (#12609)
## Thinking Path

> - Paperclip lets operators connect provider accounts for their agents.
> - Self-hosted instances can enroll with the Paperclip Cloud OAuth
broker.
> - A local identity can remain on disk when an operator changes the
broker from production to staging.
> - The old code combined the new target with the old identity and
produced a verification link that Cloud could not accept.
> - The final enrollment callback also returned to an unscoped Apps
path.
> - This pull request binds each identity to one broker target and
returns to the correct company route.
> - The benefit is a fail-closed enrollment flow that works across Cloud
targets and company-prefixed routes.

## Linked Issues or Issue Description

Refs: #12600

**What happened?**

A self-hosted instance with a saved connector identity could switch its
broker base URL and environment. Paperclip then used the saved identity
with the new target. The enrollment page received an unknown draft. A
successful callback also opened an unscoped Apps path, which the UI
treated as a company prefix.

**Expected behavior**

Paperclip must use one atomic identity and broker target. A target
change must never mix old keys with a new broker. A completed enrollment
must return to the initiating company's Connections page.

**Steps to reproduce**

1. Start a self-hosted Paperclip instance and create a pending connector
enrollment against the production broker.
2. Set the connector base URL and environment to staging.
3. Start enrollment again and open the returned verification URL.
4. Complete enrollment and inspect the final browser route.

**Paperclip version or commit**

`300a89ec1`

**Deployment mode**

Local dev (`pnpm dev`) through private HTTPS.

## What Changed

- Resolve the connector broker and environment as one target.
- Rotate a non-active identity when an administrator explicitly starts
enrollment for a different target.
- Reject active target changes and broker/environment mismatches.
- Treat managed environment identity fields as one atomic tuple.
- Require the Cloud verification URL to contain only the exact
enrollment identifier.
- Validate the configured target again before the instance redeems an
enrollment callback.
- Return successful enrollment callbacks to the company-prefixed
Connections page.
- Add regression tests for target isolation, managed identity
precedence, URL validation, and the return path.

## Verification

- `pnpm exec vitest run
server/src/services/paperclip-cloud-connector-enrollment.test.ts
server/src/services/paperclip-cloud-connector.test.ts
server/src/routes/tool-access-connection-intent.test.ts` (31 tests
passed)
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm -r typecheck`
- `pnpm build`
- `git diff --check`
- Completed a staging Cloud enrollment from a local Paperclip instance
through private HTTPS.
- Confirmed the instance reports an active staging enrollment for its
exact HTTPS origin.
- Confirmed the company-prefixed Connections route renders the
enrollment success state.
- `pnpm test:run` also reached five unrelated macOS harness failures.
Two compare `/var` with `/private/var`. Three expect listener-fixture
failures that do not occur on this host. The same five failures
reproduce when the two workspace-runtime suites run alone.

## Risks

- Low risk. The change affects only Paperclip Cloud connector identity
selection and the enrollment return route.
- An active identity now fails closed when an operator changes its
broker target. The operator must restore the original target or perform
a new enrollment flow.
- Starting a new target replaces a non-active draft, so its previous
one-time approval link no longer works.
- This change does not alter provider tokens, grants, catalogs, or tool
calls.

> 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 with GPT-5.6 Sol. The work used high-reasoning mode,
repository tools, code execution, browser automation, and parallel
review subagents.

## 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 the scoped tests 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>
2026-08-31 16:43:46 -05:00
..