opentide

Schema revision

Why every object has two version fields, what each one controls, and how schema revisions coexist.

Every opentide object carries two version-like fields, and mixing them up is the single most common authoring mistake. This page explains what each controls and why they are separate.

Two fields, two jobs

FieldExampleAnswersAuthoritative history
metadata.schemarule::1.0Which structure does this object follow?The specification
metadata.version1.2.0Which revision of this object's content?Git
  • metadata.schema — the structural schema revision. It selects the validation model and the generated rule.1.0.schema.json your editor and CLI check against. It changes only when the shape of the object changes (new required fields, renamed structures), which is rare and governed by the specifications.
  • metadata.version — the instance content version. It is your semver-style marker for how a specific detection has evolved. Bump it when you meaningfully change the rule's logic. The real, line-by-line history lives in git.

Never use metadata.version to select a schema file. Content revisions and structural revisions are independent — a rule at content version: 4 can still be schema: rule::1.0.

Naming conventions

The schema identifier maps predictably to files and specs:

LayerFormatExample
Schema identifier{family}::{major}.{minor}rule::1.0
Specification filespecs/objects/{family}-{major}.{minor}.mdrule-1.0.md
JSON Schema artifact.opentide/schemas/{family}.{major}.{minor}.schema.jsonrule.1.0.schema.json
Template artifact.opentide/templates/{family}.{major}.{minor}.template.yamlrule.1.0.template.yaml
IDE router.opentide/schemas/opentide.schema.jsonobjects/**/*.yaml, routed by metadata.schema

The router opentide.schema.json is the editor entry point. opentide setup vscode maps objects/**/*.yaml to it, and the router applies the revision schema named in each object's metadata.schema:

  • metadata.schema completes to the registered object identifiers (objective::1.0, rule::1.0, rule::1.1, threat::1.0). An unknown identifier is reported on that field with the valid values.
  • Each identifier has one if/then branch, combined with allOf. Only the branch whose identifier matches applies, so a rule::1.1 object is checked against rule.1.1.schema.json and nothing else.
  • Branches reference the revision schemas by relative file name, so they resolve to the files next to the router in .opentide/schemas/.

Map the router, not a revision schema. A folder mapping such as objects/rules/**/*.yaml → rule.1.0.schema.json checks every rule against rule::1.0 and flags valid rule::1.1 objects.

How revisions coexist

Schema revisions are additive. When a new revision such as rule::1.1 ships, both revisions can exist in the same repo at once:

  1. opentide generate schemas emits both rule.1.0.schema.json and rule.1.1.schema.json.
  2. The IDE router adds a branch and a metadata.schema value for each identifier, and routes objects by their declared metadata.schema.
  3. Objects opt in individually by setting metadata.schema: rule::1.1. Objects that still declare rule::1.0 keep validating against 1.0 until you migrate them.

This means a schema upgrade never forces a big-bang migration — you move objects over at your own pace. For CoreTide-era repos, see the migration guide.

rule::1.1 is that kind of revision. It adds optional metadata.reviewed and changes nothing else. rule::1.0 stays valid and rejects the field. opentide generate schemas writes both rule.1.0.schema.json and rule.1.1.schema.json. opentide generate templates writes both templates and leaves reviewed commented out, so a new file does not invent a review date. List stale rules with opentide rules unreviewed.

What to do when

SituationAction
You changed a rule's detection logicBump metadata.version
You upgraded the opentide packageRun opentide generate to refresh schema artifacts
A new schema revision is availableMigrate objects to the new metadata.schema when ready
Your editor stopped validating YAMLRegenerate: opentide generate schemas

Implementation detail: how the registry resolves identifiers to models and runs migrations is an internal concern documented in the SDK registry and the opentide source. Authors only need the metadata.schema value.

Normative reference

On this page