Skip to content

B-XHLP-foreman-step-protocol-json-rpc-2

foreman’s step protocol (packages/rust/foreman/src/protocol.rs) is newline-delimited JSON over stdio with a JSON-RPC-style correlation id, but it is deliberately NOT a JSON-RPC 2.0 object. Instead of method beside an untyped params, the discriminator is the externally-tagged StepPayload key: {“payload”:{“progress”:{…}}} rather than {“method”:“progress”,“params”:{…}}.

Two reasons it shipped that way. The typed one: JSON-RPC has two discriminators that can disagree — method:“progress” beside a params carrying a StepResult is well-formed and nonsense — whereas the tagged union has one, so the pairing is structural in both Rust and TypeScript rather than validated at runtime. The forced one: ontogen-ts rejects internally-tagged serde enums outright, so #[serde(tag = “method”)] was never available.

The counter-argument, and the reason to revisit: following the standard means off-the-shelf JSON-RPC clients and third-party step implementations can speak the protocol without a shim. That matters as soon as a step implementation is expected to come from outside this repo — which the tagged step-variant design (WASM plugins, shell commands) anticipates.

What a move would involve: JSON-RPC’s params is inherently polymorphic, so a generated TS binding types it as unknown and consumers cast. Keeping type safety needs either a hand-written ts_opaque union over a tagged Rust enum, or accepting the cast at the boundary. Note ontogen-ts 0.1.2 still lists tag in REJECTED_SHAPE_ATTRS (verified at the tag; only flatten was removed), so the emitter side is unchanged — this is blocked on ts_opaque work or an upstream change, not on a version bump.

Recorded as a deliberate deviation in the module doc and in the D-VSLI ledger’s E1 section.


← Back to Backlog