# Send Connector B-First Plan Date: 2026-07-10 Node: C29 / write-side connector route correction Decision owner: user/business manager ## Decision The selected send route is now: 1. **Primary route B: in-process / sidecar connector** that reuses the already logged-in `IMPlatformClient.exe` runtime and its existing message/file send classes. 2. **Fallback route A: constrained UI/RPA wrapper** only if B cannot attach, load, or invoke safely. 3. **Network replay/protocol reimplementation remains deferred** because it would require independently reproducing login/session/ack behavior. This document supersedes the previous C15/R5 conclusion for future send work. The old conclusion was correct for the evidence available at that time: no write connector had been selected. This node records the newly approved route and the evidence that makes B worth trying first. ## Business goal Expose controlled MCP actions for digital employees: - `isphere_send_message` - `isphere_send_file` The implementation must preserve these business controls: - target must be resolved from existing contact/group search results; - text/file content must be previewed before execution; - execution must use an `idempotency_key` and content hash; - every outbound attempt must produce an audit record; - early versions should support sandbox/test-target verification before normal production use. ## Static evidence summary Offline package evidence under: ```text runs/offline-evidence-intake/zyl-qqfile-20260709/ ``` Relevant extracted binaries: ```text zyl/Impp/IMPlatformClient.exe zyl/Impp/smack.dll zyl/Impp/IMPP.Interface.dll zyl/Impp/IMPP.ServiceBase.dll zyl/Impp/IMPP.Service.dll zyl/Impp/TcpFileTransfer.dll zyl/Impp/HYHC.IMPP.DAL.dll ``` Relevant IL snapshots: ```text runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPlatformClient.exe.il runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/smack.dll.il runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPP.Interface.dll.il runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPP.Service.dll.il runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPP.ServiceBase.dll.il ``` ## Text-send call chain ### Preferred sidecar candidate `IMPlatformClient.exe` contains a high-level helper: ```text IMPP.Client.Core.Plugins.Manager.AppContextManager.SendTxtMessageByJid(jid, chatType, content) ``` Observed behavior from IL: - for direct/P2P chat, it gets a `P2PChatManager` from `IMPPManager.Instance`; - it resolves a `Chat` by JID; - it finds or opens a chat form; - it calls `frmP2PChat.SendTxtMessage(content)`; - for temporary/reserved group chat, it calls the corresponding room form send method. This is the best B-route first target because it reuses the logged-in client's own state and UI/business rules. ### Central message construction candidate `IMPlatformClient.exe` also contains: ```text IMPP.Client.Core.MessageEngine.MessageScheduling.SendChatMessage(chat, msgText, toJid, messageType, isSaveMessage, msgGuid, IsReceipt) ``` Observed behavior from IL: - reads local font/style settings; - builds message body via `UtilsText.GetMessageStyleBodyText`; - decides `chat` vs `groupchat`; - creates `smack.packet.XmppMessage`; - sets body, subject, offline flag, receipt flag, time, and message type; - calls `chat.SendMessage(xmppMessage)`; - optionally persists/parses message through `MessageManager.MessageParsing`. This is the cleanest lower-level B candidate if the sidecar can obtain a valid `Chat` object from the running client context. ### Protocol bottom `smack.dll` provides the real wire-send chain: ```text com.vision.smack.Chat.SendMessage(XmppMessage) -> com.vision.smack.XMPPConnection.send(string) -> Sharp.Xmpp.Core.XmppCore.Send(string) -> stream.Write(...) ``` This proves that the send capability exists in the installed client binaries. It also shows why an external reimplementation is less attractive: it would need the same active connection, stanza format, message id, receipt, and session state. ## Important trap: plugin interface text send is not enough `IMPP.Interface.dll` declares: ```text IAppContextManager.SendP2PMessage(string pJid, string pMessage) IAppContextManager.SendP2PFiles(UserInfo[] pUserInfo, string[] pFiles) IAppContextManager.SendChatRoomMessage(string pRoomJid, string pMessage, string pluginID) IAppContextManager.SendPluginMessage(string pluginID, int command, string para) ``` But the implementation of: ```text IMPP.Client.Core.Plugins.Manager.AppContextManager.SendP2PMessage(...) ``` records the plugin call and then throws `NotImplementedException`. Therefore the B route must **not** choose `SendP2PMessage` as the text-send entry. The sidecar should prefer `SendTxtMessageByJid` or, if necessary, `MessageScheduling.SendChatMessage` with an existing `Chat` object. ## File-send call chain File sending appears split into upload plus file-message notification. ### Upload engine `IMPP.ServiceBase.dll` defines `IFileTransfer`. `IMPP.Service.dll` implements: ```text IMPP.Service.BLL.FileTransfer.FileUpload(...) IMPP.Service.BLL.FileTransfer.AsynFileUpload(...) IMPP.Service.BLL.FileTransfer.FileDownload(...) IMPP.Service.BLL.FileTransfer.SyncFileTransfer(...) ``` ### Offline file send `IMPlatformClient.exe` contains: ```text IMPP.Client.OffLineFileSend.sendFile() IMPP.Client.OffLineFileSend.trans_UploadCompleted(fileId) ``` Observed behavior: - builds a generated file GUID; - builds remote name as `filename____guid.ext`; - uses `Config.ServerInfo.HTTPFileServer` and `FileTransferManager.GetDomain`; - creates `FileUploadPara`; - calls `IMPPManager.Instance.Service.FileTransfer.FileUpload(uploadPara)`; - after upload completion, creates an `OFFLINE_FILE_TRANSFER;...` message body; - calls `Chat.sendFileMessage(...)`; - sets packet id to `fileId` and records metadata. ### Native TCP file transfer `TcpFileTransfer.dll` is native and exposes strings/exports indicating: ```text Send SendFile GetTcpFileMsgGuid _StartWaitForSendFileThread@8 _StartRecvFileThread@24 ``` This is a candidate for online/TCP file transfer, but the first B route should use the managed offline-file path because it is closer to the normal client business flow and already integrates upload metadata with XMPP file messages. ## Proposed sidecar architecture ```text Go MCP Server -> controlled action contract and audit -> C# WinHelper / Sidecar command -> B-route sidecar adapter -> running IMPlatformClient context -> existing AppContextManager / MessageScheduling / OffLineFileSend / smack.dll ``` The sidecar should be a narrow adapter, not a general-purpose remote code executor. ### Candidate sidecar operations ```text version self_check probe_client_runtime probe_send_entrypoints resolve_runtime_jid preview_send_message send_message_after_approval preview_send_file send_file_after_approval read_send_audit ``` The first implementation slice should stop before real production send: ```text version self_check probe_client_runtime probe_send_entrypoints ``` Then run a live sandbox observation before enabling `send_message_after_approval`. ## B-route validation gates ### Gate B1: runtime discovery Pass condition: - find a running `IMPlatformClient.exe` process; - record PID, bitness, install path, module list summary; - confirm the discovered path matches the extracted evidence family; - confirm whether the sidecar must be x86 or x64. Stop condition: - no logged-in process; - process bitness incompatible with available sidecar build; - module names differ too much from the extracted package. ### Gate B2: entrypoint availability Pass condition: - confirm `IMPlatformClient.exe` exposes `AppContextManager` and `MessageScheduling` in the runtime module set; - confirm `smack.dll` is loaded or loadable from the same install directory; - confirm `IMPP.Interface.dll` and `IMPP.Service*.dll` are present. Stop condition: - app is not .NET Framework / cannot inspect CLR runtime safely; - required assemblies are missing; - only `SendP2PMessage` is available but `SendTxtMessageByJid`/`MessageScheduling` cannot be reached. ### Gate B3: non-mutating dynamic observation Pass condition: - during one operator-approved manual test send, observe the expected chain: - `SendTxtMessageByJid` or UI send method; - `MessageScheduling.SendChatMessage`; - `Chat.SendMessage`; - `XMPPConnection.send`; - capture only redacted method names, argument shape, message id/hash, and success/ack indicator. Stop condition: - method chain differs from static evidence; - no success/ack indicator can be mapped; - message id/idempotency cannot be correlated. ### Gate B4: sidecar dry run Pass condition: - sidecar can resolve the target JID/chat type; - sidecar can build a preview object without sending; - preview contains target, content hash, connector, and proposed entrypoint; - audit event is appended. Stop condition: - no deterministic target resolution; - preview cannot distinguish direct vs group chat; - no auditable dry-run object. ### Gate B5: one sandbox send Pass condition: - one explicit test target only; - one idempotency key only; - one message content hash only; - success/ack or local sent-record evidence captured; - duplicate retry with same idempotency key is rejected locally. Stop condition: - duplicate send risk; - wrong target risk; - no post-send verification. ## A-route fallback A remains the backup route if B cannot be made reliable. A should not be arbitrary desktop control. It should expose only: ```text search_contact(query) open_conversation(target) write_draft(text) verify_draft(target, text_hash) send_after_approval(approval_id) upload_file(path) verify_send_result() ``` A-route fallback is activated when any of these happen: - B cannot attach/probe safely; - required runtime classes are unavailable in the logged-in process; - B can observe but cannot invoke without unstable side effects; - B cannot provide idempotency/audit guarantees; - sidecar bitness/runtime mismatch is too costly to resolve in the current cycle. ## MCP contract impact The MCP business tools should not expose B/A internals directly. They should keep the stable user-facing shape: ```text isphere_send_message(target_type, target_id, content_text, mode, idempotency_key, content_sha256) isphere_send_file(target_type, target_id, file_path, mode, idempotency_key, file_sha256) ``` Connector metadata should show the route: ```text connector = "implatform-sidecar" | "uia-rpa" connector_stage = "preview" | "sandbox_send" | "production" ``` ## Next implementation loop R5b/C30-live returned-probe intake is now complete. The live probe confirmed a running x86 `IMPlatformClient.exe` `4.1.2.6842`, installed B-route candidate DLLs, and A-route UIA controls, but it did not prove runtime send entrypoint reachability. It also observed an offline-send blocker in the captured chat windows. Next node should be **R6a/C31 non-mutating send connector preflight**: 1. Use the C# WinHelper read-only op `probe_client_runtime`. 2. Add or run `probe_send_entrypoints` against copied/installed binaries to confirm `SendTxtMessageByJid`, `MessageScheduling.SendChatMessage`, `Chat.SendMessage`, and file-upload/file-message candidates by metadata only. 3. Add or run a UIA preflight classifier for `skinAlphaTxt`, `rtbSendMessage`, `btnSend`, `ๅ‘้€ๆ–‡ไปถ`, and offline-send message state. 4. Do not send, click, type, upload, attach hooks, or capture network traffic in this node. 5. Update `capability-source-matrix.md` after B2/A-route preflight passes or fails. ## Current status B is selected as the primary send/file-send route. The first non-mutating runtime probe has now been run against a real logged-in environment through the returned live-probe package. B can continue only through non-mutating entrypoint confirmation; A remains the fallback and now has concrete UIA selector evidence, but production send remains blocked until dry-run/idempotency/audit and sandbox-send evidence exist.