Email Invites Are Mail State Before Calendar State
Email invites are mail state before calendar state
A received calendar invite is first an email with a scheduling payload. Treating it as mail state before calendar state keeps the product slice honest: parse the payload, show what it means, let the recipient answer safely, and stop there until there is a separate validated calendar problem.
The trap is to see .ics and accidentally build a calendar product. That jumps from "make this email understandable" to CalDAV, provider calendar APIs, reminders, free/busy, time-zone history, recurrence expansion, conflict resolution, and calendar UI. Those are real products, not incidental features.
The rule
When a protocol object arrives inside another workflow, make the receiving workflow better first.
For calendar email:
- detect the scheduling object in the message
- preserve the original payload
- display the event and trust state clearly
- answer through the transport it arrived on
- defer external calendar state until the calendar itself is the product
mxr search 'has:calendar newer_than:30d' --format ids
mxr invite show MESSAGE_ID
That gives scheduling context from mail without taking ownership of the user's whole calendar.
Why this generalises
Plenty of apps receive adjacent-domain objects: receipts in email, shipping events in email, identity challenges in chat, workflow approvals in comments. The smallest good feature is usually to make the embedded object legible and actionable where it already showed up.
In mxr
Mxr now handles invite email over iMIP: parse text/calendar and .ics, persist local invite rows, search has:calendar, show invite cards, and send accept/tentative/decline replies through outbound email. It still does not do CalDAV, external calendar APIs, calendar-grid UI, or automatic remote event mutation.