Resolve Tahoe fallback service from chat metadata - #832
Conversation
qayshp
left a comment
There was a problem hiding this comment.
Self-review focused on the remaining service-selection assumption and its coverage.
Validation updateValidated on the current SIP-enabled Tahoe host:
No message was sent. The exact address-fallback path supports only one-to-one chats and rejects group chats, so it cannot be exercised in the user-designated two-recipient conversation without testing a different code path. This remains an end-to-end validation gap. |
|
Superseding the earlier validation note: the final implementation no longer hardcodes Tahoe |
|
Latest-head validation (
The previously recorded privacy-minimized live iMessage, RCS, and SMS dispatch evidence remains applicable because these follow-ups do not change service selection. |
ruinthemagic
left a comment
There was a problem hiding this comment.
Independent validation on a SIP-enabled macOS 26.5.2 host confirms that the Tahoe any GUID prefix is transport-agnostic: it occurs on both SMS and iMessage chats. No identifiers or message content were inspected. Exact chat GUIDs are unique here, and every any-prefixed row inspected has a supported, non-null service_name, so resolving the transport from the exact chat metadata is the correct design. The focused 4-case suite and targeted ESLint pass locally; the production build reaches only the unrelated pre-existing ScheduledService Timer/Timeout error. One remaining concern: when resolution fails or returns an unsupported value, this PR defaults to iMessage. That is not truly legacy behavior for any GUIDs—the current code errors—and it could silently switch an SMS or RCS conversation to iMessage. Please consider failing closed with a clear service-resolution error instead. That should preserve transport correctness without affecting normal Tahoe chats, whose metadata resolves successfully.
qayshp
left a comment
There was a problem hiding this comment.
Full-diff self-review found no blocking correctness changes. One non-blocking coverage note: the focused 6-case suite is exposed as a package script but is not invoked by a root test command or GitHub Actions, so regression coverage remains manual. I would prefer wiring it into an appropriate macOS CI job when the repository has one, but I would not block this PR on introducing new CI infrastructure.
| @@ -91,7 +91,23 @@ export class ActionHandler { | |||
| try { | |||
| // Generate the new send script | |||
| log.debug(`Sending AppleScript text using fallback script...`); | |||
There was a problem hiding this comment.
Non-blocking: service resolution can now fail before a fallback script is generated or executed, so this log may say the fallback is being sent when none will be. Consider wording it as 'Preparing AppleScript text fallback...' so the logs distinguish preparation from execution.
Summary
anychat GUIDs to a concrete Messages service from the matching chat's metadata before generating the address-based AppleScript fallbackiMessage,SMS, orRCSas resolved services and fail closed when the lookup fails, returns no matching service, or returns an unsupported valueActionHandlerfallback wiringRoot cause
On macOS 26 Tahoe,
anyis a transport-agnostic chat GUID prefix observed across iMessage, SMS, and RCS chats. Messages AppleScript still requires a concrete service type, so interpolatinganyinto the fallback script raises AppleScript error-1700. A hardcoded or unresolvedany→iMessagemapping could misroute a non-iMessage conversation.Implementation
When the primary chat-ID send fails for an
any;...GUID,ActionHandlerqueries the exact matching chat without loading participants and passes itsserviceNametosendMessageFallback(). The script generator:iMessage,SMS, andRCSGUID prefixesiMessage,SMS, orRCSvalue foranyGUIDsanyservice before any fallback AppleScript is executedIf the metadata lookup itself fails, the debug log records only the generic failure decision, not the underlying exception text.
Validation
Passed on the current head:
node --test test/tahoeFallbackService.test.cjs— 6/6 testsscripts.tsstill matches the base branchgit diff --checkThe focused suite covers:
anyiMessage, SMS, and RCS selection through both the script generator andActionHandlerLive validation on a SIP-enabled Tahoe host used the current production implementation without publishing identifiers or message content:
anyiMessage route recorded outgoing, sent, delivered, and no erroranySMS route recorded outgoing, sent, and no error; no delivery receipt was available, so this is a dispatch passanyRCS route recorded outgoing, sent, delivered, and no errorEach live run forced the primary chat-ID path to fail, performed one exact-chat metadata lookup, executed one correctly resolved address-based fallback, and created one matching outgoing record. The failure-only cases are covered deterministically by the focused suite; no Messages database fault injection was needed. No recipient-confirmed delivery is claimed.
The production build reaches only the existing unrelated
ScheduledService.ts:39Timer/Timeouttype error.Fixes #777