Skip to content

feat(findmy): friend locations from searchpartyd secure-location store - #1

Open
brendandebeasi wants to merge 11 commits into
PnutCN:feat/findmy-decryptfrom
brendandebeasi:feat/findmy-decrypt
Open

brendandebeasi wants to merge 11 commits into
PnutCN:feat/findmy-decryptfrom
brendandebeasi:feat/findmy-decrypt

Conversation

@brendandebeasi

@brendandebeasi brendandebeasi commented Sep 6, 2026

Copy link
Copy Markdown

On some macOS 14.4+ builds (observed on 14.8.5), LocalStorage.db no longer has a secureLocations table: friend coordinates live only in searchpartyd's SecureLocationCache, so GET findmy/friends returns empty even when friends are sharing.

This adds a fallback: when the LocalStorage path yields no locations, decrypt the searchpartyd records instead.

  • searchPartyReader: AES-256-GCM decrypt of SecureLocationCache and SecureLocationSharedKeys .record files ([nonce, tag, ciphertext] plist, no AAD). Handles resolved from ownerHandle.destination, so the path works without LocalStorage.db at all.
  • New SearchParty key (SearchParty.key, 32 raw bytes) wired into the FindMyKeyManager load/validate/import flow and the settings key card.
  • The key can also be supplied via the FINDMY_SEARCHPARTY_KEY env var (hex-encoded), which takes precedence over the file. Useful for launchd/headless setups.
  • Items flow through the existing buildFriendLocationItem path, so live status and FMF display names still apply.
  • Friend items now carry an avatar field (base64 contact photo resolved from Contacts by handle) for clients to render.

Client rendering: BlueBubblesApp/bluebubbles-app#3260 (avatars) and BlueBubblesApp/bluebubbles-app#3262 (reverse-geocoded addresses, since this path cannot carry address strings).

Tested on macOS 14.8.5: two friends return live coordinates through /api/v1/icloud/findmy/friends, previously empty. The SearchParty master key itself is per-machine and must be obtained from the searchpartyd store (keychain-held); extraction is out of scope for this PR. See docs/notes/macos-local-build.md for build, signing, and key setup.

Brendan DeBeasi added 3 commits September 6, 2026 08:10
… store

On some macOS 14.4+ builds (observed on 14.8.5), LocalStorage.db no longer
has a secureLocations table: friend coordinates live only in searchpartyd's
SecureLocationCache. Decrypt those records as a fallback when the
LocalStorage path yields nothing.

- add searchPartyReader: AES-256-GCM decrypt of SecureLocationCache and
  SecureLocationSharedKeys .record files ([nonce, tag, ciphertext] plist,
  no AAD); handles resolved from ownerHandle.destination
- new SearchParty key (SearchParty.key, 32 raw bytes) wired into the
  FindMyKeyManager load/validate/import flow and the settings key card
- the key can also be supplied via the FINDMY_SEARCHPARTY_KEY env var
  (hex-encoded), which takes precedence over the file
- items flow through the existing buildFriendLocationItem path, so live
  status and FMF display names still apply
Adds an avatar field (base64 image) to FindMyLocationItem, resolved from
the Contacts database by handle: exact case-insensitive email match or
digit-suffix phone match across all contacts, preferring image-bearing
records (duplicate contacts are common and usually only one carries the
photo).

Thumbnails are preferred to keep payloads small. Best-effort: without
Contacts permission, or when no matching contact has an image, avatar
stays null.
Brendan DeBeasi added 8 commits September 6, 2026 20:22
Serves a self-contained Find My map + list page (Leaflet, avatar markers,
Nominatim address lookup on the viewing device, 60s auto-refresh) from the
same origin as the API, so it works through whatever tunnel/host the server
is reachable on with just the server password.

The route reads findmy-viewer.html from the app-support directory so the page
can be edited without a rebuild; canonical copy in packages/server/web/.
…atars

Find My renders friends whose Contacts card has no local image using
their iCloud shared poster; Contacts keeps only a ZIMAGEHASH for those.
Read the iMessage NickNameCache (nicknameRecordsStore handle->record-id
map, pendingNicknamesKeyStore image paths) and attach the cached -ad
image, sips-resized to 256px with an mtime-keyed cache so polling stays
cheap.
Missing or wrong API password now returns a plain 404 so authed
endpoints are indistinguishable from nonexistent ones. Three failures
from one IP within 10 minutes bans it for an hour; banned connections
are destroyed without responding. The real client IP comes from
CF-Connecting-IP behind the tunnel. Private and loopback IPs are never
banned so local clients cannot lock themselves out.
…eceipt

Plumbs a suppressReceipt flag from POST /chat/:guid/read?receipt=false
through to the helper, which drops the swizzled receipt send for that
chat. markRead now awaits the helper ack. Bundles the rebuilt helper
dylib with the headless-persistence and nil-transaction fixes.
macOS 14.8's JPEG encoder fails with Error 13 on some iPhone HEICs.
execShellCommand rejects on non-zero exit, so the conversion threw
before any output check; wrap the direct attempt and fall back to
HEIC -> PNG -> JPEG, which encodes cleanly. Failed attachments showed
as un-downloadable images in clients.
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.

1 participant