{
  "connector": "google-drive",
  "label": "Google Drive",
  "vendor_docs": "https://developers.google.com/drive/api/reference/rest/v3",
  "summary": "A Google Drive with Docs and Sheets that answers Drive v2 and v3, Docs v1, Sheets v4 and uploads for Google's client libraries, plus Drive's MCP paths.",
  "surfaces": [
    {
      "kind": "REST",
      "path": "/drive/v3",
      "notes": "files, permissions, comments, revisions, changes and watch channels; Drive v2 reads under `/drive/v2`"
    },
    {
      "kind": "REST",
      "path": "/upload/drive/v3",
      "notes": "simple, multipart and resumable uploads"
    },
    {
      "kind": "REST",
      "path": "/v1/documents",
      "notes": "Google Docs v1"
    },
    {
      "kind": "REST",
      "path": "/v4/spreadsheets",
      "notes": "Google Sheets v4"
    },
    {
      "kind": "OAuth",
      "path": "/token",
      "notes": "OAuth client credentials with Google-style scopes"
    },
    {
      "kind": "MCP",
      "path": "/mcp",
      "notes": "also at `/mcp/v1`, the path Google's Drive MCP server publishes"
    }
  ],
  "api_versions": [
    "Drive v2 (reads)",
    "Drive v3",
    "Docs v1",
    "Sheets v4"
  ],
  "supported": [
    {
      "item": "Bearer tokens and the `access_token` query parameter Google also accepts"
    },
    {
      "item": "Google scopes `drive`, `drive.readonly`, `drive.metadata.readonly`, `drive.file`, `documents`, `spreadsheets`; a read-only signed token gets `403 insufficientPermissions` on a write"
    },
    {
      "item": "`401 authError` with `WWW-Authenticate: Bearer` for a missing or unverifiable token, so an SDK refreshes its credential"
    },
    {
      "item": "The `q` search grammar"
    },
    {
      "item": "`files.export` up to 10 MiB, and `exportLinks` for larger exports"
    },
    {
      "item": "Watch channels with the `sync` handshake, per-file resource states, `X-Goog-Changed` and `expiration`"
    }
  ],
  "unsupported": [
    {
      "item": "`apps.*`, `teamdrives.*`, labels, access proposals, approvals, client-side encryption and `operations.get`"
    },
    {
      "item": "Sheets `developerMetadata.*` and the Docs and Sheets styling requests"
    },
    {
      "item": "Formula evaluation in Sheets"
    },
    {
      "item": "Converting an imported binary document (`.doc`, `.odt`, `.xlsx`) into Docs text"
    }
  ],
  "differences": [
    {
      "scenario": "Sheets values",
      "difference": "Values are stored verbatim; formulas are not evaluated and `FORMATTED_VALUE` returns the stored value.",
      "guidance": "Do not assert on computed cells or number formatting."
    },
    {
      "scenario": "Revisions",
      "difference": "Each content version is listed, but only the head revision's bytes are kept.",
      "guidance": "Do not download an older revision's content and compare it."
    },
    {
      "scenario": "Sharing and permissions",
      "difference": "Permissions are recorded and returned but not enforced per grantee; every token sees every file.",
      "guidance": "Do not use the replica to prove that a user cannot read a file."
    },
    {
      "scenario": "Scopes with an opaque token",
      "difference": "Scope checks only apply to IdP-signed tokens that carry a `scope` claim; an opaque bearer in open mode passes every request.",
      "guidance": "Request a signed token with a read-only scope from `/token` to test refusals."
    },
    {
      "scenario": "Imported binary documents",
      "difference": "Uploading a `.doc`, `.odt` or `.xlsx` as a Google Doc creates the Doc with empty text, so exporting it returns an empty body.",
      "guidance": "Do not assert on text extracted from an imported Office file."
    },
    {
      "scenario": "Watch notifications",
      "difference": "Delivery is in-process with three retries on 5xx; a notification is lost if your consumer is down for the whole backoff window, and channels do not survive a restart.",
      "guidance": "Re-read the changes feed after downtime rather than relying on every notification."
    },
    {
      "scenario": "Quotas",
      "difference": "No quota is enforced unless injected, and the injected status cannot be chosen per quota family.",
      "guidance": "Inject `throttle` or `quota_limit` to test backoff; do not test per-family quota handling."
    }
  ],
  "faults_supported": [
    {
      "fault": "throttle",
      "behaviour": "429 `userRateLimitExceeded` in Google's error envelope, with `Retry-After`"
    },
    {
      "fault": "fail_next",
      "behaviour": "The next N calls fail as `throttle` does, then clear"
    },
    {
      "fault": "quota_limit",
      "behaviour": "429 `quotaExceeded` in Google's error envelope"
    },
    {
      "fault": "error_rate",
      "behaviour": "500 `internalError` for the given fraction of calls"
    },
    {
      "fault": "latency_ms",
      "behaviour": "Fixed added latency on every data-plane request"
    }
  ]
}
