Files
platform/todo/mobile-apps/setting-up-a-phone-should-be-a-link-in-the-app.md
T
pastilhas 185aa3168e two todos from the caldav extraction
setting up a phone should be one link inside officer — open Calendar, the screen
already knows this phone is not set up, click, done. the endpoint for it exists
(POST /api/caldav/provision/ios) and nothing in the UI calls it, so the smooth
path is built and hidden while the path a new person walks has four fields.

it also does not currently work: the profile is refused by iOS 26.6 as "Invalid
Profile". the todo records what was RULED OUT with evidence rather than
reasoning, because that is the expensive part to redo — delivery works, the
phone really received it (the claim is logged now), the server side is correct,
and removing PayloadScope did not fix it. signing is untested and is the first
experiment.

second: a plugin with a sidecar proxy loses the request body on its own routes.
createSidecarProxy registers the whole mount prefix and bodyParser skips it,
which is right for forwarded traffic and load-bearing for uploads — but it
covers the plugin's own routes too. caldav works around it locally; the real fix
is the proxy claiming only the sub-path it serves, which is shared machinery and
not a thing to change with a phone waiting.
2026-08-27 05:46:57 +00:00

3.7 KiB

id, title, theme, status, created, date_source, order
id title theme status created date_source order
mobile-apps/setting-up-a-phone-should-be-a-link-in-the-app Setting up a phone for calendar and contacts should be one link inside Officer, not a manual account form mobile-apps open 2026-08-27 stated 5

The owner's shape for it, stated 2026-08-27: open Calendar or Contacts in Officer, and the screen already knows this phone is not set up. One link. Clicking it generates the profile on the server, the phone installs it, and everything works. No typing a server address, no username, no password.

The endpoint for that already exists — POST /api/caldav/provision/ios in the caldav plugin — and it is unreachable from the product: nothing in the UI calls it. The "Sync to your phone" modal offers only manual app passwords. So the smooth path is built and hidden, and the path a new person actually walks is the one with four fields in it.

What is known, from an evening of it on 2026-08-27

The profile does not install on iOS 26.6. Every attempt returned Profile Error — Invalid Profile. What was ruled out, each with evidence rather than reasoning:

  • Delivery works. Fetched over the public URL from another machine: 200, application/x-apple-aspen-config, 2,491 bytes, parses cleanly with plistlib.
  • The phone really received it. claimIosProfile now logs, and it logged ios profile claimed — 0 still pending on the attempt that failed. iOS rejected the CONTENTS.
  • The server side is correct. The principal advertises addressbook-home-set, /1/contacts/ is typed as an addressbook, and the manually-added accounts sync fine against the same URLs.
  • PayloadScope was removed (Apple documents it as macOS-only). It did not fix it. Worth stating plainly because it was briefly believed to have — the calendar had started working at the same moment for an unrelated reason: the owner had added the account by hand.

So the remaining suspect is the payload itself — some key iOS 26 refuses, or unsigned profiles being rejected outright, which would make DAV_PROFILE_SIGN_CERT/KEY a precondition rather than a nicety. Nothing has been tested against a signed profile. That is the first experiment.

The second problem, and it does not go away with a working profile

iOS folds CardDAV into an existing CalDAV account with the same server and username. Adding the calendar by hand produced one "Officer" account offering Calendars and Reminders, with no Contacts toggle anywhere — and the server confirmed nothing had ever requested /dav/1/contacts/. The workaround that worked was adding CardDAV as a separate account with a DIFFERENT description.

ios-profile.ts already carries a comment claiming a single two-payload profile sidesteps this. On 26.6 it does not, and the comment should be corrected when this is picked up rather than trusted.

A kinds option was added to buildPlist and only: 'caldav' | 'carddav' to the route so the two accounts can be split across two profiles — written, never verified, because the profile itself never installed.

What "already knows this phone is not set up" needs

Nothing exists for it today. The server can see whether a device has ever authenticated — lastUsedAt on dav_app_passwords — which is enough for "no phone has ever synced", but not for "THIS phone has not", since a browser cannot identify the device it is being read on. Worth deciding whether the weaker signal is enough before building the stronger one.

  • plugin-infrastructure/a-plugin-s-own-routes-lose-their-request-body — found while debugging this.
  • The manual path works and is what the owner is using: app password from the modal, then CalDAV and CardDAV added by hand as two accounts with different descriptions.