Google Docs
Proxy for the Google Docs v1 REST API — which is the entire API surface:
create_document, get_document, and batch_update. Dual auth by design,
like drive and calendar:
idp_passthroughmode for human users who want an agent to read or edit documents they own. Each request carries the caller's own OAuth grant.google_samode (Workspace service account with domain-wide delegation) for headless workflows that read or write shared documents on a fixed identity's behalf.
Overview
Typical uses:
- An agent reads a doc's structured content and summarizes it
(
get_document). - A drafting workflow creates a doc and inserts/templates text into it
(
create_document, thenbatch_updatewithinsertText/replaceAllText).
Two upstream-shape notes specific to Docs:
- No list endpoint. The Docs API can't enumerate documents; discover
document IDs via the Google Drive connector (filter on
mimeType = 'application/vnd.google-apps.document'), then operate on the ID here. - Everything mutating is
batch_update. All content edits and deletes (insertText,replaceAllText,deleteContentRange, table ops) are request objects onbatch_update; deleting an entire document file is the Drive connector's job.
Default policy
The connector ships policy/docs.rego
(package pbac.connectors.identos.google_docs). It enforces:
1. IdP-routing subject obligation
subject_obligations contains obl if {
input.resource.type == "urn:connector:identos:google-docs"
input.connector.upstream_auth.type == "idp_passthrough"
input.subject.idp_provider != "google"
obl := { "type": "require_authn_at", "idp": "google", ... }
}
Same pattern as google-drive/gmail — a caller from a non-Google session gets a step-up obligation before any passthrough Docs call succeeds.
2. Blocked and read-only documents
Blocking a specific document is operator config on the general file-access
control, not a rule in this connector. An identity source matches a
document by its own id: ids in blocked are denied on reads and writes, ids
in write_blocked are denied on writes only (batch_update), so reads still
work. See File access control below for the shape —
an identity source pools with any label or location source governing the
same connector.
File access control
Documents can be gated by Drive Labels and/or by folder/shared-drive
location — a document is returnable via get_document if it matches any
governing source's approval (an approved label or an approved folder),
and denied if it matches any source's blocked (pooled OR, deny-wins). This
is configured through the shared file_access operator control, used across
all Google file connectors (Docs, Sheets, Slides, Drive). Full mechanics (the
pooled predicate, OR-combine and deny-wins, fail-closed rules) live in the
File Access Control guide;
for getting label/folder IDs and the required OAuth scopes, see the
Google file access setup guide.
Configuration uses a two-level model:
- Define a policy per source — under
pbac.operator.controls.file_access.sources, each source declares atype(label,location, oridentity— the resource's own id), arequiredallowlist (any-of; file must match ≥1), ablockeddenylist (file withheld if it matches any — always wins), and an optionalwrite_blockeddenylist that applies to mutating calls only. Approving a whole folder is alocationsource with the folder ID inrequired(Google Drive does not allow labels on folders):
curl -X PUT http://localhost:8080/admin/policy/data/pbac/operator/controls/file_access \
-H "X-Admin-API-Key: $PBAC_ADMIN_API_KEY" \
-d '{
"sources": {
"google-drive-labels": {
"type": "label",
"required": ["approved-for-ai"],
"blocked": ["restricted"]
}
},
"governed": {
"urn:connector:identos:google-docs": ["google-drive-labels"]
}
}'
- Activate per connector — under
governed, list (as an array) which sources govern each connector's resource type; all listed sources pool into one OR-of-approvals, deny-wins decision — a file is returnable if it matches any source'srequiredand withheld if it matches any source'sblocked. Omitting a connector leaves it ungoverned (inert; no check). Once a source is configured and a connector is governed by it, enforcement is fail-closed: reads that cannot verify the file's values are denied (403).
The control resolves document IDs from tool invocations to fetch labels/location; file and scope requirements are documented in the spec at docs/superpowers/specs/2026-08-11-general-file-access-control-design.md.
Scope model
| Scope | Used for | |
|---|---|---|
| PBAC scopes (internal) | docs:read, docs:write | Route authorization |
| Upstream OAuth scopes | documents | Google-side grant the user consents to (idp_passthrough mode); the service-account flow uses the same scope on the SA |
See Google Workspace: multi-connector setup for how docs' scopes compose with drive, gmail, and calendar on a single Google IdP.
Manifest reference
- ID:
identos.google-docs - Version:
1.1.0 - Resource type:
urn:connector:identos:google-docs
Supported auth modes
| Type | Details |
|---|---|
idp_passthrough | requires IdP google |
google_sa | setup fields: sa_key_env, domain |
Setup fields
| ID | Label | Default | Secret? | Notes |
|---|---|---|---|---|
base_url | API base URL | https://docs.googleapis.com | no | — |
upstream_auth.type | Authentication | idp_passthrough | no | idp_passthrough forwards each user's own Google OAuth token (recommended). google_sa uses a Workspace service account with domain-wide delegation impersonating a fixed user. |
sa_key_env | Service account key | — | yes | Pick a secret containing the service-account JSON. Required only for the google_sa auth mode. / shown when upstream_auth.type == 'google_sa' |
domain | Workspace domain | — | no | placeholder: example.com / Required only for the google_sa auth mode. / shown when upstream_auth.type == 'google_sa' |
Scopes
| Scope |
|---|
docs:read |
docs:write |
Routes
| Method | Pattern | Scope | Resource template |
|---|---|---|---|
POST | /v1/documents | docs:write | — |
GET | /v1/documents/{document_id} | docs:read | docs://{{document_id}} |
POST | /v1/documents/{document_id}:batchUpdate | docs:write | docs://{{document_id}} |
MCP tools
| Name | Scope | Description |
|---|---|---|
create_document | docs:write | Create a new, empty document. Pass {"title": "..."}. Add content afterward with batch_update. |
get_document | docs:read | Get a document's full structured content (body, styles, lists, etc.). |
batch_update | docs:write | Apply one or more content edits (insertText, replaceAllText, deleteContentRange, table ops, styling, …) via Docs Request objects. This is also how you DELETE content. |