Generalize the photos-originals rclone-mount pattern to a video-projects prefix so the video studio (and imajin ETL, per storage-portability-plan §2.3) can read/write multi-GB project sources/renders as local files while only hot data stays resident on plum (bounded VFS LRU cache). Lets a small-disk laptop work with large footage without filling APFS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.5 KiB
iCalls (ICallsSync)
Purpose
Ingest macOS call history (Phone/FaceTime) into the server for timelines, recent activity, and correlation with messages/contacts/prospects.
Direction
Read-only. Call logs are append-only records emitted by the system; there is no Sender or send queue.
OS surface
~/Library/Application Support/CallHistoryDB/CallHistory.storedata (and legacy
~/Library/CallHistoryDB/CallHistory.storedata).
Direct readonly SQLite via GRDB (Core Data schema: ZCALLRECORD, ZUNIQUE_ID,
ZDATE as Apple reference time, ZADDRESS, ZORIGINATED, ZANSWERED,
ZDURATION, ZCALLTYPE, ZSERVICE_PROVIDER, ZNAME).
com.apple.security.files.all entitlement (already present for chat.db) is
sufficient. No extra TCC prompt beyond Full Disk Access.
Files
Reader.swift—CallHistoryReader:- Tries current then legacy path.
fetchCalls(since: Date?)— filters onZDATE > ref, oldest-first.- Timestamp conversion:
Date(timeIntervalSinceReferenceDate:). - Basic CNContact enrichment for display names when
ZNAMEabsent (best-effort). - Uses
PhoneUtils.normalize.
APIClient.swift:syncCalls(_:)→POST /client/icalls/syncgetStats()→GET /client/icalls/stats
SyncManager.swift— 120s read interval (per operator request), no send queue hooks. Batches of 200. SimplesyncedThisSession+ total from server.
Timing
- Read interval: 120s (
@packages/icalls/Sources/ICallsSync/SyncManager.swift).
Server
- Entity:
macsync.calls(dedicated table, not mixed into messages). Unique on(device_id, external_id). - Ingest:
features/icalls/ingestCalls(dedup + upsert). - Queries:
/my/calls(filter by deviceId, direction, callType) +/my/calls/stats. - Client ingest:
/client/icalls/sync+/stats(wrapped in sync-history 'call'). - Web tab: basic recent-calls list (no web writes).
Web
web/src/api/calls.tsweb/src/tabs/Calls/index.tsx- Registered under
/callsin App + nav.
Known characteristics
- First sync backfills available history (can be thousands of rows; rows are tiny).
ZUNIQUE_ID(or syntheticzpk:<Z_PK>) is the stable external id.- Multi-party FaceTime participants live in join tables (
Z_2REMOTEPARTICIPANTHANDLES+ZHANDLE); v1 surfaces primaryZADDRESSonly. - Duration 0 + unanswered often indicates missed/ringing-out attempts.
Adding / extending
Follow the read-only path in docs/adding-a-module.md (no send queue / Sender / admin
send routes). Add columns or participant join expansion in a follow-up migration if needed.