ADR-002: Schema Governance & Compatibility Policy
Decision record for payload schema versioning, compatibility, and registry policy for mission payloads.
Metadata
- ADR ID: ADR-002
- Title: Payload Schema Versioning & Backward Compatibility Policy
- Status: Proposed
- Date: 2026-03-15 (proposed)
- Owner: Backend/Integration lead
- Target Decision Date: 2026-04-08
- Relates to: System-Gaps-Deferred#schema-governance-and-compatibility-policy
Problem / Context
Payload schemas are defined by the mission pre-launch (e.g., "target 1 transmits CCSDS frames with telemetry struct A; target 2 transmits raw quantized I/Q"). The architecture (System-APIs-Contracts) defines several frame types and payload structures, but leaves open:
- Schema evolution: If a payload struct changes mid-mission (e.g., new field added), how do we handle mixed frame versions?
- Backward compatibility: Can central decode frames from nodes running older firmware?
- Forward compatibility: Can nodes running old firmware decode new schema definitions sent from central?
- Versioning scheme: How do we tag schema versions (semantic, git SHA, timestamp)?
- Migration windows: Do we require synchronized schema updates, or allow rolling updates?
- Fallback behavior: If central receives a frame with unknown schema version, drop it or fall back to raw?
Current State
- Schemas are inline JSON in mission config (System-OperationalFlow)
- No versioning mechanism defined
- No migration strategy for mid-flight schema changes
- Prototypes assume static schema for entire mission
Why This Matters
- Robustness: Firmware updates should not break decoding if schemas change
- Agility: Teams should be able to refine payload definitions without synchronizing across all nodes
- Auditability: Schema history for post-mission analysis (did we decode correctly?)
- Interoperability: If we add new targets mid-mission, how do they integrate without restart?
Deferred Decision Options
Option A: Semantic Versioning + Strict Compatibility
Approach: Use SemVer (major.minor.patch) for schemas. Major version bumps require schema migration plan; minor/patch are backward-compatible.
Pros:
- Clear versioning semantics (everyone understands "major vs. minor")
- Strict rules prevent hidden incompatibilities
- Standard practice (HTTP APIs, gRPC, Protobuf all use versioning)
- Schema registry tools exist (Confluent Schema Registry, etc.)
Cons:
- Requires discipline: developers must commit to backward compatibility
- Migration windows can be lengthy
- For multi-target missions, different targets may use different schema versions simultaneously
Implementation:
- Store schema in centralized registry:
/opt/schemas/target-1-telemetry-v2.1.0.json - Mission config references schema by full version:
"schema_id": "target-1-telemetry-v2.1.0" - Central decoder stores multiple schema versions (last 5 major versions)
- Node accepts schema from central; validates against local schema version
- If incompatible, node logs warning and attempts raw fallback
Option B: Git Commit SHA + Lenient Decoding
Approach: Tag each schema with the git commit SHA where it was defined. Accept any schema version; decode what you can, ignore unknown fields.
Pros:
- Zero ceremony: schemas update whenever code changes
- Lenient parsing: unknown fields don't break decoding (just ignored)
- Auditable: git history is the versioning source of truth
- Supports rolling updates: old nodes can decode new schemas partially
Cons:
- No "compatibility guarantee" , you have to test it
- Hard to understand versioning from user perspective (SHA is not human-readable)
- Silent data loss if unknown field is critical (e.g., checksum field added but old decoders ignore it)
- No way to prevent breaking changes
Implementation:
- Schema file includes git SHA as metadata:
"_schema_commit": "a3f4b5c0"
ADR-001: TLS Mutual Authentication
Decision record for TLS mutual authentication between node and central, covering bootstrap, rotation, and fallback.
ADR-003: Clock Authority & Time Synchronization
Decision record for clock authority, time synchronization, and fallback policies across nodes and central.