Files
continuum-proxy/schemas/bambulab/v1/README.md
T
octoturge 42eb0b62d5 Add JSON Schema documentation for bambulab/v1, with real inheritance
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).
2026-08-28 22:53:59 +00:00

2.8 KiB

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 base
  • module_info.schema.json — nested object used inside get_version's response
  • get_version.request.schema.json / get_version.response.schema.json
  • pushall.request.schema.json / pushall.response.schema.json
  • request.schema.json / report.schema.json — the top-level {"info": ...} / {"pushing": ...} dispatch, matching BambuRequest/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"}})