# Changelog

## 0.4.4 (2026-05-16)

### New

- **`:prefix` opt on `ExDav.CalDav.Plug` and `ExDav.CardDav.Plug`** —
  controls the first path segment the plug claims (default `"dav"` for
  backward compatibility). Set `prefix: "caldav"` (or `"carddav"`) when
  you want autodiscovery and request URLs under `/caldav/...` rather
  than `/dav/...`. Affects path matching, `.well-known/{caldav,carddav}`
  redirect target, and all emitted `<href>` elements. Combines cleanly
  with `conn.script_name` when mounted via `Phoenix.Router.forward`.

      plug ExDav.CalDav.Plug,
        prefix: "caldav",
        storage: ...,
        authenticator: ...

## 0.4.0 (2026-05-16)

### Breaking changes

**Storage behaviour renamed — all consumers must update their adapters.**

The `ExDav.Storage` behaviour has been generalised to serve both CalDAV
and CardDAV via a single `kind` parameter. Old CalDAV-specific callback
names are gone:

| Old (0.3.x) | New (0.4.0) |
|---|---|
| `list_calendars/1` | `list_collections/2` |
| `get_calendar/2` | `get_collection/3` |
| `get_calendar_with_objects/2` | `get_collection_with_resources/3` |
| `create_calendar/3` | `create_collection/4` |
| `update_calendar/3` | `update_collection/4` |
| `delete_calendar/2` | `delete_collection/3` |
| `get_object/3` | `get_resource/4` |
| `put_object/4` | `put_resource/5` |
| `delete_object/3` | `delete_resource/4` |
| `sync_changes/3` | `sync_changes/4` |

All new callbacks take `kind :: :calendar | :addressbook` as the second
argument after `username`.

**Collection type changed.** The `calendar` map type lost `components`
and `objects` top-level keys; they are now `properties` (a plain map,
`properties["components"]` for CalDAV) and `resources`.

**Resource type changed.** The `object` map type lost `ical` and
`component`; they are now `body` (the raw iCal or vCard string) and
`content_type`. The `component` field (VEVENT/VTODO) is no longer part
of the storage contract; adapters may carry it as an internal detail.

**Postgres schema renamed — consumers must run the upgrade migration.**

Run `mix ex_dav.gen.migration upgrade_to_0_4_0` in your consumer app,
then `mix ecto.migrate`. Tables renamed:

| Old | New |
|---|---|
| `caldav_calendars` | `dav_collections` |
| `caldav_calendar_objects` | `dav_resources` |
| `caldav_calendar_object_tombstones` | `dav_tombstones` |

Elixir schema modules renamed accordingly:
- `ExDav.Storage.Postgres.Schemas.Calendar` → `…Schemas.Collection`
- `ExDav.Storage.Postgres.Schemas.Object` → `…Schemas.Resource`

### New features

- **CardDAV plug** (`ExDav.CardDav.Plug`) — mirrors CalDAV plug structure
  under `/addressbooks/…` paths. Implements RFC 6352: PROPFIND, MKCOL,
  PROPPATCH, DELETE, GET, PUT, REPORT (addressbook-query,
  addressbook-multiget, sync-collection).
- **vCard 4.0 codec** (`ExDav.VCard`) — parse, validate, serialize,
  extract UID, compute ETag. vCard 3.0 is explicitly rejected.
- **Prefix-safe hrefs** — both CalDAV and CardDAV plugs prefix all
  `<href>` elements with `conn.script_name`. Consumers can now mount
  via `forward "/caldav", ExDav.CalDav.Plug, …` in their Phoenix router
  and hrefs will include the `/caldav` prefix automatically.
- **Migration generator** — `mix ex_dav.gen.migration upgrade_to_0_4_0`
  writes a reversible Ecto migration for the 0.3→0.4 schema changes.

### Unchanged

- `user_exists?/1` callback — no change.
- CalDAV URL space and XML wire format — identical to 0.3.x.
- `ExDav.ICal` helpers — no changes.
- `ExDav.Authenticator` behaviour — no changes.
