# ICS Export Requirements

## Purpose
Define requirements for generating iCalendar (.ics) output from plugin calendar data.

## Standards and RFC
ICS output must comply with the iCalendar specification:

- RFC 5545: Internet Calendaring and Scheduling Core Object Specification (iCalendar)

Where additional iCalendar properties are used beyond RFC 5545 core, they must be documented and standards-compatible.

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

- ICS feed/file generation
- Mapping from plugin event data to iCalendar properties
- Recurrence representation
- Validation and interoperability expectations

## Output Requirements
- Content type must be `text/calendar`.
- Character encoding must be UTF-8.
- Calendar payload must include required VCALENDAR envelope properties.
- Output must be consumable by common calendar clients (Apple, Google, Outlook-class clients).

## VCALENDAR Requirements
The ICS output must include, at minimum:

- `BEGIN:VCALENDAR`
- `VERSION:2.0`
- `PRODID` identifying the plugin/system
- `CALSCALE:GREGORIAN` (recommended default)
- `VTIMEZONE` definition for `Europe/London`
- `END:VCALENDAR`

## VEVENT Mapping
Each plugin calendar entry maps to at least one `VEVENT`.

Field mapping requirements:

- Plugin `title` -> `SUMMARY`
- Plugin `description` -> `DESCRIPTION`
- Plugin `location` -> `LOCATION`
- Plugin start date/time -> `DTSTART`
- Plugin end date/time -> `DTEND`
- Plugin category -> `CATEGORIES`
- Stable unique event identifier -> `UID`
- Plugin `visibility` controls public-output masking for private events
- Last update timestamp -> `DTSTAMP`

Additional mapping guidance:

- All-day events use date-based `DTSTART`/`DTEND` semantics per RFC 5545.
- Timed events must use `DTSTART;TZID=Europe/London` and `DTEND;TZID=Europe/London`.
- `DTEND` must represent a valid end boundary and not precede `DTSTART`.


Privacy behavior:

- `public` events are exported with normal mapped content.
- `private` events remain present in the feed at normal date/time positions, but with redaction:
  - `SUMMARY` must be `Private Event`
  - `DTSTART`/`DTEND` remain populated
  - `DESCRIPTION`, `LOCATION`, and `CATEGORIES` must be omitted from public ICS output

## Recurrence Mapping
Recurring entries should be represented with `RRULE` where possible.

Mapping expectations:

- Daily/weekly/monthly/yearly repeat -> corresponding `FREQ` values.
- Custom interval (`every n`) -> `INTERVAL=n`.
- Range modes:
  - No end date -> RRULE without `UNTIL` or `COUNT`.
  - Create `<n>` appointments -> RRULE with `COUNT=n`.
  - Repeat until `<date>` -> RRULE with `UNTIL=<date/time>`.

If specific recurrence shapes cannot be represented in a single RRULE, plugin may emit standards-compliant expanded VEVENT instances as fallback, documented in implementation notes.

## Timezone Requirements
- ICS generation must use a deterministic timezone strategy documented in settings/docs.
- Current project baseline timezone is `Europe/London` unless explicitly overridden by a future requirement.
- For the baseline configuration, ICS output must include a `VTIMEZONE` block describing `Europe/London`.
- For the baseline configuration, timed `DTSTART` and `DTEND` values must use `TZID=Europe/London`.
- If a future configurable timezone mode is introduced, output must remain standards-compliant and subscriber-coherent.

## Data Quality and Escaping
- Text values must be escaped/formatted according to iCalendar rules (e.g., commas, semicolons, line folding).
- Invalid or incomplete records must not produce malformed ICS output.
- Generation errors should fail safely with observable error handling.

## Security and Privacy
- Export must enforce visibility policy: private events are included with redacted content in public ICS output.
- Internal/admin-only metadata must not leak into ICS properties.

## Verification Requirements
Acceptance should verify:

- Output validates as RFC 5545-compatible ICS.
- Field mappings are correct for single and recurring events.
- All-day and timed events render correctly in major clients.
- Recurrence limits (`COUNT`/`UNTIL`) behave as configured.
