create_event writes no ORGANIZER, so events with attendees invite nobody #39

Closed
opened 2026-08-31 01:51:32 +00:00 by jlxq0 · 0 comments
Owner

create_event writes ATTENDEE and no ORGANIZER, so every event it creates with attendees invites nobody. Read off the stored object rather than the tool's response:

BEGIN:VEVENT
UID:urn:uuid:8a700f828fb56e3cba4f9147d3e57756
DTSTAMP:20260831T014928Z
DTSTART:20260915T130000Z
DTEND:20260915T131500Z
SUMMARY:Scheduling probe\, delete me
ATTENDEE:mailto:lucy@kampong.social
END:VEVENT

No ORGANIZER line. RFC 6638 scheduling keys on it, so Stalwart correctly generates no iTIP: 360 log lines in the window, zero scheduling events, measured with a control.

The create_event schema has no organizer parameter, so this is not a caller mistake and no caller can work around it.

Why it is worse than a missing feature

Every signal afterwards says it worked. The event appears on the calendar, list_events returns the attendee, and create_event's own response echoes attendees: ["lucy@kampong.social"] beside organizer: null. Nothing distinguishes an event that invited somebody from one that invited nobody, and the person who created it has no reason to look.

Julian is asking for agents that schedule for him, and Lucy has calendar access. He would find out from the person who did not turn up.

The fix

Set ORGANIZER to the authenticated principal on create. whoami already returns julian@kampong.social with a principal href, so the value is available and needs no new parameter.

Surface it on read. organizer: null on an object that has one is the next version of this defect.

The acceptance test, and it must read the stored object

create_event with one attendee
get_event_raw
assert an ORGANIZER line is present

Asserting on create_event's response would pass against today's code, because the response is built from the same struct that omits it. That is the whole reason this went unnoticed, and a test written the obvious way reproduces the blindness rather than catching it.

Break it and watch it go red: remove the ORGANIZER line from the builder and confirm the test fails on the stored object.

Two questions one step on, worth deciding rather than discovering

Does updating an event with attendees issue a REQUEST? Does removing an attendee issue a CANCEL? Both are the same class: a mutation that looks applied locally and notifies nobody. Answer them in this change or say why they are separate.

Found by mantis running a scheduling probe for Clark. It cost a wasted measurement and would otherwise have cost a real invitation.

**`create_event` writes `ATTENDEE` and no `ORGANIZER`, so every event it creates with attendees invites nobody.** Read off the stored object rather than the tool's response: BEGIN:VEVENT UID:urn:uuid:8a700f828fb56e3cba4f9147d3e57756 DTSTAMP:20260831T014928Z DTSTART:20260915T130000Z DTEND:20260915T131500Z SUMMARY:Scheduling probe\, delete me ATTENDEE:mailto:lucy@kampong.social END:VEVENT **No `ORGANIZER` line.** RFC 6638 scheduling keys on it, so Stalwart correctly generates no iTIP: 360 log lines in the window, zero scheduling events, measured with a control. **The `create_event` schema has no organizer parameter**, so this is not a caller mistake and no caller can work around it. ## Why it is worse than a missing feature **Every signal afterwards says it worked.** The event appears on the calendar, `list_events` returns the attendee, and `create_event`'s own response echoes `attendees: ["lucy@kampong.social"]` beside `organizer: null`. **Nothing distinguishes an event that invited somebody from one that invited nobody**, and the person who created it has no reason to look. **Julian is asking for agents that schedule for him**, and Lucy has calendar access. He would find out from the person who did not turn up. ## The fix **Set `ORGANIZER` to the authenticated principal on create.** `whoami` already returns `julian@kampong.social` with a principal href, so the value is available and needs no new parameter. **Surface it on read.** `organizer: null` on an object that has one is the next version of this defect. ## The acceptance test, and it must read the stored object create_event with one attendee get_event_raw assert an ORGANIZER line is present **Asserting on `create_event`'s response would pass against today's code**, because the response is built from the same struct that omits it. That is the whole reason this went unnoticed, and a test written the obvious way reproduces the blindness rather than catching it. **Break it and watch it go red**: remove the `ORGANIZER` line from the builder and confirm the test fails on the stored object. ## Two questions one step on, worth deciding rather than discovering **Does updating an event with attendees issue a `REQUEST`?** **Does removing an attendee issue a `CANCEL`?** Both are the same class: a mutation that looks applied locally and notifies nobody. Answer them in this change or say why they are separate. Found by mantis running a scheduling probe for Clark. It cost a wasted measurement and would otherwise have cost a real invitation.
jlxq0 closed this issue 2026-08-31 02:00:09 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jlxq0/caldav-mcp#39
No description provided.