Skip to main content

Google Calendar Sync (v1)

FieldValue
StatusDeferred. Not included in any current tier.
OwnerUnassigned
Target reposattunelogic-api, attunelogic-service
RelatedMonetization & Tier Packaging (v1), Feature Roadmap Index
Last updated2026-04-23

Status banner: Google Calendar sync was removed from the public Growth tier during the v1 packaging pass. Customers who need calendar visibility today should subscribe to the iCal feed planned as a tier-wide fallback.


Why this was removed from v1

  • No OAuth to Google is wired today. Launch-week would have required a fresh Google Cloud project, OAuth consent-screen verification (multi-week review for sensitive scopes), and a per-user calendar-mapping UI.
  • The overwhelming majority of "I want to see my jobs in a calendar" asks are satisfied by a read-only iCal feed per office user — which has no OAuth, no consent screen, no token refresh, and no tenant-isolation escape hatches. That path is tracked separately and will ship before v1 calendar sync is reopened.

What shipping this requires

Data model

  • User.integrations.googleCalendar:
    • connected: boolean
    • accessTokenCipher, refreshTokenCipher
    • accessTokenExpiresAt: Date
    • calendarId: string (Google's calendar target — primary, shared dispatch calendar, etc.)
    • scopes: string[]
    • pushedEventIds: Map<jobId, googleEventId> — idempotency map for update/delete.

API surface

  • POST /api/v1/integrations/google-calendar/connect — OAuth authorize URL.
  • GET /api/v1/integrations/google-calendar/callback — exchange code, persist tokens, store user-selected calendarId.
  • POST /api/v1/integrations/google-calendar/disconnect — revoke + clear.
  • Background worker listening on job.created / job.updated / job.cancelled events. Push creates an event with:
    • Summary = job number + leg summary
    • Start/end = first dispatch window / last delivery window
    • Location = first stop address
    • Description = short manifest summary + deep link back to the job in service web app.
  • Idempotency: key on googleEventId in pushedEventIds; update instead of re-create.

Service web UI

  • Settings → Integrations → Google Calendar: Connect / Disconnect, target calendar picker, "test push" button.
  • Per-office-user setting (not tenant-wide) — each dispatcher picks their own target calendar.

OAuth + secrets

  • Google Cloud project + OAuth consent screen verification for the scopes needed:
    • https://www.googleapis.com/auth/calendar.events (read/write events)
    • https://www.googleapis.com/auth/calendar.readonly (list user's calendars to populate the picker)
  • GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, redirect URIs per environment.
  • Token-refresh worker (access tokens expire in ~60 min; refresh tokens are long-lived but can be invalidated).

Tests

  • Unit: OAuth callback, token refresh, disconnect.
  • Integration: create / update / cancel round-trip against mocked Google APIs.
  • Tenant + user isolation: user A's push never reads or writes to user B's calendar.

Docs

  • "Connect Google Calendar" customer walkthrough.
  • Dev runbook on revoked refresh tokens + reconnect flow.

Dependencies on existing infra

  • User model — already multi-tenant, extends cleanly under User.integrations.
  • Job lifecycle eventssrc/controllers/jobs already emits create/update/cancel hooks.
  • Job queue — reuse existing agenda/bull queue for debounced pushes.
  • Deep-link — service web already has a job-detail route we can reference.

Estimated timeline and risk

  • Effort: 1.5–2 weeks once OAuth consent is approved. Consent-screen verification with calendar.events scope historically takes 1–3 weeks of Google review; start early.
  • Risk: Medium. The work is mechanical; the schedule risk is entirely the Google verification queue.

Open questions

  • Do we sync per-user calendars or a shared "dispatch" calendar, or both?
  • Do we want a shim for Microsoft Outlook calendar from day one, or tackle that in SSO-v1 (which already registers Microsoft as an identity provider)?
  • Is there a future "job → meeting invite for crew" flow we should design into the event schema now?

Cross-references