usrcp-google-calendar
v0.1.8
Published
Google Calendar capture adapter for USRCP - polls the configured user's primary calendar for past events they attended and appends them to the local ledger
Maintainers
Readme
usrcp-google-calendar
Capture-only Google Calendar adapter for USRCP. Polls the configured
user's primary calendar for past events they attended and appends
them to the local ledger as event_attended entries.
The cloud sees nothing from this adapter; it writes only to the local ledger (which encrypts at rest under the same master key as the rest of USRCP).
What it captures
- Events on the primary calendar with both a
start.dateTimeand anend.dateTime(i.e., timed events; all-day entries are skipped). - Only after the event has ended - we capture meetings the user actually attended, not future appointments.
- Skipped: cancelled events; events the user RSVP'd
declined.
Each ledger entry has:
domain: configurable (defaultcalendar)intent:event_attendedoutcome:successdetail: full event metadata - id, summary, description, location, url, start, end, organizer email, attendee emails, created/updated.tags:["google-calendar", "event"]channel_id: the Google event id (forgetRecentEventsByChannel).- Idempotency key:
gcal:event:<id>(re-running the poller is safe).
Setup
Google requires a real OAuth client; there is no "personal API key" shortcut for user calendar data. Setup is a one-time three-secret prompt.
1. Create the OAuth client (one-time)
- Go to console.cloud.google.com, create a project (or reuse one).
- APIs & Services > Library: enable Google Calendar API.
- APIs & Services > OAuth consent screen: set up the consent screen (External, fill the required fields, add your email as a test user).
- APIs & Services > Credentials > Create credentials > OAuth client ID: choose Desktop app. Copy the resulting client ID and client secret.
2. Run the wizard
cd packages/usrcp-google-calendar
npm install
npm run build
usrcp setup --adapter=google-calendarThe wizard prompts for client_id + client_secret and then asks
whether to authorise via browser (default Yes). The browser flow
opens a localhost listener, prints the Google sign-in URL, captures
the redirect, and persists the refresh token automatically; no copy /
paste from the OAuth Playground.
If you can't open a browser from this machine (remote shell, CI, etc.), answer "no" and the wizard falls back to the manual OAuth-Playground path:
- Visit developers.google.com/oauthplayground.
- Click the gear icon (top right). Tick Use your own OAuth credentials and paste your client ID + secret.
- In the left panel, scroll to Google Calendar API v3 and tick
https://www.googleapis.com/auth/calendar.readonly. - Click Authorize APIs, complete the Google sign-in, then Exchange authorization code for tokens.
- Copy the
refresh_tokenfrom the response and paste it into the wizard.
The wizard validates the credentials against the Calendar API before persisting, so a wrong value fails fast.
Run
usrcp-google-calendar
# or: USRCP_PASSPHRASE=<pp> usrcp-google-calendarThe poller logs each tick that captured or skipped any events.
Config
Stored at ~/.usrcp/google-calendar-config.json (mode 0600):
| Field | Type | Notes |
|---|---|---|
| oauth_client_id | string | From step 1. Plaintext (not sensitive). |
| oauth_client_secret | string | Encrypted at rest as enc:<base64> under the USRCP global key (HKDF-derived from the master key). |
| refresh_token | string | Encrypted at rest as enc:<base64> under the USRCP global key. Grants long-lived Calendar read access; the master-key wrap means an attacker who reads disk without unlocking the passphrase cannot use it. |
| domain | string | USRCP domain to write events under. |
| poll_interval_s | number | Seconds; 60-3600. Default 300 (5 min). |
| last_synced_at | string | ISO; managed by the poller. |
Pre-#54 configs with plaintext secrets are still readable; the first save (e.g. when the poller advances the cursor) auto-migrates them into the encrypted envelope.
What's out of scope (v0)
- Secondary calendars (only primary).
- Stream sync (no
stream_eventsentries; ledger only). - Capturing future events (no "I scheduled X" entries).
- Recurring-event masters (we capture each instance individually via
singleEvents=true). - Webhook push (we poll - works behind NAT on a laptop).
- Storing event bodies encrypted-at-rest with the USRCP master key
(matches Linear's posture: config is plaintext-on-disk, mode 0600,
same as
~/.ssh/id_rsa).
