mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-10 12:07:09 +02:00
## Thinking Path > - Paperclip helps people manage AI agents for work. > - The Connections page lists the apps and saved accounts that agents can use. > - Google Workspace verification is still pending. > - Google entries must be temporarily hidden from this page without removing their implementations. > - This PR filters the final page rows, including saved Google accounts, after the page resolves their provider. > - Definitions, direct setup routes, OAuth profiles, credentials, and runtime access stay intact. > - Review instances can keep the prior UI by staying on their pinned app release. ## Linked Issues or Issue Description **What existing behavior does this improve?** Temporary provider visibility on the Connections landing page. **Current behavior** The page can show Google Workspace catalog entries and saved accounts while verification is pending. **Proposed behavior** Hide all nine Google Workspace rows on this page. Keep every other connector and all Google integration code unchanged. Use an existing release pin for review instances instead of a hostname exception in the app. **Reason and benefit** Pause public discovery without disabling existing runtime tools or removing the implementation needed for verification and later re-enablement. **Breaking changes** Google accounts are no longer visible on this landing page. Direct setup and management routes remain available. This is not an access-control restriction. Related completed work: #13551 used catalog-level visibility. This change is deliberately limited to the landing page and also covers saved account rows. #14740 reduced Google scopes; this change leaves those scopes unchanged. No duplicate open PR or matching open issue was found. ## What Changed - Derive the Google app slugs from the existing Workspace profile registry. - Filter the combined catalog and saved-account rows only inside `Browse`. - Cover all nine Google entries, active/draft/disabled accounts, legacy connection metadata, mixed-provider rows, and independently identified non-Google connectors in regression tests. - Document the display-only hold, pinned review builds, and how to restore visibility after approval. ## Verification - Passed: `pnpm exec vitest run ui/src/pages/apps/Browse.test.tsx ui/src/pages/apps/AppsConnect.test.tsx` (199 tests, including the latest master changes). - Passed: `pnpm check:token-gates`. - Passed: `pnpm build`. - Passed: `pnpm -r typecheck` and `pnpm build` after merging the latest master. An earlier overlapping run hit a local runner codesign race; sequential checks passed. - Passed again after the final custom-provider fix: `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter @paperclipai/ui build`. - The full local `pnpm test:run` was started, then stopped after the full remote CI suite passed to avoid continuing duplicate long-running work on the developer machine. It is not claimed as a completed local pass. - All 54 latest-head CI checks passed. Two non-applicable Storybook jobs were skipped. One serialized server job lost its self-hosted runner connection; its single retry passed. - Greptile: 5/5 on `aeda167bf4494feed6ee0de2585960511fb02918`, with no unresolved review threads. - Confirmed in the existing review instance that all nine Google entries still appear after its current release was pinned. No new app release was deployed to that instance. - Reviewer steps: open Connections on this branch with Google catalog entries and saved Google accounts. None should appear. Non-Google connectors must remain. Direct Google setup routes must still load. ## Risks - Existing Google accounts cannot be found on this page during the hold. Their data and runtime access remain unchanged. - This is a UI-only filter, not an authorization gate. Direct routes and API access still work by design. - Review instances must not receive this UI build until the hold is removed. Their existing release pin excludes fleet app upgrades; an explicit targeted upgrade must still be avoided. - No migrations, backend changes, broker changes, or credential changes. ## Model Used OpenAI Codex (GPT-5-based coding agent), with reasoning, tool use, code execution, and browser inspection. The exact deployment model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
239 lines
13 KiB
Markdown
239 lines
13 KiB
Markdown
# Google Workspace connections
|
|
|
|
Paperclip presents Google Workspace as nine independent Apps entries, not as
|
|
one combined Google connection:
|
|
|
|
1. Gmail
|
|
2. Google Drive
|
|
3. Google Docs
|
|
4. Google Sheets
|
|
5. Google Slides
|
|
6. Google Calendar
|
|
7. Google Chat
|
|
8. Google People
|
|
9. Google Workspace Search
|
|
|
|
Each entry creates its own connection, consent grant, capability catalog,
|
|
policy, audit trail, and reconnect/revoke lifecycle. Connecting Drive does not
|
|
create a Docs or Sheets connection, and connecting Gmail does not enable
|
|
Workspace Search.
|
|
|
|
Google's hosted Workspace MCP servers are Developer Preview services. The app
|
|
cards remain independent even when several services use the same customer-owned
|
|
Google OAuth client or the same Paperclip Cloud broker deployment.
|
|
|
|
## Temporary Connections page visibility hold
|
|
|
|
While Google OAuth verification is pending, the Connections landing page
|
|
(`ui/src/pages/apps/Browse.tsx`) hides all nine Google Workspace entries,
|
|
including their saved accounts. This is a display-only filter. App definitions,
|
|
direct setup and management routes, OAuth profiles, saved credentials, and
|
|
runtime tools remain unchanged. This is not an access-control restriction.
|
|
|
|
Keep verification instances pinned to their pre-hold app release so reviewers
|
|
can still find and test the integrations. After approval, remove the page's
|
|
`GOOGLE_CONNECTOR_SLUGS` filter and update its visibility tests before upgrading
|
|
those instances. Do not disable the shared definitions or broker profiles to
|
|
control this page's visibility.
|
|
|
|
## Developer Preview enrollment
|
|
|
|
Google grants preview access to the specific Workspace email addresses and
|
|
Google Cloud project numbers registered with the program. Submitting the form
|
|
is not the approval signal:
|
|
|
|
1. Google first sends a Google Group membership notification after verifying
|
|
the Workspace account.
|
|
2. Google then sends a final confirmation after registering the Cloud project,
|
|
usually within a couple of days. This final email is the signal that MCP
|
|
testing can begin.
|
|
3. If no final confirmation arrives within a week, check spam and contact the
|
|
Developer Preview program team from the
|
|
[program page](https://developers.google.com/workspace/preview).
|
|
|
|
Enrollment does not authorize every user of an OAuth client. Additional tester
|
|
emails and Cloud projects must be added through Google's member request forms.
|
|
Google's preview terms also prohibit making a pre-GA integration available to
|
|
end users outside the enrolled company or domain unless Google grants explicit
|
|
permission. Consequently, Paperclip-managed Google OAuth is limited to
|
|
registered internal testers during preview. Other companies must enroll their
|
|
own Workspace testers and Cloud project and use a customer-owned OAuth app until
|
|
Google makes Workspace MCP generally available.
|
|
|
|
## App matrix
|
|
|
|
| App card | MCP endpoint | Capability choices |
|
|
| --- | --- | --- |
|
|
| Gmail | `https://gmailmcp.googleapis.com/mcp/v1` | Read only; read and create drafts |
|
|
| Google Drive | `https://drivemcp.googleapis.com/mcp/v1` | Read only; read and create files |
|
|
| Google Docs | `https://docsmcp.googleapis.com/mcp/v1` | Read only; read and edit |
|
|
| Google Sheets | `https://sheetsmcp.googleapis.com/mcp/v1` | Read only; read and edit; share selected sheets with the robot account |
|
|
| Google Slides | `https://slidesmcp.googleapis.com/mcp/v1` | Read only; read and edit |
|
|
| Google Calendar | `https://calendarmcp.googleapis.com/mcp/v1` | Read only; read and manage events |
|
|
| Google Chat | `https://chatmcp.googleapis.com/mcp/v1` | Read only; read and send messages |
|
|
| Google People | `https://people.googleapis.com/mcp/v1` | Read contacts |
|
|
| Google Workspace Search | `https://workspacemcp.googleapis.com/mcp/v1` | Search Workspace |
|
|
|
|
The setup flow asks for the capability first. When the managed method is
|
|
available, it uses Paperclip by default. A small **Use your own Google OAuth app**
|
|
link reveals the custom client fields; **Use Paperclip instead** returns to the
|
|
managed method. The available authentication methods are:
|
|
|
|
- **Connect with Paperclip** uses the Paperclip Cloud broker when that exact
|
|
profile is returned for this enrolled instance by the signed
|
|
`POST https://my.paperclip.app/v1/connector/instance-status` request. The
|
|
anonymous capabilities document is global discovery only and never enables
|
|
an internal-pilot method locally.
|
|
- **Use your own Google OAuth app** uses customer-supplied OAuth credentials and
|
|
the app definition's exact reviewed scopes.
|
|
- **Use the Paperclip robot account** remains an additional Google Sheets-only
|
|
option for explicitly shared spreadsheets.
|
|
|
|
Before Google consent, the setup flow asks whether the credential is for just
|
|
the connecting user or for any human in the company. A personal choice stores
|
|
the tokens only on that user's grant. A company choice stores them on the
|
|
default organization grant, while still recording which signed-in Google
|
|
principal completed consent so refresh and reconnect stay bound to that
|
|
principal.
|
|
|
|
Catalog discovery and connection creation use the same signed, instance-specific
|
|
profile availability. Local enrollment files and Cloud-delivered environment
|
|
identities follow this same path; neither enables managed methods globally in
|
|
the static app definitions. Saved connections remain recognizable for OAuth
|
|
callback, refresh, and revoke, while the broker enforces current profile access.
|
|
Switching capability or authentication methods preserves the selected credential
|
|
owner when the new method supports that owner.
|
|
|
|
## Broker profiles
|
|
|
|
The Paperclip-managed method signs every broker request with one explicit
|
|
profile. The broker binds that profile into sessions, one-time claims, sealed
|
|
token envelopes, and refresh. Per-profile removal is local-only for managed
|
|
Google grants. Google's revocation endpoint can invalidate all grants for the
|
|
same user and managed client, so Paperclip does not call it while removing one
|
|
Workspace profile.
|
|
|
|
| App | Read profile | Write profile |
|
|
| --- | --- | --- |
|
|
| Gmail | `gmail.read` | `gmail.draft` |
|
|
| Drive | `drive.read` | `drive.write` |
|
|
| Docs | `docs.read` | `docs.write` |
|
|
| Sheets | `sheets.read` | `sheets.write` |
|
|
| Slides | `slides.read` | `slides.write` |
|
|
| Calendar | `calendar.read` | `calendar.write` |
|
|
| Chat | `chat.read` | `chat.write` |
|
|
| People | `people.read` | — |
|
|
| Workspace Search | `workspace-search.read` | — |
|
|
|
|
Every new signed request includes a profile. The Cloud broker rejects a request
|
|
whose provider, profile, or exact scope set does not match its closed registry.
|
|
|
|
## Instance configuration
|
|
|
|
All Paperclip-managed Google methods use the existing enrolled-instance keys:
|
|
|
|
```dotenv
|
|
PAPERCLIP_CLOUD_CONNECTOR_BASE_URL=https://my.paperclip.app
|
|
PAPERCLIP_CLOUD_CONNECTOR_ENVIRONMENT=production
|
|
PAPERCLIP_CLOUD_CONNECTOR_INSTANCE_ID=inst_example
|
|
PAPERCLIP_CLOUD_CONNECTOR_SIGN_PRIVATE_KEY=...
|
|
PAPERCLIP_CLOUD_CONNECTOR_SEAL_PRIVATE_KEY=...
|
|
```
|
|
|
|
No per-app client secret is stored on the Paperclip instance for the managed
|
|
path. For customer-owned OAuth, the setup flow collects that customer's Google
|
|
OAuth client ID and secret and stores them through the normal instance-vault
|
|
path.
|
|
|
|
Cloud-hosted stacks receive these values through the existing per-stack secret
|
|
delivery path. A self-hosted instance creates its keys during enrollment and
|
|
stores them with owner-only permissions in the instance's ignored secret
|
|
directory. The setup page supplies its authenticated same-origin HTTPS address
|
|
to enrollment, so a normal Tailscale-hosted self-hoster does not need to edit
|
|
`config.json` or set `PAPERCLIP_PUBLIC_URL`; the enrolled origin becomes the
|
|
durable callback binding. The former `PAPERCLIP_ID_CONNECTOR_*` values use an incompatible
|
|
Paperclip ID protocol and are not read aliases. Enroll with Paperclip Cloud and
|
|
reconnect legacy grants before their old access tokens expire.
|
|
|
|
The gallery requests the broker capability document with a short cache. A
|
|
Paperclip-managed method is omitted unless its exact profile is enabled at the
|
|
broker; the independent app card and customer-owned OAuth method remain
|
|
available. This supports profile-by-profile rollout and rollback without
|
|
collapsing the nine cards into one app.
|
|
|
|
See [Gmail connection](./GMAIL.md) for the detailed enrollment, signing,
|
|
encryption, environment-isolation, and security review runbook inherited by all
|
|
profiles.
|
|
|
|
## Safety boundary
|
|
|
|
Every Google profile has an explicit MCP tool allowlist. Unknown Developer
|
|
Preview tools default to disabled. Read profiles expose only reviewed read
|
|
operations. Write profiles add only the reviewed write operations for their app;
|
|
destructive or unreviewed tools do not become available merely because Google
|
|
adds them upstream.
|
|
|
|
### Service-specific minimum scopes (2026-09-30)
|
|
|
|
Docs, Sheets, and Slides request only their service's read-only scope in the
|
|
read profile and its read/write scope in the write profile. They do not also
|
|
request `drive.readonly` or `drive.file`: those are authorization alternatives,
|
|
not additional requirements. Drive and Workspace Search retain their separate
|
|
Drive permissions. Calendar write requests `calendar.calendarlist.readonly`
|
|
and `calendar.events`; the latter also authorizes `suggest_time`. Calendar read
|
|
retains `calendar.events.freebusy` alongside list/event read-only access.
|
|
|
|
References: Google's [Docs read](https://developers.google.com/workspace/docs/api/reference/mcp/tools_list/read_doc)
|
|
and [update](https://developers.google.com/workspace/docs/api/reference/mcp/tools_list/update_doc),
|
|
[Sheets read](https://developers.google.com/workspace/sheets/api/reference/mcp/tools_list/get_spreadsheet)
|
|
and [update](https://developers.google.com/workspace/sheets/api/reference/mcp/tools_list/update_values),
|
|
[Slides read](https://developers.google.com/workspace/slides/api/reference/mcp/tools_list/read_presentation)
|
|
and [update](https://developers.google.com/workspace/slides/api/reference/mcp/tools_list/update_presentation),
|
|
and [Calendar suggest_time](https://developers.google.com/workspace/calendar/api/v3/reference/mcp/tools_list/suggest_time).
|
|
|
|
The write scopes support editing existing accessible files by ID. `drive.file`
|
|
is a valid narrower alternative for app-authorized files, but would require a
|
|
different per-file authorization workflow. Read-only profiles remain separate;
|
|
the project-wide union is not the scope set requested by every connection.
|
|
|
|
Deploy with the matching Cloud broker registry and test fresh grants in staging
|
|
before production. Signed authorization and refresh requests use exact scope
|
|
sets, so mixed versions fail closed. The broker rejects old broader grants and
|
|
refresh responses without explicit scope evidence for these reduced profiles.
|
|
Reconnect affected connections; do not relabel or globally revoke existing
|
|
tokens. Customer-owned methods request the same reduced sets on new consent;
|
|
previously issued grants are not retroactively narrowed. The 21-scope integration
|
|
union is unchanged by these profile-level reductions. Console must still keep
|
|
Drive/free-busy entries required by other profiles and separately used identity
|
|
scopes. Fresh provider proof is a release requirement, not implied by unit tests.
|
|
|
|
### Google Chat scope reduction (2026-09-22)
|
|
|
|
`chat.read` requests only `chat.spaces.readonly` and `chat.messages.readonly`.
|
|
`chat.write` adds `chat.messages.create`. The same sets apply to both managed
|
|
and customer-owned OAuth methods. Neither requests `chat.memberships.readonly`
|
|
nor `chat.users.readstate.readonly`.
|
|
|
|
Conversation lookup, message history, ordinary message search, and the write
|
|
profile's message sending remain supported. Membership listing and marking
|
|
messages read/unread remain outside the tool allowlist. `search_messages`
|
|
cannot filter by read state: the app hides `isUnread` from its agent and Test
|
|
schemas and rejects any explicit `isUnread`/`is_unread` argument, including
|
|
`false` or `null`, before dispatch. It never silently drops the filter. The
|
|
guard also applies to cached catalogs and existing broader grants.
|
|
|
|
References: Google's [Chat MCP setup](https://developers.google.com/workspace/chat/api/guides/configure-mcp-server)
|
|
and [message-search parameters](https://developers.google.com/workspace/chat/api/reference/mcp/tools_list/search_messages).
|
|
|
|
Roll out the app and Cloud broker scope registries together in staging and
|
|
production: their signed requests and sealed credentials use exact scope sets.
|
|
During a mixed-version rollout, Chat authorization/refresh can fail closed.
|
|
Existing Google tokens are not retroactively narrowed or revoked by this code
|
|
change. A refresh response still containing removed scopes, or omitting the
|
|
scope set needed to verify the grant, is rejected by the broker; reconnect
|
|
affected Chat grants for new consent. Do not revoke the
|
|
shared Google client to migrate one profile, because that can break other
|
|
Workspace connections. After deployment, verify fresh reduced-scope consent,
|
|
ordinary Chat search/history and sending, then reconcile Google Console and
|
|
the verification evidence with the deployed scope set.
|