KM43 is the bounded, authenticated and encrypted message protocol between an Origin89 controller and its clients. It is link-agnostic: UART, WebSocket, USB, BLE and MQTT change the framing beneath it, not the message semantics above it. The reasoning is in the protocol rationale; the controller that speaks it lives in origin89.
The specification is a normative draft. Nothing has shipped, so a wire format, a number and a public signature are all free to change until the first paired unit freezes the handshake, protocol versioning and serial numbers.
| Part | What it holds | Where |
|---|---|---|
| Specification | The wire, message by message, and the controller–comms link | docs/PROTOCOL.md, docs/protocol/LINK.md |
| Registry | Every allocated number, in the one file that owns them | crates/km43/protocol.toml, rendered as REGISTRY.md and MAP.md |
| Vectors | Known-good bytes from a generator that never imports the implementation | docs/protocol/vectors/ |
| Implementation | km43, a no_std crate with no allocator, built for the host and for the controller's Cortex-M0+, published to crates.io |
crates/km43/ |
| Bindings | TypeScript types generated from the registry, published as @origin89/km43 |
packages/km43/ |
| Gate | The consistency checks CI runs, and the generators | crates/xtask/ |
just --list shows every recipe. just check runs what CI runs: formatting,
Clippy, the tests, rustdoc under deny-warnings, the TypeScript checks and
cargo xtask check, the specification gate that cross-compiles the crate for
the target and refuses a registry, a vector or a binding that disagrees with
the spec. just registry
and just vectors regenerate the committed artefacts after a change to
protocol.toml or to a generator; the gate refuses a checkout where they are
stale.
See CONTRIBUTING.md for setup and the rules a protocol change has to keep.
The registry's crosswalk ([[dataset_metrics]]) names readings with the words
of the public equipment dataset, offgrid-equipment.
Its vocabulary is pinned beside the registry by hash, and cargo xtask check
refuses a crosswalk row that names a word the pin does not hold. just vocabulary fetches what the dataset publishes now, verifies it against the
dataset's index, and reports which words arrived or left; the pin moves only
with just vocabulary --accept, so a change in the dataset reaches the
registry as a diff somebody reads. The vocabulary workflow runs that check
once a day and, when the vocabulary moved, opens a pull request with the pin
moved, the bindings regenerated and the gate's result; nothing merges on its
own.
A consumer pins a version of the crate or of the bindings, and a change here
reaches it when the consumer moves its pin, not before. A consumer that logs
with defmt turns on the crate's defmt feature to get Format on the
identifier, enum and error types; keys and tags never get it. The controller in
origin89 still builds from its own copy of the crate until it is rewritten
against this one.
Consumer tests can enable vectors to read km43::VECTORS_JSON, the complete
canonical JSON (including BLE traces) shipped with the pinned crate version.
The feature adds no parser or allocator dependency; tests choose how to read it.
The packaged file comes from docs/protocol/vectors/v1.json through a symlink,
so just vectors remains the only writer.
[dev-dependencies]
km43 = { version = "0.6", features = ["vectors"] }Code is licensed under either MIT or
Apache-2.0, at your option. The specification and the other
documents under docs/ are Origin89's original technical documentation; their
public-release terms are still to be confirmed and are not implied by the code
license.
The banner and social preview are Origin89 artwork, covered by the brand-use terms.
