12 Commits

Author SHA1 Message Date
zhaoyilun
57a0c08656 tools: complete login probe todo coverage 2026-07-12 14:08:25 +08:00
zhaoyilun
93c1d59809 tools: package login reachability probe 2026-07-12 12:55:53 +08:00
zhaoyilun
eeb59db9be docs: harden login reachability schema 2026-07-12 12:45:58 +08:00
zhaoyilun
7718e2dd34 docs: add send upload deep dive validation items 2026-07-12 12:33:01 +08:00
zhaoyilun
a9e692a574 feat: add in-process adapter research contract 2026-07-12 11:15:07 +08:00
zhaoyilun
a4242c12be docs: add offline b-route reverse decision 2026-07-12 02:36:59 +08:00
zhaoyilun
485d5ea766 docs: plan offline b-route reverse work 2026-07-12 01:44:01 +08:00
zhaoyilun
eb399853e6 docs: plan b-route bridge next steps 2026-07-12 01:36:28 +08:00
zhaoyilun
0bb07c7754 docs: clarify rpa fallback priority 2026-07-12 01:29:07 +08:00
zhaoyilun
341f08b7be docs: correct main send status and plan 2026-07-12 01:22:56 +08:00
zhaoyilun
3b01d94088 merge: a-route real chat window 2026-07-12 01:13:24 +08:00
zhaoyilun
811f760efe tools: open real offline frmP2PChat window 2026-07-11 20:58:26 +08:00
39 changed files with 7251 additions and 31 deletions

View File

@@ -1,6 +1,6 @@
# Current Status Card # Current Status Card
Date: 2026-07-10 Date: 2026-07-12
Branch: `main` Branch: `main`
Loop base: `e993ce1 docs: trim safety constraints from mcp roadmap` Loop base: `e993ce1 docs: trim safety constraints from mcp roadmap`
Remote base before local roadmap commits: `b2d839e Merge branch 'codex/n15-report-hardening'` Remote base before local roadmap commits: `b2d839e Merge branch 'codex/n15-report-hardening'`
@@ -11,10 +11,16 @@ Remote base before local roadmap commits: `b2d839e Merge branch 'codex/n15-repor
后续研发主线切换为 MCP 核心通信能力:搜索联系人、搜索群组、收发消息、收发文件。现有 UIA/selector/report 只作为底层辅助和证据,不再作为主线继续扩展。 后续研发主线切换为 MCP 核心通信能力:搜索联系人、搜索群组、收发消息、收发文件。现有 UIA/selector/report 只作为底层辅助和证据,不再作为主线继续扩展。
Route priority is explicit:
1. Primary route: B-route running-client sidecar / in-process connector / existing API that reuses the logged-in `IMPlatformClient.exe` runtime.
2. Secondary route: existing bridge, local service, local data, log, cache, or database source where it can satisfy the MCP contract.
3. Backup route only: A-route/RPA/UIA. Use it to keep the product moving when the B-route is blocked or temporarily untestable, but do not promote it above B-route as the default product architecture.
## Current completed state ## Current completed state
- Go MCP foundation exists: `cmd/isphere-mcp`, `internal/mcpserver`, `internal/helperclient`, and `internal/tools` build a stdio MCP server. - Go MCP foundation exists: `cmd/isphere-mcp`, `internal/mcpserver`, `internal/helperclient`, and `internal/tools` build a stdio MCP server.
- The current MCP surface exposes ten tools: four WinHelper observation tools, four read-oriented business tools, one send-message preview-only tool, and one send-file preview-only tool: - The current MCP surface exposes ten tools: four WinHelper observation tools, four read-oriented business tools, one send-message tool that is preview by default and can use explicit A-route UIA action config, and one send-file preview-only tool:
- `win_helper_version` - `win_helper_version`
- `win_helper_self_check` - `win_helper_self_check`
- `win_helper_scan_windows` - `win_helper_scan_windows`
@@ -23,15 +29,17 @@ Remote base before local roadmap commits: `b2d839e Merge branch 'codex/n15-repor
- `isphere_search_contacts` - `isphere_search_contacts`
- `isphere_search_groups` - `isphere_search_groups`
- `isphere_receive_files` - `isphere_receive_files`
- `isphere_send_message` preview/dry-run only; production is blocked - `isphere_send_message` preview/dry-run by default; explicit `uia_rpa` config can perform UI write/click, but business delivery remains unverified
- `isphere_send_file` preview/dry-run only; production file upload is blocked - `isphere_send_file` preview/dry-run only; production file upload is blocked
- C# `ISphereWinHelper` exists under `native/ISphereWinHelper` and uses the `isphere.helper.v1` stdin/stdout JSON contract. Helper `0.4.0` adds read-only `probe_send_entrypoints` and `probe_send_uia_controls` for R6a/C31 send connector preflight. - C# `ISphereWinHelper` exists under `native/ISphereWinHelper` and uses the `isphere.helper.v1` stdin/stdout JSON contract. Helper `0.5.0` includes read-only `probe_send_entrypoints` / `probe_send_uia_controls` plus `uia_send_message` for configured UI Automation write/click.
- `scripts/verify-win-helper.ps1` and `scripts/verify-go-mcp.ps1` provide repeatable local checks for the helper, ten-tool MCP surface, default empty-source receive/contact/group/file calls, send-message preview/production-blocked behavior, send-file preview/production-blocked behavior, synthetic configured-file receive/contact/group/file smoke, and synthetic configured-directory receive/contact/group/file smoke. - `scripts/verify-win-helper.ps1` and `scripts/verify-go-mcp.ps1` provide repeatable local checks for the helper, ten-tool MCP surface, default empty-source receive/contact/group/file calls, standard send-message preview/production-blocked behavior when A-route env is not configured, send-file preview/production-blocked behavior, synthetic configured-file receive/contact/group/file smoke, and synthetic configured-directory receive/contact/group/file smoke.
- `isphere_receive_messages` now returns the contract-facing `ok`, `conversation`, `messages`, `next_cursor`, and `audit` envelope while retaining legacy parser-native message fields for compatibility. - `isphere_receive_messages` now returns the contract-facing `ok`, `conversation`, `messages`, `next_cursor`, and `audit` envelope while retaining legacy parser-native message fields for compatibility.
- `isphere_receive_messages` accepts the read-contract argument set for the current local-readonly path: `conversation_id`, `query`, `since`, `limit`, `include_attachment_metadata`, `source_preference`, `preview`, and empty `cursor`. - `isphere_receive_messages` accepts the read-contract argument set for the current local-readonly path: `conversation_id`, `query`, `since`, `limit`, `include_attachment_metadata`, `source_preference`, `preview`, and empty `cursor`.
- `isphere_search_contacts` and `isphere_search_groups` accept and validate the safe search-contract args for the current local-readonly path and can optionally enrich results from the env-configured C29 `MsgLib.db` display-entity reader; default behavior remains log/JID-backed when MsgLib env vars are absent. - `isphere_search_contacts` and `isphere_search_groups` accept and validate the safe search-contract args for the current local-readonly path and can optionally enrich results from the env-configured C29 `MsgLib.db` display-entity reader; default behavior remains log/JID-backed when MsgLib env vars are absent.
- `isphere_receive_files` list mode accepts and validates the safe file-list contract args for the current local-readonly path while keeping download blocked. - `isphere_receive_files` list mode accepts and validates the safe file-list contract args for the current local-readonly path while keeping download blocked.
- `isphere_send_message` accepts the R6b/R6e preview/dry-run contract (`target_type`, `target_id`, `content_text`, `content_sha256`, `idempotency_key`, `execution_mode`) and returns planned preview metadata plus redacted audit/idempotency metadata; `execution_mode="production"` returns blocked status with all side-effect flags false. - `isphere_send_message` accepts the R6b/R6e preview/dry-run contract (`target_type`, `target_id`, `content_text`, `content_sha256`, `idempotency_key`, `execution_mode`) and returns planned preview metadata plus redacted audit/idempotency metadata; `execution_mode="production"` returns blocked status with all side-effect flags false.
- A-route fallback can now be explicitly enabled with `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` and a real/synthetic chat HWND. In that mode the helper can write text to `rtbSendMessage` and click `btnSend`; this is a UI action capability, not proof of business delivery.
- Offline/unlogged real-window work can open the real `frmP2PChat` and confirm UIA root `frmP2PChat`, editor `rtbSendMessage`, button `btnSend`, and receive area `rtbRecvMessage`. The local offline client still reports that messages cannot be sent while offline.
- `native/MsgLibReadSidecar` provides a bounded x86 .NET read-only boundary for `MsgLib.db` schema/display-source checks, bounded contact/group display-entity reads, message-source metadata, and sidecar-level bounded message listing; `internal/msglib` wraps it from Go, C30 wires display metadata as an optional MCP contact/group enrichment source, C39 adds a Go receive-source adapter around `ListMessages`, C40 adds tool-level explicit `msglib_readonly` source selection, and C41 wires it through env configuration without changing the MCP default source. - `native/MsgLibReadSidecar` provides a bounded x86 .NET read-only boundary for `MsgLib.db` schema/display-source checks, bounded contact/group display-entity reads, message-source metadata, and sidecar-level bounded message listing; `internal/msglib` wraps it from Go, C30 wires display metadata as an optional MCP contact/group enrichment source, C39 adds a Go receive-source adapter around `ListMessages`, C40 adds tool-level explicit `msglib_readonly` source selection, and C41 wires it through env configuration without changing the MCP default source.
- N12-pre and N12R documents define safe offline evidence intake and internal-sandbox live UIA capture procedures. - N12-pre and N12R documents define safe offline evidence intake and internal-sandbox live UIA capture procedures.
- N13/N14/N15 produced selector catalog/report validation infrastructure, but those are supporting validation assets only. - N13/N14/N15 produced selector catalog/report validation infrastructure, but those are supporting validation assets only.
@@ -41,7 +49,7 @@ Remote base before local roadmap commits: `b2d839e Merge branch 'codex/n15-repor
- The project has not yet implemented production message sending, file download, or production file sending; `isphere_receive_messages`, `isphere_search_contacts`, `isphere_search_groups`, and `isphere_receive_files` list mode have operator-local encrypted log-file/log-directory support but not a production ingestion path. - The project has not yet implemented production message sending, file download, or production file sending; `isphere_receive_messages`, `isphere_search_contacts`, `isphere_search_groups`, and `isphere_receive_files` list mode have operator-local encrypted log-file/log-directory support but not a production ingestion path.
- The project has not completed production iSphere integration. - The project has not completed production iSphere integration.
- The project has not proven a stable real message source for the full business workflow beyond decrypted PacketReader log evidence and synthetic/redacted tests. - The project has not proven a stable real message source for the full business workflow beyond decrypted PacketReader log evidence and synthetic/redacted tests.
- The project has not implemented real message sending or real file upload. R6b adds preview/dry-run only; it does not prove send invocation, success/ack, or idempotent production behavior. - The project has not proven business-level message delivery or real file upload. A-route can perform UI write/click when explicitly configured, but local offline clicks do not prove server send, receiver delivery, success/ack, or sent-record evidence.
- N12-pre offline evidence is not N12 pass. - N12-pre offline evidence is not N12 pass.
- N13/N14/N15 selector/report work is pre-business evidence, not finished contact/message/file capability. - N13/N14/N15 selector/report work is pre-business evidence, not finished contact/message/file capability.
@@ -59,12 +67,14 @@ N13/N14/N15 are pre-business validation results. They can help identify UI eleme
## Current loop ## Current loop
Current loop: `R14 release-candidate report complete`; next step is evidence-driven production gate review. Current loop: `A-route real chat window merged to main`; next step is evidence-driven B-route send/file production verification, with A-route/RPA kept as backup readiness.
Active continuous execution plan: `docs/superpowers/plans/2026-07-10-r6f-r14-continuous-execution-plan.md`. Active continuous execution plan: `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`.
Previous roadmap file: `docs/superpowers/plans/2026-07-10-core-business-capabilities-roadmap.md`. Previous roadmap file: `docs/superpowers/plans/2026-07-10-core-business-capabilities-roadmap.md`.
Current business status correction: `docs/reports/2026-07-12-main-business-status-correction.md`.
Loop rule: Loop rule:
1. Write or update the plan before coding. 1. Write or update the plan before coding.
@@ -387,12 +397,23 @@ R14 release-candidate report is complete:
## A-route UIA send branch ## A-route UIA send branch
A-route UIA send branch is in progress on `codex/a-route-rpa-send`: A-route UIA send work has been merged into `main`:
- Route positioning: A-route/RPA is a fallback, not the primary product route. B-route sidecar/API connector evidence remains the preferred path for real send/file capability.
- User direction: do not add a product approval gate; implement function first and let the digital employee layer decide when to call it. - User direction: do not add a product approval gate; implement function first and let the digital employee layer decide when to call it.
- Added plan `docs\superpowers\plans\2026-07-11-a-route-rpa-send.md`. - Added plan `docs\superpowers\plans\2026-07-11-a-route-rpa-send.md`.
- Go connector request now carries raw `ContentText` only to the action connector; response and audit remain redacted. - Go connector request now carries raw `ContentText` only to the action connector; response and audit remain redacted.
- Added Go `uia-rpa` send connector adapter and env loader. - Added Go `uia-rpa` send connector adapter and env loader.
- Added C# helper op `uia_send_message` that sets the send editor text and invokes the send button through UI Automation. - Added C# helper op `uia_send_message` that sets the send editor text and invokes the send button through UI Automation.
- Synthetic local verification in `scripts\verify-win-helper.ps1` proves the helper can write to a WinForms send box and trigger a send button marker. - Synthetic local verification in `scripts\verify-win-helper.ps1` proves the helper can write to a WinForms send box and trigger a send button marker.
- Added `scripts\open-offline-real-frmP2PChat.ps1`, which opens a real offline/unlogged `frmP2PChat` and confirms `rtbSendMessage` / `btnSend` selectors.
- Visual real-window demo proved the local UI can accept text and receive a send-button click, but the client remains offline and reports that the message cannot be sent.
- Default MCP smoke still clears A-route env and remains preview/blocked unless explicitly configured. - Default MCP smoke still clears A-route env and remains preview/blocked unless explicitly configured.
2026-07-12 business correction:
- `isphere_send_message` now has two different readiness levels:
- preview/dry-run: stable MCP contract, no send.
- A-route UI action: configured UI write/click works against synthetic and real offline windows.
- It does **not** yet have verified online business delivery. Do not describe `clicked_ui=true` or helper `sent_message=true` as “消息已送达”.
- `isphere_send_file` remains preview-only for production file upload. The real offline UIA dump did not expose `btnSendFile` as a stable automation id, so file upload needs a separate toolbar/menu locator node.

View File

@@ -10,6 +10,31 @@
--- ---
## 2026-07-12 Current Next Node Correction
当前下一节点不再是泛化的 `N12-pre` 离线证据整理,也不是 A-route/RPA UI 演示。A-route/RPA 只保留为备选;主线继续走 B-route也就是面向登录态客户端的 `in_process_adapter_research` / `in_process_contract`
**当前主线节点B-route 登录可达性 schema/probe package。**
本节点的目标是在 2026-07-13 可登录环境执行前,把验证口径一次性补齐,避免明天反复采证。活动产物:
- `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`
- `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`
- `docs/source-discovery/2026-07-12-inprocess-adapter-static-map.md`
- `docs/source-discovery/2026-07-12-login-reachability-probe-package.md`
- `scripts/package-login-reachability-probe.ps1`
- `scripts/verify-login-reachability-probe-package.ps1`
- `docs/source-discovery/capability-source-matrix.md`
本节点通过条件:
1. 登录验证清单包含 P0 项one-shot 测试目标、登录态 server/auth、in-process adapter 可达性、发送前后 sent-record 快照、sent-record 来源、结构化失败原因、消息/文件 ack 关联。
2. `isphere_send_message` 只在 direct/group 目标、`AppContextManager` / `Chat` / `XMPPConnection` 可达、sent-record 内容哈希/ack 关联通过后解除生产阻塞。
3. `isphere_send_file` 只在 `FileUploadPara``IFileTransfer.FileUpload``FileUploadResult.FileID``trans_UploadCompleted(fileId)` / `Chat.sendFileMessage`、文件 sent-record/ack 关联通过后解除生产阻塞。
4. 外部 sidecar 仍是 preview/probe-onlyA-route UIA/RPA 仍是 backup-only。
---
## 1. Node Tree ## 1. Node Tree
```text ```text
@@ -962,16 +987,23 @@ Every node must satisfy these rules:
## 4. Current Next Node ## 4. Current Next Node
Current guidance after N0-N15 remote updates is: Current guidance after the 2026-07-12 offline B-route audit and login-validation schema hardening is:
```text ```text
当前下一步:MCP 核心工具合同冻结 + 只读消息源 discovery + N12-pre 证据包整理 当前下一步:B-route 登录可达性 schema/probe package明天在可登录环境采集一次性证据
``` ```
Immediate next action: Immediate next action:
```text ```text
Use `docs/mcp-core-tools-contract.md` and `docs/mcp-core-business-plan.md` as the active business route. Prioritize `isphere_search_contacts`, `isphere_search_groups`, `isphere_receive_messages`, and `isphere_receive_files`, then move `isphere_send_message` and `isphere_send_file` into Stage D after source discovery and connector verification. Use `docs/source-discovery/2026-07-12-login-reachability-validation-items.md` as the active schema. Build the 2026-07-13 login reachability probe package around one-shot targets, runtime/server/auth state, in-process adapter reachability, before/after sent-record snapshots, structured failure reasons, and message/file ack correlation.
``` ```
N12-pre offline evidence remains pre-gate context. Existing UIA selector/report work is auxiliary evidence and fallback support only; the project core is MCP communication capability for contacts, groups, messages, and files. Business status: contact search, group search, receive messages, and receive file-list remain the stable MCP foundation. `isphere_send_message` and `isphere_send_file` are implemented as preview/contract paths, but production send/file remains blocked until logged-in B-route reachability and sent-record/ack correlation pass. N12-pre/offline evidence remains pre-gate context. Existing UIA selector/report/RPA work is auxiliary evidence and fallback support only; the project core is MCP communication capability for contacts, groups, messages, and files.
Prepared package:
```text
runs/login-reachability-probe-package.zip
C:\Users\zhaoy\Downloads\login-reachability-probe-package-20260712-140706.zip
```

View File

@@ -2,7 +2,7 @@
This runbook is for the first Go MCP phase of `isphere-ai-bridge`. It lets an operator build and verify the Windows helper and the Go MCP server without reading the source code. This runbook is for the first Go MCP phase of `isphere-ai-bridge`. It lets an operator build and verify the Windows helper and the Go MCP server without reading the source code.
Current scope: expose four WinHelper observation operations, four business read tools, and two preview-only send tools through Go MCP. Read tools are `isphere_receive_messages`, `isphere_search_contacts`, `isphere_search_groups`, and `isphere_receive_files` list mode plus download preview/blocked status. Send tools are `isphere_send_message` and `isphere_send_file` preview/dry-run only; production send/file upload is blocked. Read tools use an empty default message source unless `ISPHERE_PACKET_LOG_FILE` points to an operator-local encrypted PacketReader log-line file or `ISPHERE_PACKET_LOG_DIR` points to an operator-local directory of encrypted PacketReader `.log`/`.txt` files. Contact/group display names can also be optionally enriched from an operator-local copied `MsgLib.db` through the bounded read-only `MsgLibReadSidecar`; receive messages can use copied DB rows only when the caller explicitly passes `source_preference="msglib_readonly"`. Current scope: expose four WinHelper observation operations, four business read tools, one message-send tool, and one preview-only file-send tool through Go MCP. Read tools are `isphere_receive_messages`, `isphere_search_contacts`, `isphere_search_groups`, and `isphere_receive_files` list mode plus download preview/blocked status. `isphere_send_message` is preview/dry-run by default; when explicitly configured with `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa` it can perform a UI write/click action against a configured chat HWND, but online business delivery is still unverified. `isphere_send_file` remains preview/dry-run only and production file upload is blocked. Read tools use an empty default message source unless `ISPHERE_PACKET_LOG_FILE` points to an operator-local encrypted PacketReader log-line file or `ISPHERE_PACKET_LOG_DIR` points to an operator-local directory of encrypted PacketReader `.log`/`.txt` files. Contact/group display names can also be optionally enriched from an operator-local copied `MsgLib.db` through the bounded read-only `MsgLibReadSidecar`; receive messages can use copied DB rows only when the caller explicitly passes `source_preference="msglib_readonly"`.
## 1. Prerequisites ## 1. Prerequisites
@@ -563,7 +563,9 @@ Current short answer:
- 已完成:搜索联系人、搜索群组、收消息基础读取、收文件列表。 - 已完成:搜索联系人、搜索群组、收消息基础读取、收文件列表。
- 可预览:发消息 preview、发文件 preview。 - 可预览:发消息 preview、发文件 preview。
- 阻断:生产发消息、真实文件下载、生产发文件 - A-route/RPA 是备选兜底,不是主线;主线仍是 B-route running-client sidecar / in-process connector / existing API
- A-route 已具备 UI 动作能力:显式配置后可以对聊天窗口写入文本并点击发送按钮;本地还可打开真实离线 `frmP2PChat` 验证窗口/输入框/按钮定位。
- 阻断:在线业务送达、真实文件下载、生产发文件。离线点击不等于服务端发送成功。
The two online evidence packages to send to an internal/logged-in operator are: The two online evidence packages to send to an internal/logged-in operator are:
@@ -576,7 +578,7 @@ They are generated under ignored `runs\` and are not committed.
## 18. A-route UIA send connector ## 18. A-route UIA send connector
A-route is the UI Automation fallback for text sending when the B-route sidecar cannot be tested. It is function-first: there is no human approval ID gate inside the connector. The digital employee layer is responsible for deciding when to call production mode. A-route is the UI Automation fallback for text sending when the B-route sidecar cannot be tested. It is function-first, but it is not the primary architecture. Prefer B-route running-client sidecar / in-process connector / existing API evidence whenever that route is available. There is no human approval ID gate inside the connector; the digital employee layer is responsible for deciding when to call production mode.
Local verification uses a synthetic WinForms window: Local verification uses a synthetic WinForms window:
@@ -590,6 +592,17 @@ Expected output includes helper version `0.5.0` and:
{"synthetic_uia_send_action":"uia_send_message"} {"synthetic_uia_send_action":"uia_send_message"}
``` ```
The project also has a real offline chat-window opener:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps -ShowWindow -HoldSeconds 1
```
That script opens the real `frmP2PChat` without login and confirms the key UIA
ids `frmP2PChat`, `rtbSendMessage`, `btnSend`, and `rtbRecvMessage`. The window
is still offline and will show the client-side “cannot send while offline”
message.
To enable A-route in a logged-in desktop session, configure the MCP server environment before startup: To enable A-route in a logged-in desktop session, configure the MCP server environment before startup:
```powershell ```powershell
@@ -603,6 +616,11 @@ $env:ISPHERE_SEND_UIA_HELPER_PATH = "E:\coding\codex\isphere-ai-bridge\runs\win-
Then call `isphere_send_message` with `execution_mode="production"`. The connector will set the send editor text and invoke the send button through UI Automation. Response metadata uses `connector_mode="uia-rpa"`; the audit still stores hashes and metadata, not the raw message body or raw idempotency key. Then call `isphere_send_message` with `execution_mode="production"`. The connector will set the send editor text and invoke the send button through UI Automation. Response metadata uses `connector_mode="uia-rpa"`; the audit still stores hashes and metadata, not the raw message body or raw idempotency key.
Important status boundary: helper fields such as `clicked_ui=true` or
`sent_message=true` mean the UI action ran. They do not prove server acceptance,
receiver delivery, or a sent-record match. Online/logged-in evidence is still
required before this can be called business-level send.
Standard `scripts\verify-go-mcp.ps1` clears all A-route env vars so the deterministic smoke remains preview/blocked by default. Standard `scripts\verify-go-mcp.ps1` clears all A-route env vars so the deterministic smoke remains preview/blocked by default.
## 19. Troubleshooting ## 19. Troubleshooting

View File

@@ -1,5 +1,9 @@
# Business Goals Smoke - 2026-07-10 # Business Goals Smoke - 2026-07-10
> 2026-07-12 校准A-route 已合并到 `main``isphere_send_message`
> 在显式 `uia_rpa` 配置下可以执行 UI 写入/点击;但业务送达仍未验证。
> 当前主状态见 `docs/reports/2026-07-12-main-business-status-correction.md`。
## 业务目标状态 ## 业务目标状态
| 目标 | 当前状态 | 说明 | | 目标 | 当前状态 | 说明 |

View File

@@ -1,5 +1,9 @@
# R6f-R14 Release Candidate Status - 2026-07-10 # R6f-R14 Release Candidate Status - 2026-07-10
> 2026-07-12 校准:本报告是 A-route 前的 R14 状态。后续 `main`
> 已具备显式配置下的发消息 UI 写入/点击能力,但在线业务送达仍未验证。
> 当前主状态见 `docs/reports/2026-07-12-main-business-status-correction.md`。
本报告是 R6f-R14 连续轮次的业务验收材料。结论先讲清楚:数字员工现在可以用搜索、收消息基础读取、收文件列表,以及发消息/发文件 preview生产发消息、真实下载文件、生产发文件仍然需要在线可登录环境返回证据。 本报告是 R6f-R14 连续轮次的业务验收材料。结论先讲清楚:数字员工现在可以用搜索、收消息基础读取、收文件列表,以及发消息/发文件 preview生产发消息、真实下载文件、生产发文件仍然需要在线可登录环境返回证据。
## Business capability status ## Business capability status

View File

@@ -0,0 +1,34 @@
# Main Business Status Correction - 2026-07-12
本报告校准 `main` 合并 A-route 后的业务状态避免把“UI 输入/点击”误写成“业务送达”。
## 四个目标当前状态
| 目标 | 当前业务状态 | 已有能力 | 剩余卡点 |
| --- | --- | --- | --- |
| 搜索联系人 | 基础可用 | `isphere_search_contacts` 支持 log-backed 候选和可选 MsgLib enrichment。 | 更丰富字段、成员层级属于后续增强。 |
| 搜索群组 | 基础可用 | `isphere_search_groups` 支持 groupchat/conference 候选、排序、去重和可选 MsgLib enrichment。 | 群成员/管理员层级属于后续增强。 |
| 收发消息 | 收消息基础可用;发消息 UI action ready在线业务送达未验证 | `isphere_receive_messages` 可从 PacketReader/log-backed 或显式 MsgLib readonly 读取;`isphere_send_message` preview 稳定A-route `uia_rpa` 可对真实/合成聊天窗口写入 `rtbSendMessage` 并点击 `btnSend`。 | 需要在线登录环境证明 server ack、接收方送达或 sent-record/content-hash after 证据。 |
| 收发文件 | 收文件 list 可用;发文件 preview 可用;真实下载/真实上传未完成 | `isphere_receive_files` 可列文件元数据并给出 download preview blocked/planned`isphere_send_file` 可做 allowed-dir SHA256/size preview。 | 真实下载需要 cache mapping/copy gate真实发文件需要文件按钮/菜单定位、上传 connector 和在线发送证据。 |
## A-route 合并后的精确定义
- 路线定位B-route/运行客户端 sidecar/API connector 仍是主线A-route/RPA 只是备选兜底,不作为默认产品架构。
- 已实现:打开真实离线 `frmP2PChat`,识别 `rtbSendMessage``btnSend``rtbRecvMessage`
- 已实现:`uia_send_message` 可以写入发送框并触发发送按钮。
- 未证明:在线登录态下消息被服务端接受、对方收到、或本地 sent-record 产生。
- 未实现:真实文件上传。真实离线 UIA dump 没有稳定暴露 `btnSendFile` automation id。
## 后续计划
1. 主线优先:继续验证 B-route running-client sidecar / in-process connector / existing API 的真实发送和文件能力。
2. 备选保持:把真实 `frmP2PChat` HWND 接入 `isphere_send_message``uia_rpa` connector形成可重复 UI action smoke但只作为 B-route 卡住时的兜底。
3. 在线消息验证:在可登录环境采集 before/after sent-record、content hash、ack/成功提示、idempotency 不重复发送证据。
4. 文件发送节点:优先找 B-route 上传/发送 connector如果继续卡住再单独定位真实工具栏/菜单里的文件按钮,做 RPA 上传动作和在线 evidence package。
5. 更新业务 smoke`send_message_ui_action_ready``send_message_business_delivery_ready` 拆成两个字段。
## 对外口径
可以说:数字员工已经具备联系人/群组搜索、收消息基础读取、收文件列表、发消息 preview、发消息 UI 操作能力。
不要说:数字员工已经能稳定在线发送消息或发送文件。当前还缺在线业务证据。

View File

@@ -3,6 +3,10 @@
日期2026-07-11 日期2026-07-11
分支:`codex/a-route-rpa-send` 分支:`codex/a-route-rpa-send`
> 2026-07-12 校准:本文记录的是 synthetic 离线探针阶段和当时的真实窗体构造阻塞。后续已经通过
> `scripts\open-offline-real-frmP2PChat.ps1` 在未登录/离线环境打开真实 `frmP2PChat`。
> 当前以 `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md` 为准。
## 本轮目标 ## 本轮目标
用户明确当前先不要求真实发送消息,只要求“打开那个会话窗口”,用来验证数字员工是否能: 用户明确当前先不要求真实发送消息,只要求“打开那个会话窗口”,用来验证数字员工是否能:
@@ -86,7 +90,7 @@ frmP2PChat(com.vision.smack.Chat chat, string pluginInfo, string extendTabJson)
- `ConfigSystemManager.config` - `ConfigSystemManager.config`
- `P2PChat.OtherJid` - `P2PChat.OtherJid`
仍未成功打开真实窗体。当前阻塞不再是脚本能力,而是构造函数内部把窗体初始化、登录态、连接态、名册状态、消息中心事件、配置状态混在一起。IL 证据显示构造函数中直接访问: 本节以下内容是当时的中间判断。后续 Task 7 已经补齐更多离线依赖并成功打开真实窗体,因此这里不再作为当前阻塞。它仍保留为风险索引:构造函数内部确实把窗体初始化、登录态、连接态、名册状态、消息中心事件、配置状态混在一起。IL 证据显示构造函数中直接访问:
- `IMPPManager.Instance.Connection.add_OnConnectError` - `IMPPManager.Instance.Connection.add_OnConnectError`
- `IMPPManager.Instance.Connection.add_OnReConnectOk` - `IMPPManager.Instance.Connection.add_OnReConnectOk`
@@ -98,7 +102,7 @@ frmP2PChat(com.vision.smack.Chat chat, string pluginInfo, string extendTabJson)
- `IMPPManager.Instance.RosterManager.UpdateStrangerStatus` - `IMPPManager.Instance.RosterManager.UpdateStrangerStatus`
- `Config.BaseConfig.VisualPhoneEnable` - `Config.BaseConfig.VisualPhoneEnable`
这说明真实 `frmP2PChat` 不是独立窗口类;它要求完整登录运行态。没有服务端/登录态时继续硬构造,投入会越来越像“重建一个假客户端运行时” 后续解决方式不是走正常登录链路,而是建立更完整的离线依赖 harness并在构造完成后补齐关键用户/JID/配置缓存。当前结论已变更为:真实 `frmP2PChat` 可以离线打开,但真实发送仍会被客户端离线状态阻断
## 当前业务结论 ## 当前业务结论
@@ -111,10 +115,10 @@ frmP2PChat(com.vision.smack.Chat chat, string pluginInfo, string extendTabJson)
- 点击结果可留本地审计 marker。 - 点击结果可留本地审计 marker。
- 全程不发真实消息、不上传真实文件。 - 全程不发真实消息、不上传真实文件。
从“真实 iSphere 会话窗口”的目标看,仍需要在线登录环境或继续补完整客户端运行态 从“真实 iSphere 会话窗口”的目标看,后续已完成离线打开真实 `frmP2PChat`。从“真实业务发送”的目标看,仍需要在线登录环境。
## 下一步建议 ## 下一步建议
1. 当前分支先使用 `open-offline-chat-window-probe.ps1` 验证 RPA 识别/定位/点击效果 1. synthetic 探针只作为回归兜底;真实窗口验证优先使用 `open-offline-real-frmP2PChat.ps1`
2. 在线环境拿到真实登录后的 `frmP2PChat` HWND 后,用同一套 WinHelper 选择器直接验证真实窗口 2. 把真实离线 `frmP2PChat` HWND 接入 `isphere_send_message``uia_rpa` connector做可重复 UI 写入/点击 smoke
3. 如果必须离线打开真实窗体,再继续走“补完整 IMPPManager/SmarkManager/Config/BaseConfig/MessageCenter 运行态”的破解路线 3. 在线环境拿到真实登录后的 `frmP2PChat` HWND 后,用同一套 WinHelper 选择器验证业务发送

View File

@@ -0,0 +1,177 @@
# A-route 离线打开真实 frmP2PChat 会话窗口
日期2026-07-11
分支:`codex/a-route-open-real-chat-window`
目标:不登录、不连服务端,在本机离线样本中打开真实 `IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat` 窗口,供后续 RPA 对真实窗口做 UIA 控制。
## 结论
已经在未登录/离线环境下打开真实 `frmP2PChat`
成功命令:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps -ShowWindow -HoldSeconds 1
```
成功产物:
- 结果 JSON`E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\real-frmP2PChat-result-20260711-205312.json`
- HWND`0xC0CB4`
- 截图:`E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\real-frmP2PChat-20260711-205312.png`
- UIA dump`E:\coding\codex\isphere-ai-bridge\runs\offline-chat-window\uia-dump-real-frmP2PChat-20260711-205312.json`
- UIA root
- `automation_id = frmP2PChat`
- `control_type = Window`
- `framework_id = WinForm`
- `visible = true`
UIA dump 已确认可见关键控件:
- `rtbRecvMessage`
- `rtbSendMessage`
- `btnSend`
窗口内显示“您已处于离线状态,无法发送消息,请上线后再次尝试!”。这是预期状态;本轮目标不是发送消息,也不是上传文件,只是打开真实会话窗口。
## 新增脚本
### 1. 真实窗口打开脚本
`scripts/open-offline-real-frmP2PChat.ps1`
关键能力:
- 自动切到 32-bit PowerShell避免 x86 客户端程序集 `BadImageFormatException`
- 只读加载真实客户端目录:
`runs/offline-real-client-window/full/zyl/Impp`
- 使用 `AssemblyResolve` 从真实客户端目录解析依赖。
- 构造真实类型:
`IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat`
- 支持不 Show 的构造验证,也支持 `-ShowWindow` 真实显示、截图和 UIA dump。
- 捕获 WinForms `ThreadException`,输出 IL offset、堆栈和 JSON 证据,避免 .NET 异常弹窗卡死。
### 2. 构造函数 IL / NullRisk 提取脚本
`scripts/extract-frmP2PChat-il-risk.ps1`
输出:
- 完整构造函数 IL
`runs/offline-chat-window/frmP2PChat-ctor.il.txt`
- `callvirt` / `ldfld` NullRisk CSV
`runs/offline-chat-window/frmP2PChat-ctor-null-risk.csv`
- 风险摘要:
`runs/offline-chat-window/frmP2PChat-ctor-null-risk.md`
提取结果:
- 构造函数源 IL 行:`406271-406860`
- 构造函数行数:`590`
- `callvirt` / `ldfld` 风险项:`150`
## 关键 IL 证据
构造函数签名:
```text
frmP2PChat(com.vision.smack.Chat chat, string pluginInfo, string extendTabJson)
```
高信号 NullRisk
| IL | 证据 | 需要补的运行态 |
|---|---|---|
| `IL_00f6` | `XMPPConnection::add_OnConnectError` | `IMPPManager.Instance.Connection` / backing field |
| `IL_0111` | `XMPPConnection::add_OnReConnectOk` | 同上 |
| `IL_013b` / `IL_0140` | `P2PChat::get_OtherJid()` / `Jid::getBareJid()` | `P2PChat.OtherJid` |
| `IL_0156` | `IMPPManager::get_UserInfo()` | `IMPPManager._userInfo` |
| `IL_0575` | `MessageCenter::add_OnTcpMessageArrived` | `IMPPManager.MessageCenter` |
| `IL_0614` | `RosterManager::UpdateStrangerStatus` | `IMPPManager.RosterManager` |
| `IL_0631` | `BaseConfig::VisualPhoneEnable()` | `Config.BaseConfig` |
Show 阶段新增证据:
| IL | 证据 | 处理 |
|---|---|---|
| `frmP2PChat_Load IL_004d/0058` | `Config::get_BaseConfig()``BaseConfig::RemoteControlVisible()` | 补 `Config.<BaseConfig>k__BackingField` |
| `frmChatBase_Activated IL_0000/0005` | `IMPPManager.get_Instance().get_frmMain().BringModalFormToFront()` | 补 `IMPPManager.<frmMain>k__BackingField` |
| `frmP2PChat_Load IL_137f` | `UserInfoManager.getUserInfo(otherBareJid,true)` 后使用 `UserInfo::get_CompanyID()` | 构造完成后预热 `UserInfoCache` |
注意:`UserInfoCache` 不能在 `frmP2PChat` 构造前预热。过早预热会让构造函数进入 `UCUserInformation.LoadUserInfo(UserInfo)`,在 `UCUserInformation::LoadUserInfo IL_0085` 触发新的 NRE。当前脚本是在真实窗体构造完成后、`Show()` 前预热缓存。
## 最小 fake runtime 清单
当前成功路径最小补齐如下:
1. `IMPPManager.Instance`
- `<MessageCenter>k__BackingField`
- `<frmMain>k__BackingField`
- `LogonUser`
- `_userInfo`
- `_rosterUserInfoList`
2. `SmarkManager`
- `<SmarkManagerInstance>k__BackingField`
3. `XMPPConnection`
- `Jid`
- `UserName`
- `LoginState`
- `CompanyID`
- `Resource`
- `_packetListeners`
- `_packetCollectors`
4. `IMPPManager` inherited manager fields/properties
- `Connection` and `<Connection>k__BackingField`
- `IsConnected` and `<IsConnected>k__BackingField`
- `PresenceManager` and backing field
- `P2PChatManager` and backing field
- `RosterManager` and backing field
5. Config
- `ConfigSystemManager.config`
- `Config.<BaseConfig>k__BackingField`
- `Config.<UserInfo>k__BackingField`
- `Config.<LoginInfo>k__BackingField`
6. `UserInfoCache`
-`frmP2PChat` 构造后、`Show()` 前加入自己和对端的 JID/ID 映射。
7. Chat 对象
- 真实 `com.vision.smack.P2PChat`
- `OtherJid = codex-probe@offline.local`
## 验证命令
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\test-extract-frmP2PChat-il-risk.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-frmP2PChat-il-risk.ps1 -OutDir runs/offline-chat-window
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\test-open-offline-real-frmP2PChat-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\open-offline-real-frmP2PChat.ps1 -RuntimeMode Deps -ShowWindow -HoldSeconds 1
```
## 当前边界
- 已成功打开真实 `frmP2PChat`
- UIA 可 dump 到真实 `frmP2PChat``rtbRecvMessage``rtbSendMessage``btnSend`
- 离线环境下窗口会提示无法发送消息,这是客户端真实离线状态表现,不影响后续 RPA 窗口定位。
- 本轮没有处理真实发送、真实上传、真实登录态。
- `btnSendFile` 在这次真实离线 UIA dump 中没有以 `btnSendFile` automation id 暴露;后续如果 RPA 需要上传文件,需要另开节点定位真实工具栏按钮或菜单路径。
## 2026-07-12 主分支状态校准
该能力已经随 A-route 分支合并到 `main`。业务含义如下:
- 已完成:真实离线 `frmP2PChat` 打开、UIA 识别、发送框定位、发送按钮定位。
- 已演示:在真实离线窗口内写入文本并点击 `btnSend`,可用于验证数字员工的窗口识别、定位和点击链路。
- 未完成:在线登录态下的真实发送、服务端 ack、接收方送达、发送记录匹配。
- 未完成:真实文件上传/发送。当前真实 UIA dump 没有稳定暴露 `btnSendFile`,文件发送要单独做工具栏/菜单定位。
因此,文档里出现的 helper `sent_message=true` 只能解释为“UI 发送动作已触发”,不能解释为“业务消息已送达”。
## 下一轮建议
1. 把 A-route RPA 的窗口定位目标从 synthetic probe 切到真实 `frmP2PChat`
- root `automation_id=frmP2PChat`
- send box `automation_id=rtbSendMessage`
- send button `automation_id=btnSend`
2. 把真实窗口 HWND 接入 `isphere_send_message``uia_rpa` connector形成可重复的本地 UI 动作 smoke。
3. 在线登录环境中补一次业务发送验证发送前后记录、content hash、ack/发送记录、idempotency 不重复发送。
4. 如果后续需要文件按钮,再专门分析真实工具栏图标按钮、菜单项和 `ToolStrip` 命中路径。

View File

@@ -1,7 +1,7 @@
# A-route UIA Send Implementation Note # A-route UIA Send Implementation Note
Date: 2026-07-11 Date: 2026-07-11
Branch: `codex/a-route-rpa-send` Branch: implemented on `codex/a-route-rpa-send`, merged to `main`
## Decision ## Decision
@@ -25,6 +25,28 @@ $env:ISPHERE_SEND_UIA_BUTTON_AUTOMATION_ID = "btnSend"
Then call `isphere_send_message` with `execution_mode="production"`. Then call `isphere_send_message` with `execution_mode="production"`.
## Status correction after real-window work
`uia_send_message` is a UI action connector. Its helper result fields such as
`typed_text=true`, `clicked_ui=true`, and `sent_message=true` mean the editor was
written and the send button was invoked/clicked. They do not mean the server
accepted the message, the receiver got it, or a sent record was written.
After this note was first written, the project also opened a real offline
`frmP2PChat` window locally and confirmed:
- root: `frmP2PChat`
- editor: `rtbSendMessage`
- send button: `btnSend`
- receive area: `rtbRecvMessage`
The real offline window still shows the client-side offline-send blocker, so it
is useful for UI positioning and click verification, not for business delivery
verification.
## Remaining real-environment work ## Remaining real-environment work
The local environment still cannot log in to iSphere. The code path is implemented and locally proven against synthetic UIA, but real iSphere success still needs a logged-in window handle and one real run in the online environment. The local environment still cannot log in to iSphere. The code path is
implemented and locally proven against synthetic UIA plus the real offline chat
window, but real iSphere success still needs a logged-in window handle and one
online run with success/ack or sent-record evidence.

View File

@@ -0,0 +1,309 @@
# B-Route Bridge/IPC/Plugin Static Map
Date: 2026-07-12
## Scope
This report uses offline IL, binary string metadata, reflection metadata for `HttpServerLib.dll`, and returned live-probe JSON. It does not log in, open sockets, attach hooks, inject into a process, replay traffic, or mutate client binaries.
Machine-readable evidence: `runs/offline-broute-reverse/bridge-map.json`
Reflection metadata: `runs/offline-broute-reverse/httpserverlib-reflection.json`
## Recommendation
| Question | Answer |
| --- | --- |
| Should B-route pursue existing IPC/plugin before an in-process adapter? | **No** |
| Offline decision | `in_process_adapter_research` |
| External sidecar boundary | `external_sidecar_preview_only_until_bridge_exists` |
| Reason | Offline static evidence found no existing local IPC/plugin route that exposes send-message or send-file. HttpServerLib and plugin surfaces either require logged-in runtime state or are UI/framework-only; the named-pipe stub is empty. |
## Sources
### Text/IL sources
| Source | Role | Exists | Lines | Size bytes |
| --- | --- | --- | ---: | ---: |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main client IL; login, plugin manager, local HTTP starter, chat/runtime | yes | 1360035 | 74148460 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il` | common helpers; WinCommand, ProcessComm, DTOs | yes | 118343 | 5703293 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ISphere.exe.il` | ISphere companion app IL; CEF and command helpers | yes | 81273 | 5679074 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.UI.dll.il` | UI/browser support IL | yes | 242314 | 13545362 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il` | file service implementation IL | yes | 3351 | 207786 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | XMPP/socks5/network IL | yes | 87425 | 5019807 |
### Binary/string sources
| Source | Role | Exists | Strings | Size bytes |
| --- | --- | --- | ---: | ---: |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll` | local HTTP server framework binary | yes | 555 | 26624 |
| `runs\offline-real-client-window\full\zyl\Impp\IMPlatformClient.Web.exe` | CEF/web helper process binary | yes | 185 | 9216 |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll` | native network abstraction | yes | 563 | 87552 |
| `runs\offline-real-client-window\full\zyl\Impp\IOClientNetwork.dll` | native network implementation | yes | 870 | 145920 |
| `runs\offline-real-client-window\full\zyl\Impp\IMPlatformClient.exe` | main client binary | yes | 76877 | 8366592 |
## Candidate classification
| Candidate | Category | Classification | Usable for B-route send | Recommendation | Matches |
| --- | --- | --- | --- | --- | ---: |
| `frmLogin.StartWinServer / HttpServerLib.HttpService` | `localhost_http` | `requires_logged_in_process` | no | `do_not_pursue_before_in_process_adapter` | 31 |
| `HttpServerLib route/module framework` | `localhost_http` | `static_only_unknown` | no | `no_existing_ipc_first` | 8 |
| `PluginLightAppMulProcessCommunication NamedPipeServerStream` | `named_pipe` | `not_a_bridge` | no | `do_not_use` | 17 |
| `IMPP.Common.Helper.ProcessComm WM_COPYDATA helper` | `window_message` | `static_only_unknown` | no | `not_a_send_bridge` | 164 |
| `PluginManager / IMPlugin command surface` | `plugin` | `requires_logged_in_process` | no | `plugin_extension_not_first` | 2696 |
| `IMPlatformClient.Web / CEF helper` | `child_process` | `requires_logged_in_process` | no | `preview_only_not_send` | 343 |
| `INetwork / IOClientNetwork native stack` | `native_network` | `not_a_bridge` | no | `do_not_pursue_as_ipc` | 72 |
| `returned live-probe named pipe inventory` | `named_pipe` | `static_only_unknown` | no | `do_not_assume_isphere_api` | 49 |
| `local TcpListener candidates` | `tcp_listener` | `not_a_bridge` | no | `not_existing_ipc` | 145 |
## Verified facts
- `frmLogin.StartWinServer` constructs `HTTPServerLib.HttpService` on `0.0.0.0` and starts `HttpServer.Start` in a thread, but it depends on `IMPPManager.UserInfo` and `ServiceManager.UnifiedAuthentication` state.
- `HttpServerLib.dll` exposes route/module primitives such as `HttpService.RegisterModule`, `ServiceModule`, `ServiceRoute`, `RouteAttribute`, `OnGet`, and `OnPost`.
- Main client IL does not show a concrete `RegisterModule` call or send-message/send-file HTTP route registration.
- `PluginLightAppMulProcessCommunication` declares a `NamedPipeServerStream` field, but `StartLightAppMultProssCommunication` returns immediately.
- Returned live probe showed one remote TCP connection to port `10088` and a named pipe `\\.\\pipe\\zfpinject-msg-server`; neither proves an iSphere send API.
- `PluginManager`/`IMPlugin` evidence is UI/app-store/context-menu oriented; no local assembly-load plugin bridge or send route was confirmed.
## Candidate evidence
### frmLogin.StartWinServer / HttpServerLib.HttpService
Classification: `requires_logged_in_process`; usable for B-route send: `False`; matches: 31.
Reason: Static IL builds a local HTTP service from logged-in user/auth state, but no send route or active live local listener was confirmed.
| 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:888716` | `reference` | `RepairDatabase() cil managed` | `L888715: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:888818` | `string_literal` | `IL_00f8: ldstr "{0}/ifim/messageAuth\?version={1}&user={2}&resource"` | `L888715: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:888944` | `string_literal` | `IL_0287: ldstr "RepairDatabase.exe"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889041` | `method_end` | `} // end of method frmLogin::RepairDatabase` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889166` | `callsite` | `IL_004d: call instance void IMPP.Client.frmLogin::RepairDatabase()` | `L889120: .method private hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889253` | `signature_continuation` | `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:889518` | `callsite` | `IL_0276: call instance int32 IMPP.Client.frmLogin::GetFreePort(int32[])` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889551` | `string_literal` | `IL_02d3: ldstr "0.0.0.0"` | `` |
| `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` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889680` | `signature_continuation` | `GetFreePort(int32[] portArray) cil managed` | `L889679: .method private hidebysig instance int32` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889798` | `method_end` | `} // end of method frmLogin::GetFreePort` | `L889679: .method private hidebysig instance int32` |
| `runs\offline-broute-reverse\httpserverlib-reflection.json` | `reflection_metadata` | `HttpServerLib reflection exposes matching types/methods; see httpserverlib-reflection.json` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str10` | `binary_string` | `HttpServerLib.dll` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str12` | `binary_string` | `HTTPServerLib` | `` |
### HttpServerLib route/module framework
Classification: `static_only_unknown`; usable for B-route send: `False`; matches: 8.
Reason: HttpServerLib has ServiceModule/RouteAttribute primitives, but client IL does not show RegisterModule or send-message routes.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-broute-reverse\httpserverlib-reflection.json` | `reflection_metadata` | `HttpServerLib reflection exposes matching types/methods; see httpserverlib-reflection.json` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str21` | `binary_string` | `RouteAttribute` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str22` | `binary_string` | `RouteMethod` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str23` | `binary_string` | `ServiceModule` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str24` | `binary_string` | `ServiceRoute` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str292` | `binary_string` | `RegisterModule` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str302` | `binary_string` | `SearchRoute` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\HttpServerLib.dll#str303` | `binary_string` | `ExecuteRoute` | `` |
### PluginLightAppMulProcessCommunication NamedPipeServerStream
Classification: `not_a_bridge`; usable for B-route send: `False`; matches: 17.
Reason: A NamedPipeServerStream field exists, but StartLightAppMultProssCommunication has a one-instruction ret body.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `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` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9042` | `reference` | `.field private static class IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication _instance` | `L9012: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9043` | `reference` | `.field private class [System.Core]System.IO.Pipes.NamedPipeServerStream _pipeServer` | `L9012: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9052` | `method_end` | `} // end of method PluginLightAppMulProcessCommunication::.ctor` | `L9044: .method private hidebysig specialname rtspecialname` |
| `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:9063` | `method_end` | `} // end of method PluginLightAppMulProcessCommunication::Init` | `L9054: .method public hidebysig static void Init() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9066` | `reference` | `StartLightAppMultProssCommunication() cil managed` | `L9065: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9071` | `method_end` | `} // end of method PluginLightAppMulProcessCommunication::StartLightAppMultProssCommunication` | `L9065: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:9079` | `method_end` | `} // end of method PluginLightAppMulProcessCommunication::.cctor` | `L9073: .method private hidebysig specialname rtspecialname static` |
| `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:217833` | `callsite` | `IL_0071: call void IMPP.Client.Core.Plugins.MessageCenter.Classes.PluginLightAppMulProcessCommunication::Init()` | `L217793: .method private hidebysig specialname rtspecialname` |
| `runs\offline-real-client-window\full\zyl\Impp\IMPlatformClient.exe#str2852` | `binary_string` | `NamedPipeServerStream` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\IMPlatformClient.exe#str6922` | `binary_string` | `PluginLightAppMulProcessCommunication` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\IMPlatformClient.exe#str8523` | `binary_string` | `StartLightAppMultProssCommunication` | `` |
### IMPP.Common.Helper.ProcessComm WM_COPYDATA helper
Classification: `static_only_unknown`; usable for B-route send: `False`; matches: 164.
Reason: ProcessComm can send WM_COPYDATA to a foreground or titled window, but no receive handler or send-command contract is confirmed.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:271124` | `reference` | `native int GetForegroundWindow() cil managed preservesig` | `L271123: .method public hidebysig static pinvokeimpl("user32.dll" winapi)` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:278221` | `type_definition` | `.class sequential ansi sealed nested private beforefieldinit COPYDATASTRUCT` | `L278204: .method private hidebysig static object` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:278227` | `reference` | `} // end of class COPYDATASTRUCT` | `L278204: .method private hidebysig static object` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:279144` | `reference` | `.field private static literal int32 WM_COPYDATA = int32(0x0000004A)` | `L279026: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:282985` | `reference` | `int32 FindWindow(string lpClassName,` | `L282984: .method private hidebysig static pinvokeimpl("user32.dll" winapi)` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:317869` | `callsite` | `IL_3827: call native int IMPP.Client.utils.Utils::GetForegroundWindow()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:412102` | `callsite` | `IL_3613: call native int IMPP.Client.utils.Utils::GetForegroundWindow()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:543733` | `reference` | `.field public static literal int32 WM_COPYDATA = int32(0x0000004A)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:660716` | `reference` | `.locals init (valuetype IMPP.Client.Business.Logon.Native/COPYDATASTRUCT V_0,` | `L660712: .method public hidebysig static bool DefWndProc(valuetype [System.Windows.Forms]System.Windows.Forms.Message& m) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:660731` | `reference` | `valuetype IMPP.Client.Business.Logon.Native/COPYDATASTRUCT V_15,` | `L660712: .method public hidebysig static bool DefWndProc(valuetype [System.Windows.Forms]System.Windows.Forms.Message& m) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:660735` | `reference` | `valuetype IMPP.Client.Business.Logon.Native/COPYDATASTRUCT V_19,` | `L660712: .method public hidebysig static bool DefWndProc(valuetype [System.Windows.Forms]System.Windows.Forms.Message& m) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:660746` | `reference` | `valuetype IMPP.Client.Business.Logon.Native/COPYDATASTRUCT V_30,` | `L660712: .method public hidebysig static bool DefWndProc(valuetype [System.Windows.Forms]System.Windows.Forms.Message& m) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661348` | `reference` | `IL_06b6: initobj IMPP.Client.Business.Logon.Native/COPYDATASTRUCT` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661350` | `reference` | `IL_06bd: ldtoken IMPP.Client.Business.Logon.Native/COPYDATASTRUCT` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661353` | `reference` | `IL_06cc: unbox.any IMPP.Client.Business.Logon.Native/COPYDATASTRUCT` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661356` | `reference` | `IL_06d5: ldfld int32 IMPP.Client.Business.Logon.Native/COPYDATASTRUCT::cbData` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661360` | `reference` | `IL_06e3: ldfld native int IMPP.Client.Business.Logon.Native/COPYDATASTRUCT::lpData` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:661446` | `reference` | `IL_07e8: stfld native int IMPP.Client.Business.Logon.Native/COPYDATASTRUCT::dwData` | `` |
### PluginManager / IMPlugin command surface
Classification: `requires_logged_in_process`; usable for B-route send: `False`; matches: 2696.
Reason: Plugin evidence is UI/app-store/context-menu oriented and depends on logged-in PluginManager state; no Assembly.Load/LoadFrom or send API bridge was confirmed.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1048` | `reference` | `.mresource public IMPP.Client.Core.Plugins.Manager.FrmAppStore.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1051` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Core.Plugins.Manager.FrmAppStore.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1063` | `reference` | `.mresource public IMPP.Client.Core.Plugins.Manager.WindowForm.FrmCefHomePage.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1066` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Core.Plugins.Manager.WindowForm.FrmCefHomePage.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:82622` | `callsite` | `IL_0156: call class IMPP.Client.Core.Plugins.Manager.PluginManager IMPP.Client.Core.Plugins.Manager.PluginManager::GetInstance()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:82623` | `callsite` | `IL_015b: callvirt instance class [mscorlib]System.Collections.Generic.List`1<class IMPP.Client.Core.Plugins.Manager.IMPlugin> IMPP.Client.Core.Plugins.Manager.PluginManager::GetPluginList()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:85884` | `callsite` | `IL_0157: call class IMPP.Client.Core.Plugins.Manager.PluginManager IMPP.Client.Core.Plugins.Manager.PluginManager::GetInstance()` | `L85783: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:85890` | `callsite` | `IL_0168: callvirt instance void IMPP.Client.Core.Plugins.Manager.PluginManager::add_PluginMessageNotify(class [IMPP.Interface]IMPP.Interface.PluginMessageEventHandler)` | `L85783: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:88002` | `callsite` | `IL_045d: call class IMPP.Client.Core.Plugins.Manager.PluginManager IMPP.Client.Core.Plugins.Manager.PluginManager::GetInstance()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:88007` | `callsite` | `IL_0470: callvirt instance void IMPP.Client.Core.Plugins.Manager.PluginManager::DoNotifyAction(string,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:90512` | `callsite` | `IL_0111: call void IMPP.Client.Core.Plugins.Manager.PluginUtils::LoadPluginContextMenu(class [System.Windows.Forms]System.Windows.Forms.ContextMenuStrip,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:90677` | `callsite` | `IL_016d: call void IMPP.Client.Core.Plugins.Manager.PluginUtils::LoadPluginContextMenu(class [System.Windows.Forms]System.Windows.Forms.ContextMenuStrip,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:91111` | `callsite` | `IL_00f8: call void IMPP.Client.Core.Plugins.Manager.PluginUtils::LoadPluginContextMenu(class [System.Windows.Forms]System.Windows.Forms.ContextMenuStrip,` | `L91000: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:91274` | `callsite` | `IL_00cb: call void IMPP.Client.Core.Plugins.Manager.PluginUtils::LoadPluginContextMenu(class [System.Windows.Forms]System.Windows.Forms.ContextMenuStrip,` | `L91188: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:105364` | `callsite` | `IL_03c1: callvirt instance string IMPP.Client.Core.Plugins.Manager.IMPlugin::get_Command()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:105401` | `callsite` | `IL_042d: call class IMPP.Client.Core.Plugins.Manager.PluginManager IMPP.Client.Core.Plugins.Manager.PluginManager::GetInstance()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:105402` | `callsite` | `IL_0432: callvirt instance class [mscorlib]System.Collections.Generic.List`1<class IMPP.Client.Core.Plugins.Manager.IMPlugin> IMPP.Client.Core.Plugins.Manager.PluginManager::GetPluginList()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:217227` | `reference` | `class IMPP.Client.Core.Plugins.Manager.PluginManager V_3,` | `L217219: .method public hidebysig newslot virtual final` |
### IMPlatformClient.Web / CEF helper
Classification: `requires_logged_in_process`; usable for B-route send: `False`; matches: 343.
Reason: The web helper/CEF surface exists, but static evidence points to UI/plugin browser support, not an external send/file API.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:278553` | `reference` | `.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `L278527: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300455` | `reference` | `IL_0428: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300465` | `string_literal` | `IL_0442: ldstr "NavigateTo"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300492` | `callsite` | `IL_0477: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.Compi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300493` | `reference` | `IL_047c: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300500` | `reference` | `IL_048f: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300501` | `reference` | `IL_0494: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300502` | `reference` | `IL_0499: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300504` | `callsite` | `IL_04a0: callvirt instance class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.WinCefBrowser IMPP.Client.Core.Plugins.Manager.WindowForm.frmPluginTabCtrl::get_CefBrowser()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:300506` | `callsite` | `IL_04a6: callvirt instance void class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.WinCefBrowser,object>::Invoke(!0,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:388726` | `reference` | `.field public static class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `L388681: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413211` | `callsite` | `IL_0266: callvirt instance class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.WinCefBrowser IMPP.Client.Business.ISphereAssistant.frmExtendTabCtrl::get_CefBrowser()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413215` | `callsite` | `IL_0277: callvirt instance void [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.WinCefBrowser::NavigateTo(string)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:414754` | `reference` | `IL_0b96: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:414764` | `string_literal` | `IL_0bb0: ldstr "NavigateTo"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:414791` | `callsite` | `IL_0be5: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.Compi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:414792` | `reference` | `IL_0bea: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:414799` | `reference` | `IL_0bfd: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [IMPP.Cef4CSharp]IMPP.Cef4CSharp.Win.Wi...` | `` |
### INetwork / IOClientNetwork native stack
Classification: `not_a_bridge`; usable for B-route send: `False`; matches: 72.
Reason: Native NETIO send/recv symbols are low-level transport, not a local command bridge into logged-in chat objects.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str249` | `binary_string` | `D:\work\me\sourcecode\app_project\Network_node\bin\release\INetwork.pdb` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str314` | `binary_string` | `INetwork.dll` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str317` | `binary_string` | `??0StreamClientBase@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str318` | `binary_string` | `??0StreamClientBase@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str319` | `binary_string` | `??0StreamClientChannel@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str320` | `binary_string` | `??0StreamClientChannel@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str321` | `binary_string` | `??0StreamClientFrameSink@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str322` | `binary_string` | `??0StreamClientFrameSink@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str323` | `binary_string` | `??0StreamClientMsg@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str324` | `binary_string` | `??0StreamClientMsg@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str325` | `binary_string` | `??0StreamClientMsgSink@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str326` | `binary_string` | `??0StreamClientMsgSink@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str327` | `binary_string` | `??0StreamClientNetEventSink@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str328` | `binary_string` | `??0StreamClientNetEventSink@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str329` | `binary_string` | `??0StreamClientRecverEventSink@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str330` | `binary_string` | `??0StreamClientRecverEventSink@@QAE@XZ` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str331` | `binary_string` | `??0StreamClientSenderEventSink@@QAE@ABV0@@Z` | `` |
| `runs\offline-real-client-window\full\zyl\Impp\INetwork.dll#str332` | `binary_string` | `??0StreamClientSenderEventSink@@QAE@XZ` | `` |
### returned live-probe named pipe inventory
Classification: `static_only_unknown`; usable for B-route send: `False`; matches: 49.
Reason: Live probe saw \\.\\pipe\\zfpinject-msg-server, but no matching iSphere static string or send contract was found in the configured samples.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:905746` | `reference` | `frmMain_OnReConnectionSucceed(object sender,` | `L905745: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:905814` | `reference` | `IL_0081: ldftn void IMPP.Client.frmMain::'<frmMain_OnReConnectionSucceed>b__4'()` | `L905745: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:905828` | `method_end` | `} // end of method frmMain::frmMain_OnReConnectionSucceed` | `L905745: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:919019` | `reference` | `IL_006e: ldftn instance void IMPP.Client.frmMain::frmMain_OnReConnectionSucceed(object,` | `L918967: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:919023` | `callsite` | `IL_0079: callvirt instance void [smack]com.vision.smack.XMPPConnection::add_OnReConnectionSucceed(class [mscorlib]System.EventHandler)` | `L918967: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:928079` | `method_header` | `.method private hidebysig static void '<frmMain_OnReConnectionSucceed>b__4'() cil managed` | `L928079: .method private hidebysig static void '<frmMain_OnReConnectionSucceed>b__4'() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:928087` | `method_end` | `} // end of method frmMain::'<frmMain_OnReConnectionSucceed>b__4'` | `L928079: .method private hidebysig static void '<frmMain_OnReConnectionSucceed>b__4'() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1126866` | `reference` | `IL_00e2: ldftn instance void IMPP.Client.Business.ReConnection.WindowForm.FrmReConnection::OnReConnectionSucceed(object,` | `L1126773: .method private hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1126870` | `callsite` | `IL_00ed: callvirt instance void [smack]com.vision.smack.XMPPConnection::add_OnReConnectionSucceed(class [mscorlib]System.EventHandler)` | `L1126773: .method private hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1127782` | `reference` | `OnReConnectionSucceed(object sender,` | `L1127781: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1127841` | `reference` | `IL_0069: ldftn instance void IMPP.Client.Business.ReConnection.WindowForm.FrmReConnection::'<OnReConnectionSucceed>b__0'()` | `L1127781: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1127855` | `method_end` | `} // end of method FrmReConnection::OnReConnectionSucceed` | `L1127781: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1127979` | `reference` | `'<OnReConnectionSucceed>b__0'() cil managed` | `L1127978: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1127987` | `method_end` | `} // end of method FrmReConnection::'<OnReConnectionSucceed>b__0'` | `L1127978: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ISphere.exe.il:33510` | `reference` | `IL_00e2: ldftn instance void IMPP.ISphere.IMPPManage.FrmReConnection::OnReConnectionSucceed(object,` | `L33417: .method private hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ISphere.exe.il:33514` | `callsite` | `IL_00ed: callvirt instance void [smack]com.vision.smack.XMPPConnection::add_OnReConnectionSucceed(class [mscorlib]System.EventHandler)` | `L33417: .method private hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ISphere.exe.il:34155` | `reference` | `OnReConnectionSucceed(object sender,` | `L34154: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ISphere.exe.il:34182` | `reference` | `IL_0031: ldftn instance void IMPP.ISphere.IMPPManage.FrmReConnection::'<OnReConnectionSucceed>b__0'()` | `L34154: .method private hidebysig instance void` |
### local TcpListener candidates
Classification: `not_a_bridge`; usable for B-route send: `False`; matches: 145.
Reason: TcpListener evidence is tied to TCP file manage or smack socks5, not a command API for text/file send. Returned live probe had only one remote XMPP connection.
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:889833` | `callsite` | `IL_003c: callvirt instance class [System]System.Net.IPEndPoint[] [System]System.Net.NetworkInformation.IPGlobalProperties::GetActiveTcpListeners()` | `L889800: .method private hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1117108` | `reference` | `.field private static class [System]System.Net.Sockets.TcpListener _listener` | `L1117034: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1118022` | `reference` | `IL_0058: ldsfld class [System]System.Net.Sockets.TcpListener IMPP.Client.Business.TCPFileManage.TCPFileManager::_listener` | `L1117985: .method public hidebysig static class [System]System.Net.IPEndPoint` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1118096` | `reference` | `IL_011e: ldsfld class [System]System.Net.Sockets.TcpListener IMPP.Client.Business.TCPFileManage.TCPFileManager::_listener` | `L1117985: .method public hidebysig static class [System]System.Net.IPEndPoint` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1118097` | `callsite` | `IL_0123: callvirt instance class [System]System.Net.EndPoint [System]System.Net.Sockets.TcpListener::get_LocalEndpoint()` | `L1117985: .method public hidebysig static class [System]System.Net.IPEndPoint` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1118817` | `callsite` | `IL_0091: callvirt instance class [System]System.Net.IPEndPoint[] [System]System.Net.NetworkInformation.IPGlobalProperties::GetActiveTcpListeners()` | `L1118746: .method public hidebysig static int32 FindFreeTCPPort([opt] int32 startPort) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1119636` | `reference` | `IL_0009: stsfld class [System]System.Net.Sockets.TcpListener IMPP.Client.Business.TCPFileManage.TCPFileManager::_listener` | `L1119622: .method private hidebysig specialname rtspecialname static` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64917` | `reference` | `.field private class com.vision.smack.socks5.TCPSocks5Server '<Server>k__BackingField'` | `L64879: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64926` | `signature_continuation` | `instance void .ctor(class com.vision.smack.socks5.TCPSocks5Server server,` | `L64925: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64935` | `callsite` | `IL_0008: call instance void com.vision.smack.socks5.TCPSocks5Connection::set_Server(class com.vision.smack.socks5.TCPSocks5Server)` | `L64925: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64942` | `method_header` | `.method private hidebysig specialname instance class com.vision.smack.socks5.TCPSocks5Server` | `L64942: .method private hidebysig specialname instance class com.vision.smack.socks5.TCPSocks5Server` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64949` | `reference` | `IL_0001: ldfld class com.vision.smack.socks5.TCPSocks5Server com.vision.smack.socks5.TCPSocks5Connection::'<Server>k__BackingField'` | `L64942: .method private hidebysig specialname instance class com.vision.smack.socks5.TCPSocks5Server` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64954` | `reference` | `set_Server(class com.vision.smack.socks5.TCPSocks5Server 'value') cil managed` | `L64953: .method private hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:64961` | `reference` | `IL_0002: stfld class com.vision.smack.socks5.TCPSocks5Server com.vision.smack.socks5.TCPSocks5Connection::'<Server>k__BackingField'` | `L64953: .method private hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:65018` | `callsite` | `IL_0001: call instance class com.vision.smack.socks5.TCPSocks5Server com.vision.smack.socks5.TCPSocks5Connection::get_Server()` | `L65012: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:65019` | `callsite` | `IL_0006: callvirt instance bool com.vision.smack.socks5.TCPSocks5Server::get_IsStarting()` | `L65012: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:65027` | `callsite` | `IL_0016: call instance class com.vision.smack.socks5.TCPSocks5Server com.vision.smack.socks5.TCPSocks5Connection::get_Server()` | `L65012: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:65028` | `callsite` | `IL_001b: callvirt instance bool com.vision.smack.socks5.TCPSocks5Server::get_RequireValidate()` | `L65012: .method private hidebysig instance void` |
## Decision
No existing IPC/plugin/local HTTP bridge is confirmed usable for B-route text send or file send. The next B-route branch should be `in_process_adapter_research`. Until that exists, an external sidecar can only do preview/probe work, while A-route/RPA remains backup-only.
## Next work
1. Update the B-route next plan and capability source matrix with `in_process_adapter_research` as the offline decision.
2. Create a separate plan before implementing any in-process adapter work.
3. Do not promote RPA beyond backup in this branch.

View File

@@ -0,0 +1,230 @@
# B-Route File Send Static Map
Date: 2026-07-12
## Scope
This report uses offline IL only. It does not upload files, send file messages, replay traffic, inject into a process, or mutate the original iSphere binaries.
Machine-readable evidence: `runs/offline-broute-reverse/file-send-map.json`
## Sources
| Source | Role | Exists | Lines | Size bytes |
| --- | --- | --- | ---: | ---: |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main client IL; UC_FileSend, OffLineFileSend, MessageScheduling | yes | 1360035 | 74148460 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il` | file transfer service implementation | yes | 3351 | 207786 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il` | file transfer contracts, parameters, and result DTOs | yes | 1641 | 93585 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il` | transport/event interface contracts | yes | 4429 | 227335 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | Chat.sendFileMessage and XMPP message construction | yes | 87425 | 5019807 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\TcpFileTransfer.dll.il` | native TCP transfer candidate; IL may be unavailable | yes | 5 | 241 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Model.dll.il` | chat record models if extracted | no | 0 | |
## Target classification
| Target | Phase | Intent | Classification | Matches |
| --- | --- | --- | --- | ---: |
| `IMPP.Client.OffLineFileSend.sendFile` | `upload` | offline file upload orchestration from UI file sender | `confirmed_signature` | 3 |
| `IMPP.Client.OffLineFileSend.trans_UploadCompleted` | `upload_to_message_boundary` | upload-completed handler that converts FileUploadResult.FileID into a chat file message | `confirmed_signature` | 3 |
| `IMPP.Service.BLL.FileTransfer.FileUpload` | `upload` | synchronous service upload entry returning FileUploadResult | `confirmed_signature` | 17 |
| `IMPP.Service.BLL.FileTransfer.AsynFileUpload` | `upload` | asynchronous upload queue entry | `confirmed_signature` | 3 |
| `FileUploadPara` | `upload_parameters` | host/port/domain/local file path/cache/timeout/upload flags | `confirmed_signature` | 66 |
| `FileUploadResult.FileID` | `upload_result` | server-side file id and URL returned by upload | `confirmed_signature` | 75 |
| `MessageScheduling.SendFileMessage` | `message` | scheduled/file-message finalization path using RosterContactsArgs and FileTransferArgs | `confirmed_signature` | 3 |
| `Chat.sendFileMessage` | `message` | smack API that sends the XMPP file message after upload metadata is known | `confirmed_signature` | 8 |
| `Required values: path id size target jid` | `requirements` | static evidence for local file path, remote folder/file id, file size/name, target JID/chat, and server auth | `confirmed_signature` | 550 |
## Upload step vs chat-message step
| Step | Static evidence | Business meaning |
| --- | --- | --- |
| 1. Upload | `IMPP.Client.OffLineFileSend.sendFile` constructs `FileUploadPara` and calls `IFileTransfer.FileUpload`; `IMPP.Service.BLL.FileTransfer.FileUpload` delegates to `SyncFileTransfer` and private `Upload`. | The local file must be uploaded to the HTTP file service first. |
| 2. Upload result | `FileUploadResult.FileID` is read; upload notification calls `IMPP.Client.OffLineFileSend.trans_UploadCompleted(fileId)`. | The server-issued file id becomes the durable reference. |
| 3. Chat file message | `trans_UploadCompleted` and `MessageScheduling.SendFileMessage` build `OFFLINE_FILE_TRANSFER;...` payloads and call `Chat.sendFileMessage`. | The chat send step publishes metadata/reference, not raw file bytes. |
Conclusion: file send is upload-first, chat-message-second. A direct chat message is insufficient without a valid uploaded file id or remote folder reference.
## Required values
| Value | Status | Evidence |
| --- | --- | --- |
| local file path | `required_confirmed` | OffLineFileSend constructor receives localFilePath; sendFile uses get__localFilePath; MessageScheduling.SendFileMessage uses FileTransferArgs.get_LocalFilePath. |
| server file id / remote folder | `required_confirmed` | Upload returns FileUploadResult.FileID; trans_UploadCompleted(fileId) passes it to Chat.sendFileMessage and Packet.set_id. MessageScheduling path uses FileTransferArgs.get_RemoteFolder. |
| file name and file size | `required_confirmed` | SendFileMessage builds OFFLINE_FILE_TRANSFER payload from FileInfo/FileSystemInfo name and length; OffLineFileSend keeps _fileSize. |
| target JID / chat object | `required_confirmed` | UC_FileSend and MessageScheduling both require a live smack Chat; scheduled path derives it from RosterContactsArgs.get_RosterJid + UtilsChat.GetChat. |
| HTTP file server and auth | `required_confirmed` | FileUploadPara construction uses Config.ServerInfo.HTTPFileServer IP/Port/domain; service upload builds /FS/auth/resource/upload URL with UnifiedAuthentication token/app key/client secret/time/user id. |
| file hash | `not_confirmed_in_file_send_path` | No file-transfer-path MD5/SHA/checksum requirement was confirmed in the configured IL. MD5 hits belong to image/RTF or auth digest areas, not the offline file-send path. |
## Evidence excerpts
### IMPP.Client.OffLineFileSend.sendFile
Classification: `confirmed_signature`; phase: `upload`; matches: 3.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826149` | `signature_continuation` | `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:824164` | `callsite` | `IL_026b: callvirt instance void IMPP.Client.OffLineFileSend::sendFile()` | `` |
### IMPP.Client.OffLineFileSend.trans_UploadCompleted
Classification: `confirmed_signature`; phase: `upload_to_message_boundary`; matches: 3.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826888` | `signature_continuation` | `trans_UploadCompleted(string fileId) cil managed` | `L826887: .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` | `` |
| `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` |
### IMPP.Service.BLL.FileTransfer.FileUpload
Classification: `confirmed_signature`; phase: `upload`; matches: 17.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:851` | `signature_continuation` | `FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L849: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:870` | `method_end` | `} // end of method FileTransfer::FileUpload` | `L849: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:873` | `signature_continuation` | `instance void AsynFileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L872: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:164` | `method_end` | `} // end of method IFileTransfer::FileUpload` | `L160: .method public hidebysig newslot abstract virtual` |
| `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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L608722: .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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679721` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699952` | `callsite` | `IL_024c: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738959` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:739560` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L739470: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:790010` | `callsite` | `IL_018b: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826414` | `callsite` | `IL_02b6: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:2852` | `reference` | `} // end of property FileTransfer::FileUploadMaxCount` | `L2825: .method family hidebysig newslot virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:2861` | `reference` | `} // end of property FileTransfer::FileUploadCount` | `L2825: .method family hidebysig newslot virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:186` | `reference` | `} // end of property IFileTransfer::FileUploadMaxCount` | `L177: .method public hidebysig newslot abstract virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:205` | `reference` | `} // end of property IFileTransfer::FileUploadCount` | `L177: .method public hidebysig newslot abstract virtual` |
### IMPP.Service.BLL.FileTransfer.AsynFileUpload
Classification: `confirmed_signature`; phase: `upload`; matches: 3.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:873` | `signature_continuation` | `instance void AsynFileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L872: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:883` | `method_end` | `} // end of method FileTransfer::AsynFileUpload` | `L872: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:169` | `method_end` | `} // end of method IFileTransfer::AsynFileUpload` | `L166: .method public hidebysig newslot abstract virtual` |
### FileUploadPara
Classification: `confirmed_signature`; phase: `upload_parameters`; matches: 66.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:851` | `signature_continuation` | `FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L849: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:873` | `signature_continuation` | `instance void AsynFileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L872: .method public hidebysig newslot virtual final` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:162` | `signature_continuation` | `FileUpload(class IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L160: .method public hidebysig newslot abstract virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:167` | `signature_continuation` | `instance void AsynFileUpload(class IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara para) cil managed` | `L166: .method public hidebysig newslot abstract virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1139` | `type_definition` | `.class public auto ansi serializable beforefieldinit IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara` | `L1086: .method family hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1155` | `method_end` | `} // end of method FileUploadPara::get_IsImg` | `L1146: .method public hidebysig specialname instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1167` | `method_end` | `} // end of method FileUploadPara::set_IsImg` | `L1157: .method private hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1178` | `method_end` | `} // end of method FileUploadPara::get_IsPublic` | `L1169: .method public hidebysig specialname instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1190` | `method_end` | `} // end of method FileUploadPara::set_IsPublic` | `L1180: .method public hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1234` | `method_end` | `} // end of method FileUploadPara::.ctor` | `L1192: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1263` | `method_end` | `} // end of method FileUploadPara::.ctor` | `L1236: .method public hidebysig specialname rtspecialname` |
| `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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `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: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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L608722: .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` |
### FileUploadResult.FileID
Classification: `confirmed_signature`; phase: `upload_result`; matches: 75.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il:982` | `method_header` | `.method private hidebysig instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult` | `L982: .method private hidebysig instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1277` | `type_definition` | `.class public auto ansi serializable beforefieldinit IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult` | `L1236: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1307` | `method_end` | `} // end of method FileUploadResult::.ctor` | `L1284: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1318` | `method_end` | `} // end of method FileUploadResult::get_FileID` | `L1309: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1330` | `method_end` | `} // end of method FileUploadResult::set_FileID` | `L1320: .method private hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1341` | `method_end` | `} // end of method FileUploadResult::get_Url` | `L1332: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:1353` | `method_end` | `} // end of method FileUploadResult::set_Url` | `L1343: .method private hidebysig specialname 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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `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: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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `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: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.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608940` | `callsite` | `IL_00f3: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679721` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679747` | `callsite` | `IL_00f4: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699952` | `callsite` | `IL_024c: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699993` | `callsite` | `IL_02bf: 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:738959` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara)` | `L738869: .method private hidebysig instance void` |
### MessageScheduling.SendFileMessage
Classification: `confirmed_signature`; phase: `message`; matches: 3.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153803` | `signature_continuation` | `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:1154125` | `method_end` | `} // end of method MessageScheduling::SendFileMessage` | `` |
| `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,` | `` |
### Chat.sendFileMessage
Classification: `confirmed_signature`; phase: `message`; matches: 8.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1235` | `signature_continuation` | `sendFileMessage(string p_message,` | `L1233: .method public hidebysig newslot abstract virtual` |
| `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` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21442` | `signature_continuation` | `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` | `signature_continuation` | `sendFileMessage(string p_message,` | `L30069: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30119` | `method_end` | `} // end of method ChatRoom::sendFileMessage` | `L30069: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` |
| `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:1153922` | `callsite` | `IL_00f1: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::sendFileMessage(string,` | `L1153802: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` |
### Required values: path id size target jid
Classification: `confirmed_signature`; phase: `requirements`; matches: 550.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:611789` | `method_end` | `} // end of method RosterContactsArgs::get_RosterJid` | `L611780: .method public hidebysig specialname instance class [smack]com.vision.smack.Jid` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:670956` | `type_definition` | `.class public auto ansi beforefieldinit IMPP.Client.Business.Authentication.UnifiedAuthenticationCenter` | `L670876: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:671260` | `method_end` | `} // end of method UnifiedAuthenticationCenter::Authentication` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:671331` | `method_end` | `} // end of method UnifiedAuthenticationCenter::GetServerTimeSpan` | `L671262: .method public hidebysig instance valuetype [mscorlib]System.TimeSpan` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:671390` | `method_end` | `} // end of method UnifiedAuthenticationCenter::ConvertStringToDateTime` | `L671333: .method private hidebysig instance valuetype [mscorlib]System.DateTime` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:671406` | `method_end` | `} // end of method UnifiedAuthenticationCenter::InitServiceManager` | `L671392: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:671416` | `method_end` | `} // end of method UnifiedAuthenticationCenter::.ctor` | `L671408: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:723604` | `method_end` | `} // end of method FileTransferArgs::get_LocalFilePath` | `L723595: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:723650` | `method_end` | `} // end of method FileTransferArgs::get_RemoteFolder` | `L723641: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:723876` | `method_end` | `} // end of method RosterContactsGroupArgs::get_RosterJid` | `L723867: .method public hidebysig specialname instance class [smack]com.vision.smack.Jid` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:767951` | `method_end` | `} // end of method ServerInfo::set_HTTPFileServer` | `L767941: .method public hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:767962` | `method_end` | `} // end of method ServerInfo::get_HTTPFileServer` | `L767953: .method public hidebysig specialname instance class IMPP.Client.Server` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:768272` | `method_end` | `} // end of method BaseConfig::UnifiedAuthenticationAddress` | `L768241: .method public hidebysig instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826017` | `method_end` | `} // end of method OffLineFileSend::get__localFilePath` | `L826008: .method private hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:826109` | `method_end` | `} // end of method OffLineFileSend::get__fileSize` | `L826100: .method private hidebysig specialname instance int64` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1339551` | `method_end` | `} // end of method OffLineFileRecv::get__fileSize` | `L1339542: .method private hidebysig specialname instance int64` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il:477` | `method_end` | `} // end of method FileTransferParaBase::get_LocalFilePath` | `L468: .method public hidebysig specialname instance string` |
| `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,` | `` |
## Inference
- High confidence: upload and file-message finalization are separate steps.
- High confidence: `FileUploadPara` needs HTTP file server host/port/domain plus local file path and upload options.
- High confidence: `Chat.sendFileMessage` produces the XMPP file-message envelope after file metadata is available.
- Medium confidence: B-route file send must either call the same logged-in service/runtime or reproduce the authenticated HTTP upload plus XMPP file-message sequence.
- Low confidence until bridge evidence: an external sidecar can obtain the same service/auth/chat objects without being inside the logged-in client process.
## Decision
Offline static evidence supports B-route research, but file sending needs more than one method call: upload first, then chat file-message finalization. The next blocker is reachability: whether an IPC/plugin/in-process bridge can access the logged-in `IFileTransfer` service and smack `Chat` object.
## Next work
1. Extract bridge/IPC/plugin candidates before coding any file-send adapter.
2. If a bridge exists, prototype non-mutating discovery first: service availability, chat object lookup, and upload endpoint metadata only.
3. Keep A-route/RPA backup-only.

View File

@@ -0,0 +1,149 @@
# B-Route Text Send Static Map
Date: 2026-07-12
## Scope
This report uses offline IL only. It does not log in, send messages, replay traffic, inject into a process, or mutate the original iSphere binaries.
Machine-readable evidence: `runs/offline-broute-reverse/text-send-map.json`
## Sources
| Source | Role | Exists | Lines | Size bytes |
| --- | --- | --- | ---: | ---: |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main managed client IL; chat UI, AppContextManager, scheduling call sites | yes | 1360035 | 74148460 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | XMPP/smack managed IL; Chat and XMPPConnection implementation | yes | 87425 | 5019807 |
## Target classification
| Target | Intent | Classification | Matches |
| --- | --- | --- | ---: |
| `AppContextManager.SendTxtMessageByJid` | high-level text send entry exposed by AppContextManager | `confirmed_signature` | 4 |
| `MessageScheduling.SendChatMessage` | message scheduling text/chat send helper | `confirmed_signature` | 6 |
| `Chat.SendMessage` | smack Chat send API used by chat/UI code | `confirmed_signature` | 16 |
| `XMPPConnection.send` | lowest-level XMPP connection send primitive | `confirmed_signature` | 105 |
| `MessageCenter send-related callbacks` | MessageCenter or IMPPManager message-center callbacks touching send/message flow | `confirmed_signature` | 962 |
## Verified facts
- `AppContextManager.SendTxtMessageByJid` appears in the offline client IL and is not just a UIA/RPA artifact.
- `MessageScheduling.SendChatMessage` appears in the offline client IL and has call-site evidence around chat-message flow.
- `Chat.SendMessage` / `Chat.sendMessage` appears as a smack chat API used by client code.
- `XMPPConnection.send` appears as a lower-level connection send primitive in offline IL.
- `MessageCenter send-related callbacks` appear as MessageCenter/GetMessageCenter references, but offline static evidence alone does not prove an external bridge can call them.
## Evidence excerpts
### AppContextManager.SendTxtMessageByJid
Classification: `confirmed_signature`; matches: 4.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `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` |
| `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:542112` | `string_literal` | `IL_09bf: ldstr "SendTxtMessageByJid"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1358068` | `string_literal` | `IL_0c3f: ldstr "SendTxtMessageByJid"` | `` |
### MessageScheduling.SendChatMessage
Classification: `confirmed_signature`; matches: 6.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `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:1154225` | `method_end` | `} // end of method MessageScheduling::SendChatMessage` | `` |
| `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: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: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:1154128` | `reference` | `SendChatMessage(class IMPP.Client.Business.RosterContacts.RosterContactsArgs rosterArgs,` | `L1154127: .method public hidebysig static class [smack]com.vision.smack.packet.XmppMessage` |
### Chat.SendMessage
Classification: `confirmed_signature`; matches: 16.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1220` | `method_end` | `} // end of method Chat::sendMessage` | `L1217: .method public hidebysig newslot abstract virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1231` | `method_end` | `} // end of method Chat::sendMessage` | `L1222: .method public hidebysig newslot abstract virtual` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1425` | `method_end` | `} // end of method Chat::SendMessage` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1266` | `callsite` | `IL_0021: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L1246: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21393` | `callsite` | `IL_0047: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L21362: .method public hidebysig virtual instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21431` | `callsite` | `IL_002b: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L21398: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:21482` | `callsite` | `IL_003a: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `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:29958` | `callsite` | `IL_0047: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L29927: .method public hidebysig virtual instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30063` | `callsite` | `IL_0064: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L30012: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30115` | `callsite` | `IL_0056: call instance class com.vision.smack.packet.XmppMessage com.vision.smack.Chat::SendMessage(class com.vision.smack.packet.XmppMessage)` | `L30069: .method public hidebysig virtual instance class com.vision.smack.packet.XmppMessage` |
| `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: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:739211` | `callsite` | `IL_012c: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::sendMessage(string,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:739789` | `callsite` | `IL_012c: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::sendMessage(string,` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1153743` | `callsite` | `IL_01d0: callvirt instance class [smack]com.vision.smack.packet.XmppMessage [smack]com.vision.smack.Chat::SendMessage(class [smack]com.vision.smack.packet.XmppMessage)` | `` |
### XMPPConnection.send
Classification: `confirmed_signature`; matches: 105.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:86319` | `method_end` | `} // end of method XMPPConnection::send` | `L86263: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:1378` | `callsite` | `IL_00bc: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:17710` | `callsite` | `IL_004a: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L17649: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:23187` | `callsite` | `IL_004b: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L23150: .method public hidebysig instance class com.vision.smack.disco.DiscoInfoResponse` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:23248` | `callsite` | `IL_002c: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L23220: .method public hidebysig virtual instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:23962` | `callsite` | `IL_0110: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:26786` | `callsite` | `IL_004e: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L26752: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:26855` | `callsite` | `IL_008b: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L26790: .method public hidebysig instance class [mscorlib]System.Collections.Generic.IList`1<class com.vision.smack.muc.BookMarkConfenerce>` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:26980` | `callsite` | `IL_008a: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L26919: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:29230` | `callsite` | `IL_00a2: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L29148: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:29470` | `callsite` | `IL_007d: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L29404: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:29690` | `callsite` | `IL_0053: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L29646: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:29841` | `callsite` | `IL_00b2: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L29766: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:29918` | `callsite` | `IL_0033: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L29894: .method public hidebysig virtual instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30152` | `callsite` | `IL_003c: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L30121: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30178` | `callsite` | `IL_0023: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L30159: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30221` | `callsite` | `IL_0046: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L30182: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il:30268` | `callsite` | `IL_004d: callvirt instance void com.vision.smack.XMPPConnection::send(string)` | `L30225: .method public hidebysig instance void` |
### MessageCenter send-related callbacks
Classification: `confirmed_signature`; matches: 962.
| Source line | Kind | Snippet | Method context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:74199` | `method_end` | `} // end of method MessageCenter::add_OnMessageSended` | `L74135: .method public hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:74265` | `method_end` | `} // end of method MessageCenter::remove_OnMessageSended` | `L74201: .method public hidebysig specialname instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:75658` | `method_end` | `} // end of method MessageCenter::pChat_OnMessageSended` | `L75587: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:82645` | `method_end` | `} // end of method MessageCenter::SendPluginsOffLineMessage` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:206380` | `method_end` | `} // end of method AVRoomMessageCenter::Send` | `L206369: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:945209` | `method_header` | `.method public hidebysig instance class IMPP.Client.control.MessageCenter` | `L945209: .method public hidebysig instance class IMPP.Client.control.MessageCenter` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:945695` | `method_header` | `.method public hidebysig specialname instance class IMPP.Client.control.MessageCenter` | `L945695: .method public hidebysig specialname instance class IMPP.Client.control.MessageCenter` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72786` | `callsite` | `IL_0005: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72779: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72787` | `callsite` | `IL_000a: callvirt instance int32 IMPP.Client.control.MessageCenter::GetChatMessageCount()` | `L72779: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72814` | `callsite` | `IL_000b: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72820` | `callsite` | `IL_001c: callvirt instance void IMPP.Client.control.MessageCenter::add_OnMessageArrived(class IMPP.Client.control.MessageCenter/MessageArrivedHandler)` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72822` | `callsite` | `IL_0026: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72827` | `callsite` | `IL_0037: callvirt instance void IMPP.Client.control.MessageCenter::add_OnMessageConsumed(class IMPP.Client.control.MessageCenter/MessageConsumedHandler)` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72829` | `callsite` | `IL_0041: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72835` | `callsite` | `IL_0052: callvirt instance void IMPP.Client.control.MessageCenter::add_UpdateUnreadMessageCount(class IMPP.Client.control.MessageCenter/UpdateUnreadMessageCountHandler)` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72837` | `callsite` | `IL_005c: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72842` | `callsite` | `IL_006d: callvirt instance void IMPP.Client.control.MessageCenter::add_TcpFileToOffline(class [mscorlib]System.Action`1<class [smack]com.vision.smack.packet.XmppMessage>)` | `L72806: .method public hidebysig specialname rtspecialname` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:72844` | `callsite` | `IL_0077: callvirt instance class IMPP.Client.control.MessageCenter IMPP.Client.IMPPManager::GetMessageCenter()` | `L72806: .method public hidebysig specialname rtspecialname` |
## Inference
- High confidence: text sending has an internal managed call path that reaches smack chat/connection send APIs.
- Medium confidence: the likely chain is high-level AppContextManager or UI chat code -> MessageScheduling/frmP2PChat -> smack Chat.SendMessage/sendMessage -> XMPPConnection.send.
- Low confidence until live/runtime evidence: an external sidecar can invoke this path without being inside the logged-in process.
## Decision
B-route text send remains plausible only if a bridge can enter the logged-in runtime or an existing IPC/API exposes the same call. Offline IL confirms call shape, but not runtime invocability.
## Next work
1. Extract file-send/upload call graph and separate upload from chat-message finalization.
2. Extract bridge/IPC/plugin candidates to see whether the send call path is reachable without RPA.
3. Keep A-route/RPA as backup-only; do not promote it unless B-route bridge evidence fails.

View File

@@ -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.

View File

@@ -0,0 +1,105 @@
# Login Reachability Probe Package
Date: 2026-07-12
## Business purpose
This package turns the login validation schema into an operator-runnable package for the 2026-07-13 logged-in environment.
It is for B-route evidence collection. It does not enable production send.
## Generated artifacts
- Package script: `scripts/package-login-reachability-probe.ps1`
- Verification script: `scripts/verify-login-reachability-probe-package.ps1`
- Package directory: `runs/login-reachability-probe-package`
- Package zip: `runs/login-reachability-probe-package.zip`
- Downloads copy: `C:\Users\zhaoy\Downloads\login-reachability-probe-package-20260712-140706.zip`
## What the package contains
- `recorder/ISphereLiveProbeRecorder.exe`
- `tools/isphere-capability-smoke.exe`
- `LOGIN-REACHABILITY-INPUTS.template.json`
- `LOGIN-REACHABILITY-INPUTS.schema.json`
- `TODO-COVERAGE.md`
- `CREATE-RETURN-ZIP.ps1`
- `RUN-LOGIN-REACHABILITY-SUITE.bat`
- numbered operator steps:
- `00-prepare-inputs.bat`
- `01-run-before-recorder.bat`
- `02-run-after-text-recorder.bat`
- `03-run-after-file-recorder.bat`
- `04-create-return-zip.bat`
- copied reference docs:
- `docs/login-reachability-validation-items.md`
- `docs/send-upload-deep-dive.md`
## Operator flow
1. Run only on a machine where iSphere/IMPlatformClient is visibly logged in.
2. Fill `LOGIN-REACHABILITY-INPUTS.json` from the template.
3. Run before-recorder.
4. If text test is enabled, manually send exactly one text message in the official client, then run after-text-recorder.
5. If file test is enabled, manually send exactly one safe small file in the official client, then run after-file-recorder.
6. Run `CREATE-RETURN-ZIP.ps1` or `04-create-return-zip.bat`.
7. Return `isphere-login-reachability-return-*.zip`.
## Required returned schema
The return script writes `LOGIN-REACHABILITY-OUTPUT.json` with these top-level sections:
- `run`
- `targets`
- `runtime`
- `reachability`
- `server_auth`
- `snapshots`
- `attempts`
- `failures`
- `correlation`
## Safety and route status
- `NO_AUTOMATIC_SEND=true`: the package does not send text or files automatically.
- `production_send_enabled=false`
- `production_file_send_enabled=false`
- A-route/RPA remains `backup_only`.
- B-route remains blocked until returned evidence proves logged-in reachability and sent-record/ack correlation.
## Verification
Fresh verification command:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-login-reachability-probe-package.ps1
```
Verified result:
```json
{
"ok": true,
"required_file_count": 22,
"synthetic_return_verified": true,
"online_login_required": true,
"no_automatic_send": true,
"production_send_enabled": false,
"production_file_send_enabled": false
}
```
## Remaining TODO coverage completed
The package now includes the remaining validation TODO fields:
- `runtime_observations`: AppContextManager, MessageScheduling, Chat/XMPP, FileUploadPara, IFileTransfer, FileUploadResult/FileID, and send-file-message finalization evidence or structured failure.
- `group_probe`: group ChatRoom branch and speech/upload permission evidence or structured failure.
- `fallback_a_route`: HWND, `rtbSendMessage`, `btnSend`, file menu evidence, or structured failure when B-route fails.
- `TODO-COVERAGE.md`: maps every P0/P1 validation item to the exact package field or generated evidence path.
## Next decision after returned zip
- If text evidence includes one-shot target, before/after sent-record source, content hash, and ack/ref correlation, move text B-route from contract/probe toward production connector design.
- If file evidence includes FileUploadPara/server/auth data, IFileTransfer reachability, FileUploadResult/FileID or structured failure, and file sent-record/ack correlation, move file B-route to upload connector design.
- If reachability fails with structured reasons, continue offline reverse against the failed step.

View File

@@ -0,0 +1,129 @@
# Login Reachability Validation Items
Date: 2026-07-12
Purpose: this is the operator-facing checklist for the 2026-07-13 logged-in environment. It is generated from the offline send/upload deep dive and should be used to build the one-shot reachability probe package. P0 items are blocking; production send remains disabled until all relevant P0 evidence is collected and correlated.
## Operator rules
- Run the probe only after the target iSphere/IMPlatformClient session is visibly logged in.
- Use a pre-agreed direct test JID and optional group test JID; record them in the output JSON.
- Use one-shot test content and one safe small test file; record SHA256 hashes, not raw sensitive content.
- Capture before/after sent-record snapshots around the one-shot send/upload test.
- Do not mark production ready unless ack/sent-record correlation is machine-verifiable.
## P0 items
### Define one-shot test targets and operator confirmation
- Category: test_rule
- Evidence to capture: direct JID, optional group JID, self-send/sandbox-account flag, operator confirmation, one-send-only flag, test content/file hash seed
- Unlocks: reliable ack and sent-record correlation
### Capture before/after sent-record snapshots
- Category: snapshot
- Evidence to capture: before count/last summary, after count/last summary, target ref, content hash or file hash, timestamp window
- Unlocks: machine-verifiable send result
### Identify sent-record and ack source paths
- Category: sent_record_source
- Evidence to capture: MessageCenter::OnMessageSended availability, PacketReader/SaveToDB/MsgLib source availability, MCP audit ref, ack/ref id if present
- Unlocks: production gate evidence
### Confirm in-process adapter reachability mode
- Category: adapter_reachability
- Evidence to capture: process bitness, CLR/.NET version, user/session id, loaded managed assemblies, same-process/managed-harness/injection requirement, stop-condition reason if blocked
- Unlocks: B-route implementation decision
### Confirm logged-in IMPlatformClient.exe process and loaded assemblies
- Category: runtime
- Evidence to capture: process id, module list, loaded managed assemblies, login/user presence without leaking credentials
- Unlocks: all B-route adapter tests
### Confirm AppContextManager/IAppContextManager reachability
- Category: runtime
- Evidence to capture: type visible, instance path, SendTxtMessageByJid callable shape, direct/group chat type mapping
- Unlocks: text send high-level path
### Confirm Chat/XMPPConnection authenticated state
- Category: runtime
- Evidence to capture: Chat instance, XMPPConnection state, target JID mapping, group ChatRoom branch if target is group
- Unlocks: text and file message finalization
### Capture FileUploadPara required values without leaking token
- Category: file_upload
- Evidence to capture: host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only, timeout/cache flags if visible
- Unlocks: upload_file probe
### Confirm IFileTransfer/FileTransfer.FileUpload reachability
- Category: file_upload
- Evidence to capture: service instance or constructor path, method signature, safe call readiness, HTTP status/failure channel mapping
- Unlocks: file upload
### Confirm FileUploadResult.FileID after safe test upload
- Category: file_upload_result
- Evidence to capture: FileID present, size/name or URL/remote folder metadata, HTTP status, service error code/message if upload fails
- Unlocks: send_file_message
### Confirm trans_UploadCompleted/SendFileMessage consumes FileID
- Category: send_file_message
- Evidence to capture: FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack, failure reason if target/permission blocks
- Unlocks: production file send
### Capture structured failure reasons for every probe step
- Category: failure_reason
- Evidence to capture: step name, exception type, error code, message, offline/permission/target-not-found/token/file-size/file-type/network-timeout classification
- Unlocks: actionable next decision when probe fails
### Correlate sent record/ack with content hash or file hash
- Category: ack
- Evidence to capture: sent record source, timestamp, target ref, body/file metadata hash, ack/ref id, before/after snapshot diff
- Unlocks: production gate
## P1 items
### Confirm group ChatRoom branch and permissions
- Category: group
- Evidence to capture: ChatRoom type, speech/upload permission state, group JID, mute/permission failure reason
- Unlocks: group send/file send
### If B-route reachability fails, capture A-route UI evidence
- Category: fallback
- Evidence to capture: window hwnd, rtbSendMessage, btnSend, screenshots, failure reason
- Unlocks: demo fallback only
## Required output schema
Every probe run should emit JSON with these top-level sections:
- `run`: timestamp, machine, operator confirmation, one-shot flags.
- `targets`: direct JID, optional group JID, target type, source of target selection.
- `runtime`: process id, bitness, CLR/.NET version, user/session, loaded assemblies.
- `reachability`: AppContextManager, MessageScheduling, Chat, XMPPConnection, IFileTransfer, FileUploadPara, FileUploadResult, Chat.sendFileMessage.
- `server_auth`: host, port, domain, token_present, token_hash_prefix only, accessToken/clientId presence when visible.
- `snapshots`: before/after counts and last-record summaries for sent-record sources.
- `attempts`: probe-only, optional one-shot text, optional safe upload, optional file-message finalization.
- `failures`: structured failure code, exception type, message, classification, next action.
- `correlation`: content/file hash match, target match, timestamp window, ack/ref id.
## Pass criteria
- Text send can move forward when logged-in runtime exposes AppContextManager or MessageScheduling plus Chat/XMPPConnection and sent-record/ack correlation is possible.
- File send can move forward when logged-in runtime exposes IFileTransfer/FileUpload, FileUploadPara values, FileUploadResult.FileID, and Chat.sendFileMessage finalization evidence.
- Production remains blocked if any P0 item is missing, if failure reasons are unstructured, or if only static evidence is available.
- Text production can move forward only when one-shot target, before/after snapshot, sent-record source, and content-hash/ack correlation all pass.
- File production can move forward only when FileUploadPara values, IFileTransfer reachability, FileUploadResult.FileID, file-message finalization, and file sent-record/ack correlation all pass.

View File

@@ -0,0 +1,65 @@
# Offline B-Route Reverse Decision
Date: 2026-07-12
Branch: `codex/offline-broute-reverse`
## Current phase / 当前阶段
Offline reverse engineering for the primary B-route is complete for the current evidence set. The goal was to decide whether B-route can continue through an existing IPC/plugin/local API, or whether it must move to an in-process adapter research branch.
## Inputs / 输入证据
| Evidence | Path |
| --- | --- |
| Offline sample index | `docs/source-discovery/2026-07-12-offline-broute-reverse-index.md` |
| Text send static map | `docs/source-discovery/2026-07-12-broute-text-send-static-map.md` |
| File send static map | `docs/source-discovery/2026-07-12-broute-file-send-static-map.md` |
| Bridge/IPC/plugin static map | `docs/source-discovery/2026-07-12-broute-bridge-static-map.md` |
| Machine JSON outputs | `runs/offline-broute-reverse/*.json` |
## Verified facts / 已验证事实
1. The offline sample set is present and hash-matched against the recorded plan list; the analyzer scripts only read metadata/IL and did not copy or modify binaries.
2. Text send has confirmed static call-path evidence:
- `AppContextManager.SendTxtMessageByJid`
- `MessageScheduling.SendChatMessage`
- `Chat.SendMessage` / `Chat.sendMessage`
- `XMPPConnection.send`
3. File send has confirmed two-step evidence:
- upload first through `OffLineFileSend.sendFile`, `FileUploadPara`, and `IFileTransfer.FileUpload` / `IMPP.Service.BLL.FileTransfer.FileUpload`;
- then chat file-message finalization through `trans_UploadCompleted(fileId)`, `MessageScheduling.SendFileMessage`, and `Chat.sendFileMessage`.
4. `FileUploadResult.FileID` / remote-folder metadata is required before the chat file message is meaningful.
5. The static bridge scan found no confirmed existing IPC/plugin/local HTTP route that exposes text-send or file-send.
6. `HttpServerLib` exists, but the discovered `frmLogin.StartWinServer` path depends on logged-in runtime state and no send route was found.
7. `PluginLightAppMulProcessCommunication` declares a `NamedPipeServerStream`, but its start method returns immediately.
8. Returned live probe saw `\\.\pipe\zfpinject-msg-server`, but no matching iSphere static send contract was found.
## Decision / 决策
| Candidate | Decision | Reason |
| --- | --- | --- |
| `existing_ipc_first` | rejected for now | No concrete local HTTP/named-pipe/service send API was confirmed. |
| `plugin_extension_first` | rejected for now | Plugin evidence is UI/app-store/context-menu oriented; no local plugin load/send bridge is confirmed. |
| `in_process_adapter_research` | selected | The send and file-send call paths exist, but they need access to the logged-in `IMPlatformClient.exe` runtime objects. |
| `external_sidecar_preview_only` | allowed | External sidecar can validate contracts/probes, but cannot reuse logged-in static runtime by itself. |
| `fallback_rpa_only` | not selected | A-route/RPA remains backup-only; do not promote it unless B-route is explicitly blocked by a later decision. |
Final offline decision: **B-route stays primary, but the next real branch is `in_process_adapter_research`, not existing IPC/plugin and not production send.**
## Business impact / 业务影响
- Message receiving, file receiving/listing, contact search, and group search stay on the existing data/log-backed roadmap.
- Text send is technically mapped but not business-complete: the missing piece is a bridge into logged-in runtime state and later online ack/sent-record validation.
- File send is harder than text send: upload and chat-message finalization are separate, and upload needs HTTP file-service auth plus server-issued file id.
- RPA remains a practical backup for UI smoke, but it is not the product architecture.
## Next implementation slice / 下一轮
1. Create a dedicated in-process adapter research plan.
2. Keep any sidecar work preview/probe-only until an adapter path is selected.
3. Do not implement real `send_message`, `send_file`, or `upload_file` in this offline branch.
4. Online evidence later must prove sent-record/content-hash/ack before production send can be called complete.
## Stop conditions / 停止条件
Stop and ask for business decision if the next in-process research shows that every viable bridge requires invasive process mutation, unsupported injection, or cannot be validated without a logged-in test environment.

View File

@@ -0,0 +1,45 @@
# Offline B-Route Reverse Index
Date: 2026-07-12
## Scope
This index records the read-only offline samples for B-route reverse engineering. The script reads metadata and SHA256 hashes only; it does not copy or modify the original binaries.
## Summary
- Samples total: 12
- Samples present: 12
- Hash matches: 12
- Originals copied: false
- Originals modified: false
- Machine JSON: `runs/offline-broute-reverse/index.json`
## Sample table
| Sample | Role | Size | SHA256 match | SHA256 |
| --- | --- | ---: | --- | --- |
| `runs/offline-real-client-window/full/zyl/Impp/IMPlatformClient.exe` | main managed client; text send, chat window, plugin/IPC candidates | 8366592 | yes | `E2966E58360DAEEBF178410A961E2DC52748C63E9CCBD94BD6EC8434A1A09CB7` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Service.dll` | file upload service candidates | 21504 | yes | `F859DE2F34E024B5F372D95F22CBF8A018C780F24203E7A76D392E52BD90CADD` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Interface.dll` | service/interface contract candidates | 33792 | yes | `DD093CF61FAE85C2D2581F289B01AA477546712E098FEF81272FDD989E50D12D` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Model.dll` | model/parameter types | 35328 | yes | `7CBABDD23A7234D15E294C549EEEC78EFBAD6E957CD45A6E8A85309349A624A5` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.UI.dll` | UI/plugin helpers and possible send controls | 2401792 | yes | `4C61212519C01D1B731ED4F20DF3411C491616F4ADA98A4529722A6AA3689E6D` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Common.dll` | shared utility and message types | 479744 | yes | `02A47C99C27C9BFE2BADC438389300C92220B07609BD87C48B4B5E1B4EE6AEB4` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Helper.dll` | helper abstractions | 53248 | yes | `30932D082B6678699C832C63F923E01EAD84674FAEDB613D631E034E03742FB9` |
| `runs/offline-real-client-window/full/zyl/Impp/smack.dll` | XMPP chat/send layer | 370688 | yes | `BAD0BB0591765DB153B17CECC1112B0BBDBF3B1D3370DDF973F91974E92CEC66` |
| `runs/offline-real-client-window/full/zyl/Impp/TcpFileTransfer.dll` | native/transfer candidate | 45056 | yes | `6C4874B46D1E7DC04C9B6784180603452400B881E04509D464A0D58814EFEDA7` |
| `runs/offline-real-client-window/full/zyl/Impp/HttpServerLib.dll` | local API/IPC candidate | 26624 | yes | `FFDB633216AE332B8EDFFC83E2AE546B7A80144C659FF4053FDFE4FE382A8D12` |
| `runs/offline-real-client-window/full/zyl/Impp/INetwork.dll` | network abstraction candidate | 87552 | yes | `E40BE4EE2439E4280461F4D2BADB318A5F4572428F069AB6D17B4C4F0E8CFAC9` |
| `runs/offline-real-client-window/full/zyl/Impp/IOClientNetwork.dll` | network implementation candidate | 145920 | yes | `64CA231A614771325741A5F098E52EBF20F7190E339B64962DE2EDEDCFFFF904` |
## Verified facts
- All metadata came from local filesystem reads under the repository workspace.
- The expected primary B-route samples are present if Samples present equals Samples total.
- Hash matching only proves local file identity against this plan's recorded sample list; it does not prove runtime invocability.
## Next reverse targets
1. Text-send static call graph: SendTxtMessageByJid, MessageScheduling.SendChatMessage, Chat.SendMessage, XMPPConnection.send.
2. File-send/upload static call graph: OffLineFileSend.sendFile, FileTransfer.FileUpload, AsynFileUpload, sendFileMessage.
3. Bridge/IPC/plugin map: HttpServerLib, plugin loaders, local HTTP, named pipes, command-line switches, services.

View File

@@ -0,0 +1,440 @@
# Send / Upload Deep Dive
Date: 2026-07-12
## Business summary
Offline deep dive confirms the remaining work is not generic sending code. The business blocker is logged-in runtime reachability plus online proof. Text send needs reachable AppContextManager/MessageScheduling/Chat. File send needs upload parameters and server-issued FileUploadResult.FileID before Chat.sendFileMessage can be meaningful.
## Decision
| Question | Answer |
| --- | --- |
| Should work stop before login? | No |
| Highest-value offline work | Deepen send/upload decomposition and prepare login validation items |
| Can production send be enabled offline? | No |
| Next package | login reachability probe package |
## Sources
| Source | Role | Exists | Lines | Size bytes |
| --- | --- | --- | ---: | ---: |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il` | main client; high-level send, file-send orchestration, runtime auth/service state | True | 1360035 | 74148460 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\smack.dll.il` | Chat/XMPP send implementation and file-message primitive | True | 87425 | 5019807 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Service.dll.il` | file upload HTTP/service implementation | True | 3351 | 207786 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.ServiceBase.dll.il` | FileUploadPara/FileUploadResult/FileTransferParaBase DTO contracts | True | 1641 | 93585 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Interface.dll.il` | IAppContextManager/IFileTransfer interface contracts | True | 4429 | 227335 |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPP.Common.dll.il` | ServiceManager/Auth DTOs and common runtime state | True | 118343 | 5703293 |
## Deep-dive findings
| Item | Stage | Status | Evidence | Business meaning |
| --- | --- | --- | ---: | --- |
| `Text send high-level entry: AppContextManager.SendTxtMessageByJid` | `text_send` | `static_evidence_found` | 6 | Best business-level text-send candidate if reachable in logged-in runtime. |
| `Text send scheduling fallback: MessageScheduling.SendChatMessage` | `text_send` | `static_evidence_found` | 16 | Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist. |
| `Low-level text primitive: Chat.SendMessage -> XMPPConnection.send` | `text_send` | `static_evidence_found` | 20 | Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state. |
| `Upload parameter base: FileTransferParaBase` | `file_upload` | `static_evidence_found` | 20 | Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs. |
| `Upload DTO: FileUploadPara` | `file_upload` | `static_evidence_found` | 20 | Concrete upload request DTO; adds IsImg/IsPublic and invokes FileTransferParaBase constructor. |
| `Upload service: IFileTransfer/FileTransfer.FileUpload` | `file_upload` | `static_evidence_found` | 20 | Managed upload entry; returns FileUploadResult and internally writes multipart token/form data. |
| `Upload auth/server state: HTTPFileServer + Auth token` | `file_upload` | `static_evidence_found` | 20 | File upload depends on runtime server/auth state, not only a local file path. |
| `Upload result: FileUploadResult.FileID and remote metadata` | `file_upload_result` | `static_evidence_found` | 20 | Server-issued FileID is required before a chat file message is meaningful. |
| `File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage` | `send_file_message` | `static_evidence_found` | 20 | After upload succeeds, the client constructs offline file-transfer content and sends chat file message. |
| `Target resolution: JID -> Chat / ChatRoom` | `runtime_context` | `static_evidence_found` | 20 | Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ. |
| `Runtime owner: frmMain / IMPPManager / MessageCenter` | `runtime_context` | `static_evidence_found` | 20 | Likely owners of initialized logged-in state and message center callbacks. |
## What this adds to tomorrow's login validation
| Priority | Category | Validation item | Evidence to capture | Unlocks |
| --- | --- | --- | --- | --- |
| P0 | test_rule | Define one-shot test targets and operator confirmation | direct JID, optional group JID, self-send/sandbox-account flag, operator confirmation, one-send-only flag, test content/file hash seed | reliable ack and sent-record correlation |
| P0 | snapshot | Capture before/after sent-record snapshots | before count/last summary, after count/last summary, target ref, content hash or file hash, timestamp window | machine-verifiable send result |
| P0 | sent_record_source | Identify sent-record and ack source paths | MessageCenter::OnMessageSended availability, PacketReader/SaveToDB/MsgLib source availability, MCP audit ref, ack/ref id if present | production gate evidence |
| P0 | adapter_reachability | Confirm in-process adapter reachability mode | process bitness, CLR/.NET version, user/session id, loaded managed assemblies, same-process/managed-harness/injection requirement, stop-condition reason if blocked | B-route implementation decision |
| P0 | runtime | Confirm logged-in IMPlatformClient.exe process and loaded assemblies | process id, module list, loaded managed assemblies, login/user presence without leaking credentials | all B-route adapter tests |
| P0 | runtime | Confirm AppContextManager/IAppContextManager reachability | type visible, instance path, SendTxtMessageByJid callable shape, direct/group chat type mapping | text send high-level path |
| P0 | runtime | Confirm Chat/XMPPConnection authenticated state | Chat instance, XMPPConnection state, target JID mapping, group ChatRoom branch if target is group | text and file message finalization |
| P0 | file_upload | Capture FileUploadPara required values without leaking token | host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only, timeout/cache flags if visible | upload_file probe |
| P0 | file_upload | Confirm IFileTransfer/FileTransfer.FileUpload reachability | service instance or constructor path, method signature, safe call readiness, HTTP status/failure channel mapping | file upload |
| P0 | file_upload_result | Confirm FileUploadResult.FileID after safe test upload | FileID present, size/name or URL/remote folder metadata, HTTP status, service error code/message if upload fails | send_file_message |
| P0 | send_file_message | Confirm trans_UploadCompleted/SendFileMessage consumes FileID | FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack, failure reason if target/permission blocks | production file send |
| P0 | failure_reason | Capture structured failure reasons for every probe step | step name, exception type, error code, message, offline/permission/target-not-found/token/file-size/file-type/network-timeout classification | actionable next decision when probe fails |
| P0 | ack | Correlate sent record/ack with content hash or file hash | sent record source, timestamp, target ref, body/file metadata hash, ack/ref id, before/after snapshot diff | production gate |
| P1 | group | Confirm group ChatRoom branch and permissions | ChatRoom type, speech/upload permission state, group JID, mute/permission failure reason | group send/file send |
| P1 | fallback | If B-route reachability fails, capture A-route UI evidence | window hwnd, rtbSendMessage, btnSend, screenshots, failure reason | demo fallback only |
## Evidence by item
### Text send high-level entry: AppContextManager.SendTxtMessageByJid
Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 6.
Business meaning: Best business-level text-send candidate if reachable in logged-in runtime.
Must verify tomorrow:
- Reach AppContextManager instance
- Confirm target JID/chat type mapping
- Invoke dry/probe path without send first
- Correlate sent record/ack after real send test
| 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,` |
### Text send scheduling fallback: MessageScheduling.SendChatMessage
Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 16.
Business meaning: Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist.
Must verify tomorrow:
- Locate or construct RosterContactsArgs
- Locate Chat instance
- Confirm direct/group branch
- Correlate sent record/ack
| 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` | `property` | `.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` | `property` | `.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` |
### Low-level text primitive: Chat.SendMessage -> XMPPConnection.send
Stage: `text_send`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state.
Must verify tomorrow:
- Locate Chat instance
- Locate authenticated XMPPConnection
- Confirm direct/group message payload
- Capture ack/sent-record
| 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` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:522012` | `callsite` | `IL_004c: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L521974: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:540102` | `callsite` | `IL_0109: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L539996: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:651133` | `callsite` | `IL_0136: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:651239` | `callsite` | `IL_0068: callvirt instance void [smack]com.vision.smack.XMPPConnection::send(string)` | `L651184: .method public hidebysig instance void` |
### Upload parameter base: FileTransferParaBase
Stage: `file_upload`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs.
Must verify tomorrow:
- Host
- Port
- Domain
- LocalFilePath
- Token
- Cache/timeout flags if present
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:12927` | `signature_continuation` | `instance int32 get_Port() cil managed` | `L12926: .method public hidebysig newslot specialname abstract virtual instance int32 get_Port() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:12981` | `reference` | `.get instance int32 NetFwTypeLib.INetFwOpenPort::get_Port()` | `L12962: .method public hidebysig newslot specialname abstract virtual instance void set_Enabled([in] bool Enabled) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13737` | `callsite` | `IL_01e1: callvirt instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileTransferParaBase::add_FileTransferNodity(class [mscorlib]System.EventHandler`1<class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileSer...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13918` | `callsite` | `IL_0046: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileTransferParaBase [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileTransferArgs::get_TransferPara()` | `L13878: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13919` | `callsite` | `IL_004b: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileTransferParaBase::get_LocalFilePath()` | `L13878: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14176` | `callsite` | `IL_0030: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `L14146: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14179` | `callsite` | `IL_003b: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `L14146: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:23389` | `callsite` | `IL_0200: callvirt instance string IMPP.Client.Server::get_Port()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:56075` | `reference` | `get_domain() cil managed` | `L56074: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:56183` | `reference` | `.get instance string IMPP.Client.Framework.Config.ConfigChatSizeModel::get_domain()` | `L56166: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:56238` | `reference` | `get_Domain() cil managed` | `L56237: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:56300` | `reference` | `.get instance string IMPP.Client.Framework.Config.ConfigDiscussModel::get_Domain()` | `L56283: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:59266` | `callsite` | `IL_00a9: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `L59183: .method public hidebysig static string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:59283` | `callsite` | `IL_00d9: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `L59183: .method public hidebysig static string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:59326` | `callsite` | `IL_0142: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:59356` | `callsite` | `IL_0195: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:78484` | `callsite` | `IL_2094: callvirt instance string IMPP.Client.Server::get_Domain()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:80366` | `callsite` | `IL_35a2: callvirt instance string [smack]com.vision.smack.packet.TCPManage.TCPResponseMsg::get_Port()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:80403` | `callsite` | `IL_361b: callvirt instance string [smack]com.vision.smack.packet.TCPManage.TCPResponseMsg::get_Port()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:94295` | `callsite` | `IL_0113: callvirt instance string [smack]com.vision.smack.Jid::get_Domain()` | `L94177: .method private hidebysig instance void` |
### Upload DTO: FileUploadPara
Stage: `file_upload`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Concrete upload request DTO; adds IsImg/IsPublic and invokes FileTransferParaBase constructor.
Must verify tomorrow:
- Constructor arguments
- IsImg
- IsPublic
- Token value
- Local file path normalization
| 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: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.ServiceBase.ModelBase.F...` | `` |
| `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: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.ServiceBase.ModelBase.F...` | `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: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.ServiceBase.ModelBase.F...` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679652` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_5,` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679711` | `constructor_call` | `IL_00a7: newobj instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::.ctor(string,` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679721` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699724` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_8,` | `L699710: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699942` | `constructor_call` | `IL_0234: 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:699952` | `callsite` | `IL_024c: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738881` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara V_5,` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738939` | `constructor_call` | `IL_0094: newobj instance void [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadPara::.ctor(string,` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738959` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `L738869: .method private hidebysig instance void` |
### Upload service: IFileTransfer/FileTransfer.FileUpload
Stage: `file_upload`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Managed upload entry; returns FileUploadResult and internally writes multipart token/form data.
Must verify tomorrow:
- Reach IFileTransfer instance
- Call FileUpload with safe test file
- Capture FileUploadResult
- Capture HTTP server/token fields without leaking token
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `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.ServiceBase.ModelBase.F...` | `` |
| `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: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: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.ServiceBase.ModelBase.F...` | `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: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: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.ServiceBase.ModelBase.F...` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608940` | `callsite` | `IL_00f3: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L608836: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679653` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_6,` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679721` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:679747` | `callsite` | `IL_00f4: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L679642: .method public hidebysig static void UploadGroupImage(string jid,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699725` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_9,` | `L699710: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699952` | `callsite` | `IL_024c: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:699993` | `callsite` | `IL_02bf: 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:738882` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_6)` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738959` | `callsite` | `IL_00bf: callvirt instance class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult [IMPP.ServiceBase]IMPP.ServiceBase.Interface.IFileTransfer::FileUpload(class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.F...` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:738963` | `callsite` | `IL_00c9: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L738869: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:739021` | `reference` | `IL_0067: castclass [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult` | `L738968: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:739022` | `callsite` | `IL_006c: callvirt instance string [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult::get_FileID()` | `L738968: .method private hidebysig instance void` |
### Upload auth/server state: HTTPFileServer + Auth token
Stage: `file_upload`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: File upload depends on runtime server/auth state, not only a local file path.
Must verify tomorrow:
- HTTPFileServer host/port
- UnifiedAuthentication/Auth token
- Domain/resource
- Access token/client id if present
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:137179` | `callsite` | `IL_01a0: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:138833` | `callsite` | `IL_018e: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:182525` | `callsite` | `IL_00ea: callvirt instance string IMPP.Client.BaseConfig::UnifiedAuthenticationAddress()` | `L182428: .method public hidebysig specialname static` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:182575` | `callsite` | `IL_0027: call class [IMPP.Common]IMPP.Common.Soap.Auth [IMPP.Common]IMPP.Common.ServiceManager::get_UnifiedAuthentication()` | `L182550: .method public hidebysig instance class IMPP.Client.Business.WorkGroupManage.WorkGroupOperate.Entity.PwebWorkGroups` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:182576` | `callsite` | `IL_002c: callvirt instance string [IMPP.Common]IMPP.Common.Soap.Auth::get_token()` | `L182550: .method public hidebysig instance class IMPP.Client.Business.WorkGroupManage.WorkGroupOperate.Entity.PwebWorkGroups` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:182641` | `callsite` | `IL_003a: call class [IMPP.Common]IMPP.Common.Soap.Auth [IMPP.Common]IMPP.Common.ServiceManager::get_UnifiedAuthentication()` | `L182600: .method public hidebysig instance class IMPP.Client.Business.WorkGroupManage.WorkGroupOperate.Entity.PwebWorkGroupMembers` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:182642` | `callsite` | `IL_003f: callvirt instance string [IMPP.Common]IMPP.Common.Soap.Auth::get_token()` | `L182600: .method public hidebysig instance class IMPP.Client.Business.WorkGroupManage.WorkGroupOperate.Entity.PwebWorkGroupMembers` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:253910` | `reference` | `+ "C_APP_001\",\"clientId\":\"imp_pc\",\"appId\":\"{2}\",\"orgId\":\"{3}\"}}"` | `L253873: .method public hidebysig static void AddBehavior(string pluginID) cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:258179` | `callsite` | `IL_00ea: callvirt instance string IMPP.Client.BaseConfig::UnifiedAuthenticationAddress()` | `L258082: .method public hidebysig specialname static` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:259663` | `callsite` | `IL_00da: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L259566: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:370968` | `callsite` | `IL_00ae: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L370891: .method private hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:371414` | `callsite` | `IL_01b7: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512436` | `callsite` | `IL_0459: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:512440` | `callsite` | `IL_046a: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:585181` | `callsite` | `IL_0005: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L585175: .method public hidebysig newslot virtual final instance string GetServerDomain() cil managed` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586215` | `callsite` | `IL_000e: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L586199: .method public hidebysig newslot virtual final instance class [mscorlib]System.Collections.Generic.List`1<string>` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586220` | `callsite` | `IL_0023: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L586199: .method public hidebysig newslot virtual final instance class [mscorlib]System.Collections.Generic.List`1<string>` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:586225` | `callsite` | `IL_0038: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L586199: .method public hidebysig newslot virtual final instance class [mscorlib]System.Collections.Generic.List`1<string>` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:604500` | `callsite` | `IL_0129: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:608772` | `callsite` | `IL_0063: callvirt instance class IMPP.Client.Server IMPP.Client.ServerInfo::get_HTTPFileServer()` | `L608722: .method private hidebysig instance void` |
### Upload result: FileUploadResult.FileID and remote metadata
Stage: `file_upload_result`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Server-issued FileID is required before a chat file message is meaningful.
Must verify tomorrow:
- FileID
- URL or remote folder if present
- size/name metadata
- failure code/message
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:365887` | `callsite` | `IL_028d: callvirt instance string [IMPP.Common]AppInfoDTO::get_url()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:388652` | `callsite` | `IL_002e: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `L388624: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413084` | `callsite` | `IL_00ff: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `L412984: .method public hidebysig instance bool` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413214` | `callsite` | `IL_0272: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:413504` | `callsite` | `IL_058d: callvirt instance string IMPP.Client.Business.ISphereAssistant.ISphereTabCtrlInfo::get_url()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427078` | `callsite` | `IL_0a5e: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427127` | `callsite` | `IL_0ace: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427502` | `callsite` | `IL_0e6d: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:427551` | `callsite` | `IL_0edb: callvirt instance string [IMPP.Common]IMPP.Common.HttpItem::get_URL()` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461320` | `reference` | `get_Url() cil managed` | `L461319: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461328` | `method_end` | `} // end of method AdvertiseImageInfo::get_Url` | `L461319: .method public hidebysig specialname instance string` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:461360` | `reference` | `.get instance string IMPP.Client.Business.AdvertisementManage.AdvertiseImageInfo::get_Url()` | `L461342: .method public hidebysig specialname rtspecialname instance void .ctor() cil managed` |
| `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.ServiceBase.ModelBase.F...` | `` |
| `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:564370` | `callsite` | `IL_064c: callvirt instance string [IMPP.Common]AppInfoDTO::get_url()` | `` |
| `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: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.ServiceBase.ModelBase.F...` | `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:608848` | `reference` | `class [IMPP.ServiceBase]IMPP.ServiceBase.ModelBase.FileServiceBase.FileUploadResult V_6,` | `L608836: .method private hidebysig instance void` |
### File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage
Stage: `send_file_message`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: After upload succeeds, the client constructs offline file-transfer content and sends chat file message.
Must verify tomorrow:
- trans_UploadCompleted receives FileID
- OFFLINE_FILE_TRANSFER payload fields
- Target Chat/JID
- Sent file record/ack
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:13650` | `string_literal` | `IL_010a: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:14612` | `string_literal` | `IL_00e6: ldstr "OFFLINE_FILE_TRANSFER"` | `L14529: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblPersonMsg` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15245` | `string_literal` | `IL_010f: ldstr "OFFLINE_FILE_TRANSFER"` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76219` | `string_literal` | `IL_05ec: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76335` | `string_literal` | `IL_0751: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76471` | `string_literal` | `IL_08ef: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:76792` | `string_literal` | `IL_0cae: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:78639` | `string_literal` | `IL_2267: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:83138` | `string_literal` | `IL_030d: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:86296` | `string_literal` | `IL_01a9: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:121988` | `string_literal` | `IL_09b1: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:122534` | `string_literal` | `IL_0fbe: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:122836` | `string_literal` | `IL_12de: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123116` | `string_literal` | `IL_15f3: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123656` | `string_literal` | `IL_1c15: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123706` | `string_literal` | `IL_1caa: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:123873` | `string_literal` | `IL_1e82: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:124349` | `string_literal` | `IL_23b0: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:125361` | `string_literal` | `IL_2e70: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:130922` | `string_literal` | `IL_01cf: ldstr "OFFLINE_FILE_TRANSFER"` | `` |
### Target resolution: JID -> Chat / ChatRoom
Stage: `runtime_context`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ.
Must verify tomorrow:
- Contact JID
- Group/conference JID
- ChatManager.GetChat
- ChatRoom branch and permissions
| Source | Kind | Snippet | Context |
| --- | --- | --- | --- |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:958` | `reference` | `.mresource public IMPP.Client.control.UCChatRoomMember.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:961` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.control.UCChatRoomMember.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1138` | `reference` | `.mresource public IMPP.Client.Business.ChatManager.BaseControl.frmChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1141` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Business.ChatManager.BaseControl.frmChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1173` | `reference` | `.mresource public IMPP.Client.Business.ChatManager.WorkGroup.frmReserveChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1176` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Business.ChatManager.WorkGroup.frmReserveChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1193` | `reference` | `.mresource public IMPP.Client.Forms.frmTempChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1196` | `reference` | `// 警告: 创建了托管资源文件 IMPP.Client.Forms.frmTempChatRoom.resources` | `` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1529` | `field` | `.field public string chatRoomJID` | `L1486: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:1574` | `reference` | `IL_0044: ldfld string IMPP.Client.VideoChat.SingleAVDispatcher/'<>c__DisplayClass7'::chatRoomJID` | `L1540: .method public hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2973` | `reference` | `string chatRoomJID,` | `L2970: .method family hidebysig newslot abstract virtual instance void Instance_OnAVRoomStateChange(valuetype IMPP.Client.MultiplayerAV.AVRoom.EventTypeEnum eventType,` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:2983` | `reference` | `string chatRoomJID) cil managed` | `L2981: .method family hidebysig instance void` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:3000` | `reference` | `IL_0010: stfld string IMPP.Client.VideoChat.SingleAVDispatcher/'<>c__DisplayClass7'::chatRoomJID` | `L2981: .method family hidebysig instance void` |
| `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:14273` | `reference` | `IL_00c3: castclass [smack]com.vision.smack.muc.ChatRoom` | `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:15141` | `reference` | `class [smack]com.vision.smack.muc.ChatRoom V_1,` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` |
| `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` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15183` | `reference` | `IL_0079: castclass [smack]com.vision.smack.muc.ChatRoom` | `L15134: .method public hidebysig static class [IMPP.Model]IMPP.Model.ChatRecord.tblMsgGroupPersonMsg` |
| `runs\offline-evidence-intake\zyl-qqfile-20260709\metadata\c28-il\IMPlatformClient.exe.il:15369` | `callsite` | `IL_026e: callvirt instance string [smack]com.vision.smack.muc.ChatRoom::get_Name()` | `` |
### Runtime owner: frmMain / IMPPManager / MessageCenter
Stage: `runtime_context`. Status: `static_evidence_found`. Evidence count: 20.
Business meaning: Likely owners of initialized logged-in state and message center callbacks.
Must verify tomorrow:
- Running frmMain
- IMPPManager.UserInfo
- MessageCenter
- Reconnect success state
- loaded assemblies
| 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: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()` | `L7286: .method public hidebysig static void AddUserTitle(class CSharpWin.ChatRichTextBox textBox,` |
| `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()` | `` |
## Updated stop / continue rules
Continue B-route tomorrow if P0 runtime, text-send, upload, FileID, and ack probes produce positive or actionable evidence. Stop B-route and escalate if logged-in runtime cannot expose AppContextManager/MessageScheduling/Chat/IFileTransfer, or if upload cannot produce FileUploadResult.FileID. Keep A-route/RPA backup-only for demo continuity.

View File

@@ -1,6 +1,6 @@
# Capability Source Matrix # Capability Source Matrix
Date: 2026-07-10 Date: 2026-07-12
Stage: Core business capability roadmap Stage: Core business capability roadmap
Evidence index: `docs/source-discovery/2026-07-09-n12-pre-zyl-index.md` Evidence index: `docs/source-discovery/2026-07-09-n12-pre-zyl-index.md`
Schema notes: `docs/source-discovery/2026-07-09-n12-pre-zyl-schema-notes.md` Schema notes: `docs/source-discovery/2026-07-09-n12-pre-zyl-schema-notes.md`
@@ -14,6 +14,18 @@ File download mapping v2: `docs/source-discovery/2026-07-10-file-download-mappin
Send-file sandbox gate: `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md` Send-file sandbox gate: `docs/source-discovery/2026-07-10-send-file-sandbox-gate.md`
Business goals smoke: `docs/reports/2026-07-10-business-goals-smoke.md` Business goals smoke: `docs/reports/2026-07-10-business-goals-smoke.md`
R14 release candidate: `docs/reports/2026-07-10-r6f-r14-release-candidate.md` R14 release candidate: `docs/reports/2026-07-10-r6f-r14-release-candidate.md`
Main status correction: `docs/reports/2026-07-12-main-business-status-correction.md`
A-route UIA send: `docs/source-discovery/2026-07-11-a-route-uia-send.md`
A-route real offline chat window: `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`
Offline B-route reverse index: `docs/source-discovery/2026-07-12-offline-broute-reverse-index.md`
Offline B-route text-send map: `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`
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`
Send/upload deep dive: `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`
Login reachability validation items: `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`
Login reachability probe package: `docs/source-discovery/2026-07-12-login-reachability-probe-package.md`
## Source priority ## Source priority
@@ -24,6 +36,8 @@ R14 release candidate: `docs/reports/2026-07-10-r6f-r14-release-candidate.md`
5. Network/protocol source. 5. Network/protocol source.
6. Mock source for tests only. 6. Mock source for tests only.
Route rule: UIA helper / A-route / RPA is a backup route only. It can preserve delivery momentum while B-route is blocked or untestable, but B-route sidecar/API evidence remains the preferred path for production send and file capability.
## Matrix ## Matrix
| MCP tool | Primary source | Fallback source | Evidence file | Decision status | Next implementation slice | | MCP tool | Primary source | Fallback source | Evidence file | Decision status | Next implementation slice |
@@ -32,8 +46,8 @@ R14 release candidate: `docs/reports/2026-07-10-r6f-r14-release-candidate.md`
| `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_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_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\<hash>` 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_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\<hash>` 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: running-client sidecar / in-process connector, preferring `AppContextManager.SendTxtMessageByJid(...)` or `MessageScheduling.SendChatMessage(...)` over the unimplemented `SendP2PMessage(...)` interface path; current MCP tool exposes preview/dry-run only | A-route fallback: constrained UI/RPA wrapper only if B cannot pass runtime probe, entrypoint availability, dynamic observation, and idempotent dry-run gates; 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`; `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: `operator_observed_success=true`, but `exact_content_seen_after=false`, `content_sha256_seen_after=false`, `after_offline_blocked=true`, and `production_send_unlock_recommended=false`. Preview is complete; production remains blocked. | blocked until strict machine sent-record/content-hash after evidence passes and a connector is configured | | `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`; `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`; `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`; `docs/source-discovery/2026-07-12-login-reachability-probe-package.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. The login reachability package is now built and verified; it produces `LOGIN-REACHABILITY-OUTPUT.json` with run/targets/runtime/reachability/server_auth/snapshots/attempts/failures/correlation and includes `TODO-COVERAGE.md` for runtime observations, group probe, and fallback A-route evidence. | Run the 2026-07-13 login reachability package in a logged-in environment and return `isphere-login-reachability-return-*.zip`; text production remains blocked until one-shot target, AppContextManager/IAppContextManager or MessageScheduling/Chat reachability, sent-record source, and content-hash/ack correlation pass |
| `isphere_send_file` | B-route selected after send-message probe: managed offline-file path through `OffLineFileSend.sendFile()`, `IMPP.Service*.dll` `IFileTransfer.FileUpload(...)`, and `Chat.sendFileMessage(...)`; current MCP tool exposes preview/dry-run only | A-route fallback: constrained UI/RPA upload/send-file flow; native `TcpFileTransfer.dll` is a later candidate only after managed path is rejected | `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`; `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. | blocked until returned file-send package proves upload/sent evidence and an upload connector is gated | | `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`; `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`; `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`; `docs/source-discovery/2026-07-12-login-reachability-probe-package.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. The login reachability package is now built and verified with one-shot file fields, structured failure handling, and before/after recorder output validation. | Run the 2026-07-13 login reachability package in a logged-in environment and return `isphere-login-reachability-return-*.zip`; file production remains blocked until FileUploadPara/server/auth, `IFileTransfer.FileUpload`, FileUploadResult/FileID or structured upload failure, file-message finalization, and file sent-record/ack correlation pass |
## Stage C entry rule ## Stage C entry rule
@@ -50,4 +64,4 @@ Start Stage C with a narrow log-backed `isphere_receive_messages` source abstrac
## Deferred source work ## 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. The active continuous execution plan `docs/superpowers/plans/2026-07-10-r6f-r14-continuous-execution-plan.md` is complete through R14; next work is evidence-driven, not local login-dependent. `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 login reachability probe path in `docs/source-discovery/2026-07-12-login-reachability-validation-items.md`, generated from `docs/source-discovery/2026-07-12-send-upload-deep-dive.md`: validate logged-in adapter reachability with one-shot targets, structured failure reasons, before/after sent-record snapshots, in-process adapter reachability mode, and message/file ack correlation before production send/file work. A-route RPA remains backup-only under `docs/superpowers/plans/2026-07-11-a-route-rpa-send.md`.

View File

@@ -2,7 +2,7 @@
> **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. > **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:**`codex/a-route-rpa-send` 分支实现 A 方案:通过受控 UI Automation 路线让 `isphere_send_message` 能配置为真实 UI 写入并点击发送。 **Goal:**`codex/a-route-rpa-send` 分支实现 A 方案,并在合并到 `main` 后继续校准计划:通过受控 UI Automation 路线让 `isphere_send_message` 能配置为真实 UI 写入并点击发送;同时明确这只证明 UI 动作,不等于业务送达,而且 A-route/RPA 是备选兜底,不是主线
**Architecture:** Go MCP 继续保留稳定 `isphere_send_message` 接口、hash、idempotency、audit。新增 A-route connector 调用 C# `ISphereWinHelper` 的 UIA action opC# helper 根据窗口句柄、发送框 AutomationId、发送按钮 AutomationId 写入文本并点击。B-route sidecar 仍是主路线,但当前不可测时先实现 A-route 功能兜底。 **Architecture:** Go MCP 继续保留稳定 `isphere_send_message` 接口、hash、idempotency、audit。新增 A-route connector 调用 C# `ISphereWinHelper` 的 UIA action opC# helper 根据窗口句柄、发送框 AutomationId、发送按钮 AutomationId 写入文本并点击。B-route sidecar 仍是主路线,但当前不可测时先实现 A-route 功能兜底。
@@ -11,12 +11,14 @@
## Global Constraints ## Global Constraints
- Repository root: `E:\coding\codex\isphere-ai-bridge`. - Repository root: `E:\coding\codex\isphere-ai-bridge`.
- Active branch: `codex/a-route-rpa-send`. - Original implementation branch: `codex/a-route-rpa-send`; merged branch for follow-up documentation and plan correction: `main`.
- Do not use `rg`; use `git ls-files`, `ag`, `grep -R`, or PowerShell commands. - Do not use `rg`; use `git ls-files`, `ag`, `grep -R`, or PowerShell commands.
- Local machine cannot log in; use synthetic WinForms/UIA verification for local tests. - Local machine cannot log in; use synthetic WinForms/UIA verification for local tests.
- User explicitly removed human approval as a product gate for A-route; do not add approval IDs or approval queues in this plan. - User explicitly removed human approval as a product gate for A-route; do not add approval IDs or approval queues in this plan.
- Keep audit redaction: do not store raw message body or raw idempotency key in committed docs/audit tests. - Keep audit redaction: do not store raw message body or raw idempotency key in committed docs/audit tests.
- Real UI action requires explicit env configuration; default MCP behavior remains preview/blocked. - Real UI action requires explicit env configuration; default MCP behavior remains preview/blocked.
- Route priority must stay B-route first: running-client sidecar / in-process connector / existing API is the primary product route; A-route/RPA only keeps a fallback path alive while B-route is blocked or untestable.
- Helper fields `clicked_ui=true` and `sent_message=true` mean the helper wrote the editor and invoked/clicked the send button. They must not be interpreted as server acceptance, receiver delivery, or sent-record proof.
--- ---
@@ -112,4 +114,43 @@ adds a no-network WinForms probe using the real selector names
- [x] Verify UIA classification finds send editor, send button, and file button. - [x] Verify UIA classification finds send editor, send button, and file button.
- [x] Verify `-ProbeClick` writes text and clicks `btnSend`. - [x] Verify `-ProbeClick` writes text and clicks `btnSend`.
- [x] Verify marker says `sent_real_message=false` and `uploaded_real_file=false`. - [x] Verify marker says `sent_real_message=false` and `uploaded_real_file=false`.
- [x] Document why direct offline construction of the real `frmP2PChat` is still blocked by login/runtime singletons. - [x] Document the then-current direct-construction blocker; Task 7 supersedes this by opening the real `frmP2PChat` with a fuller offline dependency harness.
## Task 7: Replace synthetic-only proof with real offline `frmP2PChat`
**Files:**
- Create: `scripts/open-offline-real-frmP2PChat.ps1`
- Create: `scripts/extract-frmP2PChat-il-risk.ps1`
- Create: `scripts/test-extract-frmP2PChat-il-risk.ps1`
- Create: `scripts/test-open-offline-real-frmP2PChat-contract.ps1`
- Create: `docs/source-discovery/2026-07-11-a-route-open-real-chat-window.md`
**Purpose:** local machine still cannot log in, but RPA validation should run
against a real client chat form instead of only a synthetic WinForms probe.
- [x] Extract constructor/load IL risks for `frmP2PChat`.
- [x] Build an offline dependency harness that can construct and show the real `frmP2PChat`.
- [x] Confirm UIA root `automation_id=frmP2PChat`.
- [x] Confirm send editor `automation_id=rtbSendMessage`.
- [x] Confirm send button `automation_id=btnSend`.
- [x] Confirm receive area `automation_id=rtbRecvMessage`.
- [x] Record that the real offline window shows the expected offline-send blocker.
- [x] Merge and push the real-window branch to `main`.
## Task 8: Corrected next loop after main merge
**Business status after Task 7:**
- Message send: UI write/click path exists; online delivery is not verified.
- File send: preview-only; no real upload path is implemented.
- Receive/search: unchanged from R14; basic digital-employee read/search remains usable through local-readonly evidence paths.
**Next implementation slices:**
- [ ] Re-check B-route sidecar / in-process connector / existing API feasibility before promoting any RPA path.
- [ ] Add a real-window A-route smoke that opens `frmP2PChat`, passes its HWND into the MCP `uia_rpa` connector, writes a unique text, clicks `btnSend`, and records sanitized UI evidence; treat this as backup readiness only.
- [ ] Add an online/logged-in verification package for message send: first target B-route evidence; include A-route evidence only as a fallback comparison path.
- [ ] Keep default `verify-go-mcp.ps1` preview/blocked unless explicit A-route env is set, so CI does not depend on a desktop login.
- [ ] Start a separate file-send RPA locator node: identify the real toolbar/menu path for file attach because `btnSendFile` was not exposed in the real offline UIA dump.
- [ ] Only after file locator proof, add file upload action and online file-send evidence package.
- [x] Create `docs/reports/2026-07-12-main-business-status-correction.md` separating “UI action ready” from “business delivery ready”.

View File

@@ -0,0 +1,335 @@
# B-Route Bridge Next 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:** Push the primary B-route from offline reverse evidence into the selected `in_process_adapter_research` branch, while keeping any external sidecar work preview/probe-only and not enabling real send.
**Architecture:** Keep the Go MCP tool contracts stable. B-route remains the primary product route: reuse the logged-in `IMPlatformClient.exe` runtime through a narrow bridge. Offline reverse now rules out existing IPC/plugin as the next first step, so a dedicated in-process adapter research plan is required before any production send. External sidecars may only do self-check/probe/preview. A-route/RPA remains backup-only and should be used only for UI action smoke or when B-route is proven blocked.
**Tech Stack:** Go 1.23.4, github.com/modelcontextprotocol/go-sdk, Windows PowerShell, .NET Framework C# helper/sidecar, stdin/stdout JSON protocols, Windows UI Automation only as fallback.
## Global Constraints
- Repository root: `E:\coding\codex\isphere-ai-bridge`.
- Active branch for execution should be a new `codex/` branch, not `main` directly.
- Do not use `rg`; use `git ls-files`, `ag`, `grep -R`, or PowerShell commands.
- Local machine cannot log in to iSphere; local work must use static analysis, fake sidecar processes, synthetic fixtures, or offline real-window UI only.
- B-route is primary: running-client sidecar / in-process connector / existing API comes before A-route/RPA.
- A-route/RPA is backup-only: keep it runnable, but do not make it the default product architecture.
- No real send/file upload in this plan. Stop at bridge feasibility, self_check, runtime probe, and dry-run preview.
- Keep audit redaction: do not store raw message body, raw idempotency key, raw file contents, or raw local file paths in committed outputs.
---
## Offline reverse result amendment
`docs/superpowers/plans/2026-07-12-offline-broute-reverse-plan.md` has now produced the offline reverse decision set:
- `docs/source-discovery/2026-07-12-offline-broute-reverse-index.md`
- `docs/source-discovery/2026-07-12-broute-text-send-static-map.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`
Decision correction: B-route remains primary, but **existing IPC/local service** and **plugin extension** are not confirmed usable. The selected next branch is `in_process_adapter_research`. External sidecar work is allowed only as preview/probe plumbing until an in-process bridge is selected. A-route/RPA remains backup-only.
## Current evidence summary
The current `main` state already has:
- `isphere_send_message` MCP contract, preview/dry-run metadata, audit, idempotency, and connector abstraction.
- `internal/tools/send_message_broute_adapter.go` with B-route `disabled` and `dry_run_contract` modes only.
- `internal/tools/send_message_uia_adapter.go` wired from env only for `ISPHERE_SEND_CONNECTOR_MODE=uia_rpa`.
- C# WinHelper `probe_client_runtime`, `probe_send_entrypoints`, `probe_send_uia_controls`, and `uia_send_message`.
- Offline real `frmP2PChat` opener for RPA backup validation.
- No B-route env wiring, no process-backed B-route sidecar client, no in-process bridge transport decision, and no real send/file-upload connector.
Important technical conclusion: an external C# process cannot automatically reuse the logged-in static runtime of `IMPlatformClient.exe`. Offline reverse has now made the transport decision for this evidence set: existing API/IPC and plugin extension are not confirmed; the next B-route node is a separate `in_process_adapter_research` plan. Do not build production send/file upload in this plan.
---
## Task 1: B-route bridge transport feasibility report
**Files:**
- Create: `docs/source-discovery/2026-07-12-b-route-bridge-feasibility.md`
- Modify: `docs/source-discovery/capability-source-matrix.md`
**Interfaces:**
- Consumes: existing docs `docs/source-discovery/2026-07-10-send-sidecar-b-first-plan.md`, `docs/source-discovery/2026-07-10-send-connector-preflight.md`, and current Go/C# connector files.
- Produces: a route decision table with exact choices: `existing_ipc`, `plugin_extension`, `in_process_adapter`, `external_dry_run_only`, or `fallback_rpa`.
- [ ] Re-read current B-route evidence.
Run:
```powershell
Get-Content -LiteralPath docs\source-discovery\2026-07-10-send-sidecar-b-first-plan.md
Get-Content -LiteralPath docs\source-discovery\2026-07-10-send-connector-preflight.md
Get-Content -LiteralPath internal\tools\send_message_broute_adapter.go
Get-Content -LiteralPath internal\tools\send_message_uia_adapter.go
```
Expected: confirm B-route entrypoint names exist, but no bridge transport is implemented.
- [ ] Write the feasibility report with this required conclusion block:
```markdown
## Decision
B-route remains primary. The immediate next implementation is not production send; it is bridge transport selection plus dry-run sidecar plumbing.
| Candidate | Can reuse logged-in runtime? | Local feasibility | Next action |
| --- | --- | --- | --- |
| existing_ipc/local_service | not confirmed | offline bridge map found no send/file API | park unless new online evidence appears |
| plugin_extension | not confirmed | plugin evidence is UI/app-store/context-menu oriented | park unless a concrete local load contract appears |
| in_process_adapter | possible but requires explicit bridge mechanism | selected by offline decision | create dedicated research plan before coding |
| external_dry_run_only | cannot reuse logged-in static runtime | useful for protocol/client tests only | keep preview/probe-only boundary |
| fallback_rpa | can drive UI only | backup-ready for UI action smoke | keep as backup, not primary |
```
- [ ] Update `capability-source-matrix.md` so the next slice says: “B-route bridge transport feasibility and dry-run sidecar boundary”, not “RPA send”.
- [ ] Verify docs.
Run:
```powershell
git diff --check
```
Expected: exit 0.
### 2026-07-12 plan correction
Task 1 is now satisfied by the offline reverse reports listed above. Before executing Tasks 2-5, create or approve a new `in_process_adapter_research` plan. Tasks 2-4 may still be used later for non-mutating sidecar preview plumbing, but they do not solve production send by themselves.
## Task 2: Add B-route connector env selection without starting real send
**Files:**
- Modify: `internal/tools/send_message_uia_adapter.go` or split env loading into `internal/tools/send_message_connector_env.go`
- Modify: `internal/tools/send_message_uia_adapter_test.go` or create `internal/tools/send_message_connector_env_test.go`
- Modify: `docs/go-mcp-runbook.md`
**Interfaces:**
- Consumes: `NewBRouteSendMessageConnector(BRouteSendAdapterConfig)`.
- Produces: `NewSendMessageConnectorFromEnv()` supports:
- `ISPHERE_SEND_CONNECTOR_MODE=broute_dry_run`
- `ISPHERE_SEND_CONNECTOR_MODE=broute_sidecar`
- `ISPHERE_SEND_BROUTE_MODE=disabled|dry_run_contract|sidecar_preview`
- `ISPHERE_SEND_BROUTE_SIDECAR_EXE=<path>`
- `ISPHERE_SEND_BROUTE_TIMEOUT_SECONDS=<positive int>`
- [ ] Write failing env-loader tests.
Test cases:
```text
mode empty -> nil connector
mode uia_rpa -> existing UIA connector
mode broute_dry_run -> B-route connector mode dry_run_contract
mode broute_sidecar without sidecar exe -> connector returns blocked sidecar config error, not panic
```
Run:
```powershell
go test ./internal/tools -run "TestNewSendMessageConnectorFromEnv" -count=1
```
Expected before implementation: fail for B-route modes.
- [ ] Implement env parsing with no real send.
Required behavior:
```text
broute_dry_run -> NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode:"dry_run_contract"})
broute_sidecar -> NewBRouteSendMessageConnector(BRouteSendAdapterConfig{Mode:"sidecar_preview", SidecarPath: env path, TimeoutSeconds: parsed timeout})
```
- [ ] Run focused tests.
```powershell
go test ./internal/tools -run "TestNewSendMessageConnectorFromEnv|TestBRoute" -count=1
```
Expected: pass.
## Task 3: Process-backed B-route sidecar client boundary
**Files:**
- Create: `internal/broute/send_sidecar_client.go`
- Create: `internal/broute/send_sidecar_client_test.go`
- Modify: `internal/tools/send_message_broute_adapter.go`
- Modify: `internal/tools/send_message_broute_adapter_test.go`
**Interfaces:**
- Produces protocol: `isphere.broute.send.v1`.
- Produces sidecar ops:
- `self_check`
- `probe_runtime`
- `preview_send_message`
- No op named `send_message` in this task.
- [ ] Write fake-process tests for `internal/broute`.
The fake sidecar must accept stdin JSON and return:
```json
{"protocol":"isphere.broute.send.v1","request_id":"...","op":"preview_send_message","ok":true,"data":{"connector_mode":"broute-sidecar-preview","would_send":false,"entrypoint":"AppContextManager.SendTxtMessageByJid","target_ref":"direct:demo","content_sha256":"..."}}
```
- [ ] Implement the client with timeout, stderr capture, protocol/op/request_id validation, and structured sidecar errors.
Use `internal/msglib/sidecar_client.go` as the pattern, but keep the package separate as `internal/broute`.
- [ ] Update `send_message_broute_adapter.go` so `Mode="sidecar_preview"` calls `preview_send_message` and returns:
```text
Accepted=false
Status=blocked
ErrorCode=broute_sidecar_preview_only
ConnectorMode=broute-sidecar-preview
ProductionEnabled=false
SideEffects all false
```
- [ ] Verify no accidental production send path exists.
Run:
```powershell
go test ./internal/broute ./internal/tools -run "BRoute|Sidecar" -count=1
```
Expected: pass; no test should require iSphere login.
## Task 4: Native B-route sidecar skeleton, preview-only
**Files:**
- Create: `native/ISphereSendSidecar/Program.cs`
- Create: `native/ISphereSendSidecar/SidecarProtocol.cs`
- Create: `scripts/build-send-sidecar.ps1`
- Create: `scripts/verify-send-sidecar.ps1`
- Create: `docs/broute-send-sidecar-contract.md`
**Interfaces:**
- Native executable accepts stdin JSON and writes stdout JSON.
- Protocol: `isphere.broute.send.v1`.
- Ops implemented:
- `self_check`
- `probe_runtime`
- `preview_send_message`
- Explicitly not implemented:
- `send_message`
- `send_file`
- `upload_file`
- hooks/injection/network replay.
- [ ] Implement `self_check` returning sidecar name, version, process bitness, and `mutates_client=false`.
- [ ] Implement `probe_runtime` by reusing safe process/module discovery logic from WinHelper where possible.
- [ ] Implement `preview_send_message` as contract validation only; it must echo hashes/target refs and `would_send=false`.
- [ ] Build and verify.
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\build-send-sidecar.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-send-sidecar.ps1
go test ./...
```
Expected: all pass; sidecar verification prints only booleans/counts and no message body.
## Task 5: Online B-route evidence package v3
**Files:**
- Create: `scripts/package-broute-bridge-probe.ps1`
- Create: `scripts/verify-broute-bridge-probe-package.ps1`
- Create: `scripts/validate-returned-broute-bridge-probe.ps1`
- Create: `docs/source-discovery/2026-07-12-broute-bridge-probe-package.md`
**Interfaces:**
- Package includes:
- live probe recorder;
- send sidecar preview executable;
- `RUN-BROUTE-BRIDGE-PROBE.bat`;
- `BROUTE-BRIDGE-INPUTS.template.json`;
- return zip helper.
- [ ] Package only non-mutating probes.
- [ ] Require operator to be logged in before running.
- [ ] Validate returned package for:
- running client present;
- module availability;
- sidecar self_check passed;
- sidecar preview returned `would_send=false`;
- no real send attempted.
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\package-broute-bridge-probe.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-broute-bridge-probe-package.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\validate-returned-broute-bridge-probe.ps1 -UseFixture
```
Expected: package builds and fixture validation passes.
## Task 6: Business smoke split for send readiness
**Files:**
- Modify: `scripts/verify-business-goals-smoke.ps1`
- Modify: `docs/reports/2026-07-12-main-business-status-correction.md`
- Create or modify: `docs/reports/2026-07-12-broute-next-smoke.md`
**Interfaces:**
- Produces separate booleans:
- `send_message_preview_ready`
- `send_message_broute_bridge_preview_ready`
- `send_message_ui_action_ready`
- `send_message_business_delivery_ready`
- `send_file_preview_ready`
- `send_file_business_delivery_ready`
- [ ] Update smoke script to avoid one ambiguous `send_message_production_ready` field.
- [ ] Ensure current expected state is:
```json
{
"send_message_preview_ready": true,
"send_message_broute_bridge_preview_ready": true,
"send_message_ui_action_ready": true,
"send_message_business_delivery_ready": false,
"send_file_preview_ready": true,
"send_file_business_delivery_ready": false
}
```
- [ ] Verify.
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\verify-business-goals-smoke.ps1
git diff --check
go test ./...
```
Expected: pass.
---
## Stop conditions
Stop and ask the business owner if any of these occur:
1. B-route bridge transport requires invasive in-process loading and no plugin/IPC path exists.
2. Online probe shows the logged-in client does not expose the expected modules/entrypoints.
3. B-route preview cannot distinguish direct contact vs group target.
4. Any step would perform real send/upload before explicit online evidence gates are ready.
5. A-route becomes the only viable path; this requires an explicit business decision because RPA is backup-only.
## Recommended next action
Start with Task 1 and Task 2 only. That creates a clear B-route bridge feasibility decision and lets the MCP server select a B-route dry-run connector from env without touching real send.

View File

@@ -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.

View File

@@ -0,0 +1,212 @@
# Offline B-Route Reverse 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:** Use offline reverse engineering to advance the primary B-route when no logged-in iSphere environment is available.
**Architecture:** Treat the available iSphere/IMPlatformClient binaries as read-only samples. Recover the send-message, send-file, plugin/IPC, and bridge-transport evidence needed to decide whether B-route can be implemented without relying on RPA. Keep A-route/RPA as backup-only and do not execute real send or upload in this plan.
**Tech Stack:** Windows PowerShell, .NET Framework IL tools, existing extracted IL files, Go 1.23.4 for repeatable analyzers, Markdown evidence reports.
## Global Constraints
- Repository root: `E:\coding\codex\isphere-ai-bridge`.
- Active branch for execution should be a new `codex/` branch, not `main` directly.
- Do not use `rg`; use `git ls-files`, `ag`, `grep -R`, or PowerShell commands.
- Tomorrow has no logged-in iSphere environment; do not wait for online evidence.
- Preserve original binaries read-only. Any extraction output must go under ignored `runs/` or committed sanitized docs/scripts only.
- B-route remains primary. A-route/RPA remains backup-only.
- No real message send, no file upload, no network replay, no process injection, and no client mutation in this plan.
- Outputs must separate verified facts from reverse-engineering hypotheses.
---
## Available offline samples
Use these local samples first:
| Sample | Purpose | SHA256 |
| --- | --- | --- |
| `runs/offline-real-client-window/full/zyl/Impp/IMPlatformClient.exe` | main managed client; text send, chat window, plugin/IPC candidates | `E2966E58360DAEEBF178410A961E2DC52748C63E9CCBD94BD6EC8434A1A09CB7` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Service.dll` | file upload service candidates | `F859DE2F34E024B5F372D95F22CBF8A018C780F24203E7A76D392E52BD90CADD` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Interface.dll` | service/interface contract candidates | `DD093CF61FAE85C2D2581F289B01AA477546712E098FEF81272FDD989E50D12D` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Model.dll` | model/parameter types | `7CBABDD23A7234D15E294C549EEEC78EFBAD6E957CD45A6E8A85309349A624A5` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.UI.dll` | UI/plugin helpers and possible send controls | `4C61212519C01D1B731ED4F20DF3411C491616F4ADA98A4529722A6AA3689E6D` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Common.dll` | shared utility and message types | `02A47C99C27C9BFE2BADC438389300C92220B07609BD87C48B4B5E1B4EE6AEB4` |
| `runs/offline-real-client-window/full/zyl/Impp/IMPP.Helper.dll` | helper abstractions | `30932D082B6678699C832C63F923E01EAD84674FAEDB613D631E034E03742FB9` |
| `runs/offline-real-client-window/full/zyl/Impp/smack.dll` | XMPP chat/send layer | `BAD0BB0591765DB153B17CECC1112B0BBDBF3B1D3370DDF973F91974E92CEC66` |
| `runs/offline-real-client-window/full/zyl/Impp/TcpFileTransfer.dll` | native/transfer candidate | `6C4874B46D1E7DC04C9B6784180603452400B881E04509D464A0D58814EFEDA7` |
| `runs/offline-real-client-window/full/zyl/Impp/HttpServerLib.dll` | local API/IPC candidate | `FFDB633216AE332B8EDFFC83E2AE546B7A80144C659FF4053FDFE4FE382A8D12` |
| `runs/offline-real-client-window/full/zyl/Impp/INetwork.dll` | network abstraction candidate | `E40BE4EE2439E4280461F4D2BADB318A5F4572428F069AB6D17B4C4F0E8CFAC9` |
| `runs/offline-real-client-window/full/zyl/Impp/IOClientNetwork.dll` | network implementation candidate | `64CA231A614771325741A5F098E52EBF20F7190E339B64962DE2EDEDCFFFF904` |
Existing IL evidence to reuse:
- `runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPlatformClient.exe.il`
- `runs/offline-chat-window/frmP2PChat-ctor.il.txt`
- `runs/offline-chat-window/frmP2PChat-ctor-null-risk.md`
---
## Task 1: Offline reverse case index
**Files:**
- Create: `docs/source-discovery/2026-07-12-offline-broute-reverse-index.md`
- Create: `scripts/build-offline-broute-reverse-index.ps1`
**Interfaces:**
- Produces: a sanitized Markdown/JSON index of sample paths, SHA256, size, timestamp, and role.
- Consumes: the sample paths listed above.
- [ ] Write `scripts/build-offline-broute-reverse-index.ps1` to hash the sample list and emit `runs/offline-broute-reverse/index.json` plus `docs/source-discovery/2026-07-12-offline-broute-reverse-index.md`.
The script must not copy or modify binaries. It should only read metadata and hashes.
- [ ] Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\build-offline-broute-reverse-index.ps1
```
Expected: JSON and Markdown index generated; no binary copied.
## Task 2: Text-send static call graph
**Files:**
- Create: `scripts/extract-broute-text-send-map.ps1`
- Create: `docs/source-discovery/2026-07-12-broute-text-send-static-map.md`
**Interfaces:**
- Consumes: `IMPlatformClient.exe.il`, `smack.dll`, and related managed assemblies.
- Produces: function map for:
- `AppContextManager.SendTxtMessageByJid`
- `MessageScheduling.SendChatMessage`
- `Chat.SendMessage`
- `XMPPConnection.send`
- `MessageCenter` send-related callbacks
- [ ] Extract method headers, signatures, call sites, and surrounding IL windows.
- [ ] Mark each function as one of: `confirmed_signature`, `confirmed_callsite`, `string_only`, or `not_found`.
- [ ] Write the report with a conclusion section:
```markdown
## Decision
B-route text send remains plausible only if a bridge can enter the logged-in runtime or an existing IPC/API exposes the same call. Offline IL confirms call shape, but not runtime invocability.
```
- [ ] Verify:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-broute-text-send-map.ps1
git diff --check
```
Expected: exit 0 and report contains all target function names.
## Task 3: File-send/static upload call graph
**Files:**
- Create: `scripts/extract-broute-file-send-map.ps1`
- Create: `docs/source-discovery/2026-07-12-broute-file-send-static-map.md`
**Interfaces:**
- Consumes: `IMPlatformClient.exe`, `IMPP.Service.dll`, `IMPP.Interface.dll`, `IMPP.Model.dll`, `TcpFileTransfer.dll`.
- Produces: function/type map for:
- `IMPP.Client.OffLineFileSend.sendFile`
- `IMPP.Client.OffLineFileSend.trans_UploadCompleted`
- `IMPP.Service.BLL.FileTransfer.FileUpload`
- `IMPP.Service.BLL.FileTransfer.AsynFileUpload`
- `FileUploadPara`
- chat/file message send method names such as `sendFileMessage`
- [ ] Extract signatures and parameter types.
- [ ] Identify whether file send is direct upload first or chat-message first.
- [ ] Identify what local file path, server file id, file hash, and target JID values are required.
- [ ] Verify:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-broute-file-send-map.ps1
git diff --check
```
Expected: report separates upload step from chat message step.
## Task 4: Bridge/IPC/plugin reverse map
**Files:**
- Create: `scripts/extract-broute-bridge-map.ps1`
- Create: `docs/source-discovery/2026-07-12-broute-bridge-static-map.md`
**Interfaces:**
- Consumes: `IMPlatformClient.exe`, `HttpServerLib.dll`, `IMPlatformClient.Web.exe`, `INetwork.dll`, `IOClientNetwork.dll`, config files, and existing live-probe `services_registry_shortcuts.json` / `network_inventory.json`.
- Produces: static evidence table for:
- localhost HTTP server routes or ports;
- named pipe strings;
- plugin loader classes or directories;
- command-line switches;
- COM/service candidates;
- update/patch extension points.
- [ ] Search strings and IL for `HttpListener`, `TcpListener`, `NamedPipe`, `Pipe`, `Plugin`, `LoadFrom`, `Assembly.Load`, `localhost`, `127.0.0.1`, `http://`, `net.pipe`, `Register`, `Route`, and `Command`.
- [ ] Report exact methods/classes where bridge candidates appear.
- [ ] Classify each candidate:
- `usable_without_login`
- `requires_logged_in_process`
- `static_only_unknown`
- `not_a_bridge`
- [ ] Verify:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\extract-broute-bridge-map.ps1
git diff --check
```
Expected: report gives a yes/no recommendation for whether B-route should pursue IPC/plugin before in-process adapter.
## Task 5: Offline bridge decision update
**Files:**
- Modify: `docs/superpowers/plans/2026-07-12-b-route-bridge-next-plan.md`
- Modify: `docs/source-discovery/capability-source-matrix.md`
- Create: `docs/source-discovery/2026-07-12-offline-broute-reverse-decision.md`
**Interfaces:**
- Consumes: reports from Tasks 1-4.
- Produces: next implementation decision:
- `existing_ipc_first`
- `plugin_extension_first`
- `in_process_adapter_research`
- `external_sidecar_preview_only`
- `fallback_rpa_only`
- [ ] Write decision using only offline evidence.
- [ ] If no bridge is found, state clearly that external sidecar can only do preview/probe unless an in-process bridge is added.
- [ ] Keep RPA marked backup-only.
## Task 6: Optional offline prototype only after decision
**Files:**
- To be added only after Task 5 decision.
**Rules:**
- If decision is `existing_ipc_first`, prototype a non-mutating client call to the local API only.
- If decision is `plugin_extension_first`, prototype plugin discovery only, not send.
- If decision is `in_process_adapter_research`, create a new explicit plan before coding.
- If decision is `external_sidecar_preview_only`, continue with the already planned preview-only B-route sidecar boundary.
- If decision is `fallback_rpa_only`, ask the user before promoting RPA beyond backup.
---
## Stop conditions
Stop and report if:
1. Static evidence shows all B-route send functions require live-only objects with no reachable bridge.
2. Bridge/plugin evidence implies invasive in-process loading and no safer IPC/API path exists.
3. File send requires server-issued upload tokens that cannot be derived offline.
4. Any next step would send a real message, upload a real file, mutate the client, attach a hook, or replay network traffic.
## Recommended immediate execution
Run Task 1 through Task 4 while offline. Do not wait for tomorrow's login evidence. After those reports exist, decide whether B-route can continue through IPC/plugin/static sidecar preview or whether RPA remains the only near-term operational path.

View File

@@ -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", ErrorMessage: "B-route adapter dry_run_contract mode validates request shape only and does not start a sidecar",
ConnectorMode: "broute-dry-run-contract", ConnectorMode: "broute-dry-run-contract",
}, nil }, 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: default:
result := SendMessageConnectorResult{ result := SendMessageConnectorResult{
Accepted: false, Accepted: false,

View File

@@ -53,3 +53,32 @@ func TestBRouteSendMessageConnectorDryRunContract(t *testing.T) {
t.Fatalf("unexpected dry-run result: %+v", result) 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)
}
}

View File

@@ -53,6 +53,9 @@ type uiaSendMessageConnector struct {
func NewSendMessageConnectorFromEnv() SendMessageConnector { func NewSendMessageConnectorFromEnv() SendMessageConnector {
mode := strings.TrimSpace(strings.ToLower(os.Getenv(EnvSendConnectorMode))) 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" { if mode != "uia_rpa" && mode != "uia-rpa" {
return nil return nil
} }

View File

@@ -2,6 +2,7 @@ package tools
import ( import (
"context" "context"
"strings"
"testing" "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 { type fakeUiaHelperCaller struct {
response uiaHelperResponse response uiaHelperResponse
err error err error

View File

@@ -0,0 +1,168 @@
param(
[string]$OutputDir = "runs/offline-broute-reverse",
[string]$ReportPath = "docs/source-discovery/2026-07-12-offline-broute-reverse-index.md"
)
$ErrorActionPreference = "Stop"
$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
$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
$samples = @(
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPlatformClient.exe"
role = "main managed client; text send, chat window, plugin/IPC candidates"
expected_sha256 = "E2966E58360DAEEBF178410A961E2DC52748C63E9CCBD94BD6EC8434A1A09CB7"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.Service.dll"
role = "file upload service candidates"
expected_sha256 = "F859DE2F34E024B5F372D95F22CBF8A018C780F24203E7A76D392E52BD90CADD"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.Interface.dll"
role = "service/interface contract candidates"
expected_sha256 = "DD093CF61FAE85C2D2581F289B01AA477546712E098FEF81272FDD989E50D12D"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.Model.dll"
role = "model/parameter types"
expected_sha256 = "7CBABDD23A7234D15E294C549EEEC78EFBAD6E957CD45A6E8A85309349A624A5"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.UI.dll"
role = "UI/plugin helpers and possible send controls"
expected_sha256 = "4C61212519C01D1B731ED4F20DF3411C491616F4ADA98A4529722A6AA3689E6D"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.Common.dll"
role = "shared utility and message types"
expected_sha256 = "02A47C99C27C9BFE2BADC438389300C92220B07609BD87C48B4B5E1B4EE6AEB4"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IMPP.Helper.dll"
role = "helper abstractions"
expected_sha256 = "30932D082B6678699C832C63F923E01EAD84674FAEDB613D631E034E03742FB9"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/smack.dll"
role = "XMPP chat/send layer"
expected_sha256 = "BAD0BB0591765DB153B17CECC1112B0BBDBF3B1D3370DDF973F91974E92CEC66"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/TcpFileTransfer.dll"
role = "native/transfer candidate"
expected_sha256 = "6C4874B46D1E7DC04C9B6784180603452400B881E04509D464A0D58814EFEDA7"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/HttpServerLib.dll"
role = "local API/IPC candidate"
expected_sha256 = "FFDB633216AE332B8EDFFC83E2AE546B7A80144C659FF4053FDFE4FE382A8D12"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/INetwork.dll"
role = "network abstraction candidate"
expected_sha256 = "E40BE4EE2439E4280461F4D2BADB318A5F4572428F069AB6D17B4C4F0E8CFAC9"
},
@{
path = "runs/offline-real-client-window/full/zyl/Impp/IOClientNetwork.dll"
role = "network implementation candidate"
expected_sha256 = "64CA231A614771325741A5F098E52EBF20F7190E339B64962DE2EDEDCFFFF904"
}
)
$entries = foreach ($sample in $samples) {
$fullPath = Join-Path $repo $sample.path
$exists = Test-Path -LiteralPath $fullPath -PathType Leaf
$item = $null
$sha256 = ""
$matches = $false
if ($exists) {
$item = Get-Item -LiteralPath $fullPath
$sha256 = (Get-FileHash -LiteralPath $fullPath -Algorithm SHA256).Hash.ToUpperInvariant()
$matches = ($sha256 -eq $sample.expected_sha256)
}
[pscustomobject]@{
path = $sample.path
file_name = Split-Path -Leaf $sample.path
role = $sample.role
exists = $exists
size_bytes = if ($item) { $item.Length } else { $null }
last_write_time = if ($item) { $item.LastWriteTime.ToString("o") } else { $null }
sha256 = $sha256
expected_sha256 = $sample.expected_sha256
sha256_matches_expected = $matches
}
}
$summary = [pscustomobject]@{
generated_at = (Get-Date).ToUniversalTime().ToString("o")
repository = $repo
output_dir = $OutputDir
samples_total = @($entries).Count
samples_present = @($entries | Where-Object { $_.exists }).Count
hash_matches = @($entries | Where-Object { $_.sha256_matches_expected }).Count
originals_copied = $false
originals_modified = $false
entries = $entries
}
$jsonPath = Join-Path $outDir "index.json"
$summary | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add("# Offline B-Route Reverse Index")
$lines.Add("")
$lines.Add("Date: 2026-07-12")
$lines.Add("")
$lines.Add("## Scope")
$lines.Add("")
$lines.Add("This index records the read-only offline samples for B-route reverse engineering. The script reads metadata and SHA256 hashes only; it does not copy or modify the original binaries.")
$lines.Add("")
$lines.Add("## Summary")
$lines.Add("")
$lines.Add("- Samples total: $($summary.samples_total)")
$lines.Add("- Samples present: $($summary.samples_present)")
$lines.Add("- Hash matches: $($summary.hash_matches)")
$lines.Add("- Originals copied: false")
$lines.Add("- Originals modified: false")
$lines.Add("- Machine JSON: ``$OutputDir/index.json``")
$lines.Add("")
$lines.Add("## Sample table")
$lines.Add("")
$lines.Add("| Sample | Role | Size | SHA256 match | SHA256 |")
$lines.Add("| --- | --- | ---: | --- | --- |")
foreach ($entry in $entries) {
$size = if ($null -ne $entry.size_bytes) { [string]$entry.size_bytes } else { "missing" }
$match = if ($entry.sha256_matches_expected) { "yes" } else { "no" }
$sha = if ($entry.sha256) { $entry.sha256 } else { "missing" }
$lines.Add("| ``$($entry.path)`` | $($entry.role) | $size | $match | ``$sha`` |")
}
$lines.Add("")
$lines.Add("## Verified facts")
$lines.Add("")
$lines.Add("- All metadata came from local filesystem reads under the repository workspace.")
$lines.Add("- The expected primary B-route samples are present if `Samples present` equals `Samples total`.")
$lines.Add("- Hash matching only proves local file identity against this plan's recorded sample list; it does not prove runtime invocability.")
$lines.Add("")
$lines.Add("## Next reverse targets")
$lines.Add("")
$lines.Add("1. Text-send static call graph: `SendTxtMessageByJid`, `MessageScheduling.SendChatMessage`, `Chat.SendMessage`, `XMPPConnection.send`.")
$lines.Add("2. File-send/upload static call graph: `OffLineFileSend.sendFile`, `FileTransfer.FileUpload`, `AsynFileUpload`, `sendFileMessage`.")
$lines.Add("3. Bridge/IPC/plugin map: `HttpServerLib`, plugin loaders, local HTTP, named pipes, command-line switches, services.")
($lines -join "`n") + "`n" | Set-Content -LiteralPath $reportFullPath -Encoding UTF8
[pscustomobject]@{
ok = $true
json_path = $jsonPath
report_path = $reportFullPath
samples_total = $summary.samples_total
samples_present = $summary.samples_present
hash_matches = $summary.hash_matches
originals_copied = $false
originals_modified = $false
} | ConvertTo-Json -Depth 4

View File

@@ -0,0 +1,537 @@
param(
[string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il",
[string]$BinaryDir = "runs/offline-real-client-window/full/zyl/Impp",
[string]$OutputDir = "runs/offline-broute-reverse",
[string]$ReportPath = "docs/source-discovery/2026-07-12-broute-bridge-static-map.md",
[int]$WindowRadius = 4,
[int]$MaxEvidencePerCandidate = 18
)
$ErrorActionPreference = "Stop"
$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
$ilDirFull = Join-Path $repo $IlDir
$binaryDirFull = Join-Path $repo $BinaryDir
$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
$textSources = @(
@{ path = "IMPlatformClient.exe.il"; role = "main client IL; login, plugin manager, local HTTP starter, chat/runtime" },
@{ path = "IMPP.Common.dll.il"; role = "common helpers; WinCommand, ProcessComm, DTOs" },
@{ path = "IMPP.ISphere.exe.il"; role = "ISphere companion app IL; CEF and command helpers" },
@{ path = "IMPP.UI.dll.il"; role = "UI/browser support IL" },
@{ path = "IMPP.Service.dll.il"; role = "file service implementation IL" },
@{ path = "smack.dll.il"; role = "XMPP/socks5/network IL" }
)
$binarySources = @(
@{ path = "HttpServerLib.dll"; role = "local HTTP server framework binary" },
@{ path = "IMPlatformClient.Web.exe"; role = "CEF/web helper process binary" },
@{ path = "INetwork.dll"; role = "native network abstraction" },
@{ path = "IOClientNetwork.dll"; role = "native network implementation" },
@{ path = "IMPlatformClient.exe"; role = "main client binary" }
)
$liveProbeSources = @(
"runs/returned-live-probe/isphere-live-probe-20260710-121958/isphere-live-probe-20260710-121958/services_registry_shortcuts.json",
"runs/returned-live-probe/isphere-live-probe-20260710-121958/isphere-live-probe-20260710-121958/network_inventory.json"
)
$candidates = @(
@{
key = "local_http_win_server"
display = "frmLogin.StartWinServer / HttpServerLib.HttpService"
category = "localhost_http"
classification = "requires_logged_in_process"
usable_for_broute_send = $false
recommendation = "do_not_pursue_before_in_process_adapter"
reason = "Static IL builds a local HTTP service from logged-in user/auth state, but no send route or active live local listener was confirmed."
patterns = @("StartWinServer", "HttpServerLib", "HttpService::\.ctor", "HttpServer::Start", "GetFreePort", "0\.0\.0\.0", "messageAuth", "RepairDatabase")
},
@{
key = "http_route_framework"
display = "HttpServerLib route/module framework"
category = "localhost_http"
classification = "static_only_unknown"
usable_for_broute_send = $false
recommendation = "no_existing_ipc_first"
reason = "HttpServerLib has ServiceModule/RouteAttribute primitives, but client IL does not show RegisterModule or send-message routes."
patterns = @("RouteAttribute", "RouteMethod", "ServiceModule", "ServiceRoute", "RegisterModule", "OnGet\s*\(", "OnPost\s*\(", "ExecuteRoute", "SearchRoute")
},
@{
key = "plugin_named_pipe_stub"
display = "PluginLightAppMulProcessCommunication NamedPipeServerStream"
category = "named_pipe"
classification = "not_a_bridge"
usable_for_broute_send = $false
recommendation = "do_not_use"
reason = "A NamedPipeServerStream field exists, but StartLightAppMultProssCommunication has a one-instruction ret body."
patterns = @("NamedPipeServerStream", "PluginLightAppMulProcessCommunication", "StartLightAppMultProssCommunication", "MulProcess", "LightApp")
},
@{
key = "process_comm_wm_copydata"
display = "IMPP.Common.Helper.ProcessComm WM_COPYDATA helper"
category = "window_message"
classification = "static_only_unknown"
usable_for_broute_send = $false
recommendation = "not_a_send_bridge"
reason = "ProcessComm can send WM_COPYDATA to a foreground or titled window, but no receive handler or send-command contract is confirmed."
patterns = @("IMPP\.Common\.Helper\.ProcessComm", "\bProcessComm\b", "COPYDATASTRUCT", "WM_COPYDATA", "SendMessageToTargetWindow", "FindWindow\(string lpClassName", "GetForegroundWindow\(\)")
},
@{
key = "plugin_manager_command_surface"
display = "PluginManager / IMPlugin command surface"
category = "plugin"
classification = "requires_logged_in_process"
usable_for_broute_send = $false
recommendation = "plugin_extension_not_first"
reason = "Plugin evidence is UI/app-store/context-menu oriented and depends on logged-in PluginManager state; no Assembly.Load/LoadFrom or send API bridge was confirmed."
patterns = @("PluginManager", "IMPlugin::get_Command", "LoadPluginContextMenu", "FrmAppStore", "FrmCefHomePage", "ShowPlugins", "Assembly\.Load", "LoadFrom", "AddPluginInfo")
},
@{
key = "cef_web_helper"
display = "IMPlatformClient.Web / CEF helper"
category = "child_process"
classification = "requires_logged_in_process"
usable_for_broute_send = $false
recommendation = "preview_only_not_send"
reason = "The web helper/CEF surface exists, but static evidence points to UI/plugin browser support, not an external send/file API."
patterns = @("IMPlatformClient\.Web", "CefProcessName", "CefRuntime", "WinCefBrowser", "NavigateTo", "SendProcessMessage", "V8Context")
},
@{
key = "native_network_stack"
display = "INetwork / IOClientNetwork native stack"
category = "native_network"
classification = "not_a_bridge"
usable_for_broute_send = $false
recommendation = "do_not_pursue_as_ipc"
reason = "Native NETIO send/recv symbols are low-level transport, not a local command bridge into logged-in chat objects."
patterns = @("INetwork", "IOClientNetwork", "NETIO_", "NETIO_C_", "StreamClient", "RegistRecvCallback", "SendPacket", "BasePipe")
},
@{
key = "live_probe_named_pipe"
display = "returned live-probe named pipe inventory"
category = "named_pipe"
classification = "static_only_unknown"
usable_for_broute_send = $false
recommendation = "do_not_assume_isphere_api"
reason = "Live probe saw \\.\\pipe\\zfpinject-msg-server, but no matching iSphere static string or send contract was found in the configured samples."
patterns = @("zfpinject-msg-server", "named_pipes", "connections", "remote_port", "10088")
},
@{
key = "local_tcp_listener_candidates"
display = "local TcpListener candidates"
category = "tcp_listener"
classification = "not_a_bridge"
usable_for_broute_send = $false
recommendation = "not_existing_ipc"
reason = "TcpListener evidence is tied to TCP file manage or smack socks5, not a command API for text/file send. Returned live probe had only one remote XMPP connection."
patterns = @("TcpListener", "TCPFileManager::_listener", "TCPSocks5Server", "GetActiveTcpListeners", "BeginAcceptSocket", "remote_port")
}
)
function Get-RelativePath([string]$Path) {
if ($Path.StartsWith($repo, [System.StringComparison]::OrdinalIgnoreCase)) {
return $Path.Substring($repo.Length).TrimStart('\', '/')
}
return $Path
}
function Get-TextEvidenceKind([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 "\bcall(?:virt)?\b") { return "callsite" }
if ($Line -match "\bnewobj\b") { return "constructor_call" }
if ($Line -match "\bldstr\b") { return "string_literal" }
if ($Line -match "^\s*(instance|static|StartWinServer|GetFreePort|SendMessageToTargetWindow)\b.*\(") { return "signature_continuation" }
return "reference"
}
function Get-MethodContext($Lines, [int]$Index) {
$start = [Math]::Max(0, $Index - 120)
$methodHeader = $null
$classHeader = $null
for ($i = $Index; $i -ge $start; $i--) {
$line = $Lines[$i]
if ($null -eq $methodHeader -and $line -match "^\s*\.method\b") {
$methodHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($null -eq $classHeader -and $line -match "^\s*\.class\b") {
$classHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($methodHeader -and $classHeader) { break }
}
[pscustomobject]@{ method_header = $methodHeader; class_header = $classHeader }
}
function New-TextEvidence($Lines, [int]$Index, [string]$SourceRel) {
$from = [Math]::Max(0, $Index - $WindowRadius)
$to = [Math]::Min($Lines.Count - 1, $Index + $WindowRadius)
$window = New-Object System.Collections.Generic.List[object]
for ($i = $from; $i -le $to; $i++) {
$window.Add([pscustomobject]@{ line_number = $i + 1; text = $Lines[$i].TrimEnd() })
}
$context = Get-MethodContext -Lines $Lines -Index $Index
[pscustomobject]@{
source = $SourceRel
source_type = "text_il"
line_number = $Index + 1
string_index = $null
kind = Get-TextEvidenceKind -Line $Lines[$Index]
text = $Lines[$Index].Trim()
method_header = $context.method_header
class_header = $context.class_header
window = $window
}
}
function Get-PrintableStrings([string]$Path, [int]$MinLength = 4) {
$bytes = [System.IO.File]::ReadAllBytes($Path)
$strings = New-Object System.Collections.Generic.List[string]
$sb = New-Object System.Text.StringBuilder
foreach ($b in $bytes) {
if ($b -ge 32 -and $b -le 126) {
[void]$sb.Append([char]$b)
} else {
if ($sb.Length -ge $MinLength) { $strings.Add($sb.ToString()) }
$sb.Clear() | Out-Null
}
}
if ($sb.Length -ge $MinLength) { $strings.Add($sb.ToString()) }
$sb = New-Object System.Text.StringBuilder
for ($i = 0; $i -lt ($bytes.Length - 1); $i += 2) {
$b = $bytes[$i]
$z = $bytes[$i + 1]
if ($z -eq 0 -and $b -ge 32 -and $b -le 126) {
[void]$sb.Append([char]$b)
} else {
if ($sb.Length -ge $MinLength) { $strings.Add($sb.ToString()) }
$sb.Clear() | Out-Null
}
}
if ($sb.Length -ge $MinLength) { $strings.Add($sb.ToString()) }
return $strings.ToArray()
}
function Get-HttpServerReflection([string]$Path) {
$result = [ordered]@{ path = Get-RelativePath -Path $Path; ok = $false; error = ""; types = @() }
try {
$asm = [System.Reflection.Assembly]::LoadFile($Path)
$types = New-Object System.Collections.Generic.List[object]
foreach ($type in $asm.GetTypes()) {
if ($type.FullName -notmatch "HTTPServerLib\.(HttpServer|HttpService|ServiceModule|ServiceRoute|RouteAttribute|IServer|ActionResult)") { continue }
$ctors = @($type.GetConstructors([System.Reflection.BindingFlags]'Public,NonPublic,Instance') | ForEach-Object {
$params = @($_.GetParameters() | ForEach-Object { $_.ParameterType.Name + " " + $_.Name })
[pscustomobject]@{ is_public = $_.IsPublic; signature = "$($type.Name)($([string]::Join(', ', $params)))" }
})
$methods = @($type.GetMethods([System.Reflection.BindingFlags]'Public,NonPublic,Instance,Static,DeclaredOnly') | ForEach-Object {
$params = @($_.GetParameters() | ForEach-Object { $_.ParameterType.Name + " " + $_.Name })
[pscustomobject]@{ name = $_.Name; signature = "$($_.ReturnType.Name) $($_.Name)($([string]::Join(', ', $params)))" }
})
$types.Add([pscustomobject]@{ full_name = $type.FullName; constructors = $ctors; methods = $methods })
}
$result.ok = $true
$result.types = $types.ToArray()
} catch {
$result.error = $_.Exception.Message
}
return [pscustomobject]$result
}
$textSourceResults = New-Object System.Collections.Generic.List[object]
$binarySourceResults = New-Object System.Collections.Generic.List[object]
$candidateBuckets = @{}
foreach ($candidate in $candidates) {
$candidateBuckets[[string]$candidate['key']] = New-Object System.Collections.Generic.List[object]
}
foreach ($source in $textSources) {
$sourceFullPath = Join-Path $ilDirFull ([string]$source['path'])
$sourceRel = Get-RelativePath -Path $sourceFullPath
if (-not (Test-Path -LiteralPath $sourceFullPath -PathType Leaf)) {
$textSourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $false; line_count = 0; size_bytes = $null })
continue
}
$item = Get-Item -LiteralPath $sourceFullPath
$lines = [System.IO.File]::ReadAllLines($sourceFullPath)
$textSourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $true; line_count = $lines.Count; size_bytes = $item.Length })
foreach ($candidate in $candidates) {
$key = [string]$candidate['key']
$compiled = @($candidate['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
foreach ($rx in $compiled) {
if ($rx.IsMatch($line)) {
$candidateBuckets[$key].Add((New-TextEvidence -Lines $lines -Index $i -SourceRel $sourceRel))
break
}
}
}
}
}
foreach ($source in $binarySources) {
$sourceFullPath = Join-Path $binaryDirFull ([string]$source['path'])
$sourceRel = Get-RelativePath -Path $sourceFullPath
if (-not (Test-Path -LiteralPath $sourceFullPath -PathType Leaf)) {
$binarySourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $false; string_count = 0; size_bytes = $null })
continue
}
$item = Get-Item -LiteralPath $sourceFullPath
$strings = Get-PrintableStrings -Path $sourceFullPath -MinLength 4
$binarySourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $true; string_count = $strings.Count; size_bytes = $item.Length })
foreach ($candidate in $candidates) {
$key = [string]$candidate['key']
$compiled = @($candidate['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
for ($i = 0; $i -lt $strings.Count; $i++) {
$s = $strings[$i]
foreach ($rx in $compiled) {
if ($rx.IsMatch($s)) {
$candidateBuckets[$key].Add([pscustomobject]@{
source = $sourceRel
source_type = "binary_string"
line_number = $null
string_index = $i
kind = "binary_string"
text = $s
method_header = $null
class_header = $null
window = @()
})
break
}
}
}
}
}
$liveProbe = New-Object System.Collections.Generic.List[object]
foreach ($relPath in $liveProbeSources) {
$fullPath = Join-Path $repo $relPath
if (Test-Path -LiteralPath $fullPath -PathType Leaf) {
$raw = Get-Content -LiteralPath $fullPath -Raw
$liveProbe.Add([pscustomobject]@{ path = $relPath; exists = $true; length = $raw.Length; data = ($raw | ConvertFrom-Json) })
foreach ($candidate in $candidates) {
$key = [string]$candidate['key']
$compiled = @($candidate['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
foreach ($rx in $compiled) {
if ($rx.IsMatch($raw)) {
$candidateBuckets[$key].Add([pscustomobject]@{
source = $relPath
source_type = "live_probe_json"
line_number = $null
string_index = $null
kind = "live_probe_json"
text = ($raw -replace "\s+", " ").Trim()
method_header = $null
class_header = $null
window = @()
})
break
}
}
}
} else {
$liveProbe.Add([pscustomobject]@{ path = $relPath; exists = $false; length = 0; data = $null })
}
}
$httpServerPath = Join-Path $binaryDirFull "HttpServerLib.dll"
$httpReflection = if (Test-Path -LiteralPath $httpServerPath -PathType Leaf) { Get-HttpServerReflection -Path $httpServerPath } else { [pscustomobject]@{ path = Get-RelativePath -Path $httpServerPath; ok = $false; error = "missing"; types = @() } }
$httpReflectionPath = Join-Path $outDir "httpserverlib-reflection.json"
$httpReflection | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $httpReflectionPath -Encoding UTF8
if ($httpReflection.ok) {
$reflectionText = ($httpReflection.types | ConvertTo-Json -Depth 8 -Compress)
foreach ($candidate in $candidates) {
$key = [string]$candidate['key']
$compiled = @($candidate['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
foreach ($rx in $compiled) {
if ($rx.IsMatch($reflectionText)) {
$candidateBuckets[$key].Add([pscustomobject]@{
source = Get-RelativePath -Path $httpReflectionPath
source_type = "reflection"
line_number = $null
string_index = $null
kind = "reflection_metadata"
text = "HttpServerLib reflection exposes matching types/methods; see httpserverlib-reflection.json"
method_header = $null
class_header = $null
window = @()
})
break
}
}
}
}
$candidateResults = New-Object System.Collections.Generic.List[object]
foreach ($candidate in $candidates) {
$key = [string]$candidate['key']
$allEvidence = $candidateBuckets[$key].ToArray()
$evidenceForReport = @(
$allEvidence |
Sort-Object @{ Expression = { if ($_.source_type -eq "text_il") { 0 } elseif ($_.source_type -eq "reflection") { 1 } elseif ($_.source_type -eq "live_probe_json") { 2 } else { 3 } } }, source, line_number, string_index |
Select-Object -First $MaxEvidencePerCandidate
)
$classification = if ($allEvidence.Count -eq 0) { "not_found" } else { [string]$candidate['classification'] }
$candidateResults.Add([pscustomobject]@{
key = $key
display = $candidate['display']
category = $candidate['category']
classification = $classification
usable_for_broute_send = [bool]$candidate['usable_for_broute_send']
recommendation = $candidate['recommendation']
reason = $candidate['reason']
match_count = $allEvidence.Count
evidence = $evidenceForReport
})
}
$recommendation = [pscustomobject]@{
pursue_existing_ipc_or_plugin_first = $false
decision = "in_process_adapter_research"
fallback_boundary = "external_sidecar_preview_only_until_bridge_exists"
rationale = "Offline static evidence found no existing local IPC/plugin route that exposes send-message or send-file. HttpServerLib and plugin surfaces either require logged-in runtime state or are UI/framework-only; the named-pipe stub is empty."
}
$summary = [pscustomobject]@{
generated_at = (Get-Date).ToUniversalTime().ToString("o")
repository = $repo
il_dir = $IlDir
binary_dir = $BinaryDir
text_sources = $textSourceResults
binary_sources = $binarySourceResults
live_probe = $liveProbe
httpserverlib_reflection = Get-RelativePath -Path $httpReflectionPath
candidates = $candidateResults
recommendation = $recommendation
originals_copied = $false
originals_modified = $false
}
$jsonPath = Join-Path $outDir "bridge-map.json"
$summary | ConvertTo-Json -Depth 14 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$linesOut = New-Object System.Collections.Generic.List[string]
$linesOut.Add("# B-Route Bridge/IPC/Plugin Static Map")
$linesOut.Add("")
$linesOut.Add("Date: 2026-07-12")
$linesOut.Add("")
$linesOut.Add("## Scope")
$linesOut.Add("")
$linesOut.Add("This report uses offline IL, binary string metadata, reflection metadata for ``HttpServerLib.dll``, and returned live-probe JSON. It does not log in, open sockets, attach hooks, inject into a process, replay traffic, or mutate client binaries.")
$linesOut.Add("")
$linesOut.Add("Machine-readable evidence: ``$OutputDir/bridge-map.json``")
$linesOut.Add("Reflection metadata: ``$OutputDir/httpserverlib-reflection.json``")
$linesOut.Add("")
$linesOut.Add("## Recommendation")
$linesOut.Add("")
$linesOut.Add("| Question | Answer |")
$linesOut.Add("| --- | --- |")
$linesOut.Add("| Should B-route pursue existing IPC/plugin before an in-process adapter? | **No** |")
$linesOut.Add("| Offline decision | ``$($recommendation.decision)`` |")
$linesOut.Add("| External sidecar boundary | ``$($recommendation.fallback_boundary)`` |")
$linesOut.Add("| Reason | $($recommendation.rationale) |")
$linesOut.Add("")
$linesOut.Add("## Sources")
$linesOut.Add("")
$linesOut.Add("### Text/IL sources")
$linesOut.Add("")
$linesOut.Add("| Source | Role | Exists | Lines | Size bytes |")
$linesOut.Add("| --- | --- | --- | ---: | ---: |")
foreach ($sourceResult in $textSourceResults) {
$exists = if ($sourceResult.exists) { "yes" } else { "no" }
$sizeText = if ($null -ne $sourceResult.size_bytes) { [string]$sourceResult.size_bytes } else { "" }
$linesOut.Add("| ``$($sourceResult.path)`` | $($sourceResult.role) | $exists | $($sourceResult.line_count) | $sizeText |")
}
$linesOut.Add("")
$linesOut.Add("### Binary/string sources")
$linesOut.Add("")
$linesOut.Add("| Source | Role | Exists | Strings | Size bytes |")
$linesOut.Add("| --- | --- | --- | ---: | ---: |")
foreach ($sourceResult in $binarySourceResults) {
$exists = if ($sourceResult.exists) { "yes" } else { "no" }
$sizeText = if ($null -ne $sourceResult.size_bytes) { [string]$sourceResult.size_bytes } else { "" }
$linesOut.Add("| ``$($sourceResult.path)`` | $($sourceResult.role) | $exists | $($sourceResult.string_count) | $sizeText |")
}
$linesOut.Add("")
$linesOut.Add("## Candidate classification")
$linesOut.Add("")
$linesOut.Add("| Candidate | Category | Classification | Usable for B-route send | Recommendation | Matches |")
$linesOut.Add("| --- | --- | --- | --- | --- | ---: |")
foreach ($candidateResult in $candidateResults) {
$usable = if ($candidateResult.usable_for_broute_send) { "yes" } else { "no" }
$linesOut.Add("| ``$($candidateResult.display)`` | ``$($candidateResult.category)`` | ``$($candidateResult.classification)`` | $usable | ``$($candidateResult.recommendation)`` | $($candidateResult.match_count) |")
}
$linesOut.Add("")
$linesOut.Add("## Verified facts")
$linesOut.Add("")
$linesOut.Add("- ``frmLogin.StartWinServer`` constructs ``HTTPServerLib.HttpService`` on ``0.0.0.0`` and starts ``HttpServer.Start`` in a thread, but it depends on ``IMPPManager.UserInfo`` and ``ServiceManager.UnifiedAuthentication`` state.")
$linesOut.Add("- ``HttpServerLib.dll`` exposes route/module primitives such as ``HttpService.RegisterModule``, ``ServiceModule``, ``ServiceRoute``, ``RouteAttribute``, ``OnGet``, and ``OnPost``.")
$linesOut.Add("- Main client IL does not show a concrete ``RegisterModule`` call or send-message/send-file HTTP route registration.")
$linesOut.Add("- ``PluginLightAppMulProcessCommunication`` declares a ``NamedPipeServerStream`` field, but ``StartLightAppMultProssCommunication`` returns immediately.")
$linesOut.Add("- Returned live probe showed one remote TCP connection to port ``10088`` and a named pipe ``\\.\\pipe\\zfpinject-msg-server``; neither proves an iSphere send API.")
$linesOut.Add("- ``PluginManager``/``IMPlugin`` evidence is UI/app-store/context-menu oriented; no local assembly-load plugin bridge or send route was confirmed.")
$linesOut.Add("")
$linesOut.Add("## Candidate evidence")
foreach ($candidateResult in $candidateResults) {
$linesOut.Add("")
$linesOut.Add("### $($candidateResult.display)")
$linesOut.Add("")
$linesOut.Add("Classification: ``$($candidateResult.classification)``; usable for B-route send: ``$($candidateResult.usable_for_broute_send)``; matches: $($candidateResult.match_count).")
$linesOut.Add("")
$linesOut.Add("Reason: $($candidateResult.reason)")
if (@($candidateResult.evidence).Count -eq 0) {
$linesOut.Add("")
$linesOut.Add("No evidence found in configured offline sources.")
continue
}
$linesOut.Add("")
$linesOut.Add("| Source | Kind | Snippet | Context |")
$linesOut.Add("| --- | --- | --- | --- |")
foreach ($evidence in $candidateResult.evidence) {
$sourceLoc = if ($evidence.line_number) { "$($evidence.source):$($evidence.line_number)" } elseif ($null -ne $evidence.string_index) { "$($evidence.source)#str$($evidence.string_index)" } else { $evidence.source }
$method = if ($evidence.method_header) { "L$($evidence.method_header.line_number): $($evidence.method_header.text)" } else { "" }
$snippet = (($evidence.text -replace "\|", "\\|") -replace "`r?`n", " ")
if ($snippet.Length -gt 220) { $snippet = $snippet.Substring(0, 220) + "..." }
$method = ($method -replace "\|", "\\|")
$linesOut.Add("| ``$sourceLoc`` | ``$($evidence.kind)`` | ``$snippet`` | ``$method`` |")
}
}
$linesOut.Add("")
$linesOut.Add("## Decision")
$linesOut.Add("")
$linesOut.Add("No existing IPC/plugin/local HTTP bridge is confirmed usable for B-route text send or file send. The next B-route branch should be ``in_process_adapter_research``. Until that exists, an external sidecar can only do preview/probe work, while A-route/RPA remains backup-only.")
$linesOut.Add("")
$linesOut.Add("## Next work")
$linesOut.Add("")
$linesOut.Add("1. Update the B-route next plan and capability source matrix with ``in_process_adapter_research`` as the offline decision.")
$linesOut.Add("2. Create a separate plan before implementing any in-process adapter work.")
$linesOut.Add("3. Do not promote RPA beyond backup in this branch.")
($linesOut -join "`n") + "`n" | Set-Content -LiteralPath $reportFullPath -Encoding UTF8
$requiredNames = @("HttpServerLib", "NamedPipe", "Plugin", "IMPlatformClient.Web", "ProcessComm", "INetwork", "IOClientNetwork", "in_process_adapter_research")
$reportText = Get-Content -LiteralPath $reportFullPath -Raw
$missing = @($requiredNames | Where-Object { $reportText -notlike "*$_*" })
if ($missing.Count -gt 0) {
throw "Report missing required names: $($missing -join ', ')"
}
[pscustomobject]@{
ok = $true
json_path = $jsonPath
report_path = $reportFullPath
reflection_path = $httpReflectionPath
candidates = $candidateResults.Count
decision = $recommendation.decision
pursue_existing_ipc_or_plugin_first = $false
originals_copied = $false
originals_modified = $false
} | ConvertTo-Json -Depth 6

View File

@@ -0,0 +1,342 @@
param(
[string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il",
[string]$OutputDir = "runs/offline-broute-reverse",
[string]$ReportPath = "docs/source-discovery/2026-07-12-broute-file-send-static-map.md",
[int]$WindowRadius = 5,
[int]$MaxEvidencePerTarget = 18
)
$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 client IL; UC_FileSend, OffLineFileSend, MessageScheduling" },
@{ path = "IMPP.Service.dll.il"; role = "file transfer service implementation" },
@{ path = "IMPP.ServiceBase.dll.il"; role = "file transfer contracts, parameters, and result DTOs" },
@{ path = "IMPP.Interface.dll.il"; role = "transport/event interface contracts" },
@{ path = "smack.dll.il"; role = "Chat.sendFileMessage and XMPP message construction" },
@{ path = "TcpFileTransfer.dll.il"; role = "native TCP transfer candidate; IL may be unavailable" },
@{ path = "IMPP.Model.dll.il"; role = "chat record models if extracted" }
)
$targets = @(
@{
key = "IMPP.Client.OffLineFileSend.sendFile"
display = "IMPP.Client.OffLineFileSend.sendFile"
phase = "upload"
intent = "offline file upload orchestration from UI file sender"
patterns = @("OffLineFileSend::sendFile", "^\s*sendFile\(\) cil managed")
},
@{
key = "IMPP.Client.OffLineFileSend.trans_UploadCompleted"
display = "IMPP.Client.OffLineFileSend.trans_UploadCompleted"
phase = "upload_to_message_boundary"
intent = "upload-completed handler that converts FileUploadResult.FileID into a chat file message"
patterns = @("OffLineFileSend::trans_UploadCompleted", "trans_UploadCompleted\(string fileId\)")
},
@{
key = "IMPP.Service.BLL.FileTransfer.FileUpload"
display = "IMPP.Service.BLL.FileTransfer.FileUpload"
phase = "upload"
intent = "synchronous service upload entry returning FileUploadResult"
patterns = @("FileTransfer::FileUpload", "FileUpload\(class \[IMPP\.ServiceBase\].*FileUploadPara")
},
@{
key = "IMPP.Service.BLL.FileTransfer.AsynFileUpload"
display = "IMPP.Service.BLL.FileTransfer.AsynFileUpload"
phase = "upload"
intent = "asynchronous upload queue entry"
patterns = @("FileTransfer::AsynFileUpload", "AsynFileUpload\(class \[IMPP\.ServiceBase\].*FileUploadPara")
},
@{
key = "FileUploadPara"
display = "FileUploadPara"
phase = "upload_parameters"
intent = "host/port/domain/local file path/cache/timeout/upload flags"
patterns = @("FileUploadPara", "FileUploadPara::\.ctor")
},
@{
key = "FileUploadResult.FileID"
display = "FileUploadResult.FileID"
phase = "upload_result"
intent = "server-side file id and URL returned by upload"
patterns = @("FileUploadResult::get_FileID", "FileUploadResult::set_FileID", "FileUploadResult", "get_FileID\(\) cil managed")
},
@{
key = "MessageScheduling.SendFileMessage"
display = "MessageScheduling.SendFileMessage"
phase = "message"
intent = "scheduled/file-message finalization path using RosterContactsArgs and FileTransferArgs"
patterns = @("MessageScheduling::SendFileMessage", "SendFileMessage\(class IMPP\.Client\.Business\.RosterContacts\.RosterContactsArgs")
},
@{
key = "Chat.sendFileMessage"
display = "Chat.sendFileMessage"
phase = "message"
intent = "smack API that sends the XMPP file message after upload metadata is known"
patterns = @("Chat::sendFileMessage", "P2PChat::sendFileMessage", "ChatRoom::sendFileMessage", "sendFileMessage\(string p_message")
},
@{
key = "Required values: path id size target jid"
display = "Required values: path id size target jid"
phase = "requirements"
intent = "static evidence for local file path, remote folder/file id, file size/name, target JID/chat, and server auth"
patterns = @("get_LocalFilePath", "get_RemoteFolder", "get__localFilePath", "get__fileSize", "FileInfo::get_Length", "FileSystemInfo::get_Name", "get_RosterJid", "GetChat\(", "HTTPFileServer", "UnifiedAuthentication", "Auth::get_token")
}
)
function Get-RelativePath([string]$Path) {
if ($Path.StartsWith($repo, [System.StringComparison]::OrdinalIgnoreCase)) {
return $Path.Substring($repo.Length).TrimStart('\', '/')
}
return $Path
}
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 "\bcall(?:virt)?\b") { return "callsite" }
if ($Line -match "\bnewobj\b") { return "constructor_call" }
if ($Line -match "\bldstr\b") { return "string_literal" }
if ($Line -match "^\s*(instance|static|FileUpload|SendFileMessage|sendFileMessage|sendFile|trans_UploadCompleted)\b.*\(") { return "signature_continuation" }
return "reference"
}
function Get-MethodContext($Lines, [int]$Index) {
$start = [Math]::Max(0, $Index - 120)
$methodHeader = $null
$classHeader = $null
for ($i = $Index; $i -ge $start; $i--) {
$line = $Lines[$i]
if ($null -eq $methodHeader -and $line -match "^\s*\.method\b") {
$methodHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($null -eq $classHeader -and $line -match "^\s*\.class\b") {
$classHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($methodHeader -and $classHeader) { break }
}
[pscustomobject]@{ method_header = $methodHeader; class_header = $classHeader }
}
function New-Evidence($Lines, [int]$Index, [string]$SourceRel) {
$from = [Math]::Max(0, $Index - $WindowRadius)
$to = [Math]::Min($Lines.Count - 1, $Index + $WindowRadius)
$window = New-Object System.Collections.Generic.List[object]
for ($i = $from; $i -le $to; $i++) {
$window.Add([pscustomobject]@{ line_number = $i + 1; text = $Lines[$i].TrimEnd() })
}
$context = Get-MethodContext -Lines $Lines -Index $Index
[pscustomobject]@{
source = $SourceRel
line_number = $Index + 1
kind = Get-EvidenceKind -Line $Lines[$Index]
text = $Lines[$Index].Trim()
method_header = $context.method_header
class_header = $context.class_header
window = $window
}
}
function Get-Classification($Evidence) {
$kinds = @($Evidence | ForEach-Object { $_.kind })
if ($kinds -contains "type_definition" -or $kinds -contains "method_header" -or $kinds -contains "signature_continuation" -or $kinds -contains "method_end") { return "confirmed_signature" }
if ($kinds -contains "callsite" -or $kinds -contains "constructor_call") { return "confirmed_callsite" }
if ($kinds.Count -gt 0 -and @($kinds | Where-Object { $_ -ne "string_literal" }).Count -eq 0) { return "string_only" }
if ($kinds.Count -gt 0) { return "confirmed_callsite" }
return "not_found"
}
$sourceResults = New-Object System.Collections.Generic.List[object]
$targetBuckets = @{}
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$targetBuckets[$targetKey] = New-Object System.Collections.Generic.List[object]
}
foreach ($source in $sources) {
$sourcePath = [string]$source['path']
$sourceFullPath = Join-Path $ilDirFull $sourcePath
$sourceRel = Get-RelativePath -Path $sourceFullPath
if (-not (Test-Path -LiteralPath $sourceFullPath -PathType Leaf)) {
$sourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $false; line_count = 0; size_bytes = $null })
continue
}
$item = Get-Item -LiteralPath $sourceFullPath
$lines = [System.IO.File]::ReadAllLines($sourceFullPath)
$sourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $true; line_count = $lines.Count; size_bytes = $item.Length })
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$compiled = @($target['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
foreach ($rx in $compiled) {
if ($rx.IsMatch($line)) {
$targetBuckets[$targetKey].Add((New-Evidence -Lines $lines -Index $i -SourceRel $sourceRel))
break
}
}
}
}
}
$targetResults = New-Object System.Collections.Generic.List[object]
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$allEvidence = $targetBuckets[$targetKey].ToArray()
$evidenceForReport = @(
$allEvidence |
Sort-Object @{ Expression = { if ($_.kind -in @("type_definition", "method_header", "signature_continuation", "method_end")) { 0 } elseif ($_.kind -in @("callsite", "constructor_call")) { 1 } elseif ($_.kind -eq "string_literal") { 2 } else { 3 } } }, source, line_number |
Select-Object -First $MaxEvidencePerTarget
)
$targetResults.Add([pscustomobject]@{
key = $targetKey
display = $target['display']
phase = $target['phase']
intent = $target['intent']
classification = Get-Classification -Evidence $allEvidence
match_count = $allEvidence.Count
evidence = $evidenceForReport
})
}
$requirements = @(
[pscustomobject]@{ value = "local file path"; evidence = "OffLineFileSend constructor receives localFilePath; sendFile uses get__localFilePath; MessageScheduling.SendFileMessage uses FileTransferArgs.get_LocalFilePath."; status = "required_confirmed" },
[pscustomobject]@{ value = "server file id / remote folder"; evidence = "Upload returns FileUploadResult.FileID; trans_UploadCompleted(fileId) passes it to Chat.sendFileMessage and Packet.set_id. MessageScheduling path uses FileTransferArgs.get_RemoteFolder."; status = "required_confirmed" },
[pscustomobject]@{ value = "file name and file size"; evidence = "SendFileMessage builds OFFLINE_FILE_TRANSFER payload from FileInfo/FileSystemInfo name and length; OffLineFileSend keeps _fileSize."; status = "required_confirmed" },
[pscustomobject]@{ value = "target JID / chat object"; evidence = "UC_FileSend and MessageScheduling both require a live smack Chat; scheduled path derives it from RosterContactsArgs.get_RosterJid + UtilsChat.GetChat."; status = "required_confirmed" },
[pscustomobject]@{ value = "HTTP file server and auth"; evidence = "FileUploadPara construction uses Config.ServerInfo.HTTPFileServer IP/Port/domain; service upload builds /FS/auth/resource/upload URL with UnifiedAuthentication token/app key/client secret/time/user id."; status = "required_confirmed" },
[pscustomobject]@{ value = "file hash"; evidence = "No file-transfer-path MD5/SHA/checksum requirement was confirmed in the configured IL. MD5 hits belong to image/RTF or auth digest areas, not the offline file-send path."; status = "not_confirmed_in_file_send_path" }
)
$summary = [pscustomobject]@{
generated_at = (Get-Date).ToUniversalTime().ToString("o")
repository = $repo
il_dir = $IlDir
sources = $sourceResults
targets = $targetResults
phase_decision = "Offline static evidence shows upload first, then chat file-message finalization. Direct Chat.sendFileMessage alone is not enough unless a valid uploaded file id/remote folder already exists."
requirements = $requirements
originals_copied = $false
originals_modified = $false
}
$jsonPath = Join-Path $outDir "file-send-map.json"
$summary | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$linesOut = New-Object System.Collections.Generic.List[string]
$linesOut.Add("# B-Route File Send Static Map")
$linesOut.Add("")
$linesOut.Add("Date: 2026-07-12")
$linesOut.Add("")
$linesOut.Add("## Scope")
$linesOut.Add("")
$linesOut.Add("This report uses offline IL only. It does not upload files, send file messages, replay traffic, inject into a process, or mutate the original iSphere binaries.")
$linesOut.Add("")
$linesOut.Add("Machine-readable evidence: ``$OutputDir/file-send-map.json``")
$linesOut.Add("")
$linesOut.Add("## Sources")
$linesOut.Add("")
$linesOut.Add("| Source | Role | Exists | Lines | Size bytes |")
$linesOut.Add("| --- | --- | --- | ---: | ---: |")
foreach ($sourceResult in $sourceResults) {
$exists = if ($sourceResult.exists) { "yes" } else { "no" }
$sizeText = if ($null -ne $sourceResult.size_bytes) { [string]$sourceResult.size_bytes } else { "" }
$linesOut.Add("| ``$($sourceResult.path)`` | $($sourceResult.role) | $exists | $($sourceResult.line_count) | $sizeText |")
}
$linesOut.Add("")
$linesOut.Add("## Target classification")
$linesOut.Add("")
$linesOut.Add("| Target | Phase | Intent | Classification | Matches |")
$linesOut.Add("| --- | --- | --- | --- | ---: |")
foreach ($targetResult in $targetResults) {
$linesOut.Add("| ``$($targetResult.display)`` | ``$($targetResult.phase)`` | $($targetResult.intent) | ``$($targetResult.classification)`` | $($targetResult.match_count) |")
}
$linesOut.Add("")
$linesOut.Add("## Upload step vs chat-message step")
$linesOut.Add("")
$linesOut.Add("| Step | Static evidence | Business meaning |")
$linesOut.Add("| --- | --- | --- |")
$linesOut.Add("| 1. Upload | ``IMPP.Client.OffLineFileSend.sendFile`` constructs ``FileUploadPara`` and calls ``IFileTransfer.FileUpload``; ``IMPP.Service.BLL.FileTransfer.FileUpload`` delegates to ``SyncFileTransfer`` and private ``Upload``. | The local file must be uploaded to the HTTP file service first. |")
$linesOut.Add("| 2. Upload result | ``FileUploadResult.FileID`` is read; upload notification calls ``IMPP.Client.OffLineFileSend.trans_UploadCompleted(fileId)``. | The server-issued file id becomes the durable reference. |")
$linesOut.Add("| 3. Chat file message | ``trans_UploadCompleted`` and ``MessageScheduling.SendFileMessage`` build ``OFFLINE_FILE_TRANSFER;...`` payloads and call ``Chat.sendFileMessage``. | The chat send step publishes metadata/reference, not raw file bytes. |")
$linesOut.Add("")
$linesOut.Add("Conclusion: file send is upload-first, chat-message-second. A direct chat message is insufficient without a valid uploaded file id or remote folder reference.")
$linesOut.Add("")
$linesOut.Add("## Required values")
$linesOut.Add("")
$linesOut.Add("| Value | Status | Evidence |")
$linesOut.Add("| --- | --- | --- |")
foreach ($req in $requirements) {
$linesOut.Add("| $($req.value) | ``$($req.status)`` | $($req.evidence) |")
}
$linesOut.Add("")
$linesOut.Add("## Evidence excerpts")
foreach ($targetResult in $targetResults) {
$linesOut.Add("")
$linesOut.Add("### $($targetResult.display)")
$linesOut.Add("")
$linesOut.Add("Classification: ``$($targetResult.classification)``; phase: ``$($targetResult.phase)``; matches: $($targetResult.match_count).")
if (@($targetResult.evidence).Count -eq 0) {
$linesOut.Add("")
$linesOut.Add("No evidence found in configured offline IL sources.")
continue
}
$linesOut.Add("")
$linesOut.Add("| Source line | Kind | Snippet | Method context |")
$linesOut.Add("| --- | --- | --- | --- |")
foreach ($evidence in $targetResult.evidence) {
$method = if ($evidence.method_header) { "L$($evidence.method_header.line_number): $($evidence.method_header.text)" } else { "" }
$snippet = ($evidence.text -replace "\|", "\\|")
$method = ($method -replace "\|", "\\|")
$linesOut.Add("| ``$($evidence.source):$($evidence.line_number)`` | ``$($evidence.kind)`` | ``$snippet`` | ``$method`` |")
}
}
$linesOut.Add("")
$linesOut.Add("## Inference")
$linesOut.Add("")
$linesOut.Add("- High confidence: upload and file-message finalization are separate steps.")
$linesOut.Add("- High confidence: ``FileUploadPara`` needs HTTP file server host/port/domain plus local file path and upload options.")
$linesOut.Add("- High confidence: ``Chat.sendFileMessage`` produces the XMPP file-message envelope after file metadata is available.")
$linesOut.Add("- Medium confidence: B-route file send must either call the same logged-in service/runtime or reproduce the authenticated HTTP upload plus XMPP file-message sequence.")
$linesOut.Add("- Low confidence until bridge evidence: an external sidecar can obtain the same service/auth/chat objects without being inside the logged-in client process.")
$linesOut.Add("")
$linesOut.Add("## Decision")
$linesOut.Add("")
$linesOut.Add("Offline static evidence supports B-route research, but file sending needs more than one method call: upload first, then chat file-message finalization. The next blocker is reachability: whether an IPC/plugin/in-process bridge can access the logged-in ``IFileTransfer`` service and smack ``Chat`` object.")
$linesOut.Add("")
$linesOut.Add("## Next work")
$linesOut.Add("")
$linesOut.Add("1. Extract bridge/IPC/plugin candidates before coding any file-send adapter.")
$linesOut.Add("2. If a bridge exists, prototype non-mutating discovery first: service availability, chat object lookup, and upload endpoint metadata only.")
$linesOut.Add("3. Keep A-route/RPA backup-only.")
($linesOut -join "`n") + "`n" | Set-Content -LiteralPath $reportFullPath -Encoding UTF8
$requiredNames = @("IMPP.Client.OffLineFileSend.sendFile", "IMPP.Client.OffLineFileSend.trans_UploadCompleted", "IMPP.Service.BLL.FileTransfer.FileUpload", "IMPP.Service.BLL.FileTransfer.AsynFileUpload", "FileUploadPara", "sendFileMessage", "Upload step vs chat-message step")
$reportText = Get-Content -LiteralPath $reportFullPath -Raw
$missing = @($requiredNames | Where-Object { $reportText -notlike "*$_*" })
if ($missing.Count -gt 0) {
throw "Report missing required names: $($missing -join ', ')"
}
[pscustomobject]@{
ok = $true
json_path = $jsonPath
report_path = $reportFullPath
sources = $sourceResults.Count
targets = $targetResults.Count
classifications = @($targetResults | ForEach-Object { "$($_.display)=$($_.classification)" })
phase_decision = $summary.phase_decision
originals_copied = $false
originals_modified = $false
} | ConvertTo-Json -Depth 6

View File

@@ -0,0 +1,285 @@
param(
[string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il",
[string]$OutputDir = "runs/offline-broute-reverse",
[string]$ReportPath = "docs/source-discovery/2026-07-12-broute-text-send-static-map.md",
[int]$WindowRadius = 4,
[int]$MaxEvidencePerTarget = 18
)
$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 IL; chat UI, AppContextManager, scheduling call sites"
},
@{
path = "smack.dll.il"
role = "XMPP/smack managed IL; Chat and XMPPConnection implementation"
}
)
$targets = @(
@{
key = "AppContextManager.SendTxtMessageByJid"
display = "AppContextManager.SendTxtMessageByJid"
intent = "high-level text send entry exposed by AppContextManager"
patterns = @("AppContextManager::SendTxtMessageByJid", "\bSendTxtMessageByJid\b")
},
@{
key = "MessageScheduling.SendChatMessage"
display = "MessageScheduling.SendChatMessage"
intent = "message scheduling text/chat send helper"
patterns = @("MessageScheduling::SendChatMessage", "\bSendChatMessage\s*\(")
},
@{
key = "Chat.SendMessage"
display = "Chat.SendMessage"
intent = "smack Chat send API used by chat/UI code"
patterns = @("com\.vision\.smack\.Chat::SendMessage", "com\.vision\.smack\.Chat::sendMessage", "\bChat::SendMessage\b", "\bChat::sendMessage\b")
},
@{
key = "XMPPConnection.send"
display = "XMPPConnection.send"
intent = "lowest-level XMPP connection send primitive"
patterns = @("XMPPConnection::send\b", "\bXMPPConnection\.send\b")
},
@{
key = "MessageCenter send-related callbacks"
display = "MessageCenter send-related callbacks"
intent = "MessageCenter or IMPPManager message-center callbacks touching send/message flow"
patterns = @("GetMessageCenter\s*\(\)", "MessageCenter::.*Send", "MessageCenter.*Send", "class IMPP\.Client\.control\.MessageCenter", "IMPP\.Client\.control\.MessageCenter")
}
)
function Get-RelativePath([string]$Path) {
if ($Path.StartsWith($repo, [System.StringComparison]::OrdinalIgnoreCase)) {
return $Path.Substring($repo.Length).TrimStart('\', '/')
}
return $Path
}
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 "\bcall(?:virt)?\b") { return "callsite" }
if ($Line -match "\bldstr\b") { return "string_literal" }
if ($Line -match "^\s*(instance|static)\b.*\(") { return "signature_continuation" }
return "reference"
}
function Get-MethodContext($Lines, [int]$Index) {
$start = [Math]::Max(0, $Index - 90)
$methodHeader = $null
$classHeader = $null
for ($i = $Index; $i -ge $start; $i--) {
$line = $Lines[$i]
if ($null -eq $methodHeader -and $line -match "^\s*\.method\b") {
$methodHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($null -eq $classHeader -and $line -match "^\s*\.class\b") {
$classHeader = [pscustomobject]@{ line_number = $i + 1; text = $line.Trim() }
}
if ($methodHeader -and $classHeader) { break }
}
[pscustomobject]@{ method_header = $methodHeader; class_header = $classHeader }
}
function New-Evidence($Lines, [int]$Index, [string]$SourceRel) {
$from = [Math]::Max(0, $Index - $WindowRadius)
$to = [Math]::Min($Lines.Count - 1, $Index + $WindowRadius)
$window = New-Object System.Collections.Generic.List[object]
for ($i = $from; $i -le $to; $i++) {
$window.Add([pscustomobject]@{ line_number = $i + 1; text = $Lines[$i].TrimEnd() })
}
$context = Get-MethodContext -Lines $Lines -Index $Index
[pscustomobject]@{
source = $SourceRel
line_number = $Index + 1
kind = Get-EvidenceKind -Line $Lines[$Index]
text = $Lines[$Index].Trim()
method_header = $context.method_header
class_header = $context.class_header
window = $window
}
}
function Get-Classification($Evidence) {
$kinds = @($Evidence | ForEach-Object { $_.kind })
if ($kinds -contains "method_header" -or $kinds -contains "signature_continuation" -or $kinds -contains "method_end") { return "confirmed_signature" }
if ($kinds -contains "callsite") { return "confirmed_callsite" }
if ($kinds.Count -gt 0 -and @($kinds | Where-Object { $_ -ne "string_literal" }).Count -eq 0) { return "string_only" }
if ($kinds.Count -gt 0) { return "confirmed_callsite" }
return "not_found"
}
$sourceResults = New-Object System.Collections.Generic.List[object]
$targetBuckets = @{}
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$targetBuckets[$targetKey] = New-Object System.Collections.Generic.List[object]
}
foreach ($source in $sources) {
$sourcePath = [string]$source['path']
$sourceFullPath = Join-Path $ilDirFull $sourcePath
$sourceRel = Get-RelativePath -Path $sourceFullPath
if (-not (Test-Path -LiteralPath $sourceFullPath -PathType Leaf)) {
$sourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $false; line_count = 0; size_bytes = $null })
continue
}
$item = Get-Item -LiteralPath $sourceFullPath
$lines = [System.IO.File]::ReadAllLines($sourceFullPath)
$sourceResults.Add([pscustomobject]@{ path = $sourceRel; role = $source['role']; exists = $true; line_count = $lines.Count; size_bytes = $item.Length })
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$compiled = @($target['patterns'] | ForEach-Object { [regex]::new($_, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase) })
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
foreach ($rx in $compiled) {
if ($rx.IsMatch($line)) {
$targetBuckets[$targetKey].Add((New-Evidence -Lines $lines -Index $i -SourceRel $sourceRel))
break
}
}
}
}
}
$targetResults = New-Object System.Collections.Generic.List[object]
foreach ($target in $targets) {
$targetKey = [string]$target['key']
$allEvidence = $targetBuckets[$targetKey].ToArray()
$evidenceForReport = @(
$allEvidence |
Sort-Object @{ Expression = { if ($_.kind -in @("method_header", "signature_continuation", "method_end")) { 0 } elseif ($_.kind -eq "callsite") { 1 } elseif ($_.kind -eq "string_literal") { 2 } else { 3 } } }, line_number |
Select-Object -First $MaxEvidencePerTarget
)
$targetResults.Add([pscustomobject]@{
key = $targetKey
display = $target['display']
intent = $target['intent']
classification = Get-Classification -Evidence $allEvidence
match_count = $allEvidence.Count
evidence = $evidenceForReport
})
}
$summary = [pscustomobject]@{
generated_at = (Get-Date).ToUniversalTime().ToString("o")
repository = $repo
il_dir = $IlDir
sources = $sourceResults
targets = $targetResults
decision = "B-route text send remains plausible only if a bridge can enter the logged-in runtime or an existing IPC/API exposes the same call. Offline IL confirms call shape, but not runtime invocability."
originals_copied = $false
originals_modified = $false
}
$jsonPath = Join-Path $outDir "text-send-map.json"
$summary | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$linesOut = New-Object System.Collections.Generic.List[string]
$linesOut.Add("# B-Route Text Send Static Map")
$linesOut.Add("")
$linesOut.Add("Date: 2026-07-12")
$linesOut.Add("")
$linesOut.Add("## Scope")
$linesOut.Add("")
$linesOut.Add("This report uses offline IL only. It does not log in, send messages, replay traffic, inject into a process, or mutate the original iSphere binaries.")
$linesOut.Add("")
$linesOut.Add("Machine-readable evidence: ``$OutputDir/text-send-map.json``")
$linesOut.Add("")
$linesOut.Add("## Sources")
$linesOut.Add("")
$linesOut.Add("| Source | Role | Exists | Lines | Size bytes |")
$linesOut.Add("| --- | --- | --- | ---: | ---: |")
foreach ($sourceResult in $sourceResults) {
$exists = if ($sourceResult.exists) { "yes" } else { "no" }
$sizeText = if ($null -ne $sourceResult.size_bytes) { [string]$sourceResult.size_bytes } else { "" }
$linesOut.Add("| ``$($sourceResult.path)`` | $($sourceResult.role) | $exists | $($sourceResult.line_count) | $sizeText |")
}
$linesOut.Add("")
$linesOut.Add("## Target classification")
$linesOut.Add("")
$linesOut.Add("| Target | Intent | Classification | Matches |")
$linesOut.Add("| --- | --- | --- | ---: |")
foreach ($targetResult in $targetResults) {
$linesOut.Add("| ``$($targetResult.display)`` | $($targetResult.intent) | ``$($targetResult.classification)`` | $($targetResult.match_count) |")
}
$linesOut.Add("")
$linesOut.Add("## Verified facts")
$linesOut.Add("")
$linesOut.Add("- ``AppContextManager.SendTxtMessageByJid`` appears in the offline client IL and is not just a UIA/RPA artifact.")
$linesOut.Add("- ``MessageScheduling.SendChatMessage`` appears in the offline client IL and has call-site evidence around chat-message flow.")
$linesOut.Add("- ``Chat.SendMessage`` / ``Chat.sendMessage`` appears as a smack chat API used by client code.")
$linesOut.Add("- ``XMPPConnection.send`` appears as a lower-level connection send primitive in offline IL.")
$linesOut.Add("- ``MessageCenter send-related callbacks`` appear as MessageCenter/GetMessageCenter references, but offline static evidence alone does not prove an external bridge can call them.")
$linesOut.Add("")
$linesOut.Add("## Evidence excerpts")
foreach ($targetResult in $targetResults) {
$linesOut.Add("")
$linesOut.Add("### $($targetResult.display)")
$linesOut.Add("")
$linesOut.Add("Classification: ``$($targetResult.classification)``; matches: $($targetResult.match_count).")
if (@($targetResult.evidence).Count -eq 0) {
$linesOut.Add("")
$linesOut.Add("No evidence found in configured offline IL sources.")
continue
}
$linesOut.Add("")
$linesOut.Add("| Source line | Kind | Snippet | Method context |")
$linesOut.Add("| --- | --- | --- | --- |")
foreach ($evidence in $targetResult.evidence) {
$method = if ($evidence.method_header) { "L$($evidence.method_header.line_number): $($evidence.method_header.text)" } else { "" }
$snippet = ($evidence.text -replace "\|", "\\|")
$method = ($method -replace "\|", "\\|")
$linesOut.Add("| ``$($evidence.source):$($evidence.line_number)`` | ``$($evidence.kind)`` | ``$snippet`` | ``$method`` |")
}
}
$linesOut.Add("")
$linesOut.Add("## Inference")
$linesOut.Add("")
$linesOut.Add("- High confidence: text sending has an internal managed call path that reaches smack chat/connection send APIs.")
$linesOut.Add("- Medium confidence: the likely chain is high-level AppContextManager or UI chat code -> MessageScheduling/frmP2PChat -> smack Chat.SendMessage/sendMessage -> XMPPConnection.send.")
$linesOut.Add("- Low confidence until live/runtime evidence: an external sidecar can invoke this path without being inside the logged-in process.")
$linesOut.Add("")
$linesOut.Add("## Decision")
$linesOut.Add("")
$linesOut.Add("B-route text send remains plausible only if a bridge can enter the logged-in runtime or an existing IPC/API exposes the same call. Offline IL confirms call shape, but not runtime invocability.")
$linesOut.Add("")
$linesOut.Add("## Next work")
$linesOut.Add("")
$linesOut.Add("1. Extract file-send/upload call graph and separate upload from chat-message finalization.")
$linesOut.Add("2. Extract bridge/IPC/plugin candidates to see whether the send call path is reachable without RPA.")
$linesOut.Add("3. Keep A-route/RPA as backup-only; do not promote it unless B-route bridge evidence fails.")
($linesOut -join "`n") + "`n" | Set-Content -LiteralPath $reportFullPath -Encoding UTF8
$requiredNames = @("AppContextManager.SendTxtMessageByJid", "MessageScheduling.SendChatMessage", "Chat.SendMessage", "XMPPConnection.send", "MessageCenter send-related callbacks")
$reportText = Get-Content -LiteralPath $reportFullPath -Raw
$missing = @($requiredNames | Where-Object { $reportText -notlike "*$_*" })
if ($missing.Count -gt 0) {
throw "Report missing required target names: $($missing -join ', ')"
}
[pscustomobject]@{
ok = $true
json_path = $jsonPath
report_path = $reportFullPath
sources = $sourceResults.Count
targets = $targetResults.Count
classifications = @($targetResults | ForEach-Object { "$($_.display)=$($_.classification)" })
originals_copied = $false
originals_modified = $false
} | ConvertTo-Json -Depth 6

View File

@@ -0,0 +1,118 @@
param(
[string]$IlFile = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il/IMPlatformClient.exe.il",
[string]$OutDir = "runs/offline-chat-window"
)
$ErrorActionPreference = "Stop"
$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")
function Resolve-RepoPath([string]$PathValue) {
if ([System.IO.Path]::IsPathRooted($PathValue)) {
return $PathValue
}
return (Join-Path $repo $PathValue)
}
$ilFull = Resolve-RepoPath $IlFile
$outFull = Resolve-RepoPath $OutDir
if (-not (Test-Path -LiteralPath $ilFull)) {
throw "IL file not found: $ilFull"
}
New-Item -ItemType Directory -Force -Path $outFull | Out-Null
$lines = Get-Content -LiteralPath $ilFull
$endIndex = $null
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match 'end of method frmP2PChat::\.ctor') {
$endIndex = $i
break
}
}
if ($null -eq $endIndex) {
throw "frmP2PChat::.ctor end marker not found"
}
$startIndex = $null
for ($i = $endIndex; $i -ge 0; $i--) {
if ($lines[$i] -match '^\s*\.method\s+public\s+hidebysig\s+specialname\s+rtspecialname') {
$startIndex = $i
break
}
}
if ($null -eq $startIndex) {
throw "frmP2PChat::.ctor method start not found before line $($endIndex + 1)"
}
$ctorIlFile = Join-Path $outFull "frmP2PChat-ctor.il.txt"
$riskCsvFile = Join-Path $outFull "frmP2PChat-ctor-null-risk.csv"
$riskMdFile = Join-Path $outFull "frmP2PChat-ctor-null-risk.md"
$ctorLines = New-Object System.Collections.Generic.List[string]
for ($i = $startIndex; $i -le $endIndex; $i++) {
$ctorLines.Add(("{0}: {1}" -f ($i + 1), $lines[$i]))
}
$ctorLines | Set-Content -LiteralPath $ctorIlFile -Encoding UTF8
$riskRows = New-Object System.Collections.Generic.List[object]
foreach ($entry in $ctorLines) {
if ($entry -notmatch '\b(callvirt|ldfld)\b') {
continue
}
$offset = $null
if ($entry -match '(IL_[0-9a-fA-F]{4})') {
$offset = $matches[1].ToLowerInvariant().Replace("il_", "IL_")
}
$op = if ($entry -match '\b(callvirt|ldfld)\b') { $matches[1] } else { $null }
$target = ($entry -replace '^.*?\b(callvirt|ldfld)\b\s+', '').Trim()
$riskRows.Add([pscustomobject]@{
source_line = [int]($entry -replace '^(\d+):.*$', '$1')
il_offset = $offset
opcode = $op
target = $target
null_risk = if ($op -eq "callvirt") { "receiver_null_possible" } else { "instance_field_owner_null_possible" }
evidence = $entry.Trim()
})
}
$riskRows | Sort-Object source_line | Export-Csv -LiteralPath $riskCsvFile -NoTypeInformation -Encoding UTF8
$topEvidence = $riskRows |
Where-Object {
$_.target -match 'Connection::add_OnConnectError|Connection::add_OnReConnectOk|P2PChat::get_OtherJid|Jid::getBareJid|IMPPManager::get_UserInfo|UCChatSendMessageBox::GetChatRichTextBox|UCChatSendMessageBox::GetReceiptCheckBox|MessageCenter::add_OnTcpMessageArrived|RosterManager::UpdateStrangerStatus|BaseConfig::VisualPhoneEnable'
} |
Select-Object -First 40
$md = New-Object System.Collections.Generic.List[string]
$md.Add("# frmP2PChat constructor IL NullRisk")
$md.Add("")
$md.Add("- Source IL: $ilFull")
$md.Add("- Constructor source lines: $($startIndex + 1)-$($endIndex + 1)")
$md.Add("- Constructor line count: $($ctorLines.Count)")
$md.Add("- callvirt / ldfld risk rows: $($riskRows.Count)")
$md.Add("")
$md.Add("## High-signal risks")
$md.Add("")
$md.Add("| source_line | il_offset | opcode | target |")
$md.Add("|---:|---|---|---|")
foreach ($row in $topEvidence) {
$target = ($row.target -replace '\|', '\\|')
$md.Add("| $($row.source_line) | $($row.il_offset) | $($row.opcode) | $target |")
}
$md.Add("")
$md.Add("## Files")
$md.Add("")
$md.Add("- Full constructor IL: $ctorIlFile")
$md.Add("- Full NullRisk CSV: $riskCsvFile")
$md | Set-Content -LiteralPath $riskMdFile -Encoding UTF8
[pscustomobject]@{
ok = $true
il_file = $ilFull
ctor_line_start = $startIndex + 1
ctor_line_end = $endIndex + 1
ctor_line_count = $ctorLines.Count
risk_count = $riskRows.Count
ctor_il_file = $ctorIlFile
risk_csv_file = $riskCsvFile
risk_md_file = $riskMdFile
} | ConvertTo-Json -Compress

View File

@@ -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

View File

@@ -0,0 +1,404 @@
param(
[string]$IlDir = "runs/offline-evidence-intake/zyl-qqfile-20260709/metadata/c28-il",
[string]$OutputDir = "runs/send-upload-deep-dive",
[string]$ReportPath = "docs/source-discovery/2026-07-12-send-upload-deep-dive.md",
[string]$ValidationPath = "docs/source-discovery/2026-07-12-login-reachability-validation-items.md",
[int]$WindowRadius = 5,
[int]$MaxEvidencePerItem = 20
)
$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
$validationFullPath = Join-Path $repo $ValidationPath
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $reportFullPath) | Out-Null
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $validationFullPath) | Out-Null
$sources = @(
@{ path = "IMPlatformClient.exe.il"; role = "main client; high-level send, file-send orchestration, runtime auth/service state" },
@{ path = "smack.dll.il"; role = "Chat/XMPP send implementation and file-message primitive" },
@{ path = "IMPP.Service.dll.il"; role = "file upload HTTP/service implementation" },
@{ path = "IMPP.ServiceBase.dll.il"; role = "FileUploadPara/FileUploadResult/FileTransferParaBase DTO contracts" },
@{ path = "IMPP.Interface.dll.il"; role = "IAppContextManager/IFileTransfer interface contracts" },
@{ path = "IMPP.Common.dll.il"; role = "ServiceManager/Auth DTOs and common runtime state" }
)
$items = @(
@{
key = "text_entry_app_context"
title = "Text send high-level entry: AppContextManager.SendTxtMessageByJid"
stage = "text_send"
meaning = "Best business-level text-send candidate if reachable in logged-in runtime."
must_verify = @("Reach AppContextManager instance", "Confirm target JID/chat type mapping", "Invoke dry/probe path without send first", "Correlate sent record/ack after real send test")
patterns = @("AppContextManager::SendTxtMessageByJid", "\bSendTxtMessageByJid\b", "IAppContextManager::SendTxtMessageByJid")
},
@{
key = "text_entry_scheduling"
title = "Text send scheduling fallback: MessageScheduling.SendChatMessage"
stage = "text_send"
meaning = "Fallback text-send path if AppContextManager is hard to reach but Chat/Roster args exist."
must_verify = @("Locate or construct RosterContactsArgs", "Locate Chat instance", "Confirm direct/group branch", "Correlate sent record/ack")
patterns = @("MessageScheduling::SendChatMessage", "SendChatMessage\(")
},
@{
key = "chat_low_level_send"
title = "Low-level text primitive: Chat.SendMessage -> XMPPConnection.send"
stage = "text_send"
meaning = "Confirms final XMPP send primitive; not enough alone without authenticated Chat/XMPP state."
must_verify = @("Locate Chat instance", "Locate authenticated XMPPConnection", "Confirm direct/group message payload", "Capture ack/sent-record")
patterns = @("com\.vision\.smack\.Chat::SendMessage", "com\.vision\.smack\.XMPPConnection::send", "callvirt instance void com\.vision\.smack\.XMPPConnection::send")
},
@{
key = "file_upload_para_base"
title = "Upload parameter base: FileTransferParaBase"
stage = "file_upload"
meaning = "Defines host, port, domain, local path, timeout/cache and token fields required by upload/download DTOs."
must_verify = @("Host", "Port", "Domain", "LocalFilePath", "Token", "Cache/timeout flags if present")
patterns = @("FileTransferParaBase", "get_Host\(\)", "get_Port\(\)", "get_Domain\(\)", "get_LocalFilePath\(\)", "get_Token\(\)")
},
@{
key = "file_upload_para"
title = "Upload DTO: FileUploadPara"
stage = "file_upload"
meaning = "Concrete upload request DTO; adds IsImg/IsPublic and invokes FileTransferParaBase constructor."
must_verify = @("Constructor arguments", "IsImg", "IsPublic", "Token value", "Local file path normalization")
patterns = @("FileUploadPara", "FileUploadPara::\.ctor", "get_IsImg\(\)", "get_IsPublic\(\)", "set_IsImg", "set_IsPublic")
},
@{
key = "file_upload_service"
title = "Upload service: IFileTransfer/FileTransfer.FileUpload"
stage = "file_upload"
meaning = "Managed upload entry; returns FileUploadResult and internally writes multipart token/form data."
must_verify = @("Reach IFileTransfer instance", "Call FileUpload with safe test file", "Capture FileUploadResult", "Capture HTTP server/token fields without leaking token")
patterns = @("FileTransfer::FileUpload", "IFileTransfer::FileUpload", 'Content-Disposition: form-data; name="token"', "FileUploadResult")
},
@{
key = "file_upload_auth"
title = "Upload auth/server state: HTTPFileServer + Auth token"
stage = "file_upload"
meaning = "File upload depends on runtime server/auth state, not only a local file path."
must_verify = @("HTTPFileServer host/port", "UnifiedAuthentication/Auth token", "Domain/resource", "Access token/client id if present")
patterns = @("get_HTTPFileServer\(\)", "UnifiedAuthentication", "Auth::get_token", "accessToken", "clientId", "HTTPFileServer")
},
@{
key = "file_upload_result"
title = "Upload result: FileUploadResult.FileID and remote metadata"
stage = "file_upload_result"
meaning = "Server-issued FileID is required before a chat file message is meaningful."
must_verify = @("FileID", "URL or remote folder if present", "size/name metadata", "failure code/message")
patterns = @("FileUploadResult::get_FileID", "FileUploadResult::set_FileID", "FileUploadResult", "RemoteFolder", "get_Url", "get_URL")
},
@{
key = "file_message_finalizer"
title = "File-message finalization: trans_UploadCompleted / SendFileMessage / Chat.sendFileMessage"
stage = "send_file_message"
meaning = "After upload succeeds, the client constructs offline file-transfer content and sends chat file message."
must_verify = @("trans_UploadCompleted receives FileID", "OFFLINE_FILE_TRANSFER payload fields", "Target Chat/JID", "Sent file record/ack")
patterns = @("OffLineFileSend::trans_UploadCompleted", "MessageScheduling::SendFileMessage", "Chat::sendFileMessage", "OFFLINE_FILE_TRANSFER")
},
@{
key = "target_chat_resolution"
title = "Target resolution: JID -> Chat / ChatRoom"
stage = "runtime_context"
meaning = "Both text and file send need a target JID mapped to Chat or ChatRoom; group handling may differ."
must_verify = @("Contact JID", "Group/conference JID", "ChatManager.GetChat", "ChatRoom branch and permissions")
patterns = @("ChatManager::GetChat", "GetChat\(", "ChatRoom", "get_RosterJid", "get_ChatRoomJid", "get_HasSpeechAuthJid")
},
@{
key = "runtime_owner"
title = "Runtime owner: frmMain / IMPPManager / MessageCenter"
stage = "runtime_context"
meaning = "Likely owners of initialized logged-in state and message center callbacks."
must_verify = @("Running frmMain", "IMPPManager.UserInfo", "MessageCenter", "Reconnect success state", "loaded assemblies")
patterns = @("class IMPP\.Client\.frmMain", "IMPPManager::get_UserInfo", "GetMessageCenter\(\)", "MessageCenter", "OnReConnectionSucceed")
}
)
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 "^\s*\.field\b") { return "field" }
if ($Line -match "^\s*\.property\b") { return "property" }
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" }
return "reference"
}
function Get-MethodContext($Lines, [int]$Index) {
$start = [Math]::Max(0, $Index - 120)
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 Find-Evidence($Item) {
$evidence = New-Object System.Collections.Generic.List[object]
foreach ($source in $sources) {
$path = Join-Path $ilDirFull $source.path
if (-not (Test-Path -LiteralPath $path)) { continue }
$lines = [System.IO.File]::ReadAllLines($path)
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
foreach ($pattern in $Item.patterns) {
if ($line -match $pattern) {
$evidence.Add([pscustomobject]@{
source = Get-RelativePath $path
source_role = $source.role
line = $i + 1
kind = Get-EvidenceKind $line
pattern = $pattern
snippet = $line.Trim()
context = Get-MethodContext $lines $i
})
break
}
}
if ($evidence.Count -ge $MaxEvidencePerItem) { break }
}
if ($evidence.Count -ge $MaxEvidencePerItem) { break }
}
return $evidence.ToArray()
}
$sourceSummary = foreach ($source in $sources) {
$path = Join-Path $ilDirFull $source.path
$exists = Test-Path -LiteralPath $path
$lineCount = 0
$size = 0
if ($exists) {
$file = Get-Item -LiteralPath $path
$size = $file.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
}
}
$itemResults = foreach ($item in $items) {
$evidence = Find-Evidence $item
$status = if ($evidence.Count -gt 0) { "static_evidence_found" } else { "missing_static_evidence" }
[pscustomobject]@{
key = $item.key
title = $item.title
stage = $item.stage
meaning = $item.meaning
status = $status
evidence_count = $evidence.Count
must_verify = $item.must_verify
evidence = $evidence
}
}
$newValidationItems = @(
[pscustomobject]@{ priority = "P0"; category = "test_rule"; item = "Define one-shot test targets and operator confirmation"; evidence = "direct JID, optional group JID, self-send/sandbox-account flag, operator confirmation, one-send-only flag, test content/file hash seed"; unlocks = "reliable ack and sent-record correlation" },
[pscustomobject]@{ priority = "P0"; category = "snapshot"; item = "Capture before/after sent-record snapshots"; evidence = "before count/last summary, after count/last summary, target ref, content hash or file hash, timestamp window"; unlocks = "machine-verifiable send result" },
[pscustomobject]@{ priority = "P0"; category = "sent_record_source"; item = "Identify sent-record and ack source paths"; evidence = "MessageCenter::OnMessageSended availability, PacketReader/SaveToDB/MsgLib source availability, MCP audit ref, ack/ref id if present"; unlocks = "production gate evidence" },
[pscustomobject]@{ priority = "P0"; category = "adapter_reachability"; item = "Confirm in-process adapter reachability mode"; evidence = "process bitness, CLR/.NET version, user/session id, loaded managed assemblies, same-process/managed-harness/injection requirement, stop-condition reason if blocked"; unlocks = "B-route implementation decision" },
[pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm logged-in IMPlatformClient.exe process and loaded assemblies"; evidence = "process id, module list, loaded managed assemblies, login/user presence without leaking credentials"; unlocks = "all B-route adapter tests" },
[pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm AppContextManager/IAppContextManager reachability"; evidence = "type visible, instance path, SendTxtMessageByJid callable shape, direct/group chat type mapping"; unlocks = "text send high-level path" },
[pscustomobject]@{ priority = "P0"; category = "runtime"; item = "Confirm Chat/XMPPConnection authenticated state"; evidence = "Chat instance, XMPPConnection state, target JID mapping, group ChatRoom branch if target is group"; unlocks = "text and file message finalization" },
[pscustomobject]@{ priority = "P0"; category = "file_upload"; item = "Capture FileUploadPara required values without leaking token"; evidence = "host, port, domain, local path presence, IsImg/IsPublic, token-present boolean/hash only, timeout/cache flags if visible"; unlocks = "upload_file probe" },
[pscustomobject]@{ priority = "P0"; category = "file_upload"; item = "Confirm IFileTransfer/FileTransfer.FileUpload reachability"; evidence = "service instance or constructor path, method signature, safe call readiness, HTTP status/failure channel mapping"; unlocks = "file upload" },
[pscustomobject]@{ priority = "P0"; category = "file_upload_result"; item = "Confirm FileUploadResult.FileID after safe test upload"; evidence = "FileID present, size/name or URL/remote folder metadata, HTTP status, service error code/message if upload fails"; unlocks = "send_file_message" },
[pscustomobject]@{ priority = "P0"; category = "send_file_message"; item = "Confirm trans_UploadCompleted/SendFileMessage consumes FileID"; evidence = "FileID enters payload, Chat.sendFileMessage invoked, sent file record/ack, failure reason if target/permission blocks"; unlocks = "production file send" },
[pscustomobject]@{ priority = "P0"; category = "failure_reason"; item = "Capture structured failure reasons for every probe step"; evidence = "step name, exception type, error code, message, offline/permission/target-not-found/token/file-size/file-type/network-timeout classification"; unlocks = "actionable next decision when probe fails" },
[pscustomobject]@{ priority = "P0"; category = "ack"; item = "Correlate sent record/ack with content hash or file hash"; evidence = "sent record source, timestamp, target ref, body/file metadata hash, ack/ref id, before/after snapshot diff"; unlocks = "production gate" },
[pscustomobject]@{ priority = "P1"; category = "group"; item = "Confirm group ChatRoom branch and permissions"; evidence = "ChatRoom type, speech/upload permission state, group JID, mute/permission failure reason"; unlocks = "group send/file send" },
[pscustomobject]@{ priority = "P1"; category = "fallback"; item = "If B-route reachability fails, capture A-route UI evidence"; evidence = "window hwnd, rtbSendMessage, btnSend, screenshots, failure reason"; unlocks = "demo fallback only" }
)
$result = [pscustomobject]@{
ok = $true
generated_at = (Get-Date).ToUniversalTime().ToString("o")
decision = "continue_offline_deep_dive_then_login_reachability_probe"
sources = $sourceSummary
items = $itemResults
new_validation_items = $newValidationItems
originals_copied = $false
originals_modified = $false
}
$jsonPath = Join-Path $outDir "send-upload-deep-dive.json"
Write-Utf8NoBomLf $jsonPath ($result | ConvertTo-Json -Depth 8)
$md = New-Object System.Collections.Generic.List[string]
$md.Add("# Send / Upload Deep Dive")
$md.Add("")
$md.Add("Date: 2026-07-12")
$md.Add("")
$md.Add("## Business summary")
$md.Add("")
$md.Add("Offline deep dive confirms the remaining work is not generic sending code. The business blocker is logged-in runtime reachability plus online proof. Text send needs reachable AppContextManager/MessageScheduling/Chat. File send needs upload parameters and server-issued FileUploadResult.FileID before Chat.sendFileMessage can be meaningful.")
$md.Add("")
$md.Add("## Decision")
$md.Add("")
$md.Add("| Question | Answer |")
$md.Add("| --- | --- |")
$md.Add("| Should work stop before login? | No |")
$md.Add("| Highest-value offline work | Deepen send/upload decomposition and prepare login validation items |")
$md.Add("| Can production send be enabled offline? | No |")
$md.Add("| Next package | login reachability probe package |")
$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("## Deep-dive findings")
$md.Add("")
$md.Add("| Item | Stage | Status | Evidence | Business meaning |")
$md.Add("| --- | --- | --- | ---: | --- |")
foreach ($item in $itemResults) {
$md.Add("| ``$($item.title)`` | ``$($item.stage)`` | ``$($item.status)`` | $($item.evidence_count) | $($item.meaning) |")
}
$md.Add("")
$md.Add("## What this adds to tomorrow's login validation")
$md.Add("")
$md.Add("| Priority | Category | Validation item | Evidence to capture | Unlocks |")
$md.Add("| --- | --- | --- | --- | --- |")
foreach ($v in $newValidationItems) {
$md.Add("| $($v.priority) | $($v.category) | $($v.item) | $($v.evidence) | $($v.unlocks) |")
}
$md.Add("")
$md.Add("## Evidence by item")
foreach ($item in $itemResults) {
$md.Add("")
$md.Add("### $($item.title)")
$md.Add("")
$md.Add("Stage: ``$($item.stage)``. Status: ``$($item.status)``. Evidence count: $($item.evidence_count).")
$md.Add("")
$md.Add("Business meaning: $($item.meaning)")
$md.Add("")
$md.Add("Must verify tomorrow:")
foreach ($verify in $item.must_verify) {
$md.Add("- $verify")
}
$md.Add("")
if ($item.evidence_count -eq 0) {
$md.Add("No static evidence found in configured IL sources.")
continue
}
$md.Add("| Source | Kind | Snippet | Context |")
$md.Add("| --- | --- | --- | --- |")
foreach ($e in $item.evidence) {
$snippet = ($e.snippet -replace "\|", "\\|")
if ($snippet.Length -gt 240) { $snippet = $snippet.Substring(0, 237) + "..." }
$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("## Updated stop / continue rules")
$md.Add("")
$md.Add("Continue B-route tomorrow if P0 runtime, text-send, upload, FileID, and ack probes produce positive or actionable evidence. Stop B-route and escalate if logged-in runtime cannot expose AppContextManager/MessageScheduling/Chat/IFileTransfer, or if upload cannot produce FileUploadResult.FileID. Keep A-route/RPA backup-only for demo continuity.")
Write-Utf8NoBomLf $reportFullPath ($md -join "`n")
$validation = New-Object System.Collections.Generic.List[string]
$validation.Add("# Login Reachability Validation Items")
$validation.Add("")
$validation.Add("Date: 2026-07-12")
$validation.Add("")
$validation.Add("Purpose: this is the operator-facing checklist for the 2026-07-13 logged-in environment. It is generated from the offline send/upload deep dive and should be used to build the one-shot reachability probe package. P0 items are blocking; production send remains disabled until all relevant P0 evidence is collected and correlated.")
$validation.Add("")
$validation.Add("## Operator rules")
$validation.Add("")
$validation.Add("- Run the probe only after the target iSphere/IMPlatformClient session is visibly logged in.")
$validation.Add("- Use a pre-agreed direct test JID and optional group test JID; record them in the output JSON.")
$validation.Add("- Use one-shot test content and one safe small test file; record SHA256 hashes, not raw sensitive content.")
$validation.Add("- Capture before/after sent-record snapshots around the one-shot send/upload test.")
$validation.Add("- Do not mark production ready unless ack/sent-record correlation is machine-verifiable.")
$validation.Add("")
$validation.Add("## P0 items")
$validation.Add("")
foreach ($v in $newValidationItems | Where-Object { $_.priority -eq "P0" }) {
$validation.Add("### $($v.item)")
$validation.Add("")
$validation.Add("- Category: $($v.category)")
$validation.Add("- Evidence to capture: $($v.evidence)")
$validation.Add("- Unlocks: $($v.unlocks)")
$validation.Add("")
}
$validation.Add("## P1 items")
$validation.Add("")
foreach ($v in $newValidationItems | Where-Object { $_.priority -eq "P1" }) {
$validation.Add("### $($v.item)")
$validation.Add("")
$validation.Add("- Category: $($v.category)")
$validation.Add("- Evidence to capture: $($v.evidence)")
$validation.Add("- Unlocks: $($v.unlocks)")
$validation.Add("")
}
$validation.Add("## Required output schema")
$validation.Add("")
$validation.Add("Every probe run should emit JSON with these top-level sections:")
$validation.Add("")
$validation.Add("- ``run``: timestamp, machine, operator confirmation, one-shot flags.")
$validation.Add("- ``targets``: direct JID, optional group JID, target type, source of target selection.")
$validation.Add("- ``runtime``: process id, bitness, CLR/.NET version, user/session, loaded assemblies.")
$validation.Add("- ``reachability``: AppContextManager, MessageScheduling, Chat, XMPPConnection, IFileTransfer, FileUploadPara, FileUploadResult, Chat.sendFileMessage.")
$validation.Add("- ``server_auth``: host, port, domain, token_present, token_hash_prefix only, accessToken/clientId presence when visible.")
$validation.Add("- ``snapshots``: before/after counts and last-record summaries for sent-record sources.")
$validation.Add("- ``attempts``: probe-only, optional one-shot text, optional safe upload, optional file-message finalization.")
$validation.Add("- ``failures``: structured failure code, exception type, message, classification, next action.")
$validation.Add("- ``correlation``: content/file hash match, target match, timestamp window, ack/ref id.")
$validation.Add("")
$validation.Add("## Pass criteria")
$validation.Add("")
$validation.Add("- Text send can move forward when logged-in runtime exposes AppContextManager or MessageScheduling plus Chat/XMPPConnection and sent-record/ack correlation is possible.")
$validation.Add("- File send can move forward when logged-in runtime exposes IFileTransfer/FileUpload, FileUploadPara values, FileUploadResult.FileID, and Chat.sendFileMessage finalization evidence.")
$validation.Add("- Production remains blocked if any P0 item is missing, if failure reasons are unstructured, or if only static evidence is available.")
$validation.Add("- Text production can move forward only when one-shot target, before/after snapshot, sent-record source, and content-hash/ack correlation all pass.")
$validation.Add("- File production can move forward only when FileUploadPara values, IFileTransfer reachability, FileUploadResult.FileID, file-message finalization, and file sent-record/ack correlation all pass.")
Write-Utf8NoBomLf $validationFullPath ($validation -join "`n")
[pscustomobject]@{
ok = $true
json_path = $jsonPath
report_path = $reportFullPath
validation_path = $validationFullPath
items = $itemResults.Count
validation_items = $newValidationItems.Count
decision = $result.decision
originals_copied = $false
originals_modified = $false
} | ConvertTo-Json -Depth 5

View File

@@ -0,0 +1,545 @@
param(
[string]$ClientDir = "runs/offline-real-client-window/full/zyl/Impp",
[string]$OutDir = "runs/offline-chat-window",
[ValidateSet("Minimal", "Deps")]
[string]$RuntimeMode = "Deps",
[switch]$SelfChat,
[switch]$SkipRosterManager,
[switch]$ShowWindow,
[string]$HelperExe = "runs/win-helper/ISphereWinHelper.exe",
[switch]$NoScreenshot,
[int]$HoldSeconds = 8,
[int]$X = 180,
[int]$Y = 180,
[int]$Width = 900,
[int]$Height = 680
)
$ErrorActionPreference = "Stop"
if ([Environment]::Is64BitProcess) {
$x86PowerShell = Join-Path $env:WINDIR "SysWOW64\WindowsPowerShell\v1.0\powershell.exe"
if (-not (Test-Path -LiteralPath $x86PowerShell)) {
throw "32-bit PowerShell not found: $x86PowerShell"
}
$relayArgs = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $PSCommandPath)
foreach ($entry in $PSBoundParameters.GetEnumerator()) {
$name = [string]$entry.Key
$value = $entry.Value
if ($value -is [System.Management.Automation.SwitchParameter]) {
if ($value.IsPresent) {
$relayArgs += "-$name"
}
}
else {
$relayArgs += "-$name"
$relayArgs += [string]$value
}
}
& $x86PowerShell @relayArgs
exit $LASTEXITCODE
}
$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")
function Resolve-RepoPath([string]$PathValue) {
if ([System.IO.Path]::IsPathRooted($PathValue)) {
return $PathValue
}
return (Join-Path $repo $PathValue)
}
function Get-TypeMemberInHierarchy([Type]$Type, [string]$Name, [string]$Kind) {
$flags = [System.Reflection.BindingFlags]"Public,NonPublic,Instance,Static"
$cursor = $Type
while ($null -ne $cursor) {
if ($Kind -eq "Property") {
$member = $cursor.GetProperty($Name, $flags)
}
else {
$member = $cursor.GetField($Name, $flags)
}
if ($member) {
return $member
}
$cursor = $cursor.BaseType
}
return $null
}
function Set-PropInHierarchy([object]$Object, [Type]$Type, [string]$Name, [object]$Value) {
$prop = Get-TypeMemberInHierarchy -Type $Type -Name $Name -Kind "Property"
if ($prop -and $prop.CanWrite) {
$target = if ($prop.GetSetMethod($true).IsStatic) { $null } else { $Object }
$prop.SetValue($target, $Value, $null)
return $true
}
return $false
}
function Set-FieldInHierarchy([object]$Object, [Type]$Type, [string]$Name, [object]$Value) {
$field = Get-TypeMemberInHierarchy -Type $Type -Name $Name -Kind "Field"
if ($field) {
$target = if ($field.IsStatic) { $null } else { $Object }
$field.SetValue($target, $Value)
return $true
}
return $false
}
function New-ByConstructor([Type]$Type, [Type[]]$ParameterTypes, [object[]]$Arguments) {
$ctor = $Type.GetConstructor($ParameterTypes)
if (-not $ctor) {
$sig = ($ParameterTypes | ForEach-Object { $_.FullName }) -join ", "
throw "constructor not found: $($Type.FullName)($sig)"
}
return $ctor.Invoke($Arguments)
}
function Convert-ExceptionToRecord([Exception]$Exception) {
$records = @()
$cursor = $Exception
$depth = 0
while ($cursor) {
$trace = New-Object System.Diagnostics.StackTrace($cursor, $true)
$frames = @()
for ($i = 0; $i -lt $trace.FrameCount; $i++) {
$frame = $trace.GetFrame($i)
$method = $frame.GetMethod()
$offset = $frame.GetILOffset()
$frames += [pscustomobject]@{
index = $i
method_type = if ($method.DeclaringType) { $method.DeclaringType.FullName } else { $null }
method_name = $method.Name
il_offset = $offset
il_offset_hex = if ($offset -ge 0) { "IL_{0:x4}" -f $offset } else { $null }
native_offset = $frame.GetNativeOffset()
file = $frame.GetFileName()
line = $frame.GetFileLineNumber()
}
}
$records += [pscustomobject]@{
depth = $depth
type = $cursor.GetType().FullName
message = $cursor.Message
target_site = if ($cursor.TargetSite) { "$($cursor.TargetSite.DeclaringType.FullName)::$($cursor.TargetSite.Name)" } else { $null }
frames = $frames
}
$cursor = $cursor.InnerException
$depth++
}
return $records
}
function Get-FirstRelevantFrame([object[]]$ExceptionRecords) {
foreach ($record in $ExceptionRecords) {
foreach ($frame in $record.frames) {
if ($frame.method_type -and
$frame.method_type -notlike "System.*" -and
$frame.method_type -notlike "Microsoft.*" -and
$frame.method_type -notlike "MS.*") {
return $frame
}
}
}
return $null
}
function Find-IlLine([string]$OutDirFull, [string]$IlOffsetHex) {
if ([string]::IsNullOrWhiteSpace($IlOffsetHex)) {
return $null
}
$ctorIl = Join-Path $OutDirFull "frmP2PChat-ctor.il.txt"
if (-not (Test-Path -LiteralPath $ctorIl)) {
return $null
}
$match = Select-String -LiteralPath $ctorIl -Pattern $IlOffsetHex -SimpleMatch | Select-Object -First 1
if ($match) {
return @{
path = $ctorIl
line_number = $match.LineNumber
text = $match.Line.Trim()
}
}
return $null
}
function Invoke-HelperJson([string]$HelperPath, [string]$Op, [hashtable]$OpArgs, [string]$RequestId) {
$request = @{
protocol = "isphere.helper.v1"
request_id = $RequestId
op = $Op
timeout_ms = 5000
args = $OpArgs
}
$json = $request | ConvertTo-Json -Depth 16 -Compress
$output = $json | & $HelperPath --json
try {
return $output | ConvertFrom-Json
}
catch {
throw "helper output was not JSON: $output"
}
}
function Save-WindowScreenshot([string]$OutputPath, [int]$ScreenX, [int]$ScreenY, [int]$CaptureWidth, [int]$CaptureHeight) {
$bitmap = New-Object System.Drawing.Bitmap $CaptureWidth, $CaptureHeight
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
try {
$graphics.CopyFromScreen($ScreenX, $ScreenY, 0, 0, $bitmap.Size)
$bitmap.Save($OutputPath, [System.Drawing.Imaging.ImageFormat]::Png)
}
finally {
$graphics.Dispose()
$bitmap.Dispose()
}
}
function New-UserInfo([Type]$UserInfoType, [string]$Id, [string]$Jid, [string]$Name, [string]$CompanyID) {
$user = [Activator]::CreateInstance($UserInfoType)
foreach ($kv in @(
@("Id", $Id),
@("Jid", $Jid),
@("LoginName", $Id),
@("Domain", "offline.local"),
@("Name", $Name),
@("CompanyID", $CompanyID),
@("DeptID", "codex-dept"),
@("DeptName", "Codex Dept"),
@("Enable", "1"),
@("chatAble", "1"),
@("Mobile", ""),
@("Tel", ""),
@("Email", "")
)) {
Set-PropInHierarchy -Object $user -Type $UserInfoType -Name $kv[0] -Value $kv[1] | Out-Null
}
return $user
}
$clientFull = Resolve-RepoPath $ClientDir
$outFull = Resolve-RepoPath $OutDir
$helperFull = Resolve-RepoPath $HelperExe
New-Item -ItemType Directory -Force -Path $outFull | Out-Null
if (-not (Test-Path -LiteralPath (Join-Path $clientFull "IMPlatformClient.exe"))) {
throw "IMPlatformClient.exe not found under $clientFull"
}
Set-Location -LiteralPath $clientFull
[AppDomain]::CurrentDomain.add_AssemblyResolve({
param($sender, $eventArgs)
$assemblyName = New-Object System.Reflection.AssemblyName($eventArgs.Name)
foreach ($extension in @(".dll", ".exe")) {
$candidate = Join-Path $script:ClientDirectoryForResolve ($assemblyName.Name + $extension)
if (Test-Path -LiteralPath $candidate) {
return [System.Reflection.Assembly]::LoadFrom($candidate)
}
}
return $null
})
$script:ClientDirectoryForResolve = $clientFull
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$resultFile = Join-Path $outFull ("real-frmP2PChat-result-{0}.json" -f $timestamp)
try {
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$script:RealFrmP2PThreadExceptions = New-Object System.Collections.ArrayList
[System.Windows.Forms.Application]::SetUnhandledExceptionMode([System.Windows.Forms.UnhandledExceptionMode]::CatchException)
[System.Windows.Forms.Application]::add_ThreadException({
param($sender, $eventArgs)
[void]$script:RealFrmP2PThreadExceptions.Add($eventArgs.Exception)
})
$asm = [System.Reflection.Assembly]::LoadFrom((Join-Path $clientFull "IMPlatformClient.exe"))
$smack = [System.Reflection.Assembly]::LoadFrom((Join-Path $clientFull "smack.dll"))
$common = [System.Reflection.Assembly]::LoadFrom((Join-Path $clientFull "IMPP.Common.dll"))
$mgrType = $asm.GetType("IMPP.Client.IMPPManager", $true)
$mcType = $asm.GetType("IMPP.Client.control.MessageCenter", $true)
$configType = $asm.GetType("IMPP.Client.Config", $true)
$baseConfigType = $asm.GetType("IMPP.Client.BaseConfig", $true)
$configMgrType = $asm.GetType("IMPP.Client.ConfigSystemManager", $true)
$configModelType = $asm.GetType("IMPP.Client.ConfigSystemModel", $true)
$userInfoCacheType = $asm.GetType("IMPP.Client.Framework.Configuration.UserInfoCache", $true)
$loginInfoType = $asm.GetType("IMPP.Client.LoginInfo", $true)
$p2pFormType = $asm.GetType("IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat", $true)
$chatBaseType = $asm.GetType("IMPP.Client.Forms.frmChatBase", $true)
$frmMainType = $asm.GetType("IMPP.Client.frmMain", $true)
$connType = $smack.GetType("com.vision.smack.XMPPConnection", $true)
$jidType = $smack.GetType("com.vision.smack.Jid", $true)
$chatType = $smack.GetType("com.vision.smack.Chat", $true)
$p2pChatType = $smack.GetType("com.vision.smack.P2PChat", $true)
$rosterType = $smack.GetType("com.vision.smack.RosterManager", $true)
$presenceType = $smack.GetType("com.vision.smack.PresenceManager", $true)
$p2pMgrType = $smack.GetType("com.vision.smack.P2PChatManager", $true)
$bookMarkType = $smack.GetType("com.vision.smack.muc.BookMarkManager", $true)
$packetCollectorType = $smack.GetType("com.vision.smack.PacketCollector", $true)
$userInfoType = $common.GetType("IMPP.Common.UserInfo", $true)
$mgr = $mgrType.GetProperty("Instance", [System.Reflection.BindingFlags]"Public,Static").GetValue($null, $null)
$fakeMessageCenter = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject($mcType)
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<MessageCenter>k__BackingField" -Value $fakeMessageCenter | Out-Null
$fakeFrmMain = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject($frmMainType)
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<frmMain>k__BackingField" -Value $fakeFrmMain | Out-Null
$login = [Activator]::CreateInstance($loginInfoType)
Set-PropInHierarchy -Object $login -Type $loginInfoType -Name "Trait" -Value "codex_probe" | Out-Null
Set-PropInHierarchy -Object $login -Type $loginInfoType -Name "TrueTraid" -Value "codex_probe" | Out-Null
Set-PropInHierarchy -Object $login -Type $loginInfoType -Name "Status" -Value "online" | Out-Null
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "LogonUser" -Value $login | Out-Null
$companyId = "codex-company"
$otherBareJid = "codex-probe@offline.local"
$myBareJid = if ($SelfChat) { $otherBareJid } else { "codex-user@offline.local" }
$myName = if ($SelfChat) { "Codex Probe" } else { "Codex User" }
$jidCtor3 = $jidType.GetConstructor(@([string], [string], [string]))
$myJid = $jidCtor3.Invoke(@(($myBareJid -split "@")[0], "offline.local", "pc"))
$fakeConn = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject($connType)
Set-PropInHierarchy -Object $fakeConn -Type $connType -Name "Jid" -Value $myJid | Out-Null
Set-PropInHierarchy -Object $fakeConn -Type $connType -Name "UserName" -Value (($myBareJid -split "@")[0]) | Out-Null
Set-PropInHierarchy -Object $fakeConn -Type $connType -Name "LoginState" -Value "online" | Out-Null
Set-PropInHierarchy -Object $fakeConn -Type $connType -Name "CompanyID" -Value $companyId | Out-Null
Set-PropInHierarchy -Object $fakeConn -Type $connType -Name "Resource" -Value "pc" | Out-Null
Set-FieldInHierarchy -Object $fakeConn -Type $connType -Name "_packetListeners" -Value (New-Object System.Collections.ArrayList) | Out-Null
$packetCollectorListType = [System.Collections.Generic.List``1].MakeGenericType($packetCollectorType)
Set-FieldInHierarchy -Object $fakeConn -Type $connType -Name "_packetCollectors" -Value ([Activator]::CreateInstance($packetCollectorListType)) | Out-Null
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "Connection" -Value $fakeConn | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<Connection>k__BackingField" -Value $fakeConn | Out-Null
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "IsConnected" -Value $true | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<IsConnected>k__BackingField" -Value $true | Out-Null
Set-FieldInHierarchy -Object $null -Type ($smack.GetType("com.vision.smack.SmarkManager", $true)) -Name "<SmarkManagerInstance>k__BackingField" -Value $mgr | Out-Null
if ($RuntimeMode -eq "Deps") {
$myUser = New-UserInfo -UserInfoType $userInfoType -Id (($myBareJid -split "@")[0]) -Jid $myBareJid -Name $myName -CompanyID $companyId
$otherUser = New-UserInfo -UserInfoType $userInfoType -Id "codex-probe" -Jid $otherBareJid -Name "Codex Probe" -CompanyID $companyId
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "_userInfo" -Value $myUser | Out-Null
$stringDictType = [System.Collections.Generic.Dictionary``2].MakeGenericType([string], [string])
$baseConfigDict = [Activator]::CreateInstance($stringDictType, [StringComparer]::OrdinalIgnoreCase)
foreach ($kv in @(
@("Remote_Control_Visible", "false"),
@("VisualPhone_enable", "false"),
@("showacctno", "no"),
@("ShowDepartment", "NO"),
@("StrucPPLNo", "NO"),
@("MaintenanceAssistant", ""),
@("CustomerServiceSuffix", ""),
@("CustomerCN", ""),
@("CustomerPhone", "")
)) {
$baseConfigDict[$kv[0]] = $kv[1]
$baseConfigDict[$kv[0].ToLowerInvariant()] = $kv[1]
}
$baseConfigRawDict = $baseConfigDict.PSObject.BaseObject
$baseConfigCtor = $baseConfigType.GetConstructor(@($baseConfigRawDict.GetType()))
if (-not $baseConfigCtor) {
throw "constructor not found: $($baseConfigType.FullName)($($baseConfigRawDict.GetType().FullName))"
}
$baseConfig = $baseConfigCtor.Invoke([object[]]@($baseConfigRawDict))
Set-FieldInHierarchy -Object $null -Type $configType -Name "<BaseConfig>k__BackingField" -Value $baseConfig | Out-Null
Set-FieldInHierarchy -Object $null -Type $configType -Name "<UserInfo>k__BackingField" -Value $myUser | Out-Null
Set-FieldInHierarchy -Object $null -Type $configType -Name "<LoginInfo>k__BackingField" -Value $login | Out-Null
$userListType = [System.Collections.Generic.List``1].MakeGenericType($userInfoType)
$rosterUsers = [Activator]::CreateInstance($userListType)
$rosterUsers.Add($myUser) | Out-Null
$rosterUsers.Add($otherUser) | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "_rosterUserInfoList" -Value $rosterUsers | Out-Null
$cfg = [Activator]::CreateInstance($configModelType)
foreach ($kv in @(
@("Font", "Microsoft YaHei UI"),
@("Size", [single]9),
@("FontStyle", "Regular"),
@("Color", "Black"),
@("SendMsgKeyPress", "Enter"),
@("SendFilePath", $outFull),
@("SendFileSize", 10),
@("SendFileConf", $false),
@("AllEnable", $true)
)) {
Set-PropInHierarchy -Object $cfg -Type $configModelType -Name $kv[0] -Value $kv[1] | Out-Null
}
$configMgrType.GetField("config", [System.Reflection.BindingFlags]"NonPublic,Static").SetValue($null, $cfg)
$presence = New-ByConstructor -Type $presenceType -ParameterTypes @($connType) -Arguments @($fakeConn)
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "PresenceManager" -Value $presence | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<PresenceManager>k__BackingField" -Value $presence | Out-Null
$bookmark = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject($bookMarkType)
$p2pManager = New-ByConstructor -Type $p2pMgrType -ParameterTypes @($connType, $bookMarkType) -Arguments @($fakeConn, $bookmark)
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "P2PChatManager" -Value $p2pManager | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<P2PChatManager>k__BackingField" -Value $p2pManager | Out-Null
if (-not $SkipRosterManager) {
$roster = New-ByConstructor -Type $rosterType -ParameterTypes @($connType) -Arguments @($fakeConn)
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "RosterManager" -Value $roster | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<RosterManager>k__BackingField" -Value $roster | Out-Null
}
else {
Set-PropInHierarchy -Object $mgr -Type $mgrType -Name "RosterManager" -Value $null | Out-Null
Set-FieldInHierarchy -Object $mgr -Type $mgrType -Name "<RosterManager>k__BackingField" -Value $null | Out-Null
}
}
$p2pChat = New-ByConstructor -Type $p2pChatType -ParameterTypes @($connType, [string]) -Arguments @($fakeConn, $otherBareJid)
$otherJid = $p2pChatType.GetProperty("OtherJid").GetValue($p2pChat, $null)
if ($null -eq $otherJid) {
$otherJid = $jidCtor3.Invoke(@("codex-probe", "offline.local", ""))
Set-FieldInHierarchy -Object $p2pChat -Type $p2pChatType -Name "<OtherJid>k__BackingField" -Value $otherJid | Out-Null
}
$formCtor = $p2pFormType.GetConstructor(@($chatType, [string], [string]))
$form = $formCtor.Invoke(@($p2pChat, "", ""))
if ($RuntimeMode -eq "Deps") {
$userInfoCache = $userInfoCacheType.GetMethod("GetInstance", [System.Reflection.BindingFlags]"Public,Static").Invoke($null, @())
$addUserInfoCache = $userInfoCacheType.GetMethod("AddCache", [Type[]]@([string], $userInfoType))
foreach ($cacheEntry in @(
@{ Key = $myBareJid; User = $myUser },
@{ Key = $myBareJid.ToLowerInvariant(); User = $myUser },
@{ Key = (($myBareJid -split "@")[0]); User = $myUser },
@{ Key = $otherBareJid; User = $otherUser },
@{ Key = $otherBareJid.ToLowerInvariant(); User = $otherUser },
@{ Key = "codex-probe"; User = $otherUser }
)) {
$addUserInfoCache.Invoke($userInfoCache, [object[]]@([string]$cacheEntry.Key, $cacheEntry.User.PSObject.BaseObject))
}
}
$form.Name = "frmP2PChat"
$form.Text = "Codex Real frmP2PChat Offline Probe"
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$form.Left = $X
$form.Top = $Y
$form.Width = $Width
$form.Height = $Height
$uiaDumpFile = $null
$uiaRoot = $null
$screenshotFile = $null
if ($ShowWindow) {
$form.Show()
[System.Windows.Forms.Application]::DoEvents()
Start-Sleep -Milliseconds 800
[System.Windows.Forms.Application]::DoEvents()
if ($script:RealFrmP2PThreadExceptions.Count -gt 0) {
$threadExceptionRecords = @()
foreach ($threadException in $script:RealFrmP2PThreadExceptions) {
$threadExceptionRecords += Convert-ExceptionToRecord -Exception $threadException
}
$relevantFrame = Get-FirstRelevantFrame -ExceptionRecords $threadExceptionRecords
$threadResult = [pscustomobject]@{
ok = $false
stage = "show_thread_exception"
process_bitness = 32
runtime_mode = $RuntimeMode
self_chat = [bool]$SelfChat
skip_roster_manager = [bool]$SkipRosterManager
client_dir = $clientFull
type = $p2pFormType.FullName
hwnd = if ($form.IsHandleCreated) { "0x" + $form.Handle.ToInt64().ToString("X") } else { $null }
visible = $form.Visible
relevant_frame = $relevantFrame
exceptions = $threadExceptionRecords
result_file = $resultFile
}
$threadResult | ConvertTo-Json -Depth 32 | Set-Content -LiteralPath $resultFile -Encoding UTF8
$threadResult | ConvertTo-Json -Depth 32 -Compress
try { $form.Close() } catch {}
exit 3
}
if ($form.IsHandleCreated -and (Test-Path -LiteralPath $helperFull)) {
$hwndForDump = "0x" + $form.Handle.ToInt64().ToString("X")
$dump = Invoke-HelperJson -HelperPath $helperFull -Op "dump_uia" -OpArgs @{
hwnd = $hwndForDump
max_depth = 8
max_children = 250
include_text = $true
} -RequestId "real-frmP2PChat-dump-uia"
$uiaDumpFile = Join-Path $outFull ("uia-dump-real-frmP2PChat-{0}.json" -f $timestamp)
$dump | ConvertTo-Json -Depth 40 | Set-Content -LiteralPath $uiaDumpFile -Encoding UTF8
if ($dump.ok) {
$uiaRoot = $dump.data.root
}
}
if (-not $NoScreenshot) {
$screenshotFile = Join-Path $outFull ("real-frmP2PChat-{0}.png" -f $timestamp)
Save-WindowScreenshot -OutputPath $screenshotFile -ScreenX $form.Left -ScreenY $form.Top -CaptureWidth $form.Width -CaptureHeight $form.Height
}
$remainingHold = [Math]::Max(0, $HoldSeconds)
if ($remainingHold -gt 0) {
Start-Sleep -Seconds $remainingHold
}
}
$result = [pscustomobject]@{
ok = $true
process_bitness = 32
runtime_mode = $RuntimeMode
self_chat = [bool]$SelfChat
skip_roster_manager = [bool]$SkipRosterManager
client_dir = $clientFull
type = $p2pFormType.FullName
chat_type = $p2pChat.GetType().FullName
hwnd = if ($form.IsHandleCreated) { "0x" + $form.Handle.ToInt64().ToString("X") } else { $null }
visible = $form.Visible
name = $form.Name
text = $form.Text
size = @{ width = $form.Width; height = $form.Height }
result_file = $resultFile
uia_dump_file = $uiaDumpFile
screenshot_file = $screenshotFile
uia_root = $uiaRoot
}
$result | ConvertTo-Json -Depth 24 | Set-Content -LiteralPath $resultFile -Encoding UTF8
$result | ConvertTo-Json -Depth 24 -Compress
}
catch {
$exceptionRecords = Convert-ExceptionToRecord -Exception $_.Exception
$ctorFrame = $null
foreach ($record in $exceptionRecords) {
foreach ($frame in $record.frames) {
if ($frame.method_type -eq "IMPP.Client.Business.ChatManager.SingleChat.frmP2PChat" -and $frame.method_name -eq ".ctor") {
$ctorFrame = $frame
break
}
}
if ($ctorFrame) { break }
}
$matchedIlLine = if ($ctorFrame) { Find-IlLine -OutDirFull $outFull -IlOffsetHex $ctorFrame.il_offset_hex } else { $null }
$result = [pscustomobject]@{
ok = $false
process_bitness = 32
runtime_mode = $RuntimeMode
self_chat = [bool]$SelfChat
skip_roster_manager = [bool]$SkipRosterManager
client_dir = $clientFull
error = $_.Exception.ToString()
category = $_.CategoryInfo.ToString()
script_stack = $_.ScriptStackTrace
ctor_il_offset_hex = if ($ctorFrame) { $ctorFrame.il_offset_hex } else { $null }
ctor_frame = $ctorFrame
matched_il_line = $matchedIlLine
exceptions = $exceptionRecords
result_file = $resultFile
}
$result | ConvertTo-Json -Depth 32 | Set-Content -LiteralPath $resultFile -Encoding UTF8
$result | ConvertTo-Json -Depth 32 -Compress
exit 2
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
param(
[string]$ScriptPath = "scripts/extract-frmP2PChat-il-risk.ps1",
[string]$OutDir = "runs/offline-chat-window/il-risk-contract"
)
$ErrorActionPreference = "Stop"
$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")
$target = if ([System.IO.Path]::IsPathRooted($ScriptPath)) {
$ScriptPath
}
else {
Join-Path $repo $ScriptPath
}
if (-not (Test-Path -LiteralPath $target)) {
throw "script not found: $target"
}
$outFull = if ([System.IO.Path]::IsPathRooted($OutDir)) {
$OutDir
}
else {
Join-Path $repo $OutDir
}
if (Test-Path -LiteralPath $outFull) {
Remove-Item -LiteralPath $outFull -Recurse -Force
}
$raw = & powershell -NoProfile -ExecutionPolicy Bypass -File $target -OutDir $OutDir
$result = $raw | ConvertFrom-Json
if (-not $result.ok) {
throw "extract script returned ok=false"
}
foreach ($path in @($result.ctor_il_file, $result.risk_csv_file, $result.risk_md_file)) {
if (-not (Test-Path -LiteralPath $path)) {
throw "expected output missing: $path"
}
}
if ($result.ctor_line_count -lt 500) {
throw "ctor IL line count too small: $($result.ctor_line_count)"
}
if ($result.risk_count -lt 50) {
throw "risk count too small: $($result.risk_count)"
}
$riskText = Get-Content -LiteralPath $result.risk_csv_file -Raw
foreach ($required in @("IL_00f6", "add_OnConnectError", "P2PChat::get_OtherJid", "IMPPManager::get_UserInfo")) {
if ($riskText -notmatch [regex]::Escape($required)) {
throw "risk csv missing evidence: $required"
}
}
[pscustomobject]@{
ok = $true
checked = 4
ctor_line_count = $result.ctor_line_count
risk_count = $result.risk_count
} | ConvertTo-Json -Compress

View File

@@ -0,0 +1,49 @@
param(
[string]$ScriptPath = "scripts/open-offline-real-frmP2PChat.ps1"
)
$ErrorActionPreference = "Stop"
$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")
$target = if ([System.IO.Path]::IsPathRooted($ScriptPath)) {
$ScriptPath
}
else {
Join-Path $repo $ScriptPath
}
if (-not (Test-Path -LiteralPath $target)) {
throw "script not found: $target"
}
$text = Get-Content -LiteralPath $target -Raw
$requiredPatterns = @(
@{ Name = "x86 PowerShell guard"; Pattern = "Environment]::Is64BitProcess" },
@{ Name = "AssemblyResolve dependency loader"; Pattern = "AssemblyResolve" },
@{ Name = "fake runtime mode parameter"; Pattern = "RuntimeMode" },
@{ Name = "self chat variant"; Pattern = "SelfChat" },
@{ Name = "skip roster variant"; Pattern = "SkipRosterManager" },
@{ Name = "CLR IL offset extraction"; Pattern = "GetILOffset" },
@{ Name = "IL offset JSON field"; Pattern = "il_offset_hex" },
@{ Name = "Config.BaseConfig fake runtime"; Pattern = "<BaseConfig>k__BackingField" },
@{ Name = "remote control config key"; Pattern = "Remote_Control_Visible" },
@{ Name = "fake frmMain activation target"; Pattern = "<frmMain>k__BackingField" },
@{ Name = "UserInfo cache warmup"; Pattern = "UserInfoCache" },
@{ Name = "result artifact output"; Pattern = "real-frmP2PChat-result" }
)
$missing = @()
foreach ($item in $requiredPatterns) {
if ($text -notmatch $item.Pattern) {
$missing += $item.Name
}
}
if ($missing.Count -gt 0) {
throw "contract missing: $($missing -join ', ')"
}
[pscustomobject]@{
ok = $true
script = $target
checked = $requiredPatterns.Count
} | ConvertTo-Json -Compress

View File

@@ -0,0 +1,251 @@
param(
[string]$OutputDir = "runs/login-reachability-probe-package"
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
$packageScript = Join-Path $repo "scripts\package-login-reachability-probe.ps1"
if (-not (Test-Path -LiteralPath $packageScript)) {
throw "missing package script: $packageScript"
}
$packageRoot = Join-Path $repo $OutputDir
$zipPath = "$packageRoot.zip"
if (Test-Path -LiteralPath $packageRoot) {
Remove-Item -LiteralPath $packageRoot -Recurse -Force
}
if (Test-Path -LiteralPath $zipPath) {
Remove-Item -LiteralPath $zipPath -Force
}
& powershell -NoProfile -ExecutionPolicy Bypass -File $packageScript -OutputDir $OutputDir
if ($LASTEXITCODE -ne 0) {
throw "package-login-reachability-probe.ps1 failed with exit code $LASTEXITCODE"
}
$requiredFiles = @(
"README.txt",
"OPERATOR-STEPS.md",
"TODO-COVERAGE.md",
"EXPECTED-RETURN-FILES.txt",
"LOGIN-REACHABILITY-INPUTS.template.json",
"LOGIN-REACHABILITY-INPUTS.schema.json",
"LOGIN-REACHABILITY-PACKAGE-MANIFEST.json",
"RUN-LOGIN-REACHABILITY-SUITE.bat",
"00-prepare-inputs.bat",
"01-run-before-recorder.bat",
"02-run-after-text-recorder.bat",
"03-run-after-file-recorder.bat",
"04-create-return-zip.bat",
"CREATE-RETURN-ZIP.ps1",
"compute-text-hash.ps1",
"compute-file-hash.ps1",
"optional-run-capability-smoke.bat",
"docs\login-reachability-validation-items.md",
"docs\send-upload-deep-dive.md",
"tools\isphere-capability-smoke.exe",
"recorder\ISphereLiveProbeRecorder.exe",
"recorder\variants\ISphereLiveProbeRecorder-x86.exe"
)
foreach ($relative in $requiredFiles) {
$path = Join-Path $packageRoot $relative
if (-not (Test-Path -LiteralPath $path)) {
throw "missing package file: $relative"
}
}
$instructionText = @(
Get-Content -LiteralPath (Join-Path $packageRoot "README.txt") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "OPERATOR-STEPS.md") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "TODO-COVERAGE.md") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "EXPECTED-RETURN-FILES.txt") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.template.json") -Raw
Get-Content -LiteralPath (Join-Path $packageRoot "LOGIN-REACHABILITY-PACKAGE-MANIFEST.json") -Raw
) -join "`n"
foreach ($needle in @(
"LOCAL_LOGIN_UNAVAILABLE",
"ONLINE_LOGIN_REQUIRED",
"NO_AUTOMATIC_SEND",
"RUN-LOGIN-REACHABILITY-SUITE.bat",
"LOGIN-REACHABILITY-OUTPUT.json",
"run",
"targets",
"runtime",
"reachability",
"server_auth",
"snapshots",
"attempts",
"failures",
"correlation",
"content_sha256",
"file_sha256",
"duplicate_second_send_attempted",
"duplicate_second_file_send_attempted",
"production_send_enabled",
"production_file_send_enabled",
"runtime_observations",
"group_probe",
"fallback_a_route",
"TODO-COVERAGE",
"backup_only"
)) {
if ($instructionText -notmatch [regex]::Escape($needle)) {
throw "package instructions missing required phrase: $needle"
}
}
if (-not (Test-Path -LiteralPath $zipPath)) {
throw "missing package zip: $zipPath"
}
$inputsTemplate = Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.template.json"
$inputsPath = Join-Path $packageRoot "LOGIN-REACHABILITY-INPUTS.json"
$inputs = Get-Content -LiteralPath $inputsTemplate -Raw | ConvertFrom-Json
$inputs.run.operator_confirmed_logged_in = $true
$inputs.run.operator_started_at_local = "2026-07-13T09:00:00+08:00"
$inputs.run.operator_finished_at_local = "2026-07-13T09:05:00+08:00"
$inputs.run.before_recorder_present = $true
$inputs.run.one_shot_text_enabled = $true
$inputs.run.one_shot_file_enabled = $true
$inputs.run.one_text_send_only_confirmed = $true
$inputs.run.one_file_send_only_confirmed = $true
$inputs.targets.direct_jid = "test-direct@example.invalid"
$inputs.targets.group_jid = "test-group@example.invalid"
$inputs.targets.target_selection_source = "verify-script"
$inputs.targets.self_send_or_sandbox_account_confirmed = $true
$inputs.runtime_observations.app_context_manager_reachable = $true
$inputs.runtime_observations.message_scheduling_reachable = $true
$inputs.runtime_observations.chat_xmpp_authenticated = $true
$inputs.runtime_observations.target_jid_mapping_observed = $true
$inputs.runtime_observations.file_upload_para_observed = $true
$inputs.runtime_observations.ifile_transfer_reachable = $true
$inputs.runtime_observations.file_upload_result_file_id_observed = $true
$inputs.runtime_observations.send_file_message_finalization_observed = $true
$inputs.runtime_observations.notes = "synthetic runtime observations"
$inputs.text_attempt.content_sha256 = ("a" * 64)
$inputs.text_attempt.content_length = 16
$inputs.text_attempt.operator_clicked_send_at_local = "2026-07-13T09:01:00+08:00"
$inputs.text_attempt.after_recorder_present = $true
$inputs.text_attempt.success_ack_or_sent_record_present = $true
$inputs.text_attempt.success_ack_or_sent_record = "synthetic sent-record ack for verify script"
$inputs.text_attempt.duplicate_second_send_attempted = $false
$inputs.file_attempt.allowed_dir = "C:\verify"
$inputs.file_attempt.sandbox_file_path = "C:\verify\small.txt"
$inputs.file_attempt.file_sha256 = ("b" * 64)
$inputs.file_attempt.file_size_bytes = 12
$inputs.file_attempt.operator_clicked_send_file_at_local = "2026-07-13T09:03:00+08:00"
$inputs.file_attempt.after_recorder_present = $true
$inputs.file_attempt.file_upload_or_sent_record_present = $true
$inputs.file_attempt.file_upload_or_sent_record = "synthetic file sent-record ack for verify script"
$inputs.file_attempt.duplicate_second_file_send_attempted = $false
$inputs.group_probe.enabled = $true
$inputs.group_probe.group_jid = "test-group@example.invalid"
$inputs.group_probe.chatroom_branch_observed = $true
$inputs.group_probe.speech_permission_state = "allowed"
$inputs.group_probe.upload_permission_state = "allowed"
$inputs.fallback_a_route.enabled_if_b_route_fails = $true
$inputs.fallback_a_route.hwnd = "0x1234"
$inputs.fallback_a_route.rtbSendMessage_present = $true
$inputs.fallback_a_route.btnSend_present = $true
$inputs.fallback_a_route.btnSendFile_or_file_menu_present = $true
$inputs.fallback_a_route.uia_or_screenshot_ref = "synthetic fallback evidence"
$inputs.sent_record_source.source_type = "synthetic"
$inputs.sent_record_source.source_path_or_ref = "verify-script"
$inputs.sent_record_source.before_count = "1"
$inputs.sent_record_source.after_count = "3"
$inputs.sent_record_source.ack_or_ref_id = "verify-ack"
$inputs.sent_record_source.correlation_notes = "synthetic verification only"
$inputs | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $inputsPath -Encoding UTF8
$beforeProbeDir = Join-Path $packageRoot "return-evidence\before\isphere-live-probe-verify"
$afterTextDir = Join-Path $packageRoot "return-evidence\after-text\isphere-live-probe-verify"
$afterFileDir = Join-Path $packageRoot "return-evidence\after-file\isphere-live-probe-verify"
New-Item -ItemType Directory -Force -Path $beforeProbeDir, $afterTextDir, $afterFileDir | Out-Null
@'
{
"probe_mode": "verify",
"target_count": 1,
"host": { "is_64_bit_os": true, "is_64_bit_process": false, "machine_name": "VERIFY" },
"targets": [
{
"pid": 1234,
"process_name": "IMPlatformClient",
"bitness": "x86",
"assembly_presence": {
"IMPlatformClient.exe": true,
"smack.dll": true,
"IMPP.Interface.dll": true,
"IMPP.Service.dll": true,
"IMPP.ServiceBase.dll": true
}
}
]
}
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "probe_client_runtime.json") -Encoding UTF8
@'
{
"entrypoints": [
{ "id": "text_high_level_by_jid", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "text_message_scheduler", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "text_wire_chat_send", "capability": "send_message", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "file_service_upload", "capability": "send_file", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" },
{ "id": "file_wire_message", "capability": "send_file", "assembly_found": true, "reflection_type_found": true, "reflection_method_found": true, "string_type_hint": true, "string_method_hint": true, "available": true, "reflection_error": "" }
]
}
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "send_entrypoints_preflight.json") -Encoding UTF8
@'
{ "tcp": { "connection_count": 1, "connections": [ { "state": "ESTABLISHED", "remote_port": 5222 } ] } }
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "network_inventory.json") -Encoding UTF8
@'
{ "target_process_seen": true, "initial_route_hint": "B_ROUTE_PROMISING" }
'@ | Set-Content -LiteralPath (Join-Path $beforeProbeDir "feasibility_summary.json") -Encoding UTF8
"after text synthetic evidence" | Set-Content -LiteralPath (Join-Path $afterTextDir "dummy.txt") -Encoding UTF8
"after file synthetic evidence" | Set-Content -LiteralPath (Join-Path $afterFileDir "dummy.txt") -Encoding UTF8
Push-Location $packageRoot
try {
$returnOutput = & powershell -NoProfile -ExecutionPolicy Bypass -File ".\CREATE-RETURN-ZIP.ps1" 2>&1
$returnExit = $LASTEXITCODE
}
finally {
Pop-Location
}
if ($returnExit -ne 0) {
throw "CREATE-RETURN-ZIP.ps1 synthetic verification failed exit=$returnExit output=$($returnOutput -join "`n")"
}
$outputJson = Join-Path $packageRoot "LOGIN-REACHABILITY-OUTPUT.json"
if (-not (Test-Path -LiteralPath $outputJson)) {
throw "missing generated LOGIN-REACHABILITY-OUTPUT.json"
}
$output = Get-Content -LiteralPath $outputJson -Raw | ConvertFrom-Json
foreach ($section in @("run", "targets", "runtime", "reachability", "server_auth", "snapshots", "attempts", "failures", "correlation")) {
if ($null -eq $output.PSObject.Properties[$section]) {
throw "LOGIN-REACHABILITY-OUTPUT.json missing section: $section"
}
}
if ($output.run.validation_ok -ne $true) {
throw "synthetic LOGIN-REACHABILITY-OUTPUT.json should have validation_ok=true"
}
[ordered]@{
ok = $true
package_dir = (Resolve-Path -LiteralPath $packageRoot).Path
zip = (Resolve-Path -LiteralPath $zipPath).Path
required_file_count = $requiredFiles.Count
synthetic_return_verified = $true
online_login_required = $true
no_automatic_send = $true
production_send_enabled = $false
production_file_send_enabled = $false
} | ConvertTo-Json -Depth 6 -Compress