> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Workspace Integration (PF-101) — Overview

> PF-101 makes Google Workspace a first-class platform connector alongside Microsoft Entra. It owns:

**Spec:** [`specs/pf/specs/PF-101-google-workspace-integration.md`](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/specs/PF-101-google-workspace-integration.md)
**Plan:** [`specs/pf/plans/PF-101-google-workspace-integration-PLAN.md`](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/plans/PF-101-google-workspace-integration-PLAN.md)
**Tasks:** [`specs/pf/tasks/PF-101-TASKS.md`](https://github.com/Encore-OS/encoreos/blob/development/specs/pf/tasks/PF-101-TASKS.md)
**Integration contract:** [`docs/architecture/integrations/PF-101-google-workspace-integration-INTEGRATION.md`](/architecture/integrations/google-workspace-integration-integration)
**Status:** Alpha — WS1/WS2/WS5/WS6 complete; WS7 in progress.

## What this integration does

PF-101 makes Google Workspace a **first-class platform connector** alongside Microsoft Entra. It owns:

* **Directory lifecycle** — provision / suspend / restore Workspace users from HR-01 employee events.
* **Gmail** — outbound mail via Workspace Domain-Wide Delegation, replacing the legacy `GMAIL_SERVICE_ACCOUNT_JSON` env-only path.
* **Calendar + Meet** — event creation, Meet conferencing, and free/busy queries for CE scheduling.
* **Licensing** — assign / revoke Google licenses (e.g., `Google-Apps-For-Business`) per user.
* **Reports** — ingest `admin`, `login`, and `token` audit activities into `pf_audit_log` (actor email SHA-256 hashed; no PHI).
* **Drive** — metadata-only mapping of Drive folders to platform resources (drive/folder IDs and names; never file contents). Explicit PF-11 export/import handles content transfer.
* **Chat** — notification delivery into mapped Chat spaces using **only** PF-10 approved templates. PHI is always blocked; no free-text parameters.

## Multi-tenant model

* One row in `pf_google_workspace_connections` per `(organization_id, primary_domain)`.
* All four PF-101 tables `ENABLE` **and** `FORCE` row level security and use the canonical `pf_has_org_access` / `pf_is_org_admin` SECURITY DEFINER helpers.
* Service account JSON, OAuth client secrets, and refresh tokens **never** live in tables, env vars, or logs — they resolve through **PF-76 Credential Vault** by stable `credential_vault_ref`.

## Capability flags & PHI gating (fail-closed)

Every Workspace operation runs through `assertCapabilityAllowed(connection, capability)` in `supabase/functions/_shared/google-workspace-client.ts`. The check denies by default and requires:

1. The capability column is `true` on the connection (e.g., `capability_gmail_enabled`).
2. For PHI-capable capabilities (Gmail, Calendar, Drive, Chat), `baa_attested_at IS NOT NULL`.
3. Sender domain (Gmail) matches the connection's `primary_domain` allowlist.

Failed checks short-circuit **before** any Google API call and write a row to `pf_google_workspace_sync_runs` with `status = 'failed'` and a sanitized `reason_code` — never the error body.

## Edge functions

| Function                               | Purpose                                                                                                                                 | Trigger                 |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| `google-workspace-test-connection`     | Per-capability health check (Directory, Gmail, Calendar, …)                                                                             | UI / cron               |
| `google-workspace-provision-user`      | Create or update Workspace user; upsert `pf_google_workspace_user_links`                                                                | HR-01 events            |
| `google-workspace-offboard-user`       | Suspend user; queue license revoke / group removal                                                                                      | HR-01 events            |
| `google-workspace-hr-event-subscriber` | Routes HR-01 employee events to provision / offboard                                                                                    | pgmq subscriber         |
| `google-workspace-directory-reconcile` | Compares HR employees vs Workspace `suspended` state                                                                                    | Cron (T5.5)             |
| `google-workspace-calendar-event`      | Create event with optional Meet link                                                                                                    | Platform API            |
| `google-workspace-calendar-freebusy`   | Query free/busy windows for one or more subjects (capability + subject-domain gated)                                                    | Platform API            |
| `google-workspace-license-manage`      | Idempotent SKU assign / revoke                                                                                                          | Platform API + offboard |
| `google-workspace-reports-ingest`      | Audit activity → `pf_audit_log` (hashed actor)                                                                                          | Cron                    |
| `google-workspace-drive-sync`          | Sync Drive folder metadata (IDs + names) into `pf_google_workspace_mappings` (`mapping_type='drive_folder'`); never reads file contents | Platform API            |
| `google-workspace-chat-notify`         | Render a PF-10 approved template into a mapped Chat space; rejects unapproved templates and over-long variables                         | Platform API            |

## Cross-core consumption

Cores never import Google client code directly. The only allowed surface is:

```ts theme={null}
import {
  createGoogleCalendarEvent,
  queryGoogleFreeBusy,
  assignGoogleLicense,
  revokeGoogleLicense,
  syncGoogleDriveMappings,
  sendGoogleChatNotification,
} from '@/platform/integrations/google-workspace';
```

`queryGoogleFreeBusy` is the only supported way to read Calendar availability; `syncGoogleDriveMappings` and `sendGoogleChatNotification` are the only supported Drive and Chat surfaces. All five enforce the same capability + BAA + sync-run pipeline as the rest of PF-101.

Gmail send routes via `supabase/functions/_shared/email-provider.ts`, which prefers a PF-101 connection and falls back to the legacy `GMAIL_SERVICE_ACCOUNT_JSON` env until each tenant migrates.

## Open decisions (per PLAN)

| Decision           | Resolution                                                                                                                          |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| HR update events   | Scheduled directory reconciliation (T5.5) until HR-01 ships `hr_employee_updated`                                                   |
| DWD key strategy   | PF-76-managed service-account key; harden toward IAM `signJwt`                                                                      |
| Drive content sync | Metadata-only (`mapping_type='drive_folder'`); explicit PF-11 action for content transfer                                           |
| Chat PHI           | Always blocked in Chat; only PF-10 templates marked `is_active` with `channel='chat'` (or `settings.chat_approved='true'`) are sent |

## See also

* [`GOOGLE_WORKSPACE_SETUP.md`](/integrations/GOOGLE_WORKSPACE_SETUP) — admin runbook
* [`GOOGLE_WORKSPACE_COMPLIANCE.md`](/integrations/GOOGLE_WORKSPACE_COMPLIANCE) — BAA, scopes, audit, retention
