JSON Schemas

The JSON Schemas Maru publishes at maru.audio/schema, the alpha rule they follow, how to point maru.config.json at one with $schema, and what a schema does not check.

Maru publishes a JSON Schema for each file and message format whose shape is defined in its contracts. Point a file at one with $schema and your editor or coding agent completes keys and flags shape errors while you type. The schemas are generated from the same definitions maru module check uses, so the editor and the check report the same shape errors.

What is published

The index at https://maru.audio/schema lists every schema as JSON, grouped by noun, with its URL, stability and the page that explains it. Each schema lives at https://maru.audio/schema/<noun>/<document>/alpha.json. The noun says what the document belongs to:

  • project: authored source, the files you write in a Project.
  • release: the published bundle a Project builds into.
  • face: the protocol between a module's interface (its face) and its host.
  • preview: the protocol between an embedded preview frame and its page.
NounNameURLDescribesWritten by
projectproject/config/schema/project/config/alpha.jsonmaru.config.json, the Project configYou
releaserelease/web-package/schema/release/web-package/alpha.jsonweb-package.json, the web package manifest inside a ReleaseThe toolchain
faceface/message/schema/face/message/alpha.jsonA message from a face to its hostThe runtime
faceface/host-message/schema/face/host-message/alpha.jsonA message from the host to a faceThe runtime
faceface/host-diagnostic/schema/face/host-diagnostic/alpha.jsonA diagnostic message from the host to a faceThe runtime
previewpreview/frame-message/schema/preview/frame-message/alpha.jsonA message from a preview frame to its hostThe runtime
previewpreview/host-message/schema/preview/host-message/alpha.jsonA transport or parameter message from the host to a preview frameThe runtime
previewpreview/parent-message/schema/preview/parent-message/alpha.jsonA message from the parent page to an embedded preview (?host=parent)The runtime
previewpreview/param/schema/preview/param/alpha.jsonThe parameter list a preview frame reportsThe runtime

Only project/config is for a file you write. The others are published so other implementations and tools can check what Maru produces.

release.json, the manifest of a Release, has no published schema yet. The toolchain writes it and validates it when it reads it; you never edit it.

The alpha rule

Every URL is alpha. The contracts are still changing and have not been confirmed, so nothing is frozen yet:

  • An alpha URL always serves the schema the current Maru contracts generate. It can change with any website release: a key can be added, and a value that used to pass can be refused.
  • A frozen version (for example v1.json) will never change once published. None exists today. When one is published, the index lists it and alpha keeps tracking the newest shape.

Responses are cached for five minutes and may be fetched from any origin.

A removed published property or schema URL is a breaking contract change, including during alpha. Narrowing a type or allowed value is also breaking. Repository maintainers can compare the registered schema shapes against an earlier commit with:

sh
node packages/audio-contracts/bin/diff-schemas.mjs <git-ref> --json

The comparison reads historical and current source, reports publication names and changed paths, and refuses breaking or uncertain changes. It also refuses any changed or deleted frozen vN.json snapshot. There is no breaking-change override yet, and this comparison is not wired into the automatic schema freshness check. It does not test handwritten validation rules or prove that an existing Release still runs; those need their owning tests and runtime qualification.

The Project config

A Project is configured by maru.config.json at its root. maru init writes one for new Projects:

json
{
  "$schema": "https://maru.audio/schema/project/config/alpha.json",
  "type": "audio-module",
  "entry": "./src/index.ts",
  "development": {
    "sources": {
      "module": "src/index.ts",
      "dsp": "src/dsp/processor.ts",
      "react": "src/ui/index.tsx"
    }
  },
  "listing": { "license": "maru-remix-1.0" }
}

The $schema line is the only thing an editor needs. VS Code and other editors with JSON Schema support read it with no extension or setting. maru module check refuses a $schema that names any other maru.audio/schema URL, so a Project never points at the wrong document.

The same object can live under the maru key of package.json, which is where older Projects keep it. Editors check package.json against the npm schema, which ignores that key, so you get no completion there. For now a new Project keeps the object in both places, because some Maru tools still read package.json. The two must stay equal: when both are present and differ, maru.config.json wins and maru module check reports the difference. maru module license on|off updates both.

Keys this version of the schema does not name are accepted, so a Project written for a newer Maru still opens with an older one. Named keys are checked strictly. For example, share.dsp must be source, program or product, and share accepts only dsp and face.

Generated documents and messages

The other schemas describe documents and messages Maru tools produce. They carry x-maru-contract, the internal contract they come from, and x-maru-stability: "alpha". Nested values whose rules belong to another part of Maru are marked x-maru-delegate or x-maru-opaque and are only loosely described. Binary fields are marked x-maru-binary; they travel between windows and workers and never appear in JSON.

What a schema does not check

A schema checks shape: which keys exist, their types and their allowed values. Some rules cannot be stated that way, and Maru checks them in code:

  • Refinements. Rules across fields, such as "not both workInProgress and localOnly" or "exactly one of sku and projectId", are listed by name under x-maru-refinements but are not enforced by the schema.
  • Files on disk. Whether the entry, the DSP source or a bank manifest a path names exists, and whether a source DSP share has the matching exports entry in package.json.
  • Release identity. Bundle digests, per-file digests and releaseSha256: a .maru bundle is checked when it is opened, not by a schema.
  • What a Release requires. Whether a host meets a Release's requires (engine, runtime line, interface and capabilities).
  • Your module itself. Parameters, ports, presets and the face contract are checked by the declaration and face gates.

maru module check runs all of these. When it and an editor disagree, the check is right.