Skip to content

ADR-020 — Canonical mission JSON schema

Status · Accepted Date · 2026-04-28 Closes · RFC-002 (mission JSON schema) TA anchor · §contracts/mission-record · §contracts/mission-index-entry

Context

RFC-002 raised three open questions about the mission JSON schema:

  1. Should the events array be optional or required-but-empty for missions without CAPCOM data?
  2. Should warning events carry a threshold field, or is anomaly detection purely in code?
  3. Is data_quality an enum (good, partial, reconstructed) or free text?

Plus the canonical field names (renaming prototype-era dep, arr, tof, dv, j2000 to readable form). Original closure was scheduled for the Slice 4 gate when the schema would be exercised by three mission types in the fly screen. We are closing it at Slice 2 entry instead — before any mission JSON is written — to avoid churning 28 files if the schema changes downstream.

Decision

File layout (three records per mission)

  • data/missions/index.json — single file, array of lightweight manifest entries
  • data/missions/[dest]/[id].json — full base record per mission, language-neutral
  • data/i18n/[locale]/missions/[dest]/[id].json — editorial overlay per mission per locale

Locked field names (renames from prototype)

PrototypeCanonicalReason
depdeparture_dateUnambiguous
arrarrival_dateUnambiguous
toftransit_daysSelf-documenting unit
dvdelta_vConsistent with physics notation
j2000(removed)Computable from dates

All other prototype field names retained: id, agency, agency_full, dest, status, year, sector, color, first, description, data_quality, credit, links, name, type, vehicle, payload.

Strictness: additionalProperties: false everywhere

Unknown fields fail validation. Catches typos and stale fields at PR time. Adding a new field is intentional, not accidental.

Answers to RFC-002 open questions

  1. events is required in mission overlays. Every Slice 4 mission has at least LAUNCH and arrival/landing events. Earth-orbit objects and Moon sites have separate overlay schemas where events does not apply.
  2. No threshold field on warning events in v1. Anomaly thresholds live in code. Adding threshold is a v2 candidate when CAPCOM gains user-configurable alerts.
  3. data_quality is an enum: good | partial | reconstructed. Free text rejected because it makes UI badging ambiguous; the enum drives a small visual contract (no badge for good, amber badge for the other two).

Events shape (in mission overlays)

json
{ "met": <number>, "label": "STRING", "note": "STRING", "type": "nominal" | "info" | "warning" }

met is days from departure (not seconds — "T+22377600s" is unreadable, "T+259d" is human).

Rationale

Closing now instead of at Slice 4 gate avoids rewriting 28 mission files if the schema needs to change after the fly screen exercises it. The risk that Slice 4 surfaces new requirements is low — RFC-002's proposed approach was already validated against the prototype's embedded data shape, and Issue #2's spec enumerates the field set exhaustively.

Strict schema (additionalProperties: false) is locked because the cost is one line per schema and the win is catching typos like agency_fl instead of agency_full at PR time.

Alternatives considered

  • Defer to Slice 4 gate — original RFC-002 plan. Rejected: real risk of churning 28 mission files if any field changes; schema design is mature enough to lock now.
  • Open schema (additionalProperties: true) — allows experimentation. Rejected per ADR-019 spirit (validation should fail loudly at PR time).
  • events optional — simpler for mission types without timeline. Rejected: every Slice 4 mission has launch/arrival events; missions without them shouldn't appear in the mission library at all.

Consequences

Positive: schema locked before any mission JSON is written → zero rework risk; strict validation catches typos; events shape unambiguous for CAPCOM mode. Negative: Slice 4 may surface a need for an additional field; adding requires updating the schema + 28 files. Mitigation: schema is informed by both the prototype (complete) and Issue #2's exhaustive field list.

Implementation notes

Schema files live in data/schemas/:

  • mission.schema.json — base mission record
  • mission-index.schema.jsonindex.json entry
  • mission-overlay.schema.json — locale overlay

Validator: scripts/validate-data.ts runs ajv against all base + overlay files. CI step blocks PR on schema failure (per ADR-019).

Orrery — architecture documentation · MIT · No tracking