Skip to Content

Schema

A LODE schema is a JSON document that defines the structure of an encodable object. Every schema must have "schema": "lode" as its discriminator.

Structure

{ "schema": "lode", "version": <number>, "name": "<string>", "fields": [ { "id": <1-255>, "name": "<string>", "type": "<type>", "required": <boolean> } ] }

Top-level Properties

PropertyTypeDescription
schema"lode"Must be the literal string "lode"
versionnumberSchema major version (≥ 1)
namestringHuman-readable name for the structure
fieldsLodeField[]Ordered list of field definitions

Field Properties

PropertyTypeDescription
idnumberBinary field key (1–255). Must be unique within the schema.
namestringField name in the source object. Must be unique.
typestringWire type. One of: string, bool, string[], map<string,string>
requiredbooleanWhether the field must be present. Defaults to true if omitted.

Field IDs

Field IDs are the stable binary identifiers for each field. They are written as a single byte in the Vein format. This means:

  • IDs range from 1 to 255 (0 is reserved)
  • Renaming a field’s name property does not break binary compatibility
  • Changing a field’s id does break binary compatibility
  • Once assigned, an ID should never be reused for a different field

Validation

The loadLode() function validates a schema at load time and throws on:

  • Missing or incorrect schema marker
  • Invalid version (must be ≥ 1)
  • Empty name
  • Empty fields array
  • Field ID out of range (< 1 or > 255)
  • Duplicate field IDs
  • Duplicate field names
  • Unknown type strings
import { loadLode } from "@stacknet/lode"; // From file const schema = loadLode("./my-schema.lode"); // From object const schema = loadLode({ schema: "lode", version: 1, name: "Example", fields: [ { id: 1, name: "title", type: "string", required: true }, ], });

Example: Model Layer Schema

model-layer-v1.lode
{ "schema": "lode", "version": 1, "name": "ModelLayer", "fields": [ { "id": 1, "name": "name", "type": "string", "required": true }, { "id": 2, "name": "isDefault", "type": "bool", "required": true }, { "id": 3, "name": "models", "type": "string[]", "required": true }, { "id": 4, "name": "defaultModel", "type": "string", "required": true }, { "id": 5, "name": "defaults", "type": "map<string,string>", "required": false } ] }

Schema Evolution

To evolve a schema without breaking existing consumers:

  1. Add new fields with new IDs and required: false
  2. Never reuse a retired field ID
  3. Bump the version for breaking changes (type changes, new required fields)

The decoder skips unknown field IDs, so a v1 consumer can safely read a v2 payload — it simply ignores the new fields.

Last updated on