Conformance — DSDS 0.21.2
What it means for a document to follow the DSDS spec: the four conformance classes, the three enforcement tiers, and every rule the validator enforces.
What it means for a document to follow the DSDS spec: every rule it enforces, and how each one is checked. For what might still change before 1.0, see Stability. For how the schema itself is organized — the building blocks every entry, section, and reference is built from — see How the schema is organized.
The words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY have a specific meaning on this page and inside the DSDS schema files, as defined by RFC 2119 (updated by RFC 8174). They only carry that meaning when written in capital letters.
#
Where the rules liveDSDS keeps its rules inside the schema's own
#
Conformance classesDSDS defines four ways something can "follow the spec" — a document, and the tools that create, read, and check it. State which one you mean.
#
Conforming documentA document that passes schema validation for the version named in its
#
Conforming producerA tool or person that creates DSDS documents. A conforming producer:
- MUST only create documents that follow the spec
- MUST NOT use an outdated field or structure in new documents (old ones are kept around only so existing documents keep working)
- SHOULD record how a document was created, using
metadata.origin
#
Conforming consumerA tool, renderer, or AI agent that reads DSDS documents. A conforming consumer:
- MUST NOT fail just because it sees an optional field it doesn't recognize
- MUST keep
$extensions data intact even if it doesn't understand it - MUST treat an unresolvable reference (an
entryId#itemId pointing nowhere) as an error, not silently ignore it - MUST take MUST/SHOULD-style guidance as seriously as the spec says to, for a document it has already decided to trust — a
must-not guideline is a hard stop for an agent writing code, not a suggestion. This does not extend that same standing to an unvetted or third-party document; see Security considerations for what that trust decision covers and doesn't - SHOULD build its own "what points to what" index when it loads a document, rather than expect the document to store that answer directly
- MUST be able to address every section item, whether or not it was written with an
id — when one is missing, derive it from the item's own text (lowercase, non-alphanumeric runs collapsed to a dash), the same way every other conforming tool does. See common/id.
#
Conforming validatorA tool that checks documents. A conforming validator MUST enforce both the schema itself (with format checks on) and the extra rules below (
#
The words this spec usesOne term per concept, so a reader and a generator mean the same thing by it. The right-hand column is what a reviewer should flag — each of those synonyms was in use somewhere before this table existed.
| Use | For | Not | Defined in |
|---|---|---|---|
| entry | One documented thing in the design system graph - a component, token, theme, or anything else. | entity, record, item, node | |
| document | One | spec, spec file, doc | |
| spec | The DSDS specification itself - this repo, the schema files, and the site that publishes them. | (never a document) | |
| section | One member of an entry's | block, documentBlock, chunk | |
| field | A named slot on an object. | property, key, attribute | (property table is the one allowed exception - it names the generated tables) |
| kind | The discriminator value that says which shape an entry or section is. | type, variant | |
| item | One member of a section's | entry, rule, criterion | |
| conforming consumer | Anything that reads a document - a renderer, an agent, a site generator. | tool, reader, client, parser, renderer | Conformance |
| conforming producer | Anything that writes a document. | generator, author tool, writer | Conformance |
| conforming validator | Anything that checks a document against the schema and the rule catalog. | linter, checker | Conformance |
#
Enforcement tiersEvery rule is enforced one of three ways:
| Tier | How it's checked | What happens if it fails |
|---|---|---|
| Structural | Directly by the schema file (required fields, patterns, and similar built-in checks) | Blocks — validation fails |
| Semantic | By | Blocks — validation fails |
| Advisory | By | Never blocks — always exits 0, warnings only |
Advisory is the newest tier and doesn't cover every SHOULD/MAY in this spec yet — it's additive, so a gap here is a missing check, not a passing one.
Every catalog entry declares its own tier explicitly, as
#
Rule catalogThe table below is generated directly from
Versions through 0.15.2 used a three-digit catalog (
| ID | Rule |
|---|---|
| At most one | |
| A system entry's | |
| A | |
| Entry and shared ids are unique within a document. | |
| An | |
| A | |
| A | |
| A bare | |
| A | |
| A | |
| A relative | |
| Capitalize RFC 2119 keywords (MUST/SHOULD) in a guideline's own statement. | |
| A token | |
| A hard-requirement guideline (must/must-not) with no | |
| A component entry with no | |
| A token | |
| An entry's own top-level fields don't follow STYLE_GUIDE.md's field order. | |
| An entry's | |
| A | |
| A base document's own top-level fields don't follow STYLE_GUIDE.md's field order. | |
| A base document's | |
| A nested object's fields don't follow the order its own schema file declares. | |
| An entry's |
#
Project-scope resolutionThe search is bounded to the folder holding the file being validated, and its subfolders — never a parent folder, a sibling folder, or the wider repo. Deliberately narrow: widening it to the nearest
An unresolved reference is a warning, not a failure, only in this cross-file case — a self-contained document's unresolved
Whether a
#
Conformance suitePublished as one versioned artifact per release, at
The runner contract — what implementing conformance against this artifact means, for a validator in any language:
- Fetch the manifest. For each entry in
fixtures , fetch the file it names (relative to the manifest itself). - Validate that file against the schema bundle for the manifest's own
schemaVersion . - Confirm the document is rejected — and rejected for the declared reason, not just rejected somehow:
rejectedBy: "schema" — at least one resulting error must be a pure JSON Schema violation (noDSDS-XX rule id attached). IferrorAt is set, one such error's instance path must equal it ("/" for the document root).rejectedBy: "semantic" — every id listed inexpect must appear among the resulting errors or warnings tagged with that id (a semantic rule may report as either, depending on whether the validator runs in a--strict -equivalent mode).
- A fixture that validates cleanly, or fails for a different reason than it declares, is a conformance failure for the validator under test — passing "some validators reject it" isn't the bar; rejecting it for the right, stated reason is.
This is exactly what
#
Open conventionsThe schema deliberately leaves some questions unanswered — not oversights, but places where a fixed rule would fit some teams and not others.
- Where does a guideline item's pointer go —
refs , or a named field?alternatives ,evidence ,related , andchecks each exist for one specificrel :alternative-to , an external standard,refines , andtest /lint-rule . Any otherrel —extends ,depends-on ,composes ,part-of ,replaces ,implements ,relates-to ,pairs-with ,excludes ,see-also — goes in the general-purposerefs field instead, alongsidesame-as andexternal-link . See sections/guidelines. - Where does an entry's primary source file go?
refs withrel: source — see common/ref. - What does
tags[0] mean? The first tag, by convention, is the entry's main category — see metadata. - How does a token's
source point at one key inside a shared DTCG file, not just the whole file? By convention, a token's ownid doubles as its path in the DTCG token tree —color.action.primary names the same token in both places, which is whyentries/token.id allows slash separators DSDS ids otherwise don't. When a project's DTCG paths don't line up with its DSDS ids, pointsource 'shref at the file plus a JSON Pointer fragment instead (./tokens.dtcg.json#/color/action/primary ) — ordinary URI syntax, no schema change. - What is a component's status when it ships on more than one platform? Author one
metadata.status entry per platform and let the overall status be inferred from them, rather than stating a separate overall value that can silently disagree. See Status across platforms below.
#
Status across platformsA component rarely reaches the same maturity everywhere at once: stable on web, beta on iOS, not started on Android.
A consumer SHOULD derive a component's overall status from the aggregate of its per-platform entries, rather than expect a separately authored overall value. There is no
How to aggregate is the consumer's decision, because it depends on the question being asked. Two conventions cover most cases:
- Least-mature wins — the honest answer to "can I depend on this everywhere?" A component that is
stable on web andbeta on iOS isbeta overall. - Per-platform, unaggregated — the honest answer to "can I depend on this here?" A renderer showing a React developer the React status shouldn't dim it because iOS lags.
A producer SHOULD declare
#
Passing isn't the same as goodA document with zero errors and zero warnings can still be bad documentation — the schema checks structure, not judgment.
#
Index of every normative statementEvery RFC 2119 sentence (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY) in the schema's own text — both
Generated from the v0.21.2 schemas by
#
common #
common/extensions- MUST — Each top-level key MUST be a dotted namespace, like
com.acme , matching the Design Tokens Community Group's own$extensions convention.common/extensions§(root).1
#
common/id- MUST — A section item's own
id is optional, but a conforming consumer MUST be able to address every item.common/id§(root).1 - MUST — When an item has no
id , consumers MUST derive one from the item's own text so content has a consistent id.common/id§(root).2
#
entries #
entries/component- MUST — When the document declares a
metadata.platforms list, this MUST be one of its entries.entries/component§[allOf][1].sourceFiles.items.platform.1 - MUST — When the document declares a
metadata.platforms list, this MUST be one of its entries.entries/component§[allOf][1].imports.items.platform.1
#
metadata #
metadata/metadata- MUST NOT — MUST NOT contain markup.
metadata/metadata§note.1 - SHOULD — A conforming consumer SHOULD treat
updated.date as the cache key for this item's documentation specifically.metadata/metadata§.updated.1
#
metadata/system-metadata- MUST — When this list is present, every other
platform value used anywhere in the document MUST match one of these.metadata/system-metadata§[allOf][1].platforms.1
#
sections #
sections/definitions- MUST —
id is optional, but a conforming consumer MUST derive one from this item's own text.sections/definitions§[allOf][1].items.items.id.1
#
sections/guidelines- SHOULD — When an item carries a
level and a ref but nostatement , a conforming consumer SHOULD show the level and the link rather than rendering it as empty content.sections/guidelines§(root).1 - SHOULD — An author who expects a person to read the guideline without following the link SHOULD add a
statement instead.sections/guidelines§(root).2 - MUST —
id is optional, but a conforming consumer MUST derive one from this item's own text.sections/guidelines§[allOf][1].items.items.id.1 - MUST — It MUST reflect
level .sections/guidelines§[allOf][1].items.items.example.1 - MUST — A
must-not item's example MUST show what not to do.sections/guidelines§[allOf][1].items.items.example.2
#
sections/section- MUST —
id is optional, but conforming consumer MUST derive one from this item's own text.sections/section§freeformEntry.id.1
#
sections/steps- MUST —
id is optional, but a conforming consumer MUST derive one from this item's own text.sections/steps§[allOf][1].items.items.id.1