One flow, one back-stack entry, as a stepper rather than four destinations —
the steps are not independently reachable, and "back" from the browser step
abandons a server-side flow rather than popping a screen. It hangs off Settings
with the same sliding-section pattern Storage -> Export uses.
address -> discovery -> (Nextcloud browser approval | username + password)
-> pick lists -> add account
Provider warnings come before the attempt, not after: type a Fastmail or iCloud
address and the app password rule is stated while you type, which is the single
most common support ticket a CalDAV client inherits. Google is refused with the
reason. A login-flow host mismatch is shown, not refused — reverse proxies are
ordinary on self-hosted installs.
PreemptiveBasicInterceptor is deleted. The vendored BasicDigestAuthHandler
already sends Basic preemptively over HTTPS, also does Digest (Baikal defaults
to it, OkHttp has none), caches the working scheme, and scopes by registrable
domain — which is what iCloud's cross-host home set needs. Two implementations
of one job is the defect chunk 1 removed from ICalendarWriter.
⚠️ That handler compares its `domain` against the *registrable* domain, so
passing the full host meant credentials were withheld from every request to
every subdomain — i.e. every self-hosted Nextcloud, silently 401ing forever.
Pinned by CalDavHttpTest.
CalDavGateway and AccountCreator put the network and the database behind
interfaces so the sign-in state machine is testable without a server, a
database, a Keystore or an AccountManager. It had no tests, and the review
found eight issues in it.
Account creation is transactional and rolls its lists back explicitly:
account_id is ON DELETE SET NULL, so deleting the row alone leaves orphan
lists behind and every retry adds another set.
New :caldav module — MIT, plain JVM, api-depends on :dav. Separate from the
vendored MPL tree so the licences stay unmixed, and so "no Android types" is a
compile-time guarantee rather than a discipline. Chunk 2 split again: the
Android account layer (Keystore, AccountManager, Custom Tabs, account-add UI)
is 2c, with different verification and an on-device review.
- ServiceDiscovery: the RFC 6764 ladder. SRV priority/weight, TXT path=,
non-443 ports, "." targets, well-known then root.
- CollectionClassifier: the two filters that are inversions of the obvious
rule. An absent or empty supported-calendar-component-set means "supports
everything", and classification is a positive test for CALDAV:calendar on an
unordered set — excluding schedule-outbox would drop SOGo's main calendar.
- CalDavDiscovery: OPTIONS gate, principal, every home set, Depth-1 by name.
A failing home set does not fail the account, and every home set failing is
reported as an error rather than as an account with no lists.
- NextcloudLoginFlow: POST not GET, a User-Agent the user can recognise when
revoking, 404-means-pending only, both URLs origin-checked, host mismatch
carried rather than refused (reverse proxies are ordinary).
- PreemptiveBasicInterceptor, ServerQuirks.
dnsjava 3.6.3 (BSD-3) added: Android's DnsResolver is callback-only and cannot
do the TXT path lookup, and JNDI's DNS provider does not exist on Android.
Behind an interface, so every trap is tested with a fake and no network.
:dav gains change 6 — <D:unauthenticated/> is parsed rather than inferred from
a null href, which also fires on a merely non-conformant empty element.
52 tests here, 78 in :dav. SYNC.md's live-probed trap table is executable now.