0018: app: Register OAuth callback providers - #7281
Conversation
Cover validation, ownership cleanup, dispatch matching, and provider failures before introducing the desktop OAuth callback registry.
Exercise provider registration and protocol callback dispatch in a real Electron main process without requiring a Kubernetes cluster.
Route validated product protocol callbacks to their owning OAuth provider so desktop integrations can complete authentication safely. Co-authored-by: René Dudfield <renedudfield@microsoft.com>
Exercise the default protocol through Electron so configurable schemes preserve the existing renderer route.
Pin the Istanbul provider to the app Vitest version so protocol branch coverage can be measured reproducibly.
Use each product's packaged protocol for deep links so branded desktop apps do not handle one another's callbacks. Co-authored-by: René Dudfield <renedudfield@microsoft.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: illume The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
Adds desktop OAuth callback provider registration and routes product protocol URLs through registered providers.
Changes:
- Adds validated OAuth provider registration and dispatch.
- Integrates startup, second-instance, and macOS callback handling.
- Adds unit, coverage, and Electron process tests.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
app/package.json |
Adds Istanbul coverage support. |
app/package-lock.json |
Locks coverage dependencies. |
app/electron/protocol.ts |
Reads and validates protocol schemes. |
app/electron/protocol.test.ts |
Tests protocol utilities. |
app/electron/oauth-provider.ts |
Implements the provider registry. |
app/electron/oauth-provider.test.ts |
Tests registry behavior. |
app/electron/main.ts |
Routes protocol callbacks. |
app/e2e-tests/tests/protocolScheme.spec.ts |
Tests custom deep-link routing. |
app/e2e-tests/tests/oauthProvider.spec.ts |
Tests Electron callback dispatch. |
app/e2e-tests/fixtures/oauth-provider-main.ts |
Provides the Electron test fixture. |
Files not reviewed (1)
- app/package-lock.json: Generated file
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
e6b98c1 to
7976769
Compare
7976769 to
f3862a6
Compare
f3862a6 to
64ae9a5
Compare
64ae9a5 to
267bc30
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- app/package-lock.json: Generated file
Suppressed comments (2)
app/electron/protocolHandler.ts:143
- This drains callbacks queued by
open-url/second-instancebefore processing the original startup callback, reversing the ordering promised bysetReadyand the callbacks' arrival order. For example, callback B from a fast second launch is delivered before startup callback A. Process the non-macOS argv callback first, then drainpendingUrls.
for (const value of pendingUrls.splice(0)) {
processUrl(value);
}
if (platform !== 'darwin') {
handleFirstProtocolUrl(argv);
app/electron/oauthProvider.ts:115
- A stale cleanup still removes a replacement when the caller re-registers the same registration object: after
firstUnregister(); registerOAuthProvider(registration); firstUnregister(), this identity check succeeds again and deletes the new registration. That contradicts the documented replacement-safety guarantee. Associate each registration call with a unique stored entry/token and compare that token during cleanup rather than the caller-owned object.
return () => {
if (providersByCallback.get(key) === registration) {
providersByCallback.delete(key);
}
Summary
Stack
This PR is stacked on prerequisite patch 0009:
The first three commits belong to that prerequisite; the final three commits are patch 0018. This PR will be rebased onto
mainafter #7252 merges.Provenance
0018-headlamp-upstream-oauth-provider-registry.patch2e4c7e7d95a8a0fcba47961e9a4e79616739b38c, authored by Thomas Gamble on 2026-07-315b78e600bbb2666969c649043bd89610f407bebfd9b4def25efc00ad66f4f2af23d2d89f9c6c0f86The implementation commit preserves Thomas Gamble as author and the original author date, with Rene Dudfield as co-author.
Improvements over the existing changes
open-urlbeforeready; without buffering, a cold-start OAuth callback can be lost.main.tsso the Electron entry point remains wiring-focused and the protocol lifecycle can be tested as one encapsulated unit.Testing
make app-i18n-checknpm --prefix app test -- electron/protocol.test.ts electron/oauthProvider.test.ts electron/protocolHandler.test.ts(55 tests)app/electron/oauthProvider.tsandapp/electron/protocolHandler.ts: 100% branches (80% threshold enforced)npm --prefix app/e2e-tests run test-app -- tests/protocolScheme.spec.ts tests/oauthProvider.spec.ts --workers=1(2 tests)npm --prefix app run tscnpm --prefix app run compile-electron -- --devgit diff --check 8464d801..HEADScreenshots
Not applicable. This change adds main-process callback infrastructure with no visual difference.
Assisted by copilot.