diff --git a/docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md b/docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md new file mode 100644 index 0000000..b2eab8a --- /dev/null +++ b/docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md @@ -0,0 +1,277 @@ +# In-Process Adapter Static Map + +Date: 2026-07-12 + +## Scope + +This report uses offline IL/static evidence only. It does not log in, attach hooks, inject into a process, modify client binaries, upload files, send messages, or open network connections. + +Machine-readable evidence: `runs\inprocess-adapter-research\inprocess-adapter-map.json` + +## Decision + +| Question | Answer | +| --- | --- | +| Selected next B-route branch | managed_in_process_adapter_contract_first | +| Can offline branch enable production send? | **No** | +| Go connector mode to expose now | in_process_contract | +| Required online proof later | logged-in adapter reachability plus sent-record/content-hash/ack evidence | + +## Sources + +| Source | Role | Exists | Lines | Size bytes | +| --- | --- | --- | ---: | ---: | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main managed client; UI, AppContextManager, MessageScheduling, frmMain, login runtime | True | 1360035 | 74148460 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | XMPP/smack managed library; Chat and XMPPConnection send primitives | True | 87425 | 5019807 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il` | file transfer service implementation | True | 3351 | 207786 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il` | file transfer DTOs and FileUploadPara/FileUploadResult contracts | True | 1641 | 93585 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il` | service and network interface contracts | True | 4429 | 227335 | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il` | common helper and runtime DTO evidence | True | 118343 | 5703293 | + +## Command contract for future in-process adapter + +| Op | Current status | Purpose | Required evidence before production | +| --- | --- | --- | --- | +| `probe_runtime` | `contract_only` | report whether adapter is inside logged-in IMPP runtime and can see required types/singletons | process identity; loaded assemblies; IMPPManager.UserInfo presence; XMPP connection state | +| `send_text` | `blocked_until_logged_in_adapter` | invoke high-level text send path after target JID and content hash are validated | AppContextManager or MessageScheduling reachability; target JID; sent record or ack containing content hash/correlation | +| `upload_file` | `blocked_until_logged_in_adapter` | call file upload service and return server FileID/remote folder metadata | FileUploadPara values; HTTP file server/auth; FileUploadResult.FileID | +| `send_file_message` | `blocked_until_upload_evidence` | finalize file message after upload returns server id | uploaded FileID; file name/size; target JID/Chat; sent record/ack | + +## Anchor summary + +| Anchor | Command | Classification | Confidence | Evidence | Required runtime | +| --- | --- | --- | --- | ---: | --- | +| `AppContextManager.SendTxtMessageByJid` | `send_text` | `in_process_candidate_static_only` | `high_static` | 6 | logged-in IMPPManager/UserInfo; target JID; initialized AppContextManager; live XMPP connection | +| `MessageScheduling.SendChatMessage` | `send_text` | `in_process_candidate_static_only` | `high_static` | 16 | MessageScheduling instance or static caller; RosterContactsArgs/contact context; Chat object; live XMPP connection | +| `com.vision.smack.Chat.SendMessage / XMPPConnection.send` | `send_text` | `in_process_candidate_static_only` | `high_static` | 16 | Chat instance; XMPPConnection authenticated session; message payload format | +| `IMPP.Client.OffLineFileSend.sendFile` | `upload_file_then_send_file` | `in_process_candidate_static_only` | `high_static` | 6 | local file path; HTTP file server/auth state; target roster/chat args; upload completion callback | +| `IFileTransfer/FileTransfer.FileUpload + FileUploadPara` | `upload_file` | `in_process_candidate_static_only` | `high_static` | 16 | FileUploadPara host/port/domain; localFilePath; token/auth; FileUploadResult.FileID | +| `MessageScheduling.SendFileMessage / Chat.sendFileMessage` | `send_file_message` | `in_process_candidate_static_only` | `high_static` | 13 | uploaded file id; remote folder metadata; file name/size; target Chat/JID | +| `IMPPManager.UserInfo / UnifiedAuthentication / Auth token` | `runtime_context` | `runtime_dependency` | `medium_static` | 16 | UserInfo; UnifiedAuthentication; Auth token; HTTPFileServer; server resource/domain | +| `frmMain / MessageCenter / chat runtime ownership` | `runtime_context` | `runtime_dependency` | `medium_static` | 16 | running frmMain; initialized message center; contact/session state | +| `frmLogin.StartWinServer / HttpServerLib` | `not_selected_bridge` | `not_a_send_bridge` | `high_static_negative` | 6 | logged-in state; route module registration not found; send route not found | + +## Verified facts + +- Text send has static in-process candidates, but all require logged-in runtime objects and a live XMPP/Chat path. +- File send is split into upload and message-finalization; FileUploadResult.FileID is a required boundary value before Chat.sendFileMessage is meaningful. +- The earlier IPC/plugin/local HTTP scan did not find a confirmed external send bridge, so this branch must stay at in_process_contract until online reachability exists. +- in_process_contract is a Go-side contract and audit mode only; it must return blocked/no-side-effect metadata in this offline branch. + +## Required runtime state + +- logged-in IMPlatformClient.exe process +- loaded IMPP.Client/AppContextManager/MessageScheduling types +- initialized IMPPManager.UserInfo and UnifiedAuthentication/Auth token +- live XMPPConnection/Chat session +- target JID or group JID resolved by existing search tools +- file upload service parameters and FileUploadResult.FileID for file sends + +## Anchor evidence + +### AppContextManager.SendTxtMessageByJid + +Classification: `in_process_candidate_static_only`; command: `send_text`; evidence count: 6. + +Adapter role: preferred high-level managed entry if an in-process adapter can reach AppContextManager + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:542112` | `string_literal` | `IL_09bf: ldstr "SendTxtMessageByJid"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:585987` | `signature_continuation` | `instance void SendTxtMessageByJid(string jid,` | `L585986: .method public hidebysig newslot virtual final instance void SendTxtMessageByJid(string jid,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586197` | `method_end` | `} // end of method AppContextManager::SendTxtMessageByJid` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1358068` | `string_literal` | `IL_0c3f: ldstr "SendTxtMessageByJid"` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il:1920` | `signature_continuation` | `instance void SendTxtMessageByJid(string jid,` | `L1919: .method public hidebysig newslot abstract virtual instance void SendTxtMessageByJid(string jid,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il:1924` | `method_end` | `} // end of method IAppContextManager::SendTxtMessageByJid` | `L1919: .method public hidebysig newslot abstract virtual instance void SendTxtMessageByJid(string jid,` | + +### MessageScheduling.SendChatMessage + +Classification: `in_process_candidate_static_only`; command: `send_text`; evidence count: 16. + +Adapter role: fallback managed entry when scheduling layer has chat and contact args + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:728720` | `callsite` | `IL_0213: call class [smack]com.vision.smack.packet.XmppMessage IMPP.Client.Core.MessageEngine.MessageScheduling::SendChatMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153541` | `reference` | `SendChatMessage(class [smack]com.vision.smack.Chat chat,` | `L1153540: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153800` | `method_end` | `} // end of method MessageScheduling::SendChatMessage` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154128` | `reference` | `SendChatMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs rosterArgs,` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154187` | `callsite` | `IL_006e: call class [smack]com.vision.smack.packet.XmppMessage IMPP.Client.Core.MessageEngine.MessageScheduling::SendChatMessage(class [smack]com.vision.smack.Chat,` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154225` | `method_end` | `} // end of method MessageScheduling::SendChatMessage` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99274` | `reference` | `get_issendchatmessage() cil managed` | `L99273: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99284` | `reference` | `set_issendchatmessage(string 'value') cil managed` | `L99283: .method public hidebysig specialname instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99582` | `reference` | `.property instance string issendchatmessage()` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99586` | `reference` | `.set instance void Schedule::set_issendchatmessage(string)` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:99587` | `reference` | `.get instance string Schedule::get_issendchatmessage()` | `L99546: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:100662` | `reference` | `get_issendchatmessage() cil managed` | `L100661: .method public hidebysig specialname instance string` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:100672` | `reference` | `set_issendchatmessage(string 'value') cil managed` | `L100671: .method public hidebysig specialname instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101019` | `reference` | `.property instance string issendchatmessage()` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101023` | `reference` | `.get instance string ScheduleTaskDetailsDTO::get_issendchatmessage()` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il:101024` | `reference` | `.set instance void ScheduleTaskDetailsDTO::set_issendchatmessage(string)` | `L100976: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | + +### com.vision.smack.Chat.SendMessage / XMPPConnection.send + +Classification: `in_process_candidate_static_only`; command: `send_text`; evidence count: 16. + +Adapter role: lowest-level send target; requires already resolved Chat/XMPPConnection + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:80284` | `callsite` | `IL_34d2: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:206378` | `callsite` | `IL_0010: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L206369: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:249554` | `callsite` | `IL_0c1e: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:249857` | `callsite` | `IL_0f27: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:299997` | `callsite` | `IL_0096: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `L299937: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:410318` | `callsite` | `IL_2257: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:412929` | `callsite` | `IL_00d2: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `L412858: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:430535` | `callsite` | `IL_0357: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:451786` | `callsite` | `IL_00b1: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L451702: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:451858` | `callsite` | `IL_018f: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454073` | `callsite` | `IL_0179: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454206` | `callsite` | `IL_00b9: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L454118: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:454298` | `callsite` | `IL_00b9: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L454210: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:520831` | `callsite` | `IL_017a: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:521914` | `callsite` | `IL_007a: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521860: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:521970` | `callsite` | `IL_0075: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521918: .method public hidebysig instance void` | + +### IMPP.Client.OffLineFileSend.sendFile + +Classification: `in_process_candidate_static_only`; command: `upload_file_then_send_file`; evidence count: 6. + +Adapter role: UI-side upload orchestration and transition into chat file message + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:821640` | `reference` | `_tcpRecvInfo_RecvCancelSendFile() cil managed` | `L821639: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:824164` | `callsite` | `IL_026b: callvirt instance void IMPP.Client.OffLineFileSend::sendFile()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826149` | `reference` | `sendFile() cil managed` | `L826148: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826572` | `method_end` | `} // end of method OffLineFileSend::sendFile` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826670` | `callsite` | `IL_0104: call instance void IMPP.Client.OffLineFileSend::trans_UploadCompleted(string)` | `L826574: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:827241` | `method_end` | `} // end of method OffLineFileSend::trans_UploadCompleted` | `` | + +### IFileTransfer/FileTransfer.FileUpload + FileUploadPara + +Classification: `in_process_candidate_static_only`; command: `upload_file`; evidence count: 16. + +Adapter role: service upload entry that must return FileUploadResult before chat file finalization + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:511999` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_11,` | `L511981: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512002` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_14,` | `L511981: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512182` | `callsite` | `IL_01d9: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.Ser...` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512315` | `callsite` | `IL_0322: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512459` | `constructor_call` | `IL_04a3: newobj instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::.ctor(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608732` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_4,` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608733` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_5,` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608787` | `constructor_call` | `IL_0092: newobj instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::.ctor(string,` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608795` | `callsite` | `IL_009c: callvirt instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::set_IsPublic(bool)` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608800` | `callsite` | `IL_00b2: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.Ser...` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608819` | `callsite` | `IL_00e0: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L608722: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608847` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_5,` | `L608836: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608848` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_6,` | `L608836: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608908` | `constructor_call` | `IL_00a5: newobj instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::.ctor(string,` | `L608836: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608916` | `callsite` | `IL_00af: callvirt instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::set_IsPublic(bool)` | `L608836: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608921` | `callsite` | `IL_00c5: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.Ser...` | `L608836: .method private hidebysig instance void` | + +### MessageScheduling.SendFileMessage / Chat.sendFileMessage + +Classification: `in_process_candidate_static_only`; command: `send_file_message`; evidence count: 13. + +Adapter role: chat file-message finalization after FileID/remote folder exists + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:728711` | `callsite` | `IL_01fb: call class [smack]com.vision.smack.packet.XmppMessage IMPP.Client.Core.MessageEngine.MessageScheduling::SendFileMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:827225` | `callsite` | `IL_034d: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::sendFileMessage(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1144766` | `callsite` | `IL_03e8: callvirt instance void [HYHC.IMPP.DAL]HYHC.IMPP.DAL.IMPPDAL::AddSendFileMessage(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1146020` | `callsite` | `IL_0237: callvirt instance void [HYHC.IMPP.DAL]HYHC.IMPP.DAL.IMPPDAL::AddSendFileMessage(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1150833` | `callsite` | `IL_14e8: callvirt instance void [HYHC.IMPP.DAL]HYHC.IMPP.DAL.IMPPDAL::AddSendFileMessage(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153803` | `reference` | `SendFileMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs rosterArgs,` | `L1153802: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153922` | `callsite` | `IL_00f1: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::sendFileMessage(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1154125` | `method_end` | `} // end of method MessageScheduling::SendFileMessage` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1235` | `reference` | `sendFileMessage(string p_message,` | `L1233: .method public hidebysig newslot abstract virtual instance class com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1244` | `method_end` | `} // end of method Chat::sendFileMessage` | `L1233: .method public hidebysig newslot abstract virtual instance class com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21442` | `reference` | `sendFileMessage(string p_message,` | `L21441: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21490` | `method_end` | `} // end of method P2PChat::sendFileMessage` | `L21441: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30070` | `reference` | `sendFileMessage(string p_message,` | `L30069: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` | + +### IMPPManager.UserInfo / UnifiedAuthentication / Auth token + +Classification: `runtime_dependency`; command: `runtime_context`; evidence count: 16. + +Adapter role: runtime state required before any production send/upload can be meaningful + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3533` | `callsite` | `IL_004c: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `L3492: .method public hidebysig static void FillDataToDataGridView(class [IMPP.UI]IMPP.UI.SkinControl.SkinDataGridView dgv,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4359` | `callsite` | `IL_01ba: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4393` | `callsite` | `IL_021a: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:4403` | `callsite` | `IL_0236: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5267` | `callsite` | `IL_02ea: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5752` | `callsite` | `IL_08ac: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:5772` | `callsite` | `IL_08ee: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6283` | `callsite` | `IL_0ea6: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6329` | `callsite` | `IL_0f2f: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:6399` | `callsite` | `IL_1006: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7402` | `callsite` | `IL_0141: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7504` | `callsite` | `IL_024f: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7855` | `callsite` | `IL_00bf: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `L7780: .method public hidebysig static void AddLinkID(class CSharpWin.ChatRichTextBox textBox,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:7997` | `callsite` | `IL_023a: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:8222` | `callsite` | `IL_047a: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:8309` | `callsite` | `IL_0557: callvirt instance class [IMPP.Common]IMPP.Common.UserInfo IMPP.Client.IMPPManager::get_UserInfo()` | `` | + +### frmMain / MessageCenter / chat runtime ownership + +Classification: `runtime_dependency`; command: `runtime_context`; evidence count: 16. + +Adapter role: likely object owner for initialized chat, reconnect, message center, and plugin runtime state + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1714` | `field` | `.field family class IMPP.Client.frmMain mainWin` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1744` | `reference` | `IL_001d: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L1721: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1789` | `reference` | `IL_002a: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L1761: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2777` | `reference` | `Init(class IMPP.Client.frmMain frmMain) cil managed` | `L2776: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2791` | `reference` | `IL_000a: stfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L2776: .method public hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3005` | `reference` | `IL_001d: ldfld class IMPP.Client.frmMain IMPP.Client.VideoChat.SingleAVDispatcher::mainWin` | `L2981: .method family hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9039` | `type_definition` | `.class private auto ansi beforefieldinit IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication` | `L9012: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9042` | `field` | `.field private static class IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication _instance` | `L9012: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9058` | `constructor_call` | `IL_0000: newobj instance void IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication::.ctor()` | `L9054: .method public hidebysig static void Init() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9059` | `reference` | `IL_0005: stsfld class IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication::_instance` | `L9054: .method public hidebysig static void Init() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9060` | `reference` | `IL_000a: ldsfld class IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication::_instance` | `L9054: .method public hidebysig static void Init() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9061` | `callsite` | `IL_000f: callvirt instance void IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication::StartLightAppMultProssCommunication()` | `L9054: .method public hidebysig static void Init() cil managed` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9081` | `reference` | `} // end of class IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication` | `L9073: .method private hidebysig specialname rtspecialname static` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13688` | `callsite` | `IL_0179: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14269` | `callsite` | `IL_00be: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `L14190: .method public hidebysig static void OpenSetRoamMessageForm(valuetype [IMPP.Model]IMPP.Model.ChatRecord.MsgType msgSource,` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15179` | `callsite` | `IL_0074: callvirt instance class [smack]com.vision.smack.Chat [smack]com.vision.smack.ChatManager::GetChat(class [smack]com.vision.smack.XMPPConnection,` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` | + +### frmLogin.StartWinServer / HttpServerLib + +Classification: `not_a_send_bridge`; command: `not_selected_bridge`; evidence count: 6. + +Adapter role: known local HTTP framework, but not a confirmed send bridge + +| Source | Kind | Snippet | Context | +| --- | --- | --- | --- | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:223` | `reference` | `.assembly extern HttpServerLib` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889253` | `reference` | `StartWinServer() cil managed` | `L889252: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889272` | `reference` | `class [HttpServerLib]HTTPServerLib.HttpService V_15,` | `L889252: .method private hidebysig instance void` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889554` | `constructor_call` | `IL_02dc: newobj instance void [HttpServerLib]HTTPServerLib.HttpService::.ctor(string,` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889559` | `reference` | `IL_02e5: ldftn instance void [HttpServerLib]HTTPServerLib.HttpServer::Start()` | `` | +| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889677` | `method_end` | `} // end of method frmLogin::StartWinServer` | `` | + +## Stop conditions + +- No logged-in process is available for runtime reachability validation. +- Adapter cannot see AppContextManager, MessageScheduling, Chat, or IFileTransfer in process. +- Every viable path requires unsupported binary patching instead of a replaceable managed adapter/harness. +- Online evidence cannot produce sent-record/content-hash/ack correlation for text send. +- File upload cannot return FileUploadResult.FileID or equivalent remote folder metadata. + +## Next work + +1. Add Go connector mode in_process_contract that validates request shape and returns blocked/no-side-effect metadata. +2. In a logged-in environment, build a recorder/probe that only checks reachability of the listed runtime objects before attempting any send. +3. Promote text send only after sent-record/content-hash/ack evidence exists. +4. Promote file send only after upload returns FileUploadResult.FileID and file-message finalization is proven online. diff --git a/docs/source-discovery/capability-source-matrix.md b/docs/source-discovery/capability-source-matrix.md index 8a3baad..19c96b0 100644 --- a/docs/source-discovery/capability-source-matrix.md +++ b/docs/source-discovery/capability-source-matrix.md @@ -22,6 +22,7 @@ Offline B-route text-send map: `docs/source-discovery/2026-07-12-broute-text-sen Offline B-route file-send map: `docs/source-discovery/2026-07-12-broute-file-send-static-map.md` Offline B-route bridge map: `docs/source-discovery/2026-07-12-broute-bridge-static-map.md` Offline B-route decision: `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md` +In-process adapter static map: `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md` ## Source priority @@ -42,8 +43,8 @@ Route rule: UIA helper / A-route / RPA is a backup route only. It can preserve d | `isphere_search_contacts` | bare sender/receiver JIDs extracted from normalized log-backed messages loaded from configured PacketReader file or directory source | validated copied `MsgLib.db` tables: `TD_Roster`, `TD_CustomEffigy`, `tblRecent`, `tblChatLevel`, `tblPersonMsg`; decrypted roster/contact stanzas from `Smark.SendReceive`; UIA helper source if display names are still missing | `docs/source-discovery/2026-07-10-msglib-readonly-schema-extraction.md`; `internal/isphere/contacts_test.go`; `internal/tools/isphere_contacts_test.go` | C34 documents optional MsgLib contact display enrichment; R2 adds deterministic exact-match-first ranking, case-insensitive de-duplication across log/MsgLib candidates, and preserves `source`/`raw_ref` | core contact search complete; optional richer fields later | | `isphere_search_groups` | decrypted `PacketReader.ProcessPacket` `type="groupchat"` stanzas and conference/MUC JIDs loaded from configured PacketReader file or directory source | validated copied `MsgLib.db` tables: `tblMsgGroupPersonMsg`, `TD_WorkGroupAuth`, `tblRecent`; UIA helper source if group display names are still missing | `docs/source-discovery/2026-07-10-msglib-readonly-schema-extraction.md`; `internal/isphere/groups_test.go`; `internal/tools/isphere_groups_test.go`; C9 ignored-log scan: PacketReader 86 groupchat/86 conference hits; Smark 24 groupchat/658 conference/631 muc hits | C34 documents optional MsgLib group display enrichment; R2 adds deterministic exact-match-first ranking, case-insensitive de-duplication across log/MsgLib candidates, and preserves `source`/`raw_ref` | core group search complete; optional member/owner hierarchy later | | `isphere_receive_files` | decrypted `PacketReader.ProcessPacket` file-transfer message stanzas via `internal/isphere.ListFilesFromMessages` and `isphere_receive_files` list mode; configured PacketReader file or directory source; `zyl\importal\` cache entries remain unlinked | MsgLib `TD_ReceiveFileRecord` safe metadata through explicit copied-DB path; decrypted `Smark.SendReceive` and `SaveToDB` traces for file-reference reconciliation; future UIA/client connector for download | `docs/source-discovery/2026-07-09-n12-pre-zyl-schema-notes.md#c12-file-transfer-evidence-precheck`; `docs/source-discovery/2026-07-10-file-download-mapping-precheck.md`; `docs/source-discovery/2026-07-10-file-cache-mapping-diagnostic.md`; `docs/source-discovery/2026-07-10-file-download-mapping-v2.md`; `docs/reports/2026-07-10-business-goals-smoke.md` | C22 verifies safe file-list contract args; R10 proves resolver scoring with fixture accepted matches; R11 adds structured download preview with `blocked`/`planned` status and side-effect flags false; R13/R14 confirms list is ready but real download is still blocked. | blocked for real download pending accepted real cache mapping and copy gate; list mode is complete | -| `isphere_send_message` | B-route selected: `in_process_adapter_research` after offline reverse. Static call path is confirmed through `AppContextManager.SendTxtMessageByJid(...)`, `MessageScheduling.SendChatMessage(...)`, `Chat.SendMessage`, and `XMPPConnection.send`, but no existing IPC/plugin/local HTTP send bridge is confirmed; default MCP tool still exposes preview/dry-run unless an explicit connector mode is configured | A-route fallback is now implemented for UI action: `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` calls WinHelper `uia_send_message` against a configured HWND, writes `rtbSendMessage`, and clicks `btnSend`; this stays backup-only and network/protocol replay remains deferred | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-sandbox-gate.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis-v2.md`; `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`; `docs/source-discovery/2026-07-11-a-route-uia-send.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `internal/tools/isphere_send_message_test.go`; `cmd/isphere-capability-smoke/main.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R6f-R6l define connector contract, audit/idempotency replay, production gate, B-route shell, strict-v2 package, and explicit production closure. R10a validates two returned sent-record packages as manual-only evidence. A-route adds local UI action readiness: synthetic window proof plus real offline `frmP2PChat` open/write/click target proof. Offline B-route reverse confirms the send call path but rejects existing IPC/plugin-first for this evidence set; business delivery is still not verified because local runtime is offline and no success/ack or sent-record hash evidence has passed. | Create a dedicated B-route `in_process_adapter_research` plan; keep external sidecar preview/probe-only and A-route UI action backup-only; business send remains blocked until adapter reachability plus online sent-record/content-hash/ack evidence passes | -| `isphere_send_file` | B-route selected after offline reverse: managed file send is upload-first through `OffLineFileSend.sendFile()`, `FileUploadPara`, `IMPP.Service*.dll` `IFileTransfer.FileUpload(...)`, then chat file-message finalization through `trans_UploadCompleted(fileId)`, `MessageScheduling.SendFileMessage`, and `Chat.sendFileMessage(...)`; current MCP tool exposes preview/dry-run only | A-route file fallback is not implemented yet; real offline UIA dump did not expose stable `btnSendFile`, so the fallback slice remains toolbar/menu locator discovery; native `TcpFileTransfer.dll` is not the first B-route bridge because managed upload/message flow is now mapped | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-file-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `internal/tools/isphere_files_test.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R7 registers send-file preview as the tenth MCP tool; R8 adds audit/idempotency duplicate/conflict hardening without raw file paths/content; R9 builds and verifies the online send-file evidence package; R13/R14 confirms preview is ready and production upload remains blocked. Offline B-route reverse confirms upload-first/file-message-second and shows file id/auth/runtime reachability are the blockers. A-route real-window work confirms file-button automation still needs a separate locator node. | blocked until B-route in-process adapter research proves access to logged-in `IFileTransfer`/`Chat` objects and returned file-send package proves upload/sent evidence; A-route locator remains backup-only | +| `isphere_send_message` | B-route selected: `in_process_adapter_research` after offline reverse. Static call path is confirmed through `AppContextManager.SendTxtMessageByJid(...)`, `MessageScheduling.SendChatMessage(...)`, `Chat.SendMessage`, and `XMPPConnection.send`, but no existing IPC/plugin/local HTTP send bridge is confirmed; default MCP tool still exposes preview/dry-run unless an explicit connector mode is configured | A-route fallback is now implemented for UI action: `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` calls WinHelper `uia_send_message` against a configured HWND, writes `rtbSendMessage`, and clicks `btnSend`; this stays backup-only and network/protocol replay remains deferred | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-sandbox-gate.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis.md`; `docs/source-discovery/2026-07-10-returned-send-sandbox-analysis-v2.md`; `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`; `docs/source-discovery/2026-07-11-a-route-uia-send.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `internal/tools/isphere_send_message_test.go`; `cmd/isphere-capability-smoke/main.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R6f-R6l define connector contract, audit/idempotency replay, production gate, B-route shell, strict-v2 package, and explicit production closure. R10a validates two returned sent-record packages as manual-only evidence. A-route adds local UI action readiness: synthetic window proof plus real offline `frmP2PChat` open/write/click target proof. Offline B-route reverse confirms the send call path but rejects existing IPC/plugin-first for this evidence set; business delivery is still not verified because local runtime is offline and no success/ack or sent-record hash evidence has passed. | B-route now exposes only the `in_process_contract` connector mode for request-shape/audit validation; keep external sidecar preview/probe-only and A-route UI action backup-only; production remains blocked until logged-in adapter reachability plus online sent-record/content-hash/ack evidence passes | +| `isphere_send_file` | B-route selected after offline reverse: managed file send is upload-first through `OffLineFileSend.sendFile()`, `FileUploadPara`, `IMPP.Service*.dll` `IFileTransfer.FileUpload(...)`, then chat file-message finalization through `trans_UploadCompleted(fileId)`, `MessageScheduling.SendFileMessage`, and `Chat.sendFileMessage(...)`; current MCP tool exposes preview/dry-run only | A-route file fallback is not implemented yet; real offline UIA dump did not expose stable `btnSendFile`, so the fallback slice remains toolbar/menu locator discovery; native `TcpFileTransfer.dll` is not the first B-route bridge because managed upload/message flow is now mapped | `docs/source-discovery/2026-07-10-send-message-source-precheck.md`; `docs/source-discovery/2026-07-10-send-message-connector-selection.md`; `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`; `docs/source-discovery/2026-07-10-returned-live-probe-analysis.md`; `docs/source-discovery/2026-07-10-send-connector-preflight.md`; `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md`; `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`; `docs/source-discovery/2026-07-12-broute-file-send-static-map.md`; `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`; `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`; `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`; `internal/tools/isphere_files_test.go`; `docs/reports/2026-07-10-business-goals-smoke.md` | R7 registers send-file preview as the tenth MCP tool; R8 adds audit/idempotency duplicate/conflict hardening without raw file paths/content; R9 builds and verifies the online send-file evidence package; R13/R14 confirms preview is ready and production upload remains blocked. Offline B-route reverse confirms upload-first/file-message-second and shows file id/auth/runtime reachability are the blockers. A-route real-window work confirms file-button automation still needs a separate locator node. | blocked until B-route in-process adapter research proves logged-in access to `IFileTransfer.FileUpload`, returned `FileUploadResult.FileID`, and `Chat.sendFileMessage` finalization; production file upload/send remains blocked until online evidence exists; A-route locator remains backup-only | ## Stage C entry rule @@ -60,4 +61,4 @@ Start Stage C with a narrow log-backed `isphere_receive_messages` source abstrac ## Deferred source work -`MsgLib.db` has a validated copied read-only open path through the bundled 32-bit `System.Data.SQLite.dll` and password `123`. C27 adds `MsgLibReadSidecar` as the bounded x86 .NET reader boundary, C28 adds the Go `internal/msglib` process client, C29 adds bounded `display_entities` extraction, C30 wires it as optional contact/group MCP enrichment, C31 proves real copied-DB MCP enrichment with sanitized output, C32 reuses it for receive-message display fields, C33 proves that receive display path through a real copied-DB MCP smoke without printing entity values, C34 documents the operator setup/verification path, C35 maps MsgLib message tables to receive-message contract fields without reading row values, C36 adds metadata-only `message_sources` readiness, C37 defines the bounded DB-backed receive-source design, C38 implements sidecar/Go-wrapper `list_messages` with sanitized verification, C39 adds a Go adapter from MsgLib list results to the receive-message domain model, C40 adds explicit tool-level `msglib_readonly` source selection, C41 wires env-configured explicit MsgLib receive with optional sanitized smoke, R1 documents source reconciliation keys, and R2 hardens contact/group search ranking and de-duplication. R6j/R6k confirm the send-message strict-v2 production gate is still not passed; R10a confirms the returned sent-record packages are manual-only evidence and do not unlock production send; R10/R11 define file-download resolver/preview behavior while keeping real copy blocked; R12 adds receive-source reconciliation without changing default routing; R13/R14 publish business-goals smoke and the release-candidate status. A-route now proves UI write/click readiness against synthetic and real offline chat windows, but not online delivery. The active B-route follow-up is now the offline decision path in `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`: create a dedicated `in_process_adapter_research` plan before production send/file work. A-route RPA remains backup-only under `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`. +`MsgLib.db` has a validated copied read-only open path through the bundled 32-bit `System.Data.SQLite.dll` and password `123`. C27 adds `MsgLibReadSidecar` as the bounded x86 .NET reader boundary, C28 adds the Go `internal/msglib` process client, C29 adds bounded `display_entities` extraction, C30 wires it as optional contact/group MCP enrichment, C31 proves real copied-DB MCP enrichment with sanitized output, C32 reuses it for receive-message display fields, C33 proves that receive display path through a real copied-DB MCP smoke without printing entity values, C34 documents the operator setup/verification path, C35 maps MsgLib message tables to receive-message contract fields without reading row values, C36 adds metadata-only `message_sources` readiness, C37 defines the bounded DB-backed receive-source design, C38 implements sidecar/Go-wrapper `list_messages` with sanitized verification, C39 adds a Go adapter from MsgLib list results to the receive-message domain model, C40 adds explicit tool-level `msglib_readonly` source selection, C41 wires env-configured explicit MsgLib receive with optional sanitized smoke, R1 documents source reconciliation keys, and R2 hardens contact/group search ranking and de-duplication. R6j/R6k confirm the send-message strict-v2 production gate is still not passed; R10a confirms the returned sent-record packages are manual-only evidence and do not unlock production send; R10/R11 define file-download resolver/preview behavior while keeping real copy blocked; R12 adds receive-source reconciliation without changing default routing; R13/R14 publish business-goals smoke and the release-candidate status. A-route now proves UI write/click readiness against synthetic and real offline chat windows, but not online delivery. The active B-route follow-up is now the in-process contract path in `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`: validate logged-in adapter reachability before production send/file work. A-route RPA remains backup-only under `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`. diff --git a/docs/superpowers/plans/2026-07-12-in-process-adapter-research.md b/docs/superpowers/plans/2026-07-12-in-process-adapter-research.md new file mode 100644 index 0000000..768208d --- /dev/null +++ b/docs/superpowers/plans/2026-07-12-in-process-adapter-research.md @@ -0,0 +1,285 @@ +# In-Process Adapter Research Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Convert the offline B-route decision into a reproducible in-process adapter research slice that identifies reachable runtime objects, defines the minimum helper contract, and keeps production send blocked until logged-in evidence exists. + +**Architecture:** This branch does not mutate the iSphere client and does not claim production send. It adds deterministic IL/static analysis for in-process anchors, then updates the Go connector with an explicit `in_process_contract` mode that validates the future bridge request/response shape while returning a blocked/no-side-effect result. Later online work can replace the contract stub with a logged-in managed adapter. + +**Tech Stack:** PowerShell static analyzers over IL/text evidence, Markdown reports under `docs/source-discovery`, Go MCP tool connector code under `internal/tools`, and `go test ./...` for regression verification. + +## Global Constraints + +- Do not use ripgrep (`rg`); use `git ls-files`, `ag`, `grep -R`, PowerShell, or `Select-String`. +- Do not stage or commit `.codex-remote-attachments/`. +- Do not copy, patch, or modify original iSphere binaries. +- Do not enable real text send, file upload, or file send in this offline branch. +- A-route/RPA remains backup-only; do not promote it as the product path. +- B-route primary path for this branch is `in_process_adapter_research`. +- Every claimed completion must be backed by fresh command output. + +--- + +## File Structure + +- Create `scripts/extract-inprocess-adapter-map.ps1`: deterministic static analyzer for in-process anchors, object ownership, method accessibility, required runtime state, and stop conditions. +- Create `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`: human-readable report generated by the script. +- Create ignored runtime JSON at `runs/inprocess-adapter-research/inprocess-adapter-map.json`: machine-readable evidence generated by the script; not committed unless the repo already tracks runs output. +- Modify `internal/tools/send_message_broute_adapter.go`: add `in_process_contract` mode that validates request shape and returns blocked/no-side-effect contract metadata. +- Modify `internal/tools/send_message_broute_adapter_test.go`: add tests for `in_process_contract` mode, including no accepted send and no side effects. +- Modify `internal/tools/send_message_uia_adapter.go`: extend the existing send connector env factory to route `ISPHERE_SEND_CONNECTOR_MODE=in_process_contract` to the B-route contract connector. +- Modify `internal/tools/send_message_uia_adapter_test.go`: prove the env factory builds the in-process contract connector. +- Modify `docs/source-discovery/capability-source-matrix.md`: point send-message/send-file next slices to the generated static map and keep production blocked. + +--- + +### Task 1: Static In-Process Anchor Map + +**Files:** +- Create: `scripts/extract-inprocess-adapter-map.ps1` +- Create: `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md` + +**Interfaces:** +- Consumes: IL files under `runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/` and offline B-route reports. +- Produces: Markdown report and JSON with these top-level keys: `ok`, `decision`, `anchors`, `commands`, `required_runtime_state`, `stop_conditions`, `originals_modified`. + +- [ ] **Step 1: Create the analyzer script** + +Create `scripts/extract-inprocess-adapter-map.ps1` with these behaviors: + +```powershell +param( + [string]$OutDir = "runs/inprocess-adapter-research", + [string]$ReportPath = "docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md" +) + +$ErrorActionPreference = 'Stop' +# Resolve repository root from the script location, not caller cwd. +# Read IL files only; never write into the sample directories. +# Extract anchors for AppContextManager, MessageScheduling, Chat, XMPPConnection, +# OffLineFileSend, FileUploadPara, FileUploadResult, FileTransfer, frmMain, and logged-in user/auth state. +# Emit JSON to $OutDir and Markdown to $ReportPath. +``` + +- [ ] **Step 2: Run the analyzer** + +Run: + +```powershell +powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-inprocess-adapter-map.ps1 +``` + +Expected output contains: + +```json +{ + "ok": true, + "decision": "managed_in_process_adapter_contract_first", + "originals_modified": false +} +``` + +- [ ] **Step 3: Verify report content** + +Run: + +```powershell +Get-Content docs\source-discovery\2026-07-12-inprocess-adapter-static-map.md -Raw | Select-String -Pattern 'AppContextManager|MessageScheduling|Chat|FileUploadResult|in_process_contract|Stop conditions' +``` + +Expected: all listed terms are present. + +--- + +### Task 2: Go Connector In-Process Contract Mode + +**Files:** +- Modify: `internal/tools/send_message_broute_adapter.go` +- Modify: `internal/tools/send_message_broute_adapter_test.go` +- Modify: `internal/tools/send_message_uia_adapter.go` +- Modify: `internal/tools/send_message_uia_adapter_test.go` + +**Interfaces:** +- Consumes: `SendMessageConnectorRequest` from `internal/tools/send_message_connector.go`. +- Produces: new connector mode string `in_process_contract` with blocked result: + - `Accepted: false` + - `Status: "blocked"` + - `ErrorCode: "broute_in_process_contract_only"` + - `ConnectorMode: "broute-in-process-contract"` + - `ProductionEnabled: false` + - `SideEffects["attached_hook"] == false` + - `SideEffects["sent_message"] == false` + +- [ ] **Step 1: Add a failing test for contract mode** + +Add this test to `internal/tools/send_message_broute_adapter_test.go`: + +```go +func TestBRouteSendMessageConnectorInProcessContract(t *testing.T) { + connector := NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode: "in_process_contract"}) + result, err := connector.ExecuteSendMessage(context.Background(), SendMessageConnectorRequest{ + TargetType: "direct", + TargetID: "u1", + TargetRef: "contact:u1", + ContentText: "hello", + ContentSHA256: strings.Repeat("a", 64), + ContentLength: 5, + IdempotencyKeySHA256: strings.Repeat("b", 64), + ExecutionMode: "production", + }) + if err != nil { + t.Fatalf("in_process_contract should be a structured blocked result, not process error: %v", err) + } + if result.Accepted || result.ProductionEnabled { + t.Fatalf("contract mode must not accept production send: %+v", result) + } + if result.Status != "blocked" || result.ErrorCode != "broute_in_process_contract_only" { + t.Fatalf("unexpected contract result: %+v", result) + } + if result.ConnectorMode != "broute-in-process-contract" { + t.Fatalf("connector mode = %q", result.ConnectorMode) + } + if result.SideEffects["sent_message"] != false || result.SideEffects["attached_hook"] != false { + t.Fatalf("contract mode must report no side effects: %#v", result.SideEffects) + } +} +``` + +- [ ] **Step 2: Run the failing test** + +Run: + +```powershell +go test ./internal/tools -run TestBRouteSendMessageConnectorInProcessContract -count=1 +``` + +Expected before implementation: FAIL because `in_process_contract` is not handled. + +- [ ] **Step 3: Implement minimal mode branch** + +In `internal/tools/send_message_broute_adapter.go`, add a `case "in_process_contract"` branch that calls `validateBRouteSendMessageRequest(request)` and returns a structured blocked result with no side effects. + +- [ ] **Step 4: Add and run env factory coverage** + +Add `TestSendMessageConnectorFromEnvBuildsInProcessContractConnector` to `internal/tools/send_message_uia_adapter_test.go` and update `NewSendMessageConnectorFromEnv()` so `ISPHERE_SEND_CONNECTOR_MODE=in_process_contract` returns `NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode: "in_process_contract"})`. + +Run: + +```powershell +go test ./internal/tools -run 'Test(BRouteSendMessageConnector|SendMessageConnectorFromEnv)' -count=1 +``` + +Expected: PASS. + +- [ ] **Step 5: Run the targeted test again** + +Run: + +```powershell +go test ./internal/tools -run TestBRouteSendMessageConnectorInProcessContract -count=1 +``` + +Expected: PASS. + +--- + +### Task 3: Capability Matrix Correction + +**Files:** +- Modify: `docs/source-discovery/capability-source-matrix.md` + +**Interfaces:** +- Consumes: `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`. +- Produces: updated business-facing capability status showing B-route next step is contract/in-process reachability, not production send. + +- [ ] **Step 1: Update send-message and send-file rows** + +Add the new report path to the evidence references and update next-slice language: + +```markdown +- In-process adapter static map: `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md` +``` + +For send-message, state: + +```markdown +Next slice: validate `in_process_contract` reachability in a logged-in runtime; production remains blocked until adapter invocation plus sent-record/content-hash/ack evidence exists. +``` + +For send-file, state: + +```markdown +Next slice: validate logged-in access to `IFileTransfer.FileUpload` and returned `FileUploadResult.FileID`; production file upload/send remains blocked until online evidence exists. +``` + +- [ ] **Step 2: Verify diff contains no RPA promotion** + +Run: + +```powershell +git diff -- docs\source-discovery\capability-source-matrix.md | Select-String -Pattern 'RPA|in_process|production remains blocked|FileUploadResult' +``` + +Expected: in-process language appears and RPA remains backup-only. + +--- + +### Task 4: Verification and Branch Closure + +**Files:** +- All files from Tasks 1-3. + +**Interfaces:** +- Consumes: scripts and tests from previous tasks. +- Produces: committed and pushed branch `codex/in-process-adapter-research`. + +- [ ] **Step 1: Run static analyzer** + +```powershell +powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-inprocess-adapter-map.ps1 +``` + +Expected: `ok=true`, `decision=managed_in_process_adapter_contract_first`, `originals_modified=false`. + +- [ ] **Step 2: Run targeted tests** + +```powershell +go test ./internal/tools -run TestBRouteSendMessageConnector -count=1 +``` + +Expected: PASS. + +- [ ] **Step 3: Run full tests** + +```powershell +go test ./... +``` + +Expected: PASS. + +- [ ] **Step 4: Run diff hygiene** + +```powershell +git diff --check +git diff --cached --check +``` + +Expected: no output and exit code 0 after staging. + +- [ ] **Step 5: Commit and push** + +```powershell +git add scripts\extract-inprocess-adapter-map.ps1 docs\source-discovery\2026-07-12-inprocess-adapter-static-map.md docs\source-discovery\capability-source-matrix.md internal\tools\send_message_broute_adapter.go internal\tools\send_message_broute_adapter_test.go docs\superpowers\plans\2026-07-12-in-process-adapter-research.md +git commit -m "feat: add in-process adapter research contract" +git push -u gitea codex/in-process-adapter-research +``` + +Expected: branch pushed to `gitea/codex/in-process-adapter-research`. + +--- + +## Self-Review + +- Spec coverage: The plan covers B-route in-process research, static evidence, Go connector contract, capability matrix, verification, commit, and push. +- Placeholder scan: No task uses TBD/TODO/fill-in-later language; every implementation task names exact files and commands. +- Type consistency: `in_process_contract` maps to `broute-in-process-contract`; `SendMessageConnectorResult.SideEffects` reuses the existing `sendMessageNoSideEffects()` shape. diff --git a/internal/tools/send_message_broute_adapter.go b/internal/tools/send_message_broute_adapter.go index c03cedb..13bd8ea 100644 --- a/internal/tools/send_message_broute_adapter.go +++ b/internal/tools/send_message_broute_adapter.go @@ -52,6 +52,26 @@ func (c bRouteSendMessageConnector) ExecuteSendMessage(_ context.Context, reques ErrorMessage: "B-route adapter dry_run_contract mode validates request shape only and does not start a sidecar", ConnectorMode: "broute-dry-run-contract", }, nil + case "in_process_contract": + if err := validateBRouteSendMessageRequest(request); err != nil { + return SendMessageConnectorResult{ + Accepted: false, + Status: "failed", + ErrorCode: "broute_invalid_request", + ErrorMessage: err.Error(), + ConnectorMode: "broute-in-process-contract", + SideEffects: sendMessageNoSideEffects(), + }, nil + } + return SendMessageConnectorResult{ + Accepted: false, + Status: "blocked", + ErrorCode: "broute_in_process_contract_only", + ErrorMessage: "B-route in_process_contract mode validates the future in-process adapter contract only; logged-in runtime reachability and sent-record evidence are still required", + ConnectorMode: "broute-in-process-contract", + ProductionEnabled: false, + SideEffects: sendMessageNoSideEffects(), + }, nil default: result := SendMessageConnectorResult{ Accepted: false, diff --git a/internal/tools/send_message_broute_adapter_test.go b/internal/tools/send_message_broute_adapter_test.go index 7ea619b..eda9798 100644 --- a/internal/tools/send_message_broute_adapter_test.go +++ b/internal/tools/send_message_broute_adapter_test.go @@ -53,3 +53,32 @@ func TestBRouteSendMessageConnectorDryRunContract(t *testing.T) { t.Fatalf("unexpected dry-run result: %+v", result) } } + +func TestBRouteSendMessageConnectorInProcessContract(t *testing.T) { + connector := NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode: "in_process_contract"}) + result, err := connector.ExecuteSendMessage(context.Background(), SendMessageConnectorRequest{ + TargetType: "direct", + TargetID: "u1", + TargetRef: "contact:u1", + ContentText: "hello", + ContentSHA256: strings.Repeat("a", 64), + ContentLength: 5, + IdempotencyKeySHA256: strings.Repeat("b", 64), + ExecutionMode: "production", + }) + if err != nil { + t.Fatalf("in_process_contract should be a structured blocked result, not process error: %v", err) + } + if result.Accepted || result.ProductionEnabled { + t.Fatalf("contract mode must not accept production send: %+v", result) + } + if result.Status != "blocked" || result.ErrorCode != "broute_in_process_contract_only" { + t.Fatalf("unexpected contract result: %+v", result) + } + if result.ConnectorMode != "broute-in-process-contract" { + t.Fatalf("connector mode = %q", result.ConnectorMode) + } + if result.SideEffects["sent_message"] != false || result.SideEffects["attached_hook"] != false { + t.Fatalf("contract mode must report no side effects: %#v", result.SideEffects) + } +} diff --git a/internal/tools/send_message_uia_adapter.go b/internal/tools/send_message_uia_adapter.go index b98b245..0e547d6 100644 --- a/internal/tools/send_message_uia_adapter.go +++ b/internal/tools/send_message_uia_adapter.go @@ -53,6 +53,9 @@ type uiaSendMessageConnector struct { func NewSendMessageConnectorFromEnv() SendMessageConnector { mode := strings.TrimSpace(strings.ToLower(os.Getenv(EnvSendConnectorMode))) + if mode == "in_process_contract" || mode == "in-process-contract" { + return NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode: "in_process_contract"}) + } if mode != "uia_rpa" && mode != "uia-rpa" { return nil } diff --git a/internal/tools/send_message_uia_adapter_test.go b/internal/tools/send_message_uia_adapter_test.go index 97c630c..c17a68d 100644 --- a/internal/tools/send_message_uia_adapter_test.go +++ b/internal/tools/send_message_uia_adapter_test.go @@ -2,6 +2,7 @@ package tools import ( "context" + "strings" "testing" ) @@ -103,6 +104,31 @@ func TestSendMessageConnectorFromEnvBuildsUiaRPAConnector(t *testing.T) { } } +func TestSendMessageConnectorFromEnvBuildsInProcessContractConnector(t *testing.T) { + t.Setenv(EnvSendConnectorMode, "in_process_contract") + + connector := NewSendMessageConnectorFromEnv() + if connector == nil { + t.Fatalf("NewSendMessageConnectorFromEnv returned nil for in_process_contract config") + } + result, err := connector.ExecuteSendMessage(context.Background(), SendMessageConnectorRequest{ + TargetType: "direct", + TargetID: "u1", + TargetRef: "contact:u1", + ContentText: "hello", + ContentSHA256: strings.Repeat("a", 64), + ContentLength: 5, + IdempotencyKeySHA256: strings.Repeat("b", 64), + ExecutionMode: sendMessageProductionMode, + }) + if err != nil { + t.Fatalf("in_process_contract should return structured blocked result, got err=%v", err) + } + if result.Accepted || result.ProductionEnabled || result.ErrorCode != "broute_in_process_contract_only" { + t.Fatalf("unexpected in-process contract result: %+v", result) + } +} + type fakeUiaHelperCaller struct { response uiaHelperResponse err error diff --git a/scripts/extract-inprocess-adapter-map.ps1 b/scripts/extract-inprocess-adapter-map.ps1 new file mode 100644 index 0000000..9924b01 --- /dev/null +++ b/scripts/extract-inprocess-adapter-map.ps1 @@ -0,0 +1,410 @@ +param( + [string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il", + [string]$OutputDir = "runs/inprocess-adapter-research", + [string]$ReportPath = "docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md", + [int]$WindowRadius = 4, + [int]$MaxEvidencePerAnchor = 16 +) + +$ErrorActionPreference = "Stop" + +$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path +$ilDirFull = Join-Path $repo $IlDir +$outDir = Join-Path $repo $OutputDir +$reportFullPath = Join-Path $repo $ReportPath +New-Item -ItemType Directory -Force -Path $outDir | Out-Null +New-Item -ItemType Directory -Force -Path (Split-Path -Parent $reportFullPath) | Out-Null + +$sources = @( + @{ path = "IMPlatformClient.exe.il"; role = "main managed client; UI, AppContextManager, MessageScheduling, frmMain, login runtime" }, + @{ path = "smack.dll.il"; role = "XMPP/smack managed library; Chat and XMPPConnection send primitives" }, + @{ path = "IMPP.Service.dll.il"; role = "file transfer service implementation" }, + @{ path = "IMPP.ServiceBase.dll.il"; role = "file transfer DTOs and FileUploadPara/FileUploadResult contracts" }, + @{ path = "IMPP.Interface.dll.il"; role = "service and network interface contracts" }, + @{ path = "IMPP.Common.dll.il"; role = "common helper and runtime DTO evidence" } +) + +$anchors = @( + @{ + key = "text_high_level_entry" + display = "AppContextManager.SendTxtMessageByJid" + command = "send_text" + adapter_role = "preferred high-level managed entry if an in-process adapter can reach AppContextManager" + confidence = "high_static" + usable_offline = $false + required_runtime = @("logged-in IMPPManager/UserInfo", "target JID", "initialized AppContextManager", "live XMPP connection") + patterns = @("AppContextManager::SendTxtMessageByJid", "\bSendTxtMessageByJid\b") + }, + @{ + key = "text_scheduling_entry" + display = "MessageScheduling.SendChatMessage" + command = "send_text" + adapter_role = "fallback managed entry when scheduling layer has chat and contact args" + confidence = "high_static" + usable_offline = $false + required_runtime = @("MessageScheduling instance or static caller", "RosterContactsArgs/contact context", "Chat object", "live XMPP connection") + patterns = @("MessageScheduling::SendChatMessage", "SendChatMessage\(", "SendChatMessage\(class IMPP\.Client") + }, + @{ + key = "text_low_level_chat" + display = "com.vision.smack.Chat.SendMessage / XMPPConnection.send" + command = "send_text" + adapter_role = "lowest-level send target; requires already resolved Chat/XMPPConnection" + confidence = "high_static" + usable_offline = $false + required_runtime = @("Chat instance", "XMPPConnection authenticated session", "message payload format") + patterns = @("com\.vision\.smack\.Chat::SendMessage", "com\.vision\.smack\.Chat::sendMessage", "XMPPConnection::send\b") + }, + @{ + key = "file_upload_orchestrator" + display = "IMPP.Client.OffLineFileSend.sendFile" + command = "upload_file_then_send_file" + adapter_role = "UI-side upload orchestration and transition into chat file message" + confidence = "high_static" + usable_offline = $false + required_runtime = @("local file path", "HTTP file server/auth state", "target roster/chat args", "upload completion callback") + patterns = @("OffLineFileSend::sendFile", "sendFile\(\) cil managed", "OffLineFileSend::trans_UploadCompleted") + }, + @{ + key = "file_upload_service" + display = "IFileTransfer/FileTransfer.FileUpload + FileUploadPara" + command = "upload_file" + adapter_role = "service upload entry that must return FileUploadResult before chat file finalization" + confidence = "high_static" + usable_offline = $false + required_runtime = @("FileUploadPara host/port/domain", "localFilePath", "token/auth", "FileUploadResult.FileID") + patterns = @("FileTransfer::FileUpload", "FileUploadPara", "FileUploadResult::get_FileID", "FileUploadResult") + }, + @{ + key = "file_message_finalizer" + display = "MessageScheduling.SendFileMessage / Chat.sendFileMessage" + command = "send_file_message" + adapter_role = "chat file-message finalization after FileID/remote folder exists" + confidence = "high_static" + usable_offline = $false + required_runtime = @("uploaded file id", "remote folder metadata", "file name/size", "target Chat/JID") + patterns = @("MessageScheduling::SendFileMessage", "Chat::sendFileMessage", "sendFileMessage\(") + }, + @{ + key = "logged_in_identity_auth" + display = "IMPPManager.UserInfo / UnifiedAuthentication / Auth token" + command = "runtime_context" + adapter_role = "runtime state required before any production send/upload can be meaningful" + confidence = "medium_static" + usable_offline = $false + required_runtime = @("UserInfo", "UnifiedAuthentication", "Auth token", "HTTPFileServer", "server resource/domain") + patterns = @("IMPPManager::get_UserInfo", "IMPPManager.UserInfo", "UnifiedAuthentication", "HTTPFileServer", "Auth::get_token", "get_token") + }, + @{ + key = "main_window_runtime_owner" + display = "frmMain / MessageCenter / chat runtime ownership" + command = "runtime_context" + adapter_role = "likely object owner for initialized chat, reconnect, message center, and plugin runtime state" + confidence = "medium_static" + usable_offline = $false + required_runtime = @("running frmMain", "initialized message center", "contact/session state") + patterns = @("class IMPP\.Client\.frmMain", "frmMain::", "GetMessageCenter\(\)", "MessageCenter", "OnReConnectionSucceed", "GetChat\(") + }, + @{ + key = "existing_http_not_bridge" + display = "frmLogin.StartWinServer / HttpServerLib" + command = "not_selected_bridge" + adapter_role = "known local HTTP framework, but not a confirmed send bridge" + confidence = "high_static_negative" + usable_offline = $false + required_runtime = @("logged-in state", "route module registration not found", "send route not found") + patterns = @("StartWinServer", "HttpServerLib", "HttpService::\.ctor", "RegisterModule", "RouteAttribute") + } +) + +function Get-RelativePath([string]$Path) { + if ($Path.StartsWith($repo, [System.StringComparison]::OrdinalIgnoreCase)) { + return $Path.Substring($repo.Length).TrimStart([char[]]@('\', '/')) + } + return $Path +} + +function Write-Utf8NoBomLf([string]$Path, [string]$Text) { + $utf8NoBom = [System.Text.UTF8Encoding]::new($false) + $normalized = $Text -replace "`r`n", "`n" + $normalized = $normalized -replace "`r", "`n" + $normalized = $normalized.TrimEnd() + "`n" + [System.IO.File]::WriteAllText($Path, $normalized, $utf8NoBom) +} + +function Get-EvidenceKind([string]$Line) { + if ($Line -match "^\s*\.class\b") { return "type_definition" } + if ($Line -match "^\s*\.method\b") { return "method_header" } + if ($Line -match "\bend of method\b") { return "method_end" } + if ($Line -match "\bnewobj\b") { return "constructor_call" } + if ($Line -match "\bcall(?:virt)?\b") { return "callsite" } + if ($Line -match "\bldstr\b") { return "string_literal" } + if ($Line -match "^\s*(instance|static)\b.*\(") { return "signature_continuation" } + if ($Line -match "^\s*\.field\b") { return "field" } + return "reference" +} + +function Get-MethodContext($Lines, [int]$Index) { + $start = [Math]::Max(0, $Index - 100) + for ($i = $Index; $i -ge $start; $i--) { + if ($Lines[$i] -match "^\s*\.method\b") { + $header = $Lines[$i].Trim() + if (($i + 1) -lt $Lines.Count -and $Lines[$i + 1] -match "^\s+(instance|static|default)\b") { + $header = ($header + " " + $Lines[$i + 1].Trim()) + } + return "L$($i + 1): $header" + } + } + return "" +} + +function Get-WindowSnippet($Lines, [int]$Index, [int]$Radius) { + $start = [Math]::Max(0, $Index - $Radius) + $end = [Math]::Min($Lines.Count - 1, $Index + $Radius) + $parts = New-Object System.Collections.Generic.List[string] + for ($i = $start; $i -le $end; $i++) { + $parts.Add(("L{0}: {1}" -f ($i + 1), $Lines[$i].Trim())) + } + return ($parts -join "`n") +} + +function Find-AnchorEvidence($Anchor) { + $items = New-Object System.Collections.Generic.List[object] + foreach ($source in $sources) { + $sourcePath = Join-Path $ilDirFull $source.path + if (-not (Test-Path -LiteralPath $sourcePath)) { continue } + $lines = [System.IO.File]::ReadAllLines($sourcePath) + for ($i = 0; $i -lt $lines.Count; $i++) { + $line = $lines[$i] + foreach ($pattern in $Anchor.patterns) { + if ($line -match $pattern) { + $items.Add([pscustomobject]@{ + source = Get-RelativePath $sourcePath + source_role = $source.role + line = $i + 1 + kind = Get-EvidenceKind $line + pattern = $pattern + snippet = $line.Trim() + context = Get-MethodContext $lines $i + window = Get-WindowSnippet $lines $i $WindowRadius + }) + break + } + } + if ($items.Count -ge $MaxEvidencePerAnchor) { break } + } + if ($items.Count -ge $MaxEvidencePerAnchor) { break } + } + return $items.ToArray() +} + +function Classify-Anchor($Anchor, $Evidence) { + if ($Evidence.Count -eq 0) { return "missing_static_evidence" } + if ($Anchor.command -eq "not_selected_bridge") { return "not_a_send_bridge" } + if ($Anchor.command -eq "runtime_context") { return "runtime_dependency" } + return "in_process_candidate_static_only" +} + +$sourceSummary = foreach ($source in $sources) { + $path = Join-Path $ilDirFull $source.path + $exists = Test-Path -LiteralPath $path + $lineCount = 0 + $size = 0 + if ($exists) { + $item = Get-Item -LiteralPath $path + $size = $item.Length + $lineCount = ([System.IO.File]::ReadLines($path) | Measure-Object).Count + } + [pscustomobject]@{ + path = Get-RelativePath $path + role = $source.role + exists = $exists + lines = $lineCount + size_bytes = $size + } +} + +$anchorResults = foreach ($anchor in $anchors) { + $evidence = Find-AnchorEvidence $anchor + [pscustomobject]@{ + key = $anchor.key + display = $anchor.display + command = $anchor.command + adapter_role = $anchor.adapter_role + classification = Classify-Anchor $anchor $evidence + confidence = $anchor.confidence + usable_offline = $anchor.usable_offline + required_runtime = $anchor.required_runtime + evidence_count = $evidence.Count + evidence = $evidence + } +} + +$commands = @( + [pscustomobject]@{ + op = "probe_runtime" + status = "contract_only" + purpose = "report whether adapter is inside logged-in IMPP runtime and can see required types/singletons" + required_evidence = @("process identity", "loaded assemblies", "IMPPManager.UserInfo presence", "XMPP connection state") + }, + [pscustomobject]@{ + op = "send_text" + status = "blocked_until_logged_in_adapter" + purpose = "invoke high-level text send path after target JID and content hash are validated" + required_evidence = @("AppContextManager or MessageScheduling reachability", "target JID", "sent record or ack containing content hash/correlation") + }, + [pscustomobject]@{ + op = "upload_file" + status = "blocked_until_logged_in_adapter" + purpose = "call file upload service and return server FileID/remote folder metadata" + required_evidence = @("FileUploadPara values", "HTTP file server/auth", "FileUploadResult.FileID") + }, + [pscustomobject]@{ + op = "send_file_message" + status = "blocked_until_upload_evidence" + purpose = "finalize file message after upload returns server id" + required_evidence = @("uploaded FileID", "file name/size", "target JID/Chat", "sent record/ack") + } +) + +$requiredRuntimeState = @( + "logged-in IMPlatformClient.exe process", + "loaded IMPP.Client/AppContextManager/MessageScheduling types", + "initialized IMPPManager.UserInfo and UnifiedAuthentication/Auth token", + "live XMPPConnection/Chat session", + "target JID or group JID resolved by existing search tools", + "file upload service parameters and FileUploadResult.FileID for file sends" +) + +$stopConditions = @( + "No logged-in process is available for runtime reachability validation.", + "Adapter cannot see AppContextManager, MessageScheduling, Chat, or IFileTransfer in process.", + "Every viable path requires unsupported binary patching instead of a replaceable managed adapter/harness.", + "Online evidence cannot produce sent-record/content-hash/ack correlation for text send.", + "File upload cannot return FileUploadResult.FileID or equivalent remote folder metadata." +) + +$result = [pscustomobject]@{ + ok = $true + generated_at = (Get-Date).ToUniversalTime().ToString("o") + decision = "managed_in_process_adapter_contract_first" + sources = $sourceSummary + anchors = $anchorResults + commands = $commands + required_runtime_state = $requiredRuntimeState + stop_conditions = $stopConditions + originals_copied = $false + originals_modified = $false +} + +$jsonPath = Join-Path $outDir "inprocess-adapter-map.json" +$jsonText = $result | ConvertTo-Json -Depth 8 +Write-Utf8NoBomLf $jsonPath $jsonText + +$md = New-Object System.Collections.Generic.List[string] +$md.Add("# In-Process Adapter Static Map") +$md.Add("") +$md.Add("Date: 2026-07-12") +$md.Add("") +$md.Add("## Scope") +$md.Add("") +$md.Add("This report uses offline IL/static evidence only. It does not log in, attach hooks, inject into a process, modify client binaries, upload files, send messages, or open network connections.") +$md.Add("") +$md.Add("Machine-readable evidence: ``$(Get-RelativePath $jsonPath)``") +$md.Add("") +$md.Add("## Decision") +$md.Add("") +$md.Add("| Question | Answer |") +$md.Add("| --- | --- |") +$md.Add("| Selected next B-route branch | `managed_in_process_adapter_contract_first` |") +$md.Add("| Can offline branch enable production send? | **No** |") +$md.Add("| Go connector mode to expose now | `in_process_contract` |") +$md.Add("| Required online proof later | logged-in adapter reachability plus sent-record/content-hash/ack evidence |") +$md.Add("") +$md.Add("## Sources") +$md.Add("") +$md.Add("| Source | Role | Exists | Lines | Size bytes |") +$md.Add("| --- | --- | --- | ---: | ---: |") +foreach ($source in $sourceSummary) { + $md.Add("| ``$($source.path)`` | $($source.role) | $($source.exists) | $($source.lines) | $($source.size_bytes) |") +} +$md.Add("") +$md.Add("## Command contract for future in-process adapter") +$md.Add("") +$md.Add("| Op | Current status | Purpose | Required evidence before production |") +$md.Add("| --- | --- | --- | --- |") +foreach ($cmd in $commands) { + $required = ($cmd.required_evidence -join "; ") + $md.Add("| ``$($cmd.op)`` | ``$($cmd.status)`` | $($cmd.purpose) | $required |") +} +$md.Add("") +$md.Add("## Anchor summary") +$md.Add("") +$md.Add("| Anchor | Command | Classification | Confidence | Evidence | Required runtime |") +$md.Add("| --- | --- | --- | --- | ---: | --- |") +foreach ($anchor in $anchorResults) { + $required = ($anchor.required_runtime -join "; ") + $md.Add("| ``$($anchor.display)`` | ``$($anchor.command)`` | ``$($anchor.classification)`` | ``$($anchor.confidence)`` | $($anchor.evidence_count) | $required |") +} +$md.Add("") +$md.Add("## Verified facts") +$md.Add("") +$md.Add("- Text send has static in-process candidates, but all require logged-in runtime objects and a live XMPP/Chat path.") +$md.Add("- File send is split into upload and message-finalization; `FileUploadResult.FileID` is a required boundary value before `Chat.sendFileMessage` is meaningful.") +$md.Add("- The earlier IPC/plugin/local HTTP scan did not find a confirmed external send bridge, so this branch must stay at `in_process_contract` until online reachability exists.") +$md.Add("- `in_process_contract` is a Go-side contract and audit mode only; it must return blocked/no-side-effect metadata in this offline branch.") +$md.Add("") +$md.Add("## Required runtime state") +$md.Add("") +foreach ($state in $requiredRuntimeState) { + $md.Add("- $state") +} +$md.Add("") +$md.Add("## Anchor evidence") +foreach ($anchor in $anchorResults) { + $md.Add("") + $md.Add("### $($anchor.display)") + $md.Add("") + $md.Add("Classification: ``$($anchor.classification)``; command: ``$($anchor.command)``; evidence count: $($anchor.evidence_count).") + $md.Add("") + $md.Add("Adapter role: $($anchor.adapter_role)") + $md.Add("") + if ($anchor.evidence_count -eq 0) { + $md.Add("No static evidence found for this anchor in the configured IL set.") + continue + } + $md.Add("| Source | Kind | Snippet | Context |") + $md.Add("| --- | --- | --- | --- |") + foreach ($e in $anchor.evidence) { + $snippet = ($e.snippet -replace "\|", "\\|" ) + if ($snippet.Length -gt 220) { $snippet = $snippet.Substring(0, 217) + "..." } + $context = ($e.context -replace "\|", "\\|" ) + if ($context.Length -gt 180) { $context = $context.Substring(0, 177) + "..." } + $md.Add("| ``$($e.source):$($e.line)`` | ``$($e.kind)`` | ``$snippet`` | ``$context`` |") + } +} +$md.Add("") +$md.Add("## Stop conditions") +$md.Add("") +foreach ($condition in $stopConditions) { + $md.Add("- $condition") +} +$md.Add("") +$md.Add("## Next work") +$md.Add("") +$md.Add("1. Add Go connector mode `in_process_contract` that validates request shape and returns blocked/no-side-effect metadata.") +$md.Add("2. In a logged-in environment, build a recorder/probe that only checks reachability of the listed runtime objects before attempting any send.") +$md.Add("3. Promote text send only after sent-record/content-hash/ack evidence exists.") +$md.Add("4. Promote file send only after upload returns `FileUploadResult.FileID` and file-message finalization is proven online.") + +Write-Utf8NoBomLf $reportFullPath ($md -join "`n") + +[pscustomobject]@{ + ok = $true + json_path = $jsonPath + report_path = $reportFullPath + anchors = $anchorResults.Count + decision = $result.decision + originals_copied = $false + originals_modified = $false +} | ConvertTo-Json -Depth 5