Integrate the groupware calendar

Use authenticated, tenant-bound REST resources below /api/v1/calendar/ and CalDAV discovery at /.well-known/caldav. Workspace does not expose an anonymous slot-booking API.

Calendar feeds expose bounded occurrence queries of at most 366 days. Resources live below /api/v1/calendar/resources, delegations below /api/v1/self/calendar/feeds/delegations, and external connections below /api/v1/calendar/sync-connections. Resolve sync conflicts explicitly with a local or remote decision.

Authenticated users list appointments organized by another member at /api/v1/self/calendar/invitations. Access is authorized by the tenant-local identity participant record. Responses include the current event sequence and stale responses are rejected. External response tokens are revoked after the first successful response, and the email links to the HTML representation of the same public endpoint.

Start an import preview at /api/v1/self/calendar/feeds/{feedId}/imports/preview with an owned storage fileId and optional resourceMappings. Poll /api/v1/self/calendar/imports/{jobId} and read the identity-scoped JSON report at .../{jobId}/report. Apply only the reviewed plan through /api/v1/self/calendar/feeds/{feedId}/imports/{previewJobId}/apply.

Preview and apply run asynchronously as ImportJob records. Apply is bound to the same tenant, identity, source file, target feed, importer version, options, and plan digest. Components are grouped by UID and each series is applied atomically. Higher sequences update stored components; an equal sequence is idempotent only when the content fingerprint is unchanged. Migration writes do not enqueue scheduling or reminder deliveries.

CalDAV supports stable UIDs, ETags, calendar query, multiget, incremental sync tokens, tombstones, recurrence, participants, and alarms. One CalDAV resource contains the master and all exceptions of its UID series, preserves component sequences, and does not contain METHOD. Domain projections are separate read-only collections. Always handle machine-readable errors and never surface raw upstream or database details.

Incoming text/calendar mail parts are available through GET /api/v1/self/calendar/scheduling-messages. Apply or reject a message with POST /api/v1/self/calendar/scheduling-messages/{messageId}/apply and POST /api/v1/self/calendar/scheduling-messages/{messageId}/reject. The apply body contains the personal target feedId. Mail intake stores the part first and records only an identity-bound ledger reference and payload hash. REQUEST, REPLY, and CANCEL remain inert until explicit confirmation. Apply reloads the authoritative attachment and validates hash, UID, sequence, organizer, and the method-specific sender. Raw mail headers or gateway names do not establish author trust.

For new local events in a personal calendar, the service uses the bound calendar owner's uniquely verified email address as the organizer when the request omits one. Import and synchronization paths do not invent a missing organizer.