Skip to content

CardDAV: discover the address-book home instead of assuming /addressbooks/ - #5

Merged
rutgerhofste merged 1 commit into
mainfrom
claude/carddav-prefill-providers-zls88y
Jul 28, 2026
Merged

CardDAV: discover the address-book home instead of assuming /addressbooks/#5
rutgerhofste merged 1 commit into
mainfrom
claude/carddav-prefill-providers-zls88y

Conversation

@rutgerhofste

Copy link
Copy Markdown
Member

What

The CardDAV backend appended /addressbooks/ to whatever carddav_url it was
given — Soverin's layout, and nobody else's. _discover() now walks RFC 6764's
current-user-principaladdressbook-home-set hops instead, starting at the
URL as given, then /.well-known/carddav, then the origin.

Why

CardDAV standardises no paths, so the URL a provider publishes is whatever that
provider felt like publishing:

shape example before
bare host name iCloud, GMX, Yandex missed
discovery root mailbox.org missed
the home collection itself Fastmail, Gandi (SOGo) missed
SabreDAV root + /addressbooks/ Soverin worked

Everything but the last resolved to a 404, so a customer could paste the exact
address their provider documents and be told there were no address books. That
is what kept the admin package's provider catalog from prefilling a CardDAV URL
at all: only a home collection spelled out per customer would have worked, and
most providers do not publish one.

The CalDAV side never had this problem — the caldav library's principal()
already does the same discovery.

Behaviour kept

  • The old /addressbooks/ path survives as the fallback for a server answering
    neither property, so an existing Soverin-shaped setup keeps working
    unchanged.
  • A 401 during discovery raises ProviderAuthError immediately rather than
    being retried against the next URL — otherwise a wrong password surfaced as a
    confusing "no address books found" three requests later.
  • An unreachable host becomes a ProviderError, so httpx's own exception stops
    leaking through the protocol layer.

Tests

tests/test_carddav_discovery.py (fast suite, httpx.MockTransport, no
network) pins all four URL shapes, the fallback, the 401 and the unreachable
host. Full fast suite green: 53 passed; ruff and ty clean.


Generated by Claude Code

…ooks/

The backend appended /addressbooks/ to whatever carddav_url it was given --
Soverin's layout, and nobody else's. Any provider that publishes a bare host
name (iCloud, GMX, Yandex), a discovery root (mailbox.org) or the home
collection itself (Fastmail) was therefore unreachable unless the customer
found and pasted a home collection by hand, which is why prefilling a CardDAV
URL was not something the admin catalog could do.

_discover now walks RFC 6764's current-user-principal -> addressbook-home-set
hops from the URL as given, then /.well-known/carddav, then the origin. The old
path stays as the fallback for a server answering neither property, so an
existing Soverin-shaped setup keeps working. A 401 during discovery raises
ProviderAuthError immediately rather than being retried into a confusing "no
address books found", and an unreachable host becomes a ProviderError instead
of leaking httpx's own exception through the protocol layer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ktjy3ubr7ESGeSN1dYuKx5
@rutgerhofste
rutgerhofste marked this pull request as ready for review July 28, 2026 13:22
@rutgerhofste
rutgerhofste merged commit 5551597 into main Jul 28, 2026
3 checks passed
@rutgerhofste
rutgerhofste deleted the claude/carddav-prefill-providers-zls88y branch August 13, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants