Skip to content

iCalDAV/ical-dependency-graph

Repository files navigation

RFC 5545 VEVENT Property Dependency Graph

DOI

A formal, machine-readable specification of inter-property dependencies for iCalendar VEVENT components, extracted from RFC 5545, RFC 7986, RFC 5546, RFC 6047, and RFC 6638.

Why

RFC 5545 defines property interaction rules in prose scattered across hundreds of pages of MUST/SHOULD language. No published, standalone representation of these rules exists in a form suitable for machine consumption. This project extracts them into a formal dependency graph that enables:

  • Property-level merge in CalDAV sync engines (beyond whole-event ETag conflicts)
  • Validation of iCalendar objects at parse and edit time
  • Correct RRULE expansion by making DTSTART dependencies explicit

The Problem

CalDAV treats calendar resources as opaque blobs. When two clients modify the same event, the only options are whole-event replacement or manual resolution. Property-level merge requires knowing which properties depend on which -- and that knowledge exists only in RFC prose today.

The EXDATE-type-must-match-DTSTART rule alone accounts for 7+ separate bugs across different projects. The RRULE-DTSTART interaction has bugs dating back 13 years. We documented 25 bugs across 17 projects spanning 8 languages that trace to violated property dependencies.

Files

File Format Purpose
rfc5545-deps.yaml YAML Human-readable specification with inline commentary
rfc5545-deps.json JSON Machine-consumable equivalent for cross-language use
RFC5545_DEPENDENCY_GRAPH.md Markdown Full paper: prose rationale, evidence catalog, related work

The YAML and JSON are structurally equivalent (27 properties, 20 edges, same merge safety classifications). The JSON uses _note fields for annotations and a _schema object documenting all field types. Fields prefixed with _ are non-normative.

Quick Start

import yaml

with open('rfc5545-deps.yaml') as f:
    graph = yaml.safe_load(f)

# Which properties does RRULE depend on?
rrule = graph['properties']['RRULE']
for edge in rrule['depends_on']:
    print(f"RRULE depends on {edge['target']} (strength: {edge['strength']})")
# Output: RRULE depends on DTSTART (strength: must)

# What is EXDATE's merge safety?
print(graph['properties']['EXDATE']['merge_safety'])  # "dependent"

# Can SUMMARY be independently merged?
print(graph['properties']['SUMMARY']['merge_safety'])  # "safe"

Graph Structure

Edge Types

Edge Type Meaning
depends_on B's interpretation requires A. Changing A makes B's cached result stale.
derived_from B's value was computed from A at creation time. A can change afterward.
requires A requires B to be present. A without B is a protocol violation.
mutually_exclusive_with A and B MUST NOT both be present.
type_consistency A and B must use the same value type (DATE or DATE-TIME). Bidirectional.
computes_with A and B are used together in computation. Neither needs updating when the other changes.

Merge Safety Classification

Category Properties Meaning
safe SUMMARY, DESCRIPTION, LOCATION, URL, GEO, PRIORITY, CATEGORIES, COLOR, CLASS, TRANSP, STATUS No cross-property dependencies. Independent merge always valid.
dependent DTSTART, DTEND, DURATION, RRULE, EXDATE, RDATE, VALARM Can be merged if graph validation passes.
scheduling ATTENDEE, ORGANIZER, REQUEST-STATUS Requires iTIP workflow (RFC 6638). See scheduling_fallback for non-RFC-6638 servers.
immutable UID, CREATED, RECURRENCE-ID Set once, never changed.
always_update SEQUENCE, DTSTAMP, LAST-MODIFIED Automatically set on any edit.

Edge Strength

Strength Meaning
must RFC MUST/MUST NOT. Violation is a protocol error.
should RFC SHOULD/SHOULD NOT. Suboptimal but conformant.
advisory Not a conformance requirement. Useful for warnings.
informational Annotation only. No conformance implication.

Scope and Limitations

  • VEVENT only. VTODO and VJOURNAL have different dependency structures.
  • Inter-property dependencies only. Single-property cardinality (DTSTART is REQUIRED) and value-level constraints (DTEND >= DTSTART) are not modeled.
  • No conditional edges. VALARM TRIGGER's dependency on DTSTART vs DTEND depends on the RELATED parameter; this is noted in comments but not captured structurally.
  • Cross-VEVENT edges (RECURRENCE-ID referencing master's RRULE/RDATE) are marked with cross_vevent: true. A merge engine must operate on the full UID group.

Versioning

The version field uses semantic versioning:

  • Patch (1.0.x): Corrects an incorrect edge. No new properties or edge types.
  • Minor (1.x.0): Adds new properties, edge types, or schema fields. Existing edges unchanged.
  • Major (x.0.0): Changes existing edge semantics or restructures the schema.

Related Projects

  • iCalDAV -- Kotlin CalDAV library. Reference implementation consumer of this graph.
  • KashCal -- Android calendar app. Implementation validation across 6 CalDAV servers with 295+ RFC-specific tests.

Contributing

See CONTRIBUTING.md.

Edge corrections and new properties should include:

  1. The RFC section number justifying the edge
  2. A test vector (input VEVENT + change + expected violation/result)
  3. Whether the edge affects merge safety classification

License

CC-BY-4.0

Citation

If you use this graph in academic work:

@misc{kashyap2026ical,
  title = {Formalizing Implicit Property Dependencies in {RFC} 5545: Toward Safe Property-Level Calendar Synchronization},
  author = {Kashyap, Ravi},
  year = {2026},
  doi = {10.5281/zenodo.19299690},
  url = {https://doi.org/10.5281/zenodo.19299690},
  note = {Preprint. Repository: https://github.com/iCalDAV/ical-dependency-graph}
}

About

RFC 5545 VEVENT Property Dependency Graph: machine-readable specification of inter-property dependencies for iCalendar merge safety

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages