fix: correct googledrive action scopes
loading diff…
https://www.googleapis.com/auth/docs scope from 20 Google Drive actions whose real HTTP calls go to Drive v2/v3 methods that do not accept Docs OAuthGOOGLEDRIVE_DOWNLOAD_FILE to the true byte-download/export intersection and add the missing drive.meet.readonly alternative to GOOGLEDRIVE_EXPORT_FILEGOOGLEDRIVE_STOP_WATCH_CHANNEL by dropping the invented Docs scope and adding the documented drive.meet.readonly alternativeNo tracker issue was provided in the task, so this PR is not auto-closing an issue.
uv run python -m mercury.tools._base.action validate_scopes apps/googledrive/actionsuvx ruff format --check apps/googledrive/actionsuvx ruff check apps/googledrive/actionspython3 -m compileall apps/googledrive/actions| Action | Real HTTP call(s) from code | Scope change | Why | Docs |
|---|---|---|---|---|
GOOGLEDRIVE_DELETE_CHILD_V2 | DELETE /drive/v2/files/{folder_id}/children/{child_id} | drop invented docs | Real call is Drive children.delete; Docs scope is not accepted by the Drive method. | children.delete |
GOOGLEDRIVE_DELETE_FILE | DELETE /drive/v3/files/{file_id} | drop invented docs | Workbook cited v2, but the action actually calls Drive v3 files.delete; the accepted set is drive, drive.appdata, or drive.file. | files.delete |
GOOGLEDRIVE_DELETE_PARENT_V2 | DELETE /drive/v2/files/{file_id}/parents/{parent_id} | drop invented docs | Real call is Drive parents.delete; Docs scope is not accepted. | parents.delete |
GOOGLEDRIVE_DELETE_PROPERTY_V2 | DELETE /drive/v2/files/{file_id}/properties/{property_key} | drop invented docs | Real call is Drive properties.delete; Docs scope is not accepted. | properties.delete |
GOOGLEDRIVE_DOWNLOAD_FILE | Always GET /drive/v3/files/{file_id} for metadata, then either GET /drive/v3/files/{file_id}/export or GET /drive/v3/files/{file_id}?alt=media | narrow to drive, drive.file, drive.meet.readonly, drive.readonly | Metadata-only/appdata/photo scopes can read file metadata but cannot satisfy the action's primary purpose of returning bytes. The non-Workspace download path must be authorized to download content, and the Workspace path must satisfy files.export; the real intersection stays these four scopes. | files.get, files.export, Download and export files |
GOOGLEDRIVE_EXPORT_FILE | GET /drive/v3/files/{file_id} then GET /drive/v3/files/{file_id}/export | add drive.meet.readonly | The action always exports bytes after reading metadata, so the valid set is the files.export scope set; drive.meet.readonly was missing. | files.get, files.export |
GOOGLEDRIVE_GET_APP | GET /drive/v2/apps/{app_id} | drop invented docs | Real call is Drive apps.get; Docs scope is not accepted. | apps.get |
GOOGLEDRIVE_GET_CHANGE_V2 | GET /drive/v2/changes/{change_id} | drop invented docs | Real call is Drive changes.get; Docs scope is not accepted. | changes.get |
GOOGLEDRIVE_GET_CHILD_V2 | GET /drive/v2/files/{folder_id}/children/{child_id} | drop invented docs | Real call is Drive children.get; Docs scope is not accepted. | children.get |
GOOGLEDRIVE_GET_FILE_V2 | GET /drive/v2/files/{file_id} | drop invented docs | The implementation only parses the JSON metadata response; the accepted scope set is Drive files.get without Docs scope. | files.get (v2) |
GOOGLEDRIVE_GET_PARENT_V2 | GET /drive/v2/files/{fileId}/parents/{parentId} | drop invented docs | Real call is Drive parents.get; Docs scope is not accepted. | parents.get |
GOOGLEDRIVE_GET_PERMISSION_ID_FOR_EMAIL | GET /drive/v2/permissionIds/{email} | drop invented docs | Real call is Drive permissions.getIdForEmail; Docs scope is not accepted. | permissions.getIdForEmail |
GOOGLEDRIVE_GET_PROPERTY_V2 | GET /drive/v2/files/{fileId}/properties/{propertyKey} | drop invented docs | Real call is Drive properties.get; Docs scope is not accepted. | properties.get |
GOOGLEDRIVE_INSERT_CHILD_V2 | POST /drive/v2/files/{folderId}/children | drop invented docs | Real call is Drive children.insert; Docs scope is not accepted. | children.insert |
GOOGLEDRIVE_INSERT_PARENT_V2 | POST /drive/v2/files/{fileId}/parents | drop invented docs | Real call is Drive parents.insert; Docs scope is not accepted. | parents.insert |
GOOGLEDRIVE_INSERT_PROPERTY_V2 | POST /drive/v2/files/{file_id}/properties | drop invented docs | Real call is Drive properties.insert; Docs scope is not accepted. | properties.insert |
GOOGLEDRIVE_LIST_ACCESS_PROPOSALS | GET /drive/v3/files/{file_id}/accessproposals | drop invented docs | Real call is Drive accessproposals.list; Docs scope is not accepted. | accessproposals.list |
GOOGLEDRIVE_LIST_CHILDREN_V2 | GET /drive/v2/files/{folder_id}/children | drop invented docs | Real call is Drive children.list; Docs scope is not accepted. | children.list |
GOOGLEDRIVE_LIST_PROPERTIES_V2 | GET /drive/v2/files/{file_id}/properties | drop invented docs | Real call is Drive properties.list; Docs scope is not accepted. | properties.list |
GOOGLEDRIVE_PATCH_PERMISSION | PATCH /drive/v2/files/{file_id}/permissions/{permission_id} | drop invented docs | Real call is Drive permissions.patch; Docs scope is not accepted. | permissions.patch |
GOOGLEDRIVE_PATCH_PROPERTY_V2 | PATCH /drive/v2/files/{file_id}/properties/{property_key} | drop invented docs | Real call is Drive properties.patch; Docs scope is not accepted. | properties.patch |
GOOGLEDRIVE_STOP_WATCH_CHANNEL | POST /drive/v3/channels/stop | drop invented docs; add drive.meet.readonly | The Drive channels.stop method accepts the standard Drive/file/metadata/read scopes plus drive.meet.readonly, but not Docs scope. | channels.stop |
GOOGLEDRIVE_UPDATE_FILE_METADATA_PATCH | PATCH /drive/v2/files/{file_id} | drop invented docs | Real call is Drive files.patch; Docs scope is not accepted. | files.patch (v2) |
GOOGLEDRIVE_UPDATE_PROPERTY_V2 | PUT /drive/v2/files/{file_id}/properties/{property_key} | drop invented docs | Real call is Drive properties.update; Docs scope is not accepted. | properties.update |
| Action | Workbook signal | Why no change | Docs |
|---|---|---|---|
GOOGLEDRIVE_CREATE_FILE_FROM_TEXT | Rows 8/10/11/12: Slides rows marked ⚠ OVERLY BROAD; follow-up Drive rows mixed FULL MATCH/FAILED | This action has mutually exclusive branches. The normal branch is a Drive multipart upload (POST /upload/drive/v3/files), which legitimately keeps drive.appdata. The Slides branch creates a presentation, batch-updates slides, then does Drive files.get and optional files.update to move/read the result. presentations, spreadsheets, spreadsheets.readonly, or drive.readonly alone cannot satisfy the Drive write/move path. Branch-union result stays drive OR drive.appdata OR drive.file. | presentations.create, presentations.batchUpdate, files.create, files.get, files.update |
GOOGLEDRIVE_UPLOAD_FROM_URL | Row 101: ⚠ NOT FOUND | The workbook could not resolve the dynamic external source_url. That GET is not a Google OAuth-scoped API call; the only Google-authenticated call is the Drive multipart upload POST /upload/drive/v3/files, whose documented scopes already match Mercury (drive, drive.appdata, drive.file). | files.create |
download_file keeps only scopes that can actually return bytes, not scopes that stop at metadata.export_file inherits the files.export scope set because the metadata GET is only a precursor to export.create_file_from_text stays on the branch union, not an artificial AND across mutually exclusive Drive-vs-Slides flows.