Skip to content

fix(core): repoint entity credentialId when re-auth produces a different credential#583

Merged
d-klotz merged 1 commit into
nextfrom
fix/core-persist-tokens-on-oauth-reauth
May 5, 2026
Merged

fix(core): repoint entity credentialId when re-auth produces a different credential#583
d-klotz merged 1 commit into
nextfrom
fix/core-persist-tokens-on-oauth-reauth

Conversation

@d-klotz
Copy link
Copy Markdown
Contributor

@d-klotz d-klotz commented May 5, 2026

Summary

Follow-up to #582. When a user re-authenticates against a different workspace/account of the same provider (e.g. switching between two Pipedrive workspaces under the same Frigg user), the re-auth flow leaves the entity linked to the prior workspace's credential while the freshly-issued tokens land on a different credential row.

Root cause

upsertCredential matches/creates a credential keyed by externalId from getCredentialDetails (e.g. Pipedrive userProfile.data.id). findOrCreateEntity matches the entity by its own externalId from getEntityDetails (e.g. Pipedrive userProfile.data.company_id). When the user has multiple workspaces, both methods can hit different existing rows — upsertCredential resolves to credential B's row, findOrCreateEntity returns the entity already pointing at credential A.

The OAuth callback then reports { credentialId: B, entityId: matched-entity }, but the entity's credentialId foreign key still references A. Downstream integration creation reads the stale link, and the just-issued tokens sit on credential B with no entity pointing to it.

Observed in dev

  • Pipedrive integration 136 (user 16) created via re-auth into workspace 24952048 (cred 188).
  • Entity 159 was previously linked to cred 166 (workspace 23384438 from a prior install).
  • After OAuth: cred 188 had fresh tokens, cred 166 was unchanged at the OAuth time. Entity 159 still pointed at cred 166. Webhook setup later succeeded only because the runtime auto-refresh on cred 166's separate refresh_token happened to still be alive.

Fix

findOrCreateEntity now repoints existingEntity.credentialId to the just-upserted credentialId via moduleRepository.updateEntity whenever they differ. No-ops when they match.

Tests

  • repoints existing entity credentialId when re-auth produces a different credential — locks in the new behavior
  • does not repoint when the existing entity already points at the upserted credential — guards against unnecessary writes
  • All 6 existing tests still pass

🤖 Generated with Claude Code

…ent credential

When a user re-authenticates against a different workspace/account of the
same provider (e.g. switching between two Pipedrive workspaces),
upsertCredential matches/creates a credential keyed by externalId from
getCredentialDetails — but findEntity matches the entity by its own
externalId from getEntityDetails. These keys can resolve to different
credential rows when the user has multiple workspaces, leaving the
entity still linked to the prior workspace's credential after re-auth.

Without this fix, the OAuth callback reports
{credentialId, entityId} where credentialId is the freshly-persisted
credential, but the entity in the DB still references a different
credential. Downstream integration creation reads the stale link and
runs against the prior workspace's tokens, while the just-issued tokens
sit on a different credential row no entity points to.

Repoint the entity's credentialId via moduleRepository.updateEntity
when findOrCreateEntity returns an existing entity whose credentialId
differs from the just-upserted credential.

Tests: two new cases — repoints when upsert produces a different
credential, no-ops when the entity already points at the upserted one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@d-klotz d-klotz added the release Create a release when this pr is merged label May 5, 2026
@d-klotz d-klotz merged commit b649f7f into next May 5, 2026
5 of 6 checks passed
@d-klotz d-klotz deleted the fix/core-persist-tokens-on-oauth-reauth branch May 5, 2026 17:43
@seanspeaks
Copy link
Copy Markdown
Contributor

🚀 PR was released in v2.0.0-next.83 🚀

@seanspeaks seanspeaks added the prerelease This change is available in a prerelease. label May 5, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
58.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prerelease This change is available in a prerelease. release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants