feat(google-docs): managed OAuth-redirect Picker (no API key, no BYOK)#620
Merged
Conversation
Adds the managed (rowboat-mode) Google Docs picker via Google's trigger_onepick flow. The Rowboat backend runs a standalone drive.file OAuth with the company client, renders the Picker inside the browser consent screen, and deep-links the selection back; the desktop downloads the picked doc with the fresh drive.file token the backend returns. No Picker API key, appId, or BYOK credentials on the desktop. - core: importGoogleDocWithToken downloads a picked doc with an explicit token; fetch/metadata helpers take an optional Drive client and share writeDocxAndLink. claimPickedFilesViaBackend claims the parked file ids + token from the api. - main: google-picker-managed.ts opens the backend start URL and resolves on the rowboat://oauth/google/picker/done deep link; deeplink.ts routes that completion. - ipc: google-docs:pickViaManaged. - renderer: the picker dialog gates on Rowboat sign-in (the picker grants drive.file per-file, so no pre-existing connection or scope is required). Backend contract: rowboatlabs/rowboatx-backend#7 (GET /oauth/google/picker/{start,callback}, POST /v1/google-oauth/claim-picked).
813e5ad to
581a071
Compare
The managed picker replaced the only consumer (the picker dialog), so the experimental API-key Picker is now unused. Removes: - main: google-docs:openPicker handler (system-browser loopback Picker) - shared: google-docs:openPicker + google-docs:getAccessToken IPC schemas - core: getGoogleAccessToken (token plumbing for the client-side Picker) - renderer: lib/google-picker.ts (Picker JS SDK loader) Kept GoogleClientIdModal / google-credentials-store — still used by the general BYOK Google connect in onboarding, connectors, and settings.
Gagancreates
added a commit
that referenced
this pull request
Jun 22, 2026
* add drive sync up and down * add drive button * google doc icon * icon changes * show error state with retry in google doc picker * feat(google-docs): import and sync down as Markdown, record remote revision * feat(google-docs): structure-preserving sync up with remote-conflict guard * feat(google-docs): overwrite-confirm on sync conflict and last-synced indicator * feat(google-docs): store linked docs as .docx, edit in docx editor, sync via Drive * feat(google-docs): offer BYOK connect in picker so signed-in users can grant Drive/Docs scopes * fix(google-docs): request full drive scope so .docx sync-up can write back * fix(google-docs): search all drives in doc picker, log result count * feat(google-docs): import native Docs AND uploaded .docx files from Drive * chore(google-docs): drop dev-only test file * feat(google-docs): use Google Picker + drive.file scope instead of full-drive listing * fix(google-oauth): request offline access so BYOK tokens refresh BYOK never requested access_type=offline/prompt=consent so no refresh token was issued and tokens died after ~1h; also stop handing back expired tokens and extend the connect timeout to 10m. * feat(google-docs): pick docs via system-browser Google Picker Runs the Picker in the user's real browser (it 403s inside Electron), sets appId so the drive.file grant attaches to the picked file, and downloads + opens the selected doc. * feat(google-docs): managed OAuth-redirect Picker (no API key, no BYOK) (#620) * feat(google-docs): managed OAuth-redirect Picker (no API key, no BYOK) Adds the managed (rowboat-mode) Google Docs picker via Google's trigger_onepick flow. The Rowboat backend runs a standalone drive.file OAuth with the company client, renders the Picker inside the browser consent screen, and deep-links the selection back; the desktop downloads the picked doc with the fresh drive.file token the backend returns. No Picker API key, appId, or BYOK credentials on the desktop. - core: importGoogleDocWithToken downloads a picked doc with an explicit token; fetch/metadata helpers take an optional Drive client and share writeDocxAndLink. claimPickedFilesViaBackend claims the parked file ids + token from the api. - main: google-picker-managed.ts opens the backend start URL and resolves on the rowboat://oauth/google/picker/done deep link; deeplink.ts routes that completion. - ipc: google-docs:pickViaManaged. - renderer: the picker dialog gates on Rowboat sign-in (the picker grants drive.file per-file, so no pre-existing connection or scope is required). Backend contract: rowboatlabs/rowboatx-backend#7 (GET /oauth/google/picker/{start,callback}, POST /v1/google-oauth/claim-picked). * chore(google-docs): remove the dead API-key/system-browser Picker The managed picker replaced the only consumer (the picker dialog), so the experimental API-key Picker is now unused. Removes: - main: google-docs:openPicker handler (system-browser loopback Picker) - shared: google-docs:openPicker + google-docs:getAccessToken IPC schemas - core: getGoogleAccessToken (token plumbing for the client-side Picker) - renderer: lib/google-picker.ts (Picker JS SDK loader) Kept GoogleClientIdModal / google-credentials-store — still used by the general BYOK Google connect in onboarding, connectors, and settings. --------- Co-authored-by: Gagancreates <gaganp000999@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the experimental Google Docs pickers with the managed (rowboat-mode) OAuth-redirect Picker (
trigger_onepick) — no Picker API key, no appId, no BYOK credentials on the desktop. Verified end-to-end on staging ✅. Pairs with backend rowboatlabs/rowboatx-backend#7 (merged to develop/staging).Flow
${webappUrl}/oauth/google/picker/start.drive.fileOAuth (company client) withtrigger_onepick— Google shows the Picker in the consent screen and returnspicked_file_ids.drive.filetoken and deep-linksrowboat://oauth/google/picker/done?session=….{ fileIds, tokens }viaPOST /v1/google-oauth/claim-pickedand downloads the doc with that token — imports as an editable.docxand opens it.Adds (managed picker)
importGoogleDocWithToken(download with an explicit token; fetch/metadata helpers take an optional Drive client, sharingwriteDocxAndLink) +claimPickedFilesViaBackend.google-picker-managed.ts(opens start URL, resolves on the picker deep link) + completion routing indeeplink.ts.google-docs:pickViaManaged.drive.fileper-file, so no pre-existing Google connection or scope is required.Removes (the now-dead picker experiments)
The managed dialog is the only picker consumer, so the prior experiments are removed:
google-docs:openPickerhandler + schema, rendererlib/google-picker.ts(Picker JS SDK),google-docs:getAccessToken+ coregetGoogleAccessToken.trigger_onepick:google-picker-oauth.ts,pickViaOAuth+ schema,google-picker.tsredirect-URL helpers.GoogleClientIdModal/google-credentials-store— still used by the general BYOK Google connect (onboarding, connectors, settings).Notes
tscclean (main + renderer), lint clean on changed files (one pre-existingEmailBlockSchemaunused-import inshared/ipc.tsis unrelated).drive.file, so the picker mints its own token — existing managed users aren't forced to reconnect.To ship to prod
develop → main+ deploy (api.x / app.x).https://app.x.rowboatlabs.com/oauth/google/picker/callbackon the prod company OAuth client.drive(Drive #583) →dev, then cut a new desktop app release. (Backend must reach prod before the desktop release.)