> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oximail.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Groupware

> Operating the collaboration surfaces: calendar scheduling (iTIP), free-busy and availability, time zones, notifications, tasks and default lists, contacts, and the repair CLIs.

Beyond mail, OxiMail serves calendars, contacts, tasks, files, and chat over JMAP, with CalDAV/CardDAV bridges for classic clients ([legacy protocols](./legacy-protocols)). This page covers the behaviours an operator needs to understand and the knobs and repair tools that go with them.

## Calendar scheduling (iTIP)

When users invite each other, the server exchanges the scheduling messages (REQUEST / REPLY / CANCEL) by email, per [RFC 5546](https://www.rfc-editor.org/rfc/rfc5546). Two rules keep this from misfiring:

* **Organizer-side only.** OxiMail sends scheduling mail only for events whose ORGANIZER resolves to a **local account** (RFC 5546 §3.2: only the organizer's server sends invitations). An event that arrived as an inbound invitation never re-emits a REQUEST when the attendee's client writes it back, and deleting a received copy never broadcasts an unauthorized CANCEL — on both the JMAP and CalDAV paths, fail-closed.
* **Emitted after the commit.** iTIP messages and calendar events are emitted only once the transaction that changed the event has actually committed. A concurrent-edit conflict (`stateMismatch`) or any commit failure emits **nothing** — invitations can no longer escape for a change that was rolled back, and an update REQUEST always carries the post-change content with the bumped `SEQUENCE`.

Inbound invitations (`text/calendar` parts) are processed on ingestion, including Outlook's parameterised property style, and update the recipient's calendar.

## Free-busy and availability

Three read surfaces answer "when is this person free", all through one occurrence-enumeration authority (a recurring event expands identically everywhere, DST included):

* **`Principal/getAvailability`** (JMAP) composes availability from subscribed calendars whose `includeInAvailability` is `all` or `attending`; a `privacy: "secret"` event hides its busy time entirely; event details are only populated for callers who hold real read access — free-busy access never implies detail access. A caller with free-busy rights on none of the subject's calendars gets an explicit `forbidden`, not a misleading empty answer.
* **CalDAV `free-busy-query`** returns a `VFREEBUSY` of merged busy periods (tentative counts as busy; free/transparent, trashed, and cancelled events are excluded).
* **The scheduling UI** in a client builds on the same data.

## Time zones

Floating events (no explicit zone) resolve through a fallback chain: **event zone → user zone → organization default → UTC**. The wizard captures the organization default at install ([first boot](../first-boot)); change it later with:

```bash theme={null}
oximail tenant update --default-timezone Europe/Zurich
```

Windows registry zone names (from Outlook, Exchange, eM Client) are normalized to IANA on every ingest path, and exported VEVENTs embed the matching `VTIMEZONE` so strict clients compute correct local times.

## Notifications

Calendar changes produce `CalendarEventNotification` objects for the people concerned: a grantee's write on a shared calendar notifies the owner, and an inbound scheduling message notifies the affected user (REQUEST/CANCEL → the recipient, REPLY → the organizer; self-authored changes are suppressed). Notifications are change-logged and pushed, so clients see them without polling. Alerts (reminders) support both offset and absolute triggers and fire once per occurrence through a deduplication table.

## Tasks

Task lists mirror calendars: JMAP methods, CalDAV VTODO bridge, shared lists. Each account has exactly **one default task list**, enforced by a database invariant — a `Task/set` create without `taskListIds` goes there. Alerts on tasks support absolute triggers without requiring a due date.

## Contacts

Contacts are JMAP ContactCards (RFC 9610) with a CardDAV bridge. The server owns the `uid` (a client-supplied one on create is rejected), and a CardDAV `PUT` that would create a cross-source duplicate of an existing UID is refused rather than silently forked. Name and address components round-trip completely between vCard and the JMAP form.

## Sharing

Calendars, task lists, address books, and drive folders share one grant model (`shareWith` maps keyed by principal, RFC 9670 shapes). Two operator-relevant guarantees:

* **Per-viewer state stays per-viewer.** A grantee hiding a shared calendar (`isVisible`) or starring a shared file affects their own view only, never the owner's object.
* **Grantees must be human-backed.** A grant to a non-loginnable technical identity is rejected at write time on every domain — a grant that could never be exercised is a lie in the ACL. Shared accounts' drive custody has its own surface: `oximail account custodian` (see [multi-tenancy](./multi-tenancy)).

## Repair one-shots

Migration-era artifacts have dedicated, **dry-run-by-default** repair commands:

| Command                                                                          | Repairs                                                                                                                                                                          |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `oximail account dedupe-folders (--account <email> \| --all-accounts) [--apply]` | Duplicate localized folders next to role folders (pre-#131 JMAP imports): merges mail through the canonical membership path, reparents children, destroys the emptied duplicate. |
| `oximail account dedupe-tasks (--account <email> \| --all-accounts) [--apply]`   | Exact-duplicate task rows from repeated imports; same-UID rows with diverging content are listed, never touched.                                                                 |

Both record JMAP changes so clients resync cleanly. See the [CLI reference](./cli).
