# Canonical Model Backward-Compatibility Playbook This playbook captures the policies and workflow required when evolving the canonical `StellaOps.Feedser.Models` surface. ## Principles - **Additive by default** – breaking field removals/renames are not allowed without a staged migration plan. - **Version-the-writer** – any change to serialization that affects downstream consumers must bump the exporter version string and update `CANONICAL_RECORDS.md`. - **Schema-first** – update documentation (`CANONICAL_RECORDS.md`) and corresponding tests before shipping new fields. - **Dual-read period** – when introducing a new field, keep old readers working by: 1. Making the field optional in the canonical model. 2. Providing default behavior in exporters/mergers when the field is absent. 3. Communicating via release notes and toggles when the field will become required. ## Workflow for Changes 1. **Proposal** – raise an issue describing the motivation, affected records, and compatibility impact. Link to the relevant task in `TASKS.md`. 2. **Docs + Tests first** – update `CANONICAL_RECORDS.md`, add/adjust golden fixtures, and extend regression tests (hash comparisons, snapshot assertions) to capture the new shape. 3. **Implementation** – introduce the model change along with migration logic (e.g., mergers filling defaults, exporters emitting the new payload). 4. **Exporter bump** – update exporter version manifests (`ExporterVersion.GetVersion`) whenever the serialized payload differs. 5. **Announcement** – document the change in release notes, highlighting optional vs. required timelines. 6. **Cleanup** – once consumers have migrated, remove transitional logic and update docs/tests to reflect the permanent shape. ## Testing Checklist - `StellaOps.Feedser.Models.Tests` – update unit tests and golden examples. - `Serialization determinism` – ensure the hash regression tests cover the new fields. - Exporter integration (`Json`, `TrivyDb`) – confirm manifests include provenance + tree metadata for the new shape. Following this playbook keeps canonical payloads stable while allowing incremental evolution.