Context
Many organizations already have calendar infrastructure in place — Exchange on-premises, Exchange Online / Microsoft 365, Google Workspace — that does not speak CalDAV natively. These organizations often struggle with room and resource booking: fragmented tooling, no unified interface, complex integrations.
Calendars has the potential to become the go-to solution for meeting and resource scheduling — but only if it can connect to the calendar backends organizations already run, rather than requiring a full migration to CalDAV.
Observation
The codebase already applies a clean backend abstraction pattern for entitlements (EntitlementsBackend with swappable LocalBackend and DeployCenterBackend). The calendar protocol layer does not yet have an equivalent abstraction.
CalDAV/SabreDAV is currently the only backend, wired in four specific places:
- CalDAVHTTPClient / CalDAVClient in caldav_service.py
- CalDAVProxyView in viewsets_caldav.py
- provision_default_calendar / delete_user_caldav_data signals in signals.py
- ResourceService in resource_service.py
Everything else — Organization, User, Channel, entitlements, OIDC, calendar_invitation_service — is already fully protocol-agnostic and would be inherited for free by any alternative backend.
Proposal
Introduce a CalendarBackend abstract base class following the same pattern as EntitlementsBackend:
class CalendarBackend(ABC):
@abstractmethod
def create_calendar(self, user, name, **kwargs) -> str: ...
@abstractmethod
def delete_calendar(self, user, calendar_path) -> None: ...
@abstractmethod
def create_event(self, user, calendar_path, event_data) -> str: ...
@abstractmethod
def get_events(self, user, calendar_path, start, end) -> list: ...
@abstractmethod
def find_event_by_uid(self, user, uid) -> tuple: ...
@abstractmethod
def update_attendee_partstat(self, data, email, partstat) -> str: ...
@abstractmethod
def get_free_busy(self, user, emails, start, end) -> dict: ...
@abstractmethod
def provision_resource(self, user, name, resource_type) -> dict: ...
@abstractmethod
def delete_resource(self, user, resource_id) -> None: ...
...
CalDAVBackend would be the default implementation — zero behavior change for existing deployments.
Concrete examples
Exchange on-premises exposes EWS (Exchange Web Services), not CalDAV. A native EWSBackend would handle room booking, free/busy, recurring events and resource provisioning directly against Exchange — without the double-invitation and sync issues a CalDAV bridge introduces.
Exchange Online / Microsoft 365 exposes the Graph API. A GraphAPIBackend would allow organizations on M365 to use Calendars as their room booking interface without migrating their calendar infrastructure.
The same abstraction would also enable a MockBackend for testing without a live calendar server — a practical benefit regardless of which backends are eventually implemented.
Relationship to "active sync with external calendars"
I noticed this item in your roadmap. Active sync is a valid approach for read access and calendar visibility, but it has limitations for room booking specifically: conflict detection requires real-time availability, and bidirectional sync introduces double-invitation issues and reconciliation complexity.
A native backend abstraction would complement sync — sync for personal calendar visibility, native backend for resource booking where real-time accuracy matters.
Questions
- Is protocol-agnosticism in scope for Calendars, or is CalDAV a deliberate permanent constraint?
- Are you open to this direction? Happy to discuss the approach before going further.
Context
Many organizations already have calendar infrastructure in place — Exchange on-premises, Exchange Online / Microsoft 365, Google Workspace — that does not speak CalDAV natively. These organizations often struggle with room and resource booking: fragmented tooling, no unified interface, complex integrations.
Calendars has the potential to become the go-to solution for meeting and resource scheduling — but only if it can connect to the calendar backends organizations already run, rather than requiring a full migration to CalDAV.
Observation
The codebase already applies a clean backend abstraction pattern for entitlements (EntitlementsBackend with swappable LocalBackend and DeployCenterBackend). The calendar protocol layer does not yet have an equivalent abstraction.
CalDAV/SabreDAV is currently the only backend, wired in four specific places:
Everything else — Organization, User, Channel, entitlements, OIDC, calendar_invitation_service — is already fully protocol-agnostic and would be inherited for free by any alternative backend.
Proposal
Introduce a CalendarBackend abstract base class following the same pattern as EntitlementsBackend:
class CalendarBackend(ABC):
CalDAVBackend would be the default implementation — zero behavior change for existing deployments.
Concrete examples
Exchange on-premises exposes EWS (Exchange Web Services), not CalDAV. A native EWSBackend would handle room booking, free/busy, recurring events and resource provisioning directly against Exchange — without the double-invitation and sync issues a CalDAV bridge introduces.
Exchange Online / Microsoft 365 exposes the Graph API. A GraphAPIBackend would allow organizations on M365 to use Calendars as their room booking interface without migrating their calendar infrastructure.
The same abstraction would also enable a MockBackend for testing without a live calendar server — a practical benefit regardless of which backends are eventually implemented.
Relationship to "active sync with external calendars"
I noticed this item in your roadmap. Active sync is a valid approach for read access and calendar visibility, but it has limitations for room booking specifically: conflict detection requires real-time availability, and bidirectional sync introduces double-invitation issues and reconciliation complexity.
A native backend abstraction would complement sync — sync for personal calendar visibility, native backend for resource booking where real-time accuracy matters.
Questions