Documentation source
Documentation source
Documentation source
Read-only Gmail, Calendar, Drive, Docs, Sheets, and Meet ingestion with incremental cursors and disabled watch channels.
## Shipping posture
The Google Workspace integration is read-only and disabled until an operator
connects it and Tyler approves the first production sync. It contains no Gmail
send or Calendar mutation operation. The scheduled Sprinter action ships with
`status: disabled`, real reads are blocked unless
`GOOGLE_WORKSPACE_READ_SYNC_ENABLED` is exactly `true`, and watch registration
is independently blocked unless
`GOOGLE_WORKSPACE_WATCH_ENABLED` is exactly `true`.
The OAuth preset requests only:
- `gmail.readonly`
- `calendar.readonly`
- `drive.readonly`
- `documents.readonly`
- `spreadsheets.readonly`
- `meetings.space.readonly`
OAuth client credentials use `GOOGLE_WORKSPACE_CLIENT_ID` and
`GOOGLE_WORKSPACE_CLIENT_SECRET`. Values stay in the encrypted connection and
deployment environment; they are never placed in a connector spec or tenant
declaration.
## Read resources
| Service | Read path | Amble result |
| -------- | -------------------------------------------------------- | --------------------------------------------------- |
| Gmail | Message inventory or history, followed by message detail | `google-workspace-email` entity |
| Calendar | Primary-calendar events | `google-workspace-calendar-event` entity |
| Drive | Change feed followed by file metadata | `google-workspace-drive-file` entity |
| Docs | `documents.get` for Docs discovered by Drive | linked `google-workspace-doc` entity and document |
| Sheets | `spreadsheets.values.get` for Sheets discovered by Drive | linked `google-workspace-sheet` entity and document |
| Meet | Conference records, transcripts, and transcript entries | meeting and transcript entities |
Google-native Docs and Sheets and supported Drive binaries also have a bounded
post-sync attachment pass. It attaches through the shared document upload
pipeline, records the Drive external ID plus version/checksum as provenance,
and skips an identical second version. Binaries do not enter the JSON raw
ledger.
## Incremental behavior
Google exposes three different checkpoint protocols:
- Gmail persists the final `historyId` and calls `users.history.list` on the
next run. An expired history ID returns 404; the integration performs a
bounded full message pull and proposes a fresh history ID.
- Calendar persists the final `nextSyncToken` from a completed events listing.
A 410 resets only Calendar and performs a bounded full events pull.
- Drive persists `startPageToken`/the final `newStartPageToken`. A 410 resets
only Drive, performs a bounded full file inventory, and proposes a fresh
baseline.
Intermediate `nextPageToken` values remain in memory. The shared runner writes
the three final checkpoints only after an apply run completes with zero mapping
failures. Dry runs never advance them.
Meet is a bounded full listing with in-memory page tokens; it does not add a
fourth durable checkpoint.
## Dry-run and apply
Use the generic admin sync endpoint after creating a `google-workspace`
connection. Start with a five-row dry run:
```bash
curl -X POST "$APP/api/admin/integrations/google-workspace/sync" \
-H "Content-Type: application/json" \
-d '{"mode":"dry_run","count":5}'
```
Dry run writes no entities or documents. Review the per-resource samples and
conflicts before an apply. Apply uses tenant-scoped external identities such as
`google-workspace:gmail-message` and is safe to repeat.
Gmail raw-ledger capture is an allow-listed metadata projection: it excludes
message bodies, snippets, headers, and correspondents. Meet raw capture excludes
transcript text and participant identities. Mapping still receives the
in-memory response so the intended tenant entity/document can be created.
All automated tests use seeded responses and injected fetches. They do not
prove live Google access.
## Watch channels remain off
The code models registration, seven-day expiry, and renewal for Gmail,
Calendar, and Drive. It does not schedule registration and cannot make a watch
request while the Tyler gate is false.
- Gmail watch needs a production Google Cloud Pub/Sub topic and calls
`users.watch`.
- Calendar and Drive need a stable public HTTPS callback for their channel
endpoints.
- Tracking rows contain channel/resource IDs and expiry only. The table has
tenant and connection foreign keys, RLS, and service-role-only access. It
stores no credential or channel verification value.
No live watch channel was registered while this integration was developed.
## Tyler enablement checklist
Do not enable the first production sync or any watch registration until Tyler
has approved every item:
1. Select the production Google Cloud project and verify the OAuth consent
screen, app ownership, support contact, and authorized redirect URI.
2. Verify the requested grant is exactly the six read-only scopes above. Reject
any Gmail send, Calendar write, Drive write, or broader Workspace grant.
3. Configure `GOOGLE_WORKSPACE_CLIENT_ID` and
`GOOGLE_WORKSPACE_CLIENT_SECRET` in the production deployment, then complete
one tenant-scoped OAuth connection.
4. Obtain Tyler's approval to set
`GOOGLE_WORKSPACE_READ_SYNC_ENABLED=true`, then run a five-row dry run;
inspect Gmail/Meet capture redaction, entity mapping, document provenance,
and all three proposed cursors.
5. Obtain Tyler's separate approval before the first apply and keep the cron
action disabled until that apply is reviewed.
6. For watch only: provision the Gmail Pub/Sub topic and publisher permission,
deploy and verify the stable HTTPS callback, confirm the seven-day renewal
monitor, then obtain separate Tyler approval before setting
`GOOGLE_WORKSPACE_WATCH_ENABLED=true`.
Turning on scheduled reads does not turn on watch registration. The watch gate
is a separate production decision.