Mirrors src/printer/bambu_commands/ as language-agnostic schema docs (not used for codegen — the Rust structs stay hand-written). envelope.schema.json is the base; get_version/pushall request+response schemas extend it via allOf + $ref, which is genuinely closer to real inheritance than anything else in this project's schema stack: proto and Rust only ever gave us composition (embed a field holding the base struct), never a mechanism that reuses a *referenced* schema's constraints automatically. Verified with the jsonschema Python library, not just written by hand: all three real examples from the conversation validate correctly, and — importantly — negative tests confirm the base schema's required fields and the command consts are actually enforced through the allOf chain, not just documented. README covers the one real gotcha (additionalProperties: false on a base schema silently breaks allOf composition, since allOf validates each sub-schema against the whole instance independently rather than merging them).
bambulab/v1 JSON Schemas
Documentation/validation schemas mirroring src/printer/bambu_commands/ —
not used for codegen (the Rust structs are hand-written, see that module's
doc comment for why), but useful on their own: as language-agnostic
documentation of the wire format, or for validating a captured MQTT
payload without writing Rust to do it.
The "inheritance" pattern
envelope.schema.json is the base — sequence_id + command, the two
fields every command/response shares. Every other schema here extends
it with allOf + $ref:
{
"allOf": [
{ "$ref": "envelope.schema.json" },
{ "type": "object", "properties": { "command": { "const": "get_version" } } }
]
}
This is genuinely closer to real inheritance than anything else in this
project's schema stack (proto, Rust): the instance must satisfy the base
schema and the extension schema simultaneously, and — verified, not just
asserted — the base's required: ["sequence_id", "command"] is actually
enforced on every schema that extends it, not just copy-pasted as
documentation. Proto and Rust only ever gave us composition (embed a field
holding the base), never something that reuses a named, referenced
schema's constraints automatically like this.
One gotcha if you add a new base-style schema: don't set
"additionalProperties": false on something meant to be allOf-extended.
allOf validates every sub-schema against the whole instance
independently — it doesn't merge object schemas — so a closed base schema
would reject every field the extending schema adds. Leave
additionalProperties unset (defaults to allowed) on anything used as a
base; enforce closedness only on the top-level schemas
(request.schema.json/report.schema.json do this correctly — check
their additionalProperties: false).
Files
envelope.schema.json— the basemodule_info.schema.json— nested object used insideget_version's responseget_version.request.schema.json/get_version.response.schema.jsonpushall.request.schema.json/pushall.response.schema.jsonrequest.schema.json/report.schema.json— the top-level{"info": ...}/{"pushing": ...}dispatch, matchingBambuRequest/BambuReport
Validating something
from referencing import Registry, Resource
from jsonschema import Draft202012Validator
import json, glob, os
resources = []
for path in glob.glob("*.schema.json"):
contents = json.load(open(path))
resources.append((contents["$id"], Resource.from_contents(contents)))
resources.append((os.path.basename(path), Resource.from_contents(contents)))
registry = Registry().with_resources(resources)
schema = json.load(open("request.schema.json"))
Draft202012Validator(schema, registry=registry).validate({"info": {"sequence_id": "0", "command": "get_version"}})