# Architecture ## Runtime topology ```mermaid flowchart TD UI[DSH Web: current Session] -->|session-scoped HTTP API| Host[dsh-echo Host plugin] Host --> Ann[tool/result.meta.dshCassette] Host --> Reg[configured cassette registry] Profile[reversible profile overlay] --> MCP[official DSH MCP client] MCP -->|stdio argv or loopback HTTP| Engine[mcp-cassette core] Engine --> Tape[versioned JSONL cassette] Engine -->|record only| Real[real MCP server] Engine -->|replay hit| MCP Engine -.->|explicit passthrough only| Real Reg --> Tape ``` The imported core owns protocol framing, stdio and Streamable HTTP/SSE transport, recording, matching, replay, redaction, and contract diff. The DSH layer owns configuration adaptation, lifecycle, Session annotations, path policy, APIs, and UI. ## Why the profile adapter is used DSH `0.1.1-rc.2` directly constructs its MCP SDK transports and does not expose a supported transport-provider seam. Replacing that client would duplicate reconnection, registration, timeout, credential-scrubbing, and disposal logic. For v0.1, DSH keeps its official MCP client and connects through the mature CLI or a loopback HTTP proxy. - stdio record wraps the original argv after `dsh-echo record`; - stdio replay contains the cassette command only, which structurally prevents starting the real server; - stdio passthrough contains the original argv only after explicit selection; - HTTP record/replay proxies are started by the Host plugin and closed by its Cordis effect cleanup. The adapter writes an overlay and recovery manifest as new files. It does not edit the source profile. The DSH Loader row uses the package root (`dsh-echo`), whose default export is the Host service. This is intentional: DSH discovers `dsh.client` from that exact package root and then serves the `./client` export under `/plugins`. ## Session data flow 1. DSH calls a public MCP tool named `mcp____`. 2. The Host plugin observes `tools/execute`, looks up the configured cassette, and calculates the interaction ordinal and match state without consuming the replay engine's state. 3. The normal tool result gains `meta.dshCassette` containing IDs, mode, relative path, hit/miss/passthrough, fingerprint and a compact diff. 4. DSH persists the ordinary `tool/result` event in its Session/Trajectory. 5. The Web tab requests that Session only, resolves referenced configured cassettes, and renders re-redacted interaction details. Full arguments and results are not copied into a new custom Session event. This keeps one sensitive source of truth and remains compatible with DSH's existing event persistence. ## Trust and lifecycle boundaries - `rootDir` is the filesystem boundary. Symlinked roots and paths escaping the root are rejected. - The Web API addresses preconfigured cassette IDs rather than arbitrary paths. - UI frames pass through redaction even when a legacy cassette says redaction was disabled. - Record mode starts a real server. Replay mode never does. Passthrough is an explicit side-effect boundary. - Host disposal closes all HTTP listeners and removes routes/listeners. DSH owns and terminates configured stdio wrapper processes. For the alternatives and audited DSH extension points, see [dsh-integration-options.md](dsh-integration-options.md).