diff --git a/docs/docs/design/core-target-contract.md b/docs/docs/design/core-target-contract.md index 00638dd..def283d 100644 --- a/docs/docs/design/core-target-contract.md +++ b/docs/docs/design/core-target-contract.md @@ -14,7 +14,9 @@ layer is replaced by real `wire` (framing) + `transport` (`Transport` trait, modules (7d–7e), tested end to end over both transports. The §4.4 IR changes are landed in `comline-core` (drop `synchronous`, `Function.parameters`, `KindValue::Unit` — core#46; `throws: Vec` + error ordinals — core#47). -Open: the `Alloc` seam, a JSON-RPC framing option, the async layer (7f+) · +Pluggable framing with a JSON-RPC impl (runtime#10 + comline-rust#8) and the +per-`protocol` `@framing` selector (comline-rust#9) are built. +Open: the `Alloc` seam, a config-level framing default, the async layer (7f+) · Affects `ComlineProject/core`, `ComlineProject/generation`, `ComlineProject/runtime`, `ComlineProject/comline-`, `ComlineProject/cli` @@ -192,11 +194,14 @@ built and tested (no more `todo!()` on this path): **Framing is a pluggable axis** (built — [runtime#10](https://github.com/ComlineProject/runtime/pull/10) + [comline-rust#8](https://github.com/ComlineProject/comline-rust/pull/8)). `contract::Framing` is orthogonal to `WireFormat` — `Client` / `Server` are generic over one, default `DatagramFraming`. `framing::JsonRpcFraming` (std) is the name-oriented alternative: `{"jsonrpc":"2.0","method":…,"params":…,"id":N}`, a raised schema error → a JSON-RPC `error` object keyed by ordinal, pairs with `format::Json`. `Dispatch` writes into a `Reply` (framing-agnostic ok/err/none) instead of an `Envelope` buffer, and exposes `calls()` so a method name resolves to an ordinal; the generated stub passes `Call::new(id, name)` (both addresses, the framing picks). +**A schema selects its framing** ([comline-rust#9](https://github.com/ComlineProject/comline-rust/pull/9)). `@framing = "jsonrpc"` on a `protocol` (frozen into `Protocol.parameters` as a `Property`, same path as `@timeout_ms` / `@provider` — no core change) makes the generator emit the JSON-RPC stack instead of the datagram one: `Client` wraps `Client`, `connect` / `serve` call `Client::connect_with_framing` / `Server::with_framing`, and the `Handshake` carries `framing.name()` rather than `FRAMING_DATAGRAM`. Absent / unrecognised keeps the datagram default byte-for-byte. Recognised: `jsonrpc`, `json-rpc`, `jsonrpc-2.0`. + Still open, to fix as part of this design: - The `Alloc` seam for owned bits (`.to_owned()`, decoded collection spines). -- A framing *selector* on the generated `connect` / `serve` helpers (they're - datagram-only today) + how a schema/config declares its framing. +- A `comline.toml` / config-level framing default (the schema annotation is + per-`protocol`; a package-wide `default_framing` is the same shape as + `default_wire`). - The async (`std`) layer — `AsyncDispatch` + an executor, emitted additively. ### 4.2 — The generated protocol @@ -685,11 +690,12 @@ what remains is below the decision line: trait signatures are built (7b–7e), and the IR changes the decisions imply are landed (`Function.parameters`, `KindValue::Unit`, drop `synchronous` — core#46; `throws: Vec` + error ordinals — core#47). The connection handshake - (runtime#8 + comline-rust#6) and pluggable framing incl. JSON-RPC (runtime#10 + - comline-rust#8) are built. Still open at the wire level: a framing selector on - the generated helpers + how a schema declares its framing, a `WarnOnly` - handshake mode, multi-`throws` (`! A, B`) grammar, version-diff enforcement of - the ordinal append-only rule, and the transport-requirements config unit. + (runtime#8 + comline-rust#6), pluggable framing incl. JSON-RPC (runtime#10 + + comline-rust#8), and the per-`protocol` `@framing` selector on the generated + `connect` / `serve` helpers (comline-rust#9) are built. Still open at the wire + level: a package-wide framing default in config, a `WarnOnly` handshake mode, + multi-`throws` (`! A, B`) grammar, version-diff enforcement of the ordinal + append-only rule, and the transport-requirements config unit. - **§4.6** — decided; the buffer-reuse budget is met by 7d–7e (`Client` / `Server`), the dispatcher's reply-body scratch and the arena `Alloc` mode are the follow-ons. diff --git a/docs/docs/guide/idl/protocol.md b/docs/docs/guide/idl/protocol.md index b83ea05..ad82f88 100755 --- a/docs/docs/guide/idl/protocol.md +++ b/docs/docs/guide/idl/protocol.md @@ -35,6 +35,23 @@ protocol Mail { Functions take [docstrings](docstrings.md) (including the `/// @name:` form for arguments) and `@key=value` annotations. +## Protocol annotations + +A `@key=value` annotation on the `protocol` itself configures the whole service. + +``` py linenums="1" +@framing = "jsonrpc" +protocol Mail { + function send_message(message: Message) -> str ! RecipientNotFound; +} +``` + +- **`@framing`** picks the wire framing the generated client and server use. + `"jsonrpc"` (`json-rpc`, `jsonrpc-2.0`) emits a + [JSON-RPC 2.0](https://www.jsonrpc.org/specification) stack; omit it for the + default compact datagram framing. Both ends of a connection must agree — the + [handshake](../runtime/call-system.md) refuses a mismatch. + How a call travels between caller and implementation is the [runtime](../runtime/index.md)'s job, over a pluggable [call system](../runtime/call-system.md).