Polls Google Calendar events for configured accounts and writes individual JSON files with SHA-256 hash-based change detection.
| Script | Description |
|---|---|
poll.ts |
Iterates the pipeline.accounts that have a calendar block, fetches events via the Calendar API, writes JSON files to silo-routed directories with change detection |
flowchart LR
config["pipeline.accounts\n(instance config)"] --> poll["poll.ts"]
poll --> gcal["Google Calendar REST API\n(gog OAuth client or service account)"]
gcal --> events["per-event JSON files\n(silo-routed by email domain)"]
lib/calendar-api.ts) with an access token from createGoogleAuth (from the platform package, @karmaniverous/jeeves), read-only scope (calendar.readonly). It does not shell out to the gog binary; it only reads the credential files gog manages.freeBusyReader are skipped), and fetches all events in the window, also following every page. Both lists share one pager (listAllPages() in lib/calendar-api.ts).lastSync - 24 h (first run: 90 days back) to 90 days forward._hash) of the significant fields (summary, description, start, end, location, status, attendee emails and responses, recurrence, updated). An event whose hash is unchanged is not rewritten.{silo}/calendar/{accountEmail}/{calendar name}/{eventId}.json, where {silo} is getBasePathForEmailDomain(<account's domain>) and {calendar name} is the calendar's summary (or id), sanitized. Each file is the API event plus _calendarId, _calendarSummary, _ingestedAt and _hash, and _people ({ id, name } of the organizer, creator and attendees listed in the people config, config.md) when any are listed. _people is not part of the hash, so an unchanged event picks up a people change when it next changes.calendar, key lastSync-<email> (ISO timestamp), written after the account's calendars are polled.Calendar accounts are the entries of pipeline.accounts in the instance config that have a calendar block (see the pipeline block):
"calendar": { "serviceAccount": "auto" }: a Workspace mailbox through domain-wide delegation. The poller uses the service-account registration gog keeps for that mailbox, sa-<base64(email), "=" padding stripped>.json, looked up in <GOG_CONFIG_DIR>/data/ first, then in the <GOG_CONFIG_DIR> root (older gog builds without data/). Resolved by findServiceAccountFile() in lib/gog-credentials.ts."calendar": { "tokenFile": "<path>" }: a personal account with an OAuth refresh token. tokenFile is relative to CREDENTIALS_DIR, and the account also needs the gog OAuth client at GOG_CLIENT_PATH (<GOG_CONFIG_DIR>/credentials.json).GOG_CONFIG_DIR is gog's home: GOG_HOME when set, else paths.gogHome, else {configDir}/gogcli (paths().gogHome). The key file jeeves-tools deploy writes (<GOG_CONFIG_DIR>/service-account.json) is not read by the poller; only the per-mailbox sa-*.json that gog auth service-account set registers is.
pipeline.accounts (above).lib/calendar-accounts.ts before polling): a tokenFile account needs the OAuth client, and a serviceAccount: "auto" account needs that mailbox's own sa-*.json; an unrelated credential does not count. An instance with only service-account mailboxes and no OAuth client works for its serviceAccount accounts.[credentials] errors, the other accounts are still polled, and then the run fails (non-zero exit). So a run with calendar accounts configured but neither an OAuth client nor any matching service-account registration fails rather than skipping. With no calendar accounts configured the run skips (exit 0).| Job | Schedule | Manifest |
|---|---|---|
calendar-poll |
Every 17 min | core jobs/calendar.json |
The manifest entry carries a non-null prerequisite.
| File | Purpose |
|---|---|
lib/calendar-api.ts |
Google Calendar REST API helpers — listCalendars() and getAllEvents(), each following every page (nextPageToken) |
lib/calendar-accounts.ts |
resolveCalendarAccounts(): maps each configured account to its auth config and reports accounts missing their own credential |
../lib/gog-credentials.ts |
detectGogCredentials() (OAuth client present?) and findServiceAccountFile() |
../config/pipeline-accessors.ts |
Provides getCalendarAccounts() |
../config/silo-router.ts |
Provides getBasePathForEmailDomain() for output routing |