Skip to content

Add Google Drive node with interactive OAuth2 - #416

Merged
mbakgun merged 15 commits into
mainfrom
impl/gdrive-node
Jul 27, 2026
Merged

Add Google Drive node with interactive OAuth2#416
mbakgun merged 15 commits into
mainfrom
impl/gdrive-node

Conversation

@mbakgun

@mbakgun mbakgun commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a googleDrive node with popup OAuth2 and six operations: listFolderFiles, downloadFile, syncToHeymDrive, updateFile, removeFile, removeFolder.

This is separate from the existing drive node, which is Heym Drive (internal GeneratedFile storage). syncToHeymDrive is the bridge between the two — it pulls a file out of Google Drive and stores it in Heym Drive.

Architecture mirrors the Google Sheets integration: GoogleDriveService owns all Drive v3 calls and token refresh, the node handler stays thin, and a dedicated router runs the consent flow.

Design decisions worth reviewing

  • Full auth/drive scope. The narrower drive.file scope only sees files the OAuth client itself created, so listing/updating/deleting a user's existing files would silently return nothing. Consequence: sharing this credential grants full Drive access, documented as a required warning in credentials-sharing.md and surfaced in the credential dialog.
  • Google-native files are exported, not downloaded. Docs/Sheets/Slides have no downloadable bytes (alt=media returns 403), so downloadFile and syncToHeymDrive auto-export — Docs→PDF, Sheets→XLSX, Slides→PPTX — overridable via gdExportFormat.
  • Deletes trash by default. gdPermanentDelete opts into destruction. removeFile refuses folders and removeFolder refuses files, so a mistyped ID cannot delete the wrong thing.
  • DSL section appended as deps(backend)(deps): update python-jose[cryptography] requirement from >=3.3.0 to >=3.5.0 in /backend #42 rather than inserted near googleSheets, to avoid renumbering 17 sections.

Canvas affordances

All 8 expression-capable fields are wired for both evaluate-dialog 1/n navigation (n varies by operation: updateFile 4, listFolderFiles 3, syncToHeymDrive 2) and agent autofill via field-key. No backend work was needed for agent tools — agentProvidedFields is already node-type agnostic.

Docs

New node page plus updates to features.md (per-node section and the node-types summary), node-types.md, integrations.md, credentials.md, and credentials-sharing.md.

Test Plan

  • ./check.sh green — 2503/2503 backend tests, ruff + eslint + vue-tsc clean
  • 55 new backend tests: 35 service (mocked httpx: token refresh, export vs media branching, paging, trash vs permanent, type guards), 15 handler, 5 OAuth (state signing, TTL, cross-flow rejection, scope)
  • Migration applied and verified against a live database
  • Frontend build and docs build pass
  • Live OAuth consent round-trip is untested — needs a real Google Cloud project. Unit tests cover state signing, scope, and token refresh only. Worth a manual check before release.

Notes for reviewers

  • alembic_version.version_num is varchar(32); the revision id is 103_add_google_drive_cred_type to fit. test_alembic_migrations.py hard-codes the expected head and is updated here.
  • The design spec and implementation plan are included under docs/superpowers/.

🤖 Generated with Claude Code

mbakgun added 15 commits July 27, 2026 12:21
Design for a googleDrive node with interactive OAuth2 and six operations:
listFolderFiles, downloadFile, syncToHeymDrive, updateFile, removeFile,
removeFolder.
…"{}"

evaluate_message_template returns str(inputs) for an empty template, so every
blank optional field came back as the literal "{}". This leaked into the Drive
query as "and ({})", made an empty gdFolderId query "'{}' in parents" instead of
the root, turned a blank gdExportFormat into an unsupported-format error, and —
worst — made syncToHeymDrive store every file under the name "{}".

The handler now short-circuits blank fields before templating. Expressions still
resolve as before.

Also raise a clear error when a credential has no access token; httpx previously
failed with "Illegal header value b'Bearer '".

The existing tests missed all of this because the mocked evaluate_message_template
echoed its input, so blanks stayed blank. The mock now mirrors the real executor.
@mbakgun
mbakgun merged commit b60b629 into main Jul 27, 2026
2 checks passed
@mbakgun
mbakgun deleted the impl/gdrive-node branch July 27, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant