# 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.
