Source snapshot bcc79fcc · Declared package version 2.1.4. This page combines the checked-in package guide and manifest; commands and runtime behavior were not executed in this review.
Calendar provider implementations for ContractSpec. Each implementation conforms to the shared CalendarProvider interface (listEvents / createEvent /
updateEvent / deleteEvent) from @lssm-tech/lib.contracts-integrations, so they are interchangeable behind the same port (e.g. the OPA
calendar_execution adapter).
Implementations
Subpath
Export
Notes
./impls/google-calendar
GoogleCalendarProvider
Google Calendar via googleapis.
./impls/google-calendar-booking
GoogleBookingCalendar, GoogleCalendarOAuthFlow
Least-scope booking OAuth, free/busy, and deterministic known-ID writes.
Graph change subscriptions (validation handshake, clientState) and calendarView/delta.
Usage
Import the root entrypoint for the domain surface, or import a concrete implementation from the ./impls/* subpaths:
ts
import { MicrosoftGraphCalendarProvider } from '@lssm-tech/integration.provider-calendar/impls/microsoft-graph';
const calendar = new MicrosoftGraphCalendarProvider({ auth });
Boundaries
Provider SDK code lives here, not in OPA runtime/module or the OPA bridges.
Read-only sources (IcsFeedCalendarProvider) fail closed on write operations rather than silently no-op'ing.
Managed CompanyOS booking posture
The booking-specific Google surface uses only calendar.events.freebusy,
calendar.events.owned, and calendar.calendarlist.readonly. The last scope is limited to protected topology discovery; launch does not call events.list. OAuth configuration is server-only under
MANAGED_COMPANYOS_GOOGLE_CALENDAR_CLIENT_ID,
MANAGED_COMPANYOS_GOOGLE_CALENDAR_CLIENT_SECRET, and
MANAGED_COMPANYOS_GOOGLE_CALENDAR_REDIRECT_URI.
Availability uses explicit RFC3339 bounds/timezone and fails closed on any calendar/group error. Writes are pinned to one configured owned calendar, carry a deterministic private marker, and use sendUpdates=all. Polling plus scheduled daily known-ID reconciliation is the default; stale availability fails closed. Push/webhook signals, when added by a host, are invalidation-only. Original booking creates derive their deterministic Google ID from tenant plus persisted booking identity. Reschedules may supply an explicit ID only when the protected host resolver has proven it is the exact saga-owned replacement ID; create and ambiguity recovery preserve that identity rather than deriving a new one. Arbitrary caller IDs fail closed.
Authenticated OPA focus blocks use the same write boundary with an even narrower managed-event adapter. The adapter derives one stable Google event ID from the opaque focus reference, stores only digested ownership markers in private extended properties, requires the marker before update/delete, and uses ETag fencing for rescheduling. Ambiguous creates recover by reading the same known event rather than creating a replacement.
Managed writes can opt into conferenceMode: "google_meet". The adapter sends
conferenceDataVersion=1 and a conference create request whose non-PII request ID is stable for retries of the same known event and distinct for replacement events. Results normalize asynchronous conference creation to pending,
ready, failed, or ambiguous; only an HTTPS meet.google.com video entry point is returned. Legacy callers default to none, and full event updates preserve conference data already returned by Google.
No event-body sync or broad events.list discovery is enabled here. G009 live sandbox evidence remains a launch residual and is intentionally not exercised by repository tests.
Protected topology setup paginates CalendarList and returns only provider- enumerated identifiers plus display/access metadata. A write calendar must have Google owner access, and every busy calendar must be readable in the same enumeration. Manually authored or stale identifiers fail closed before materialization.
Attendee addresses
GoogleBookingCalendar.listIntelligenceEvents keeps each attendee's address in attendees ({ email, displayName? }) next to the display labels in
attendeeLabels (name, else address). The ./calendar surface exports the shared rule, normalizeCalendarAttendeeAddresses: it trims, lower-cases and deduplicates addresses in provider order, drops declined attendees, resources and malformed or over-long addresses, and keeps at most 100 per event (CALENDAR_ATTENDEE_ADDRESS_LIMITS). Google room and equipment resources are dropped; the generic CalendarAttendee mapping of Microsoft Graph does not carry the attendee type, so Graph rooms are not dropped yet.
The addresses are personal data. Their purpose (owner-reviewed follow-up recipients), retention (read memory only unless a consumer contract stores them), access (the meeting owner, server-side) and logging rule belong to
COMPANYOS_CALENDAR_ATTENDEE_ADDRESS_POLICY in @lssm-tech/lib.companyos-spec. Never log them: pass free-text error fields through
redactCalendarAttendeeAddresses, which replaces every e-mail-shaped substring (also %40-encoded) with redacted_email.
Compatibility
This package owns the calendar implementation slice split out of
@lssm-tech/integration.providers-impls. The legacy package continues to re-export these subpaths for existing consumers.
Microsoft Graph pagination follows the unchanged absolute @odata.nextLink URL, without turning it into a skip token or reapplying query options. The injected transport must accept validated absolute v1.0 URLs. This adapter restricts continuations to https://graph.microsoft.com and the same selected calendar collection; sovereign clouds and alternate returned path forms require separate qualification. Calendar IDs are encoded as path segments. See https://learn.microsoft.com/en-us/graph/paging. Live Microsoft connection, recurrence and Teams booking qualification remain open.
Microsoft reads with both timeMin/timeMax use calendarView to expand occurrences and exceptions over the requested window. UTC/text response preferences are supplied through the injected transport. Offset-free UTC dateTime values are parsed as UTC, never host-local time; missing dates, invalid intervals, absent IDs and unsupported offset-free non-UTC zones fail explicitly. Queries without both bounds retain the events collection and do not claim recurrence expansion. One-sided filters use interval overlap semantics. See https://learn.microsoft.com/en-us/graph/api/user-list-calendarview?view=graph-rest-1.0. Live recurring-event/DST/provider qualification remains required.
Microsoft update/delete requests now retain the selected calendar path, including the configured default when the caller omits a calendar ID. Calendar and event identifiers are encoded as single resource segments; empty event IDs, dot segments and control characters cannot issue requests. Update responses must identify the requested event. A mismatch is an unconfirmed provider effect, not permission to retry creation or target another event. See https://learn.microsoft.com/en-us/graph/api/event-update?view=graph-rest-1.0 and https://learn.microsoft.com/en-us/graph/api/event-delete?view=graph-rest-1.0.
Microsoft create/update validates supplied start/end instants before HTTP and rejects invalid, zero-length or reversed supplied intervals. A partial update cannot validate an untouched boundary without a current provider read. Online-meeting description replacement still requires preserving the provider meeting blob and conditional-write qualification; generic description updates are not qualified for Teams production use.
Microsoft time updates now GET the exact selected event, validate the resulting start/end pair, require its ETag and send If-Match on PATCH. The host transport must forward these headers and propagate conditional-write failures; no unconditional retry is attempted. This prevents a partial edit from being validated without its unchanged boundary. Live conditional-write enforcement remains unqualified; this does not implement Teams body-preservation or booking conflict reconciliation.
Google free/busy snapshots now carry normalized query provenance. Cache reuse requires the same calendars, time window and timezone, and rejects future or unbound observations. CompanyOS preparation requires covered planning time plus a matching refresh snapshot digest, evaluated at current server time after refresh. Additive migration 0085 adds query_binding; apply it before deploying the new store/read paths. Historical rows remain readable without earning freshness, and older refreshes cannot overwrite newer observations. Calendar identifiers stay in the tenant-scoped server store.
Microsoft create identity and Teams
Pass a host-persisted requestId (8–128 ASCII identifier characters) to reuse Graph transactionId on retries. Set conference: { create: true, type: 'microsoft_teams' } explicitly. Missing or unsafe returned Teams URLs produce GRAPH_CONFERENCE_RESULT_INCOMPLETE; the event may already exist, so retain the same request identity for repair. The adapter does not automatically retry or qualify live calendar support. Google rejects an explicit Teams request.
Microsoft event reads preserve optional cancellation and connected-owner response status separately from attendee responses. Consumers must apply these flags when excluding cancelled or declined occurrences from preparation and scheduling.
Push channels and delta sync
A host keeps one push channel per owner calendar (Google events.watch, or a Microsoft Graph subscription on me/calendars/{id}/events) and one delta cursor (Google syncToken, Graph deltaLink). The channel token / Graph
clientState is calendarPushChannelToken(secret, provider, channelRef): an HMAC the host derives and never stores; verifyCalendarPushChannelToken
compares in constant time. Notifications carry no event content and are invalidation-only. A delta read returns raw event ids with their new start or a cancellation; resync_required means the cursor is gone (Google 410, Graph 410) and unavailable means the initial sync did not finish within its page bound. The Graph transport admits /subscriptions and calendarView/delta
links on graph.microsoft.com/v1.0/me only. The Google watch needs a scope that permits events.watch on the owned calendar.
Declared capabilities.
Integration Provider Calendar
Calendar provider implementations for ContractSpec.
Use it to
Adopt calendar provider implementations for contractspec
Requires
TypeScript
Choose another boundary when
The @lssm-tech/integration.provider-calendar package constraints do not match the target runtime or platform.
These are package-manifest entry points. Named symbols listed above come from the capability catalogue; this is not an exhaustive TypeScript symbol reference.