calendar-plugin/requirements/caldav.md

203 lines
10 KiB
Markdown

# CalDAV Requirements
## Purpose
Define requirements for exposing the plugin calendar through a CalDAV endpoint with read/write behavior and standards-compatible resource representations.
## Standards and RFC
CalDAV behavior must be standards-compatible with:
- RFC 4791: Calendaring Extensions to WebDAV (CalDAV)
- RFC 4918: HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)
- RFC 5545: Internet Calendaring and Scheduling Core Object Specification (iCalendar)
- RFC 6578: Collection Synchronization for WebDAV (sync report)
- RFC 7232: HTTP conditional requests (ETag/If-Match semantics)
If additional CalDAV/WebDAV extensions are used, they must be documented and not break baseline client interoperability.
## Timezone Assumption
Unless explicitly overridden by a future requirement, all plugin dates and times are assumed to be in the `Europe/London` timezone.
## Scope
This document covers:
- CalDAV endpoint structure and resources
- Required WebDAV/CalDAV operations
- Mapping between plugin data and CalDAV/iCalendar resources
- Concurrency, sync, and error behavior
## Normative Boundaries
To avoid ambiguity across requirement documents:
- Exact CalDAV URI layout, method matrix, and DAV property/report behavior are defined in `requirements/caldav_endpoints.md`.
- Authentication and authorization policy is defined in `requirements/authentication.md` and `requirements/authorization.md`.
- Error response normalization is defined in `requirements/error_model.md`.
- Recurrence exception semantics are defined in `requirements/recurrence_exceptions.md`.
- Concrete persistence schema is defined in `requirements/data_schema.md`.
## Endpoint and Resource Model
The plugin must expose a CalDAV hierarchy with authenticated user principals and calendar collections.
Minimum resource model:
- Principal resource per authenticated CalDAV user
- Shared calendar home set
- Single shared `public` calendar collection
- Event resources as `text/calendar` (`VEVENT`-based `.ics` objects) within collections
URI requirements:
- Resource URIs must be stable for the lifetime of each object.
- Event resource URI should be derived from a stable internal event identifier.
- Recurrence exceptions must remain part of the same logical series and not create split series artifacts.
## Authentication and Authorization
- CalDAV access must require HTTPS and authenticated credentials.
- Authorization must enforce account approval state (`pending_approval` vs `active`).
- Unverified or non-approved users must be denied authentication/authorization.
- `active` users are write-enabled for the shared calendar.
- All authenticated users access the same shared calendar collection.
## Required CalDAV/WebDAV Operations
The endpoint must support these operations at minimum.
### Discovery and Collection Introspection
- `OPTIONS`: advertise DAV capabilities, including CalDAV support.
- `PROPFIND`:
- discover principals, calendar home sets, and calendar collections
- retrieve core properties (display name, resource type, ctag/sync metadata where available)
### Read and Query
- `REPORT` (`calendar-query`): return events in collection, including time-range filtering.
- `REPORT` (`calendar-multiget`): fetch specific event resources by href.
- `GET`: retrieve individual event resource (`text/calendar`).
- `GET` on CalDAV collection resources should return `200` (empty body acceptable) for client availability probes.
### Create and Update
- `PUT`: create new event resource or replace an existing event resource.
- `PUT` updates must preserve recurrence/exception semantics from iCalendar input.
- CalDAV clients (including Thunderbird) must be able to read current event privacy and update it on edit (for example via `CLASS`).
- Write operations must require approved authenticated access.
### Delete
- `DELETE`: remove event resource when permitted.
- Deleting a single occurrence of a recurring event must be represented as a recurrence exception in the series (`EXDATE` and/or `RECURRENCE-ID` override pattern), not by splitting into multiple independent series.
### Concurrency and Sync
- `ETag` must be emitted for event resources.
- `If-Match`/`If-None-Match` preconditions must be honored for safe updates/creates.
- `REPORT` (`sync-collection`) should be supported for incremental sync tokens.
- Sync token invalidation/rotation behavior must be deterministic and documented.
- `sync-collection` no-change requests (client token equals current token) should return an empty change set (`207` with no changed/deleted `response` entries).
- `sync-collection` should prefer stable incremental behavior over historical replay; unchanged resyncs must not emit large historical tombstone sets.
## iCalendar Representation Requirements
CalDAV event payloads must be standards-compatible `VCALENDAR` with `VEVENT` components.
Minimum mapping expectations:
- Internal stable event id -> `UID`
- Title -> `SUMMARY`
- Description -> `DESCRIPTION`
- Location -> `LOCATION`
- Category -> `CATEGORIES`
- Start/end -> `DTSTART` / `DTEND`
- Last modification timestamp -> `DTSTAMP` (and `LAST-MODIFIED` when available)
- Recurrence rules -> `RRULE`
- Recurrence exceptions -> `EXDATE` and/or additional `VEVENT` with matching `UID` plus `RECURRENCE-ID`
- Parsing must correctly handle quoted property parameters containing `:` (for example `DESCRIPTION;ALTREP="data:text/html,..."`) so field values are not polluted by parameter content.
Privacy visibility mapping:
- Event visibility must round-trip through CalDAV/iCalendar semantics (for example `CLASS:PUBLIC` and `CLASS:PRIVATE` where supported).
- Authenticated CalDAV users must receive full event content for both public and private events.
- CalDAV feeds are not subject to the public redaction model used by anonymous web/ICS surfaces.
Recurrence behavior:
- Series-level recurrence remains a single logical event sequence keyed by `UID`.
- Exception instances must be represented as exceptions to that `UID`, not a new split sequence.
- Sequence/version metadata should be updated on write operations so clients detect changes.
- Monthly ordinal rules must round-trip accurately, including `BYDAY=2SA`-style forms and `BYSETPOS=-1` (`last` weekday in month).
## Plugin Data Mapping Requirements
Plugin persistence must represent CalDAV resources in a way that supports idempotent read/write sync.
Required persisted mapping fields (direct columns or normalized equivalents):
- Internal event id
- CalDAV resource path/name
- `UID`
- Current `ETag`
- Calendar collection id
- Last-modified-by user id (nullable for system/import operations)
- Serialized recurrence rule data
- Recurrence exception records (date-only exceptions and/or overridden instances)
- Created/updated timestamps
Behavior requirements:
- Importing/updating from CalDAV must map to existing records by stable identifiers (`UID` + resource identity rules).
- Duplicate creation from repeated client retries must be prevented.
- Data model must preserve enough metadata to regenerate standards-compliant responses.
## Error Handling Requirements
- Malformed iCalendar payloads must return appropriate client error responses.
- Authorization failures must return appropriate auth status without leaking sensitive details.
- Write precondition failures (etag mismatch) must return precondition errors and no partial write.
- Server errors must be logged with enough detail for troubleshooting.
## Security and Privacy
- Transport must be TLS-only for credentials and calendar data.
- Sensitive tokens/credentials must not be logged in plaintext.
- Responses must not leak admin-only or internal plugin metadata.
## Interoperability Targets
The implementation should interoperate with common CalDAV clients, including:
- Apple Calendar
- Thunderbird
- DAVx5-class clients
Client-specific workarounds, if required, must be documented.
## Majority-Client Compatibility Strategy
There is no single guaranteed feature set that satisfies every CalDAV client implementation, but interoperability for the majority can be managed by combining:
- strict baseline standards compliance (RFC 4791 + RFC 4918 + RFC 5545)
- a stable compatibility profile for discovery/auth/report/write behavior
- continuous regression tests against representative client patterns
The project must maintain a compatibility profile with three levels:
- Level A (required for release): standards-critical discovery/auth/read
- `401` with `WWW-Authenticate` on unauthenticated CalDAV access
- principal discovery (`current-user-principal`)
- principal `calendar-home-set`
- discoverable calendar collection with `<C:calendar/>`
- `REPORT` support for `calendar-query` and `calendar-multiget`
- Level B (required for release): practical write/sync interoperability
- `PUT`/`DELETE` with stable ETag behavior
- recurrence + exception round-trip fidelity
- sync collection stability for incremental updates
- Level C (best effort): client-specific ergonomics/extensions
- optional properties beyond baseline RFC surface
- minor behavior adjustments for specific client quirks that do not break A/B
Release gating must include at least:
- `fixture-tests/fixture_caldav_client_compat_smoke.sh` (legacy local discovery/auth compatibility; retained for archival comparison)
- existing fixture smoke + security smoke suites
- at least one real-client manual smoke (for example Thunderbird or Apple Calendar) for release candidates
## Verification Requirements
Acceptance should verify:
- Principal and calendar discovery works via `OPTIONS` and `PROPFIND`.
- Calendar query and multiget reports return correct data for time-range and href selection.
- `GET`, `PUT`, and `DELETE` behaviors match access level permissions.
- ETag and conditional writes prevent lost updates.
- Sync collection reports provide incremental changes.
- Recurring-event single-occurrence delete results in exception representation, not sequence split.
- Returned iCalendar validates against RFC 5545 expectations and is accepted by target clients.
- Privacy values round-trip through CalDAV edit flows (including Thunderbird) without losing event detail fidelity.