This repository hosts the open specifications for the Labelcopy ecosystem.
It currently contains:
- JSON Schemas for releases, editions, rights, manufacturing, and related entities
- The LCX container format specification
- Supporting documentation for identifiers, hierarchy, repository architecture, and time-travel semantics
- A web-based test app for working with Labelcopy release data during schema development
This is a specs monorepo. It contains multiple specification families, but the repository itself is not the semantic versioning unit.
- Keep Labelcopy schemas, format specifications, and supporting documents in one canonical place
- Version schemas and LCX independently while keeping their relationship explicit
- Model music-industry entities accurately across works, recordings, releases, editions, and rights
- Favor content-addressed, machine-validated, and cryptographically verifiable structures
- Support practical authoring and review with real example data and development tooling
/
├─ schemas/
│ ├─ CHANGELOG.md
│ └─ v0.1-draft/
│ ├─ edition.schema.json
│ ├─ contribution.schema.json
│ ├─ group.schema.json
│ ├─ commit.schema.json
│ ├─ manufacture_manifest.schema.json
│ ├─ medium.schema.json
│ ├─ party.schema.json
│ ├─ recording.schema.json
│ ├─ recording_version.schema.json
│ ├─ release.schema.json
│ ├─ resolver.schema.json
│ ├─ resource.schema.json
│ ├─ rights_profile.schema.json
│ ├─ track.schema.json
│ ├─ tree.schema.json
│ └─ work.schema.json
├─ formats/
│ └─ lcx/
│ ├─ CHANGELOG.md
│ └─ v0.1-draft/
│ └─ specification.md
├─ docs/
│ ├─ REPOSITORY_ARCHITECTURE.md
│ ├─ cd-manufacturing.md
│ ├─ identifier-design.md
│ ├─ labelcopy-release-workspace-architecture.md
│ ├─ labelcopy-schema-hierarchy.md
│ └─ time-travel.md
├─ tools/
│ ├─ conformance/
│ │ ├─ build-examples.mjs
│ │ ├─ fixtures/
│ │ ├─ package.json
│ │ ├─ README.md
│ │ └─ validate.mjs
│ └─ test-app/
│ ├─ app.js
│ ├─ data/
│ ├─ index.html
│ ├─ package.json
│ ├─ server.js
│ └─ style.css
├─ examples/
│ ├─ README.md
│ └─ release-basic/
│ ├─ README.md
│ ├─ commit.json
│ ├─ contribution-1.json
│ ├─ contribution-2.json
│ ├─ edition.json
│ ├─ group.json
│ ├─ medium.json
│ ├─ party.json
│ ├─ recording-1.json
│ ├─ recording-2.json
│ ├─ recording_version-1.json
│ ├─ recording_version-2.json
│ ├─ release.json
│ ├─ resolver.json
│ ├─ track-1.json
│ ├─ track-2.json
│ ├─ tree.json
│ └─ work.json
├─ CHANGELOG.md
├─ CONTRIBUTING.md
├─ GOVERNANCE.md
├─ LICENSE
├─ LICENSE-docs
├─ LICENSE-examples
├─ SECURITY.md
└─ README.md
Open identifier policy:
- JSON Schema
$idvalues usehttps://labelcopy.org/schemas/<version>/<name>.schema.json - LCX format specifications use
https://labelcopy.org/formats/lcx/<version>/
This repository contains more than one versioned spec family.
- Schemas evolve under
schemas/<version>/ - LCX evolves under
formats/lcx/<version>/ - A schema update does not automatically imply an LCX update
- An LCX update does not automatically imply a schema update
Use the specification family as the release unit, not the repository as a whole.
Recommended release naming:
schemas-v0.1.0lcx-v0.1.0
Avoid unqualified repo-level tags such as v0.1.0 when they would imply that all spec families changed together.
Changelog scope follows the same model:
schemas/CHANGELOG.mdtracks the schema family across schema directoriesformats/lcx/CHANGELOG.mdtracks the LCX family across LCX directories- root
CHANGELOG.mdrecords repository-level, date-based changes across the monorepo
- Place files under
schemas/vX.Y(-draft)/ - Each schema should set:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://labelcopy.org/schemas/v0.1-draft/<name>.schema.json",
"title": "<name> (v0.1-draft)"
}- Once a non-draft version is released, do not modify files in place. Publish a new version directory instead.
The LCX specification lives in formats/lcx/v0.1-draft/specification.md.
LCX defines how Labelcopy releases can be packaged, signed, transported, and validated as content-addressed release packages.
Current LCX coverage includes:
- package header structure and package metadata
- commit-rooted release graphs (commits + trees)
- floating (branch) and sealed (tag) workflows
- signatures and integrity validation
- optional encryption and future delta support
For CD manufacturing details, see docs/cd-manufacturing.md.
Labelcopy can use TheNodes as underlying P2P infrastructure, but Labelcopy owns its own network layer, protocols, and realm-level behavior. TheNodes should be understood as infrastructure, not as the place where Labelcopy-specific standards or application code live.
For repository-level architecture and separation of concerns, see docs/REPOSITORY_ARCHITECTURE.md.
Labelcopy is intended to be a verifiable source-of-truth model for releases, assets, editions, and rights.
- DDEX remains relevant where partners require established business-message formats
- LCX addresses package delivery with stronger integrity and provenance guarantees than legacy delivery formats
- DDP remains important for CD-specific manufacturing workflows and can be treated as an interoperability target when needed
In practice:
- Labelcopy is the authoritative internal model
- DDEX is an export or interoperability format where required
- LCX is the native package format for Labelcopy release exchange
- Use
snake_casefor JSON properties and schema fields - Prefer explicit enums where the vocabulary is known
- Reuse shared shapes under
$defs - Set
additionalProperties: falseon top-level schema objects unless there is a deliberate extensibility reason
All cross-entity references should reuse the same structure:
{
"$defs": {
"ref": {
"type": "object",
"properties": {
"id": { "type": "string", "pattern": "^lcid:[a-z_]+:[0-9A-HJKMNP-TV-Z]{26}$" }
},
"required": ["id"],
"additionalProperties": false
}
}
}A ref is a logical reference: it names another entity by its stable id and nothing more. Which version that entity resolves to is read from the active commit's tree, never pinned inside the reference — so an entity's CID depends only on its own content and editing a child never re-hashes its parents.
Content references are a separate, deliberate set and carry a bare CID instead of a ref: a tree's entries (lcid → cid), a commit's tree and parents, a resolver's branch/tag pointers, resource.cid_ref (an external blob), and manufacture_manifest.edition_cid (a manufacturing seal). Pin content only where the referent is immutable by nature.
- Logical IDs use
lcid:<type>:<ulid> - CIDs are immutable content-addressed identifiers
- History is a content-addressed commit DAG: a commit pins a tree (a snapshot mapping each logical ID to its current CID) and links to its parent commit(s), making the timeline tamper-evident
- A resolver is a thin, mutable set of branches and tags (named revision pointers to commit CIDs); nothing in the content-addressed graph references it, so the graph stays acyclic
- Sealing is an immutable tag on a commit, not a field stored on the edition
- Tree entries can represent redirects and tombstones for identity lifecycle
Schemas should reference related objects by logical ID rather than embedding full objects inline.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://labelcopy.org/schemas/v0.1-draft/<schema-name>.schema.json",
"$comment": "SPDX-License-Identifier: Apache-2.0",
"title": "<schema-name> (v0.1-draft)",
"type": "object",
"additionalProperties": false,
"$defs": {
"ref": { /* import or inline the shared ref shape */ }
},
"properties": {
"type": { "const": "<schema-name>" },
"id": {
"type": "string",
"pattern": "^lcid:<schema-name>:[0-9A-HJKMNP-TV-Z]{26}$"
},
"spec_version": { "const": "0.1-draft" }
},
"required": ["type", "id", "spec_version"]
}The authoritative validation surface in this repository is the conformance tool under tools/conformance. The web test app remains useful for interactive authoring, but schema/example integrity should be judged by the conformance gate.
Run it with:
cd tools/conformance
npm ci
npm run build-examples
npm run validateThe conformance tool currently checks:
- all typed example files validate against their target schemas
- controller threshold policies (
m-of-n) are internally consistent - every entity CID in the tree recomputes from canonical content
- logical refs are
{ id }only and resolve in the tree - resolver -> commit -> tree linkage is internally consistent
- intentionally invalid fixtures are rejected
Run it with:
cd tools/test-app
npm install
npm startThen open http://localhost:3001 in your browser.
The test app provides:
- schema-aware editing workflows for release data
- local file-based storage under
tools/test-app/data/ - rapid iteration while adjusting schema structures
- a practical emitter for the current release graph model
Current sample release data for the test app lives under tools/test-app/data/releases.
These have different purposes:
- examples is for curated, portable Labelcopy examples intended for documentation, interoperability, and validation
tools/test-app/data/is for application-oriented working data used by the development test app
They should not be treated as the same thing.
When a schema or shared shape changes, update schemas, examples, conformance tooling, and the test-app emitter together.
The examples directory is reserved for curated Labelcopy examples such as release data, entity graphs, and future reference packages.
When examples are added, they should:
- include
type,id, andspec_versionwhere relevant - use Labelcopy logical IDs consistently
- validate against the target schema family and version
- be stable enough to serve as documentation and interoperability references
The current canonical example graph is examples/release-basic.
- Open an issue describing the schema, format, documentation, or architecture change.
- Prepare changes in the appropriate draft version directory.
- Update examples when the change affects expected data shapes.
- Update CHANGELOG.md when the change should be visible to maintainers and consumers.
- Ensure any test-app workflows or example data still make sense after the change.
- Promote a draft to a stabilized version by publishing a new version directory rather than mutating released files.
- Draft versions may temporarily accept aliases during migration, but deprecated names should be removed before stabilization
- When renaming or moving fields, document the migration in
docs/ - When removing a field, leave a clear deprecation trail and make the next version fail clearly rather than ambiguously
- Fields carrying keys, signatures, hashes, or CIDs should declare explicit format and length constraints
- Public metadata and encrypted payload references should be clearly separated
- Cryptographic ownership and provenance should remain explicit in both schemas and LCX packaging
- Governance documents live at repo root, including GOVERNANCE.md and SECURITY.md
- Major changes should include a short impact analysis and explicit review of compatibility consequences
This repository uses a split license model:
- Code and JSON Schemas: Apache-2.0
- Specifications and Markdown documentation: CC BY 4.0
- Examples and sample data: CC0 1.0
Folder mapping:
schemas/→ Apache-2.0formats/anddocs/→ CC BY 4.0tools/→ Apache-2.0examples/→ CC0 1.0
If a file contains a different SPDX header, the file header takes precedence.
Questions or proposals can be opened as issues for schema, format, architecture, or documentation changes.