Drops the 0.15 REST management API and routes all account/auth/crypto/
principal operations through Stalwart 0.16's schema-driven JMAP
endpoint via a single passthrough (/api/account/stalwart/jmap).
- New client helper `stalwartJmap` + typed `requireResult`
- account-security-store rewritten against x:AccountPassword, x:AppPassword,
x:AccountSettings, x:Account (with currentSecret for TOTP ops)
- Client-side TOTP setup via `otpauth`; server-generated app password
secrets shown once on create
- Admin check switched to /api/account permissions
(sysAccountQuery/sysTenantQuery/sysSystemSettingsGet)
- Removed sieve vacation-overwrite workaround (fixed upstream #1251)
- Deleted old REST routes, StalwartClient, stale tests; added new
tests for passthrough + store
Two issues prevented tasks created in Thunderbird (or other CalDAV
clients) from appearing in the task view:
1. percentComplete was not in CALENDAR_TASK_PROPERTIES, so it was
never requested from the server and the heuristic check for it
was always false (dead code).
2. The hasTaskFields heuristic used strict value checks:
- 'progress' in obj && typeof obj.progress === 'string'
→ fails when Stalwart returns progress: null instead of the
RFC 8984 default "needs-action"
- 'due' in obj && obj.due != null
→ fails when Stalwart includes due: null for tasks without a
DUE date (key present, value null)
RFC 8984 §5.2 defines due, progress and percentComplete as Task-only
properties — a VEVENT will never include them in a JMAP response.
Checking for key presence alone (even when null) is therefore a
reliable discriminator, regardless of the actual value.
Three issues addressed in sendImipReply, sendImipInvitation and
sendImipCancellation:
1. Line folding (RFC 5545 §3.1)
Add foldIcsLine() helper that wraps iCalendar content lines at
74 characters, inserting CRLF + SPACE as required by the spec.
Previously, long lines (e.g. ATTENDEE with a full CN and mailto
URI) could exceed the 75-octet limit and cause strict parsers to
silently reject the ICS.
2. MIME wrapper type (RFC 6047 §3 + CalConnect iMIP Best Practices)
Change bodyStructure from multipart/alternative to multipart/mixed.
The CalConnect interoperability guide recommends multipart/mixed as
the outer wrapper for messages carrying a text/calendar part; many
clients skip iTIP processing when they see multipart/alternative.
3. Calendar part metadata
Add charset=UTF-8 to the text/calendar Content-Type, disposition
inline, and a descriptive filename (reply.ics / invite.ics /
cancel.ics) to each outgoing calendar MIME part.
Note: Gmail-to-Gmail events are handled by Google's internal scheduling
API and cannot be updated via iMIP regardless of MIME structure. This
fix improves interoperability with Outlook, Thunderbird, Fastmail and
standard CalDAV servers.
Stalwart's CalendarEvent/query ignores Task-type objects and does not
support the 'types' filter (returns unsupportedFilter error). This
caused tasks both locally created and from external clients like
Thunderbird to disappear on reload.
Root causes:
- CalendarEvent/query only returns @type:'Event' objects on Stalwart,
so tasks were invisible to the query endpoint.
- CALENDAR_EVENT_PROPERTIES lacked Task-specific fields (due, progress,
progressUpdated, priority), causing garbled data when tasks were
fetched with Event properties (e.g. utcStart:'32548-12-04T15:30:07Z').
Changes:
- Add CALENDAR_TASK_PROPERTIES with Task-specific fields (due, progress,
progressUpdated, priority).
- Rewrite getCalendarTasks() to first try CalendarEvent/query with
types:['Task'] filter, then fall back to CalendarEvent/get ids:null
which returns all calendar objects regardless of @type per JMAP spec.
- Rewrite createCalendarTask() to fetch back created tasks using
CALENDAR_TASK_PROPERTIES instead of piggybacking on createCalendarEvent.
- Add comprehensive debug logging throughout the task fetch/create flow
(TaskStore, JMAP client) visible when Debug Mode is enabled.
- Add 'types' field to CalendarEventFilter interface.
- Fix buildDuration() trailing "T" producing invalid ISO 8601 durations
- Fix DURATION_RE missing week (W) support in alerts and invitation parsing
- Fix computeFireTime() end fallback when utcEnd is missing
- Fix recurrenceOverrides patch escaping per RFC 6901 (updateEvent/rsvpEvent)
- Fix layoutOverlappingEvents endMin overflow past 1440
- Fix addDurationToDate() to support weeks and use UTC methods for UTC inputs
- Fix getEffectiveAlerts() null guard on calendarIds
- Fix buildAllDayDuration() DST-safe day calculation using differenceInCalendarDays
- Fix participant matching to check calendarAddress and sendTo (not just email)
- Fix buildParticipantMap() using crypto.randomUUID() instead of hardcoded IDs
- Fix overnight preview negative endMin in week view
- Fix sendImipInvitation() to emit DURATION when utcEnd is absent
- Fix sendImipCancellation() to validate status before sending
- Fix createEvent() to remap all calendarIds for shared calendars
- Fix getCalendarTasks() to clone before mutating @type
- Fix importEvents() error matching to include 'duplicate' and 'conflict'
- Fix looksLikeReply() false positive by requiring organizer + responded attendee
- Fix alert offset regex to require T before minutes
- Fix handleDuplicate() to generate new UID
- Fix formatSnapTime() input clamping
- Replace console.log/error with debug.log/error/warn in iMIP functions
Tasks created in Thunderbird via CalDAV were not visible because
getCalendarTasks() used a strict @type === 'Task' check. Stalwart
may not set @type when converting VTODO from CalDAV to JMAP.
- Use case-insensitive @type matching for server variations
- Add fallback heuristic: detect tasks by presence of 'progress'
property (exclusive to JSCalendar Task, never on Event objects)
- Normalize @type to 'Task' on detected tasks for consistent
downstream handling
- Refresh task store on CalendarEvent state changes so tasks
created externally appear without manual page refresh
Fixes#84
- Created demo emails with various states (inbox, sent, drafts, trash, etc.) in `emails.ts`.
- Added demo file nodes representing directories and files in `files.ts`.
- Implemented demo Sieve capabilities and scripts in `filters.ts`.
- Defined demo identities for users in `identities.ts`.
- Established demo mailboxes with permissions and counts in `mailboxes.ts`.
- Created a demo vacation response in `vacation.ts`.
- Introduced a comprehensive JMAP client interface in `client-interface.ts` to standardize interactions with the JMAP API.