summaryrefslogtreecommitdiff
path: root/lib/render/emit_ics.mli
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 09:09:36 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 09:09:36 +0200
commit6abc243e5d40bd60174a3fb1affc9517b0ac5617 (patch)
tree8c3b03fa7cab2e4239250d572a53fa012755a279 /lib/render/emit_ics.mli
parent544836cf0f6373a0a753d0953ce7e60fd96337af (diff)
downloadcolitur-6abc243e5d40bd60174a3fb1affc9517b0ac5617.tar.gz
colitur-6abc243e5d40bd60174a3fb1affc9517b0ac5617.zip
feat(render): iCalendar emitter, RFC 5545
Not a template job: folding, escaping, exclusive DTEND and stable UIDs are rules a logic-less template cannot enforce, and each fails silently in a subscriber's client rather than loudly at generation. DTEND is EXCLUSIVE for an all-day event (section 3.6.1). Wrong here shows every event a day short, everywhere. UIDs are YYYYMMDD-<rite>@colitur and stable across regenerations (section 3.8.4.7). Wrong here duplicates the whole year in every subscriber's phone, months later. Every line is CRLF-terminated and folded at 75 octets (section 3.1). No RRULE: a liturgical calendar is not a recurrence rule. Asserted, so nobody optimises it later. DTSTAMP is a parameter, not a clock read. RFC 5545 requires it and the obvious implementation reads the wall clock -- which violates the kernel's determinism rule and would make two feeds from identical data differ byte-for-byte, defeating reproducible builds and any reviewable diff on a published tree. Corrected one test literal against real engine output: DTSTAMP is a per-VEVENT property (section 3.8.7.2), not calendar-level, so the default-value line count is 365 (every event), not 1. Mutation-tested: a non-exclusive DTEND reddens the suite.
Diffstat (limited to 'lib/render/emit_ics.mli')
-rw-r--r--lib/render/emit_ics.mli15
1 files changed, 15 insertions, 0 deletions
diff --git a/lib/render/emit_ics.mli b/lib/render/emit_ics.mli
new file mode 100644
index 0000000..270bd76
--- /dev/null
+++ b/lib/render/emit_ics.mli
@@ -0,0 +1,15 @@
+(* emit_ics.mli *)
+(** RFC 5545 iCalendar. NOT a template job: folding, escaping, exclusive DTEND
+ and stable UIDs are rules a logic-less template cannot enforce, and getting
+ any of them wrong produces a feed that fails silently in a subscriber's
+ client (spec section 6). *)
+
+(** [year ?dtstamp ?calname view].
+
+ [dtstamp] defaults to [YYYY0101T000000Z] for the view's own year. It is a
+ PARAMETER, never a clock read: RFC 5545 requires DTSTAMP, the obvious
+ implementation reads the wall clock, and that would both violate the
+ kernel's determinism rule and make two feeds from identical data differ
+ byte-for-byte -- defeating reproducible builds and a reviewable git diff on
+ a published tree. Same data in, same bytes out. *)
+val year : ?dtstamp:string -> ?calname:string -> Template.value -> string