## Thinking Path
> - Paperclip is the open source app that people use to manage AI agents
for work.
> - Connections give agents access to external services with a selected
credential identity.
> - A removed connection keeps its database row so Paperclip can retain
its history.
> - A fresh GitHub setup can select a different identity from the
removed connection.
> - The retained row incorrectly kept its old credential policy after
that new selection.
> - The GitHub callback then could not save the new grant and returned
the user to setup.
> - This pull request applies the explicit identity selection when
Paperclip revives an archived row.
> - The benefit is a successful GitHub reconnect after the user changes
from a dedicated agent account to a personal account.
## Linked Issues or Issue Description
**What happened?**
After a user removed a dedicated-agent GitHub connection, a fresh setup
with “My GitHub account” returned to the setup page with `oauth=failed`.
The Cloud claim succeeded, but the local connection still used the old
`per_agent` policy.
**Expected behavior**
A fresh setup must apply the explicit identity choice. An interrupted
draft or an explicit reconnect must keep its existing identity.
**Steps to reproduce**
1. Connect GitHub with a dedicated agent identity.
2. Remove the connection.
3. Start a fresh GitHub connection with “My GitHub account.”
4. Complete GitHub OAuth.
5. Observe that Paperclip returns to the setup page instead of the
permissions page.
**Paperclip version or commit**
`342c01fee`
**Deployment mode**
Local dev (`pnpm dev`) with embedded Postgres and the staging managed
connector.
**Additional context**
This follows the GitHub access UI change in #12893.
## What Changed
- Apply an explicit Access identity when a fresh gallery setup revives
an archived connection row.
- Preserve the identity for interrupted drafts and explicit reconnects.
- Do not carry credential material across an identity change.
- Apply the omitted organization default during a fresh archived-row
recovery.
- Restore the prior grants and credential policy transactionally if a
revived setup rolls back.
- Disable the connection and surface a specific failure if that
restoration cannot complete.
- Preserve newer concurrent grant changes with a row lock and optimistic
version check.
- Preserve newer concurrent connection identity/configuration changes
with a locked state fingerprint.
- Add regressions for dedicated-to-personal OAuth, organization-default
recovery, rollback, rollback failure, and concurrent grant/connection
changes.
## Verification
- `pnpm exec vitest run
server/src/__tests__/tool-access-service.test.ts` — 222 tests passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- Browser proof on an isolated local instance: dedicated connection
removed, personal setup selected, staging GitHub OAuth completed,
permissions page opened, connection reported active and healthy,
personal grant active, old agent grant revoked.
## Risks
- Low migration risk. This change has no schema migration.
- The behavior changes only when a fresh setup explicitly selects an
identity for an archived connection row.
- Existing draft resume and explicit reconnect behavior stays unchanged.
- Connection-manager checks still protect changes to a retained
credential identity.
> 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, with reasoning, browser control, tool use, and
code execution.
## 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>
Server tests that need a real PostgreSQL process must use
./helpers/embedded-postgres.ts instead of constructing embedded-postgres
directly.
The shared helper creates a throwaway data directory and a reserved-safe
loopback port for each test database. This protects the live Paperclip
control-plane Postgres from server vitest runs; see PAP-2033 for the incident
that introduced this guard.