Runbook: Gsuite Disabled-Mode Behavior
P3 / informational. What the platform does when Google Workspace is not configured โ no
GSUITE_SERVICE_ACCOUNT_KEY_JSON/GSUITE_ADMIN_USER_EMAIL, or creds present but broken. This is the expected state in dev/test and in any env before Workspace Admin DWD is provisioned. SeeOWNERS.mdfor on-call.
The contract (ADR-0002 Phase 2, #1179): never crash, never silently write a half-provisioned OSA row, always surface a clear "disabled" indicator.
Full verification recap (all scenarios + evidence): gsuite-disabled-mode-verification.md.
How to tell which mode you're inโ
At boot, GoogleAdminClient logs exactly one line:
| Boot log | disabledReason | Meaning |
|---|---|---|
WARN Gsuite disabled โ no service account configured โฆ | no-credentials | Expected dev/test state. Provisioning is skipped. |
ERROR Gsuite config incomplete โ exactly one of โฆ | config-incomplete | Only one of the key/admin-email pair is set. Misconfig โ set both. |
ERROR Gsuite credentials invalid โ โฆ | invalid-credentials | Key present but unparseable. Misconfig โ fix the SA JSON. |
LOG Google Admin SDK initialized (impersonating โฆ) | null | Enabled. |
Boot never aborts on any of these โ a malformed secret degrades to disabled rather than crash-looping the API under active-active.
What each surface does when disabledโ
- Provisioning jobs (
workspace-provisioningqueue) โ behavior depends on thedisabledReason:no-credentials(intentional disable): every job (create/suspend/archive/restore/set-sendas) completes as a no-op withJob โฆ skipped: gsuite disabled (no-credentials) โ OSA โฆ left unprovisioned. No Sentry event, no AM notification, no DB write ofgsuite_user_id/gsuite_provisioned_at.email_aliasmay already be set (a pure string compute) โ that's fine.invalid-credentials/config-incomplete(misconfiguration): the job throws (gsuite is misconfigured (<reason>) โ refusing to silently no-op โฆ) โ BullMQ retries โonFailedfires the Sentry + AM alert. This is deliberate: a misconfig must not silently drop a lifecycle op. It matters most for suspend/archive under credential rot โ otherwise a Specialist would silently keep Workspace access they should have lost. Fix the creds and the retried job (or a re-trigger) completes.
- Per-org enqueue gate: in dev/staging the producer
(
isGsuiteProvisioningEnabledForOrg) does not even enqueue. The processor guard above is defense-in-depth for the explicit AM Provision action, which overrides the env default. - OAuth token reads (
OAuthTokenService.getAccessToken): an OSA with no refresh token throws the typedOAuthTokenUnavailableError(carriesosaId), not a generic error. Catch it and no-op. - OSA detail UI (
/ops/clients/[id]/specialists/[assignmentId]): shows theemail_alias, rendersgsuite_user_idas "Not provisioned" and timestamps as "โ", status badge Pending. Noundefined, no console error.
To enable Gsuite in an environmentโ
- Set both
GSUITE_SERVICE_ACCOUNT_KEY_JSON(full SA JSON) andGSUITE_ADMIN_USER_EMAIL(admin to impersonate via DWD). - Restart the API; confirm the boot log reads
Google Admin SDK initialized (impersonating โฆ). - Per-org: flip the GSuite provisioning toggle on the client detail page, or
rely on the
productionenv default. See workspace-provisioning-failure.md for the enabled-path failure runbook.
When this is a real problem (not expected)โ
config-incompleteorinvalid-credentialsin staging/production โ a misconfigured secret. The boot logs an error, and lifecycle jobs fail loudly (Sentry + AM "provisioning failed" alert) rather than skipping โ so this also shows up as failedworkspace-provisioningjobs. Fix the env var and restart; cross-check against workspace-provisioning-failure.md.- OSAs stuck at
gsuite_user_id = NULLin an env you expected to be enabled โ check the boot log'sdisabledReasonfirst; it's the fastest triage signal.