Repository navigation
Closed
Labels
1.0-blockerMust be done before the 1.0 announcement (docs conduct/readiness.md)Must be done before the 1.0 announcement (docs conduct/readiness.md)P0Now: top priorityNow: top priorityenhancementNew feature or requestNew feature or requestextensibilityThird-party encodings and generatorsThird-party encodings and generators
Milestone
Description
How developers extend Comline with their own wire formats, framings, transports and dispatchers, and what separates an official extension from a third-party one. Proposed, open for discussion; nothing implemented. The full write-up is the proposal page in ComlineProject/docs#48.
Where things stand
- Transports: open. Rust's
Transportand TS's equivalent take anything that moves bytes. - Wire formats: open at runtime (
WireFormatin Rust,Codecin TS).contract/wire.rsalready asks third-party formats to namespace their names. - Framings: the runtime trait is open, but generated code isn't. Generators bake the framing in and know only
datagramandjsonrpc. Core checks@framingagainst that list, so a third-party framing can't be named in a schema. An unknowndefault_framingsilently becomes datagram (cli#81). - Dispatchers: the generated
<Proto>DispatcherimplementsDispatch, and wrapping it works, but that isn't documented as an extension point. - Generators: compiled into the CLI (Generators outside the CLI build: loading, discovery, compatibility #8). Process plugins (Proposal D) are blocked by the playground.
- Nothing lets a schema say "this protocol uses
com.acme.frame@1, and here is what that means".
Proposal
- Official encodings use the same public mechanism as third-party ones. "Official" means maintained here and shipped by default, not built in through a private path, the same principle as std being a package.
- An encoding is a definition: a versioned name (bare for official, namespaced otherwise), a profile (Compatibility rules: what a version bump means #119, encoding profiles) and vectors in the corpus format. Implementations are per language and separate. The corpus format and the profile schema become a public, versioned spec. The conformance runner becomes a library a third party runs in their own CI.
- Core learns about a third-party encoding from a dependency. A package declares the encodings it defines (name plus profile) in
config.idp. A dependent package can then use those names in@framingand in its declared formats. The profile is trusted like the dependency's schemas: declared, and proven in the author's CI. An encoding with no profile gets the strictest one. - Generated code gets the implementation from the consumer's config.
comline.tomlmaps each name to a type per target, e.g."com.acme.frame@1" = "acme_frame::AcmeFraming". The generator needs no plugin to wire it. A declared but unmapped encoding is a generation error, never a fallback. The per-package format trait (generation#67) is implemented for each mapped name instead of being sealed. - A format serializes the generated data model (serde in Rust, Shapes in TS). Needing more from the schema, such as tags or ordinals, makes it a language feature, not a plug-in.
- Transports and dispatchers stay runtime-only: no name, profile or declaration, since they can't affect compatibility. They get documented patterns (middleware by wrapping
Dispatch). - Generators stay separate (Generators outside the CLI build: loading, discovery, compatibility #8 / Proposal D). Nothing above needs runtime generator loading.
Promotion path: a third-party encoding becomes official by contributing its profile, vectors and implementations to the official runtimes. It keeps its namespaced name, because renaming would change the handshake. Bare names are reserved for encodings that start out official.
Open questions
- Trust: is "declared by a dependency" enough, or should core require the dependency to ship vectors too, and could a CI tool run a third-party implementation against them?
- Where the name → type mapping lives:
comline.tomlper target (consumer-side), or also a default shipped by the encoding's package per language. - Whether a third-party encoding package can also carry its implementations (a crate, an npm package) and have generated
lib-mode output depend on them automatically. - Whether the same mechanism should cover transports later (for example, a handshake capability naming the transport).
Work (after discussion)
- Public spec: the corpus case format and the profile schema, versioned.
- The conformance runner as a reusable library (Rust; TS follows).
-
config.idp: a package declares the encodings it defines (builds on config.idp: declare the encodings a package uses, and framing instances #117). - Core:
@framingand declared formats accept names declared by dependencies. -
comline.toml: a per-target name → type mapping; the generators wire mapped types (builds on generation#67). - Handshake as a declared axis (
comline@1,none, custom), with@handshakeand the call-site skip renamed*_unverified: Handshake as a declared, pluggable axis; *_unchecked skip paths runtime#18 - Giving up a guarantee:
@unverified = "reason"; core works out the set; off by default; consumers accept per protocol, recording the set: @unverified: an explicit, opt-in marker for giving up a peer guarantee #121 - Docs: a guide to writing a format, a framing, a handshake, a transport and a dispatcher wrapper.
Metadata
Metadata
Assignees
Labels
1.0-blockerMust be done before the 1.0 announcement (docs conduct/readiness.md)Must be done before the 1.0 announcement (docs conduct/readiness.md)P0Now: top priorityNow: top priorityenhancementNew feature or requestNew feature or requestextensibilityThird-party encodings and generatorsThird-party encodings and generators
Type
Projects
- StatusShow more project fieldsDone
Activity
Kinflou commentedon Oct 19, 2026
Related: #123 (packet dispatch) is the first concrete use of a framing that needs schema-level addressing (explicit ids, families, phases). That's the case the "what a format can't be" rule sends to the language rather than to a plug-in. Its official
comline.packet@1and any custom packet framing would read generated dispatch tables.Kinflou commentedon Oct 20, 2026
Decided 2026-10-20 (recorded in ComlineProject/docs#64):
comline conformance. Without vectors: encoding conformance is given up (@unverified+ consumer acceptance).comline.tomlonly overrides it. Declared but neither mapped nor suggested is a generation error.Kinflou commentedon Oct 31, 2026
Decided 2026-10-31:
.wasm. The CLI runs a.wasmunder wasmtime; the playground runs it through a browser WASI shim.liboutput depends on it automatically, and a consumer can override it incomline.toml.The extension API and the generator protocol are part of the 1.0 promise (docs
conduct/readiness.md). An implementation plan comes next.Kinflou commentedon Oct 31, 2026
Status (2026-11-01):
encodingsdeclarations in config.idp (config: declare encodings in config.idp (core#120, B1) #142), the official package (encodings: the official ones, declared by an embedded package (core#120, B2) #143), mappings in comline.toml and the generators (codegen: resolve encodings to a target's mappings (core#120 B3) generation#88, Map framings, formats and handshakes through the request's encodings (core#120 B4) comline-rust#80, Map framings and codecs through the request's encodings (core#120 B4) comline-typescript#92, generate: map encodings in comline.toml (core#120 B3) cli#105), and custom handshakes (codegen: run a namespaced handshake wherever generated code opens comline-rust#81, codegen: run a namespaced handshake wherever generated code opens comline-typescript#93, handshake: an async handshake, and AsyncConnection::connect_with/accept_with runtime#65, codegen: run a namespaced handshake on an async connection too comline-rust#82).comline conformance(comline conformance: run an implementation against an encoding's vectors cli#106) and the guides (Guides for extending Comline docs#99).Kinflou commentedon Oct 31, 2026
Status (2026-11-01): the guides shipped in ComlineProject/docs#105, and
comline conformancein ComlineProject/cli#108. This stays open for #147: third-party encodings and handshakes currently give up guarantees silently.Kinflou commentedon Oct 31, 2026
Done:
comline conformance(conformance: run an encoding's implementation against its package's vectors cli#108, conformance: the runner as a library, and the corpus as a versioned spec runtime#69);Follow-ups: #149 (an encoding's own
unverifiedreason), ComlineProject/language-server#88, ComlineProject/comline-typescript#98 and #99.