Skip to content

fix(drivers): bind rotated OAuth secrets to a credential owner - #1508

Draft
frahlg wants to merge 1 commit into
masterfrom
cursor/oauth-credential-owner-658d
Draft

frahlg wants to merge 1 commit into
masterfrom
cursor/oauth-credential-owner-658d

Conversation

@frahlg

@frahlg frahlg commented Oct 3, 2026

Copy link
Copy Markdown
Member

Refs #1109.

Problem and result

Rotated OAuth secrets are stored as driver_secret:<display-name>:<key>. A rename looks up the new name and falls back to the stale YAML token. Reusing the old name applies the leftover rotation to another account. That is the release-blocker found on v3.0.3-beta.1; it is still true on current master (552c864a).

This draft mints a stable credential_owner on first Settings save, keys KV rows as driver_secret:<owner>:<key>, and migrates leftover name-keyed rows only when the same named driver continues. A reused name gets a new owner and does not inherit the old rotation. Ambiguous name-keyed and owner-keyed values for the same key are rejected. Config document and credential writes stay in one SaveConfiguration transaction.

Related: community #1503 / draft #1507 fix myUplink Test connection (#1502) by sharing the live name-keyed row with the probe. They do not fix this owner bug. After this lands, a later probe rotation must look up SecretOwner() (not the display name). Leftover name-keyed copies are not deleted, so #1507 still works until the next rotation.

Scope and safety

  • credential_owner is bookkeeping, not a household setting. Settings GET/POST already round-trips the live document, so the UI keeps the id without a new field.
  • Forecast learning hashes ignore credential_owner, so minting it on upgrade does not reset PV/load models.
  • Hardware identity is not used: it is learned after init and may be absent before OAuth.
  • Name-keyed leftovers are copied, not deleted. Registry lookup is owner-first.
  • No overlapping open PR owns this write path. fix(api): rebase driver Test connection secrets onto master #1507 touches probe wiring only.

Verification

go test ./internal/config/ ./internal/state/ ./internal/api/ ./cmd/ftw/ -count=1
ok

Covers rename, name reuse with a different account, explicit reauthorization, restart, first-import and Bind migration of name-keyed rows, ambiguous ownership, and the existing myUplink OAuth persist tests (now owner-keyed).

No real accounts. No hardware.

Checklist

  • The change follows VISION.md and one selected scope.
  • I checked overlapping PRs and coordinated shared files/contracts.
  • Relevant checks cover the changed behaviour and failure paths.
  • A human reviewed changed UI in a browser, or no UI changed.
  • A Changeset is included, or the change is exempt.
  • Every commit has a DCO sign-off.

What Fredrik needs to decide

Open in Web Open in Cursor 

Rename and name reuse looked up driver_secret:<display-name>, so a
rotated refresh token could be dropped or attached to another account.
Mint credential_owner on first save, key KV rows by that id, and migrate
continuing name-keyed leftovers atomically. Forecast learning ignores
the new field so an upgrade does not reset PV/load models.

Refs #1109

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants