Repository navigation
SDK: ship a fake-transport testkit for consumer-side mocking #872
Description
Parent
Sub-issue of #821 (Prototype @stacklok/mecatl TypeScript SDK).
Problem
Neither #761 nor #821 describes any story for client-side SDK mocking. The only testing strategy either issue names is running a real mecated --mock (a real daemon with a mocked LLM behind it) for the SDK's own test suite — nothing addresses how a downstream app built on @stacklok/mecatl (Studio included) unit/e2e-tests its own code without spinning up a real daemon.
This matters more than a generic "add test helpers" ask, for two reasons:
- TypeScript SDK for mecatl (browser + Node) #761/Prototype @stacklok/mecatl-sdk TypeScript SDK #821 already commit to Connect-ES for the Node/Bun transport ("Connect-ES gRPC transport" / "UDS Connect-ES session provider"). Connect-ES ships
createRouterTransport— an in-memory fakeTransportthat runs real (de)serialization with hand-written handlers, no wire framing to fake. The primitive already exists; nobody has wired it into the SDK. - A naive canned-response mock can't exercise the bug class PR feat(engine,server): durable run identity — a host-minted run_id #827/feat(server): expected_run_id on controls, and strict steer #828 exist to fix. Those two PRs harden a race — a stale approve/cancel/steer control landing on the wrong run after a run ends. A mock that just returns fixed JSON validates UI wiring but can never reproduce that race. Testing it needs a fake transport that models at least two concurrent runs and actually rejects a stale
expected_run_id, not just echoes a canned response.
There's also a downstream-specific wrinkle: an app with its own BFF (e.g. a Next.js server holding the real gRPC connection) needs its own process-level fake (MSW-in-Node via instrumentation.ts, or a sibling fake-server process) — a pattern that exists in the wild but that nobody has documented against this SDK's shape.
Proposal
Ship a small, official mocking surface as part of @stacklok/mecatl (exact export shape TBD — likely alongside ./node):
- A
createMockTransport()-style helper wrapping Connect-ES'screateRouterTransport, pre-wired with the harness's actual service definitions from./gen. - Scenario/fixture ergonomics (a
MockScenarios-style.scenario()/.override()API) so tests can switch canned behavior without rewriting handlers per test. - Coverage for both unary and streaming calls (
Converse, the futureWatchSessionEvents), including a minimal simulated run-identity/expected_run_idstate machine so the stale-control rejection path is actually testable. - A short doc/example showing the Next.js/BFF pattern (server-side interceptor + scenario-signal propagation) for consumers who can't rely on browser-visible
page.route()/MSW interception because their gRPC call happens server-side.
Non-goals
- A generic gRPC mocking library — this is scoped to
@stacklok/mecatl's own generated surface. - Browser-side mocking guidance — the browser transport is plain HTTP/SSE, already trivially mockable with
page.route()/MSW; no new primitive needed there.
References
- TypeScript SDK for mecatl (browser + Node) #761, Prototype @stacklok/mecatl-sdk TypeScript SDK #821 (parent SDK proposal/plan)
- ADR 0248, ADR 0249 (compatibility/error contract, durable run identity)
- PR feat(engine,server): durable run identity — a host-minted run_id #827, feat(server): expected_run_id on controls, and strict steer #828 (the run-identity race this mock needs to be able to reproduce)
Fully or partially written by an AI agent.
Activity
docs: ADR 0253 — SDK mocking testkit
docs: ADR 0253 — SDK mocking testkit (#875)
samuv commentedon Sep 11, 2026
Removed from the completed SDK implementation parent. This remains an
independent downstream testing improvement, with ecosystem integration tracked
under #877. It does not block the
v0.1.0release in #1394.