Files
PaperClipAI/server/src
DottaandPaperclip e625505ac9 fix(auth): preserve credential sign-in during server overlap (#20839)
## Thinking Path

> - Paperclip controls AI agent work across software updates.
> - Authenticated instances must keep human sign-in available during an
update.
> - Better Auth 1.7.16 identifies accounts by provider and account ID.
> - It creates credential accounts without the issuer required by the
previous reader.
> - A new account can therefore fail to sign in through a surviving
1.7.2 process.
> - This pull request keeps the legacy credential issuer on trusted
account creation.
> - The security upgrade and provider/account uniqueness stay in place.

## Linked Issues or Issue Description

Refs #18906.

**What happened?**

After the Better Auth upgrade, a credential account created by the new
version has a NULL issuer. A surviving Better Auth 1.7.2 process rejects
its correct password because it selects only the `local:credential`
account identity.

**Expected behavior**

A new credential account must sign in through both versions during an
update. The new version must keep its provider/account lookup and
uniqueness rules.

**Steps to reproduce**

1. Apply migration 0465 to a disposable database.
2. Create an email/password account with the new auth mount.
3. Sign in to the same database through Better Auth 1.7.2.
4. Without this change, signup and new-version sign-in return 200, but
old-version sign-in returns 401.

## What Changed

- Register issuer as an optional internal account field with client
input and response output disabled.
- Set `local:credential` in the trusted before-create hook. Preserve any
nonempty issuer supplied by internal code.
- Leave unconfigured providers without an issuer on the new NULL-issuer
behavior. No social provider is configured by this module.
- Add credential integration and issuer-policy controls. Document the
exact compatibility scope.

## Verification

- Node 24: `node scripts/agent-preflight.mjs` passed using the existing
build cache.
- `node cli/node_modules/tsx/dist/cli.mjs
packages/db/src/test-postgres-command.ts -- node
node_modules/vitest/vitest.mjs run --project @paperclipai/server
server/src/__tests__/better-auth.test.ts
server/src/__tests__/better-auth-credential-signup.integration.test.ts`:
22 passed.
- Separate local qualification used the actual cached Better Auth 1.7.2
SDK and the current 1.7.16 mount against one disposable PostgreSQL
database. Before this change, old-version sign-in returned 401 for the
new account. After this change, signup through either writer and sign-in
through both readers returned 200.
- The integration covers forged client issuer input, the frozen 1.7.2
credential selector, current-version sign-in for existing NULL-issuer
rows, and the unchanged provider/account unique index.
- `pnpm --filter @paperclipai/server typecheck`: passed, including all
server and test-tree layers.
- The first required Runner support run failed three SDK proof suites
because two generated lock references were stale on the current base.
The existing generator corrected those references and the three suites
passed locally (58 tests in 17.07 seconds). Master then merged the same
repair in #20834 and advanced its runtime/dependency lock. This branch
was rebased onto current master; the duplicate proof commit was omitted.
The final diff contains only the four auth/test/doc files. The
exact-head checks and review listed below passed on the rebased
candidate.
- Final candidate `577fd7612a6d80ac35e2f5ee9ea2ce9b77169687`: focused
auth verification passed again (22 tests, 51.81 seconds). [Required
CI](https://github.com/paperclipai/paperclip/actions/runs/43051216288)
passed, including build, typecheck, server/Runner tests and all eight
browser shards. One unchanged Rust process-lineage orphan-census test
failed on the first attempt; the failed job was rerun after the workflow
completed and passed. This PR changes no Rust source.
- [Greptile
review](https://github.com/paperclipai/paperclip/pull/20839#issuecomment-6799551882)
is 5/5 on the final head with no actionable findings or open review
threads. No deployment or original database change was performed for
this branch.

## Risks

The bridge applies to new credential accounts. It does not backfill
existing NULL issuers or claim old-reader compatibility for unconfigured
social providers. Trusted internal issuers retain their exact value.
Account lookup, password checks, account linking, provider/account
uniqueness, and migration 0465 remain with their existing owners.

## Model Used

OpenAI Codex (GPT-6), with tool-assisted code editing and local
PostgreSQL qualification. The exact serving model ID and context window
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 `#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>
2026-11-11 10:17:49 -06:00
..
…
…
…