# Privacy and data handling [中文说明](#中文说明) ## English `dsh-llm-call-inspector` is a debugging instrument. Treat its captured content with the same care as the original conversation, workspace, and tool output. This document describes plugin `v0.2.1` on DSH `0.1.2-alpha.2`. That is the only DSH release declared compatible with `v0.2.1`; DSH rc.8/rc.1/rc.2 users should retain plugin `v0.2.0`. ### What is captured For every DSH-normalized `llm/stream` call carrying a `sessionId`, the plugin keeps call metadata and, by default, a detached JSON snapshot of an explicit request-field allowlist plus the ordered normalized response chunks. The request allowlist is `provider`, `model`, `reasoningEffort`, `messages`, `system`, `tools`, `temperature`, `maxTokens`, `stop`, `sessionId`, and `purpose`. Top-level HTTP headers, API-key fields, abort signals, and undeclared adapter-private fields on the request object are not copied. Normalized `messages` are copied whole rather than recursively allowlisted. Current built-in image blocks contain DSH attachment-reference metadata, and the plugin does not independently read attachment bytes or observe provider-side base64 payloads; however, custom message blocks can embed arbitrary nested fields, including bytes or base64, which would be captured. Response chunks are also copied whole: JSON-compatible adapter replay metadata such as `finish.replayState` is included when emitted. When one terminal replay response has `kind: pi-ai`, `version: 2`, a bounded lowercase-hyphen `api` id, and provider/model matching this call, the Host additionally exposes that attribution as narrow, body-free `apiEvidence`; missing evidence remains distinct from malformed, mismatched, getter-failing, and conflicting attribution. This structural exclusion is not a redaction engine: prompts, tool arguments, tool results, system text, model output, attachment metadata, custom block fields, or replay metadata may themselves contain credentials, personal data, or proprietary content. ### Where it lives - The authoritative retained store lives only in the Host process's plugin-owned memory. - State is separated by DSH session id and bounded by `maxSessions`, `maxCallsPerSession`, and the cross-session `maxTotalBodyBytes` captured-JSON budget. - Request and response bodies have all-or-nothing JSON byte ceilings. Oversized or non-JSON bodies are replaced by explicit omission metadata. - The browser receives body-free summaries—including narrow protocol `apiEvidence` when validated—and requests only the selected call's full detail. A DSH session-scoped view store retains only interaction state—selection, search, filters, active detail tab, per-call manual API-reference choice, list scroll, and at most 300 recent call/tab body-scroll positions—and never stores captured bodies. Positions and manual choices for calls absent from the latest authoritative snapshot are pruned. - To restore a view after a tab switch, an apply-lifecycle-owned browser-memory cache may retain the latest body-free snapshot and one selected detail for at most four recent sessions. It is least-recently-used bounded and ephemeral; it does not use `localStorage`, `sessionStorage`, IndexedDB, or another browser-persistent store. - Using a copy action writes the selected JSON or semantic API reference to the system clipboard. - On DSH `0.1.2-alpha.2`, the Connection RPC channel uses DSH's Host/Origin fence and browser token/cookie authentication. The plugin adds no separate network listener and no export destination, but it does not impose an additional loopback-only restriction. - The plugin does not write request or response bodies to files, Session events, telemetry, or a third-party service. ### API Comparison boundary The API Comparison tab derives a semantic shape reference from captured normalized fields and an attributed or manually selected API protocol. It is not an HTTP or SSE capture. For validated call-level pi-ai replay-v2 evidence, projections are implemented for `openai-completions`, `openai-responses`, `azure-openai-responses`, `anthropic-messages`, `google-generative-ai`, `google-vertex`, `bedrock-converse-stream`, and `mistral-conversations`. Adapter reports for `openai-codex-responses` and `pi-messages` are recognized but not projected. With no accepted evidence, only the exact `deepseek-official` route may use the inspected DSH 0.1.2-alpha.2 contract as a labeled fallback; accepted adapter evidence takes precedence. An unresolved or unprojected call can use a manually selected shape reference. This per-call choice is session view state for comparison only; it does not change `apiEvidence` or prove which protocol ran. Similar route names, custom gateways, model names, prefixes, and provider branding are never guessed as protocol evidence. The inspector does not read Authorization, API keys, other request headers, the resolved endpoint, provider response headers, raw frames, adapter compatibility defaults, or hidden physical attempts. Complex history that needs adapter-private materialization is not projected. Adapter-final values that can change after capture are shown only as non-sendable `{$unobserved, dshInput}` markers. The comparison is computed locally from data already in browser memory. Opening it, switching tabs, choosing a manual reference, or copying it does not replay the call, contact the provider, consume tokens, or create an additional provider charge. The projected reference still contains prompt and tool content from the captured normalized request and must be treated as sensitive; copying it creates a clipboard copy. Connection authentication is the access boundary, not proof that the caller is physically local. If DSH Web admits a trusted non-loopback host, a browser session on that host that passes DSH authentication can access this channel and its captured bodies. Even on loopback, other software running as the same user, browser extensions, screen recording, process inspection, crash dumps, or a compromised DSH/browser process may expose displayed or in-memory content. ### When it disappears Authoritative Host records are removed when any of these occurs: - the user clears the active session in the LLM Calls view; - a per-session or session-count bound evicts them; - the plugin reloads after a config/source change; - the plugin is disabled or removed; or - the DSH Host process stops or restarts. Switching away from the LLM Calls view is intentionally not in that list: the browser can restore the current inspection context when the view remounts. Browser copies disappear independently when their four-session LRU bound evicts a session, the active session is cleared, the client plugin apply lifecycle is disposed or reloaded, or the browser page closes. There is no recovery path after the owning memory is gone because this plugin creates no persistent copy. ### Safer operation - Use `captureBodies: false` when call metadata is sufficient. - Run DSH on a trusted local machine and keep the Web surface loopback-only. - Avoid placing raw credentials in prompts, tool arguments, fixtures, or screenshots. - Lower per-body, global-body, and retention limits for sensitive work. - Clear the session before screen sharing or handing the machine to another person. - Review and pin the installed commit; the `dsh-plugin` GitHub topic is not a security review. ## 中文说明 `dsh-llm-call-inspector` 是调试仪器。请用与原始对话、工作区和工具输出相同的安全级别处理采集内容。 本文描述插件 `v0.2.1` 在 DSH `0.1.2-alpha.2` 上的行为;这是 `v0.2.1` 唯一声明兼容的 DSH 版本。仍使用 DSH rc.8/rc.1/rc.2 的用户应保留插件 `v0.2.0`。 ### 采集什么 对于每个带 `sessionId` 的 DSH 标准化 `llm/stream` 调用,插件保留调用元数据;默认还会保存一个脱离原对象的 JSON 快照,其中只包括明确允许的请求字段和有序标准化响应 chunks。 请求白名单是 `provider`、`model`、`reasoningEffort`、`messages`、`system`、`tools`、`temperature`、`maxTokens`、`stop`、`sessionId` 和 `purpose`。 插件不会复制顶层 HTTP headers、API-key 字段、终止信号或请求对象上未声明的适配器私有字段。标准化 `messages` 是整体复制的,不会递归执行字段白名单。当前内置图片块只包含 DSH 附件引用元数据,插件也不会主动读取附件字节或观察供应商侧的 base64 请求体;但自定义消息块可以嵌入任意字段,包括字节或 base64,这些内容会被采集。响应 chunks 同样会被完整复制;适配器产生的 JSON 兼容回放元数据(例如 `finish.replayState`)也会包含在内。如果某个终态 replay response 同时给出 `kind: pi-ai`、`version: 2`、有界的小写连字符 `api` id,且 provider/model 与本次调用匹配,Host 还会把该归因作为窄化、无正文的 `apiEvidence` 暴露;缺失证据与格式异常、不匹配、getter 读取失败、冲突归因保持区分。但这种结构性排除不是脱敏引擎:提示词、工具参数、工具结果、system 文本、模型输出、附件元数据、自定义块字段或回放元数据本身仍可能包含凭证、个人信息或专有内容。 ### 存在哪里 - 权威保留存储只存在于 Host 进程内、由插件持有的内存中。 - 状态按 DSH session id 隔离,并受 `maxSessions`、`maxCallsPerSession` 与跨会话 captured JSON 预算 `maxTotalBodyBytes` 限制。 - 请求和响应正文采用全有或全无的 JSON 字节上限;超限或不可 JSON 化的正文会替换成明确的 omission 元数据。 - 浏览器先获取不含正文的摘要,其中可能包括经过校验的窄化协议 `apiEvidence`;只为当前选中调用请求完整详情。DSH 会话级 view store 只保留选中项、搜索、筛选、当前详情页签、逐调用手动 API 参考、列表滚动位置,以及最多 300 个近期“调用/页签”的正文滚动位置,从不保存采集正文;最新权威摘要中已不存在的调用,其位置和手动选择都会被修剪。 - 为了在切换页面后恢复视图,一个由插件 apply 生命周期持有的浏览器内存缓存可以保留最多 4 个近期会话的最新无正文摘要和一个已选详情。它按最近最少使用淘汰,只是临时内存,不使用 `localStorage`、`sessionStorage`、IndexedDB 或其他浏览器持久化存储。 - 使用复制操作会把当前 JSON 或 API 语义参考写入系统剪贴板。 - 在 DSH `0.1.2-alpha.2` 中,Connection RPC channel 使用 DSH 的 Host/Origin 防线与浏览器 token/cookie 认证。插件不新增网络监听,也没有导出目标,但不会额外强制仅 loopback。 - 插件不会把请求/响应正文写进文件、Session 事件、遥测或第三方服务。 ### API 对照边界 API 对照页签根据已经采集的标准化字段,以及已经归因或手动选择的 API 协议生成语义结构参考。它不是 HTTP 或 SSE 抓包。对于经过校验的调用级 pi-ai replay-v2 证据,已实现投影的协议包括 `openai-completions`、`openai-responses`、`azure-openai-responses`、`anthropic-messages`、`google-generative-ai`、`google-vertex`、`bedrock-converse-stream` 和 `mistral-conversations`。适配器报告的 `openai-codex-responses` 与 `pi-messages` 可以被识别,但不会被投影。没有可信证据时,只有精确的 `deepseek-official` 路由可以使用已审计 DSH 0.1.2-alpha.2 契约作为明确标注的兜底;有效适配器证据优先。 没有证据或尚未实现投影的调用可以手动选择结构参考。该逐调用选择只是会话级 view state,不会改变 `apiEvidence`,也不能证明实际运行了哪个协议。相似 route 名、自定义 gateway、模型名、前缀和 provider 品牌都不会被猜测成协议证据。 Inspector 不会读取 Authorization、API key、其他请求 headers、最终 endpoint、供应商响应 headers、原始帧、适配器兼容默认值或隐藏的物理尝试。需要适配器私有物化的复杂历史不会被投影;采集后仍可能变化的适配器最终值只显示为不可发送的 `{$unobserved, dshInput}` 标记。对照只在浏览器中使用已有数据计算。打开它、切换页签、选择手动参考或复制内容都不会回放调用、连接供应商、消耗 token 或新增供应商费用。投影参考仍可能包含标准化请求中的提示词和工具内容,必须按敏感内容处理;复制还会产生一份剪贴板副本。 Connection 认证是访问边界,并不能证明调用方物理上位于本机。如果 DSH Web 允许某个可信的非 loopback host,该 host 上通过 DSH 认证的浏览器会话就可以访问此 channel 及其采集正文。即使只开放 loopback,同一用户下运行的其他软件、浏览器扩展、录屏、进程检查、崩溃转储,或已经被攻破的 DSH/浏览器进程,仍可能暴露显示中或内存中的内容。 ### 什么时候消失 发生以下任一情况,Host 中的权威记录都会被移除: - 用户在“LLM 调用”页面清空当前会话; - 达到单会话或会话数量上限后被淘汰; - 配置/源码变化导致插件重载; - 插件被禁用或移除; - DSH Host 进程停止或重启。 “切换离开 LLM 调用页面”有意不在上面的列表中:view 重挂载时,浏览器可以恢复当前检查上下文。浏览器副本会在 4 会话 LRU 淘汰、清空当前会话、client plugin apply 生命周期结束或重载、或者浏览器页面关闭时独立消失。相关内存消失后没有恢复路径,因为本插件没有建立持久副本。 ### 更安全的使用方式 - 只需要调用元数据时,设置 `captureBodies: false`。 - 在可信本机运行 DSH,并保持 Web 仅 loopback 可访问。 - 不要把原始凭证放进提示词、工具参数、fixture 或截图。 - 对敏感工作降低单正文、全局正文预算与保留数量上限。 - 共享屏幕或把机器交给他人前,先清空当前会话。 - 审查并锁定安装 commit;GitHub 的 `dsh-plugin` topic 不是安全审核。