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.
| Noun | Name | URL | Describes | Written by |
|---|---|---|---|---|
| project | project/config | /schema/project/config/alpha.json | maru.config.json, the Project config | You |
| release | release/web-package | /schema/release/web-package/alpha.json | web-package.json, the web package manifest inside a Release | The toolchain |
| face | face/message | /schema/face/message/alpha.json | A message from a face to its host | The runtime |
| face | face/host-message | /schema/face/host-message/alpha.json | A message from the host to a face | The runtime |
| face | face/host-diagnostic | /schema/face/host-diagnostic/alpha.json | A diagnostic message from the host to a face | The runtime |
| preview | preview/frame-message | /schema/preview/frame-message/alpha.json | A message from a preview frame to its host | The runtime |
| preview | preview/host-message | /schema/preview/host-message/alpha.json | A transport or parameter message from the host to a preview frame | The runtime |
| preview | preview/parent-message | /schema/preview/parent-message/alpha.json | A message from the parent page to an embedded preview (?host=parent) | The runtime |
| preview | preview/param | /schema/preview/param/alpha.json | The parameter list a preview frame reports | The 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
alphaURL 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 andalphakeeps 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:
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:
{
"$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
workInProgressandlocalOnly" or "exactly one ofskuandprojectId", are listed by name underx-maru-refinementsbut 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
sourceDSP share has the matchingexportsentry inpackage.json. - Release identity. Bundle digests, per-file digests and
releaseSha256: a.marubundle 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.