diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 699f874e..9d18d200 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1523,3 +1523,27 @@ other world honest against it: `enforcedBy`. The lifecycle fixtures in `test/fixtures/config-lifecycle/` pin the load contract: oldest-supported and future-field configs pass the schema losslessly. + +## Schema as the source of truth (#33, 2026-08-30) + +The Voluptuous schema in `custom_components/houseplan/validation.py` is the +single owner of the persisted config/layout shape. Three artefacts keep every +other world honest against it: + +- `scripts/dump-config-schema.py` walks the schema into the deterministic + `scripts/config-schema-manifest.json` (265 leaf paths at introduction); + a pytest regenerates it and fails on any uncommitted drift. +- `test/config-schema-parity.test.mjs` compares manifest enums with the + exported frontend const lists (`DISPLAY_MODES`, `TAP_ACTIONS`, + `SPACE_FILL_MODES`/`ROOM_FILL_MODES`, `OPENING_TYPES`, + `VACUUM_TRAIL_MODES`, `ZERO_WALL_STYLES`, `BG_MODES`). Every divergence + must be blessed in `scripts/schema-compat-allowlist.mjs` with a reason and + an owning issue — and an allow-list entry that stops matching a real + divergence fails the test too, so the list cannot rot. +- `scripts/config-field-registry.mjs` stays the DECISION layer on top of the + manifest: only fields with a non-trivial fate live there, each resolving to + a manifest path or carrying an explicit `schema: 'allow-extra'` / + `'lovelace-card'` passport; implemented mechanisms cite their code point in + `enforcedBy`. The lifecycle fixtures in `test/fixtures/config-lifecycle/` + pin the load contract: oldest-supported and future-field configs pass the + schema losslessly. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f25e9f3d..a5906adf 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +- Old and future plan configs are now guarded by machinery instead of habit: + the backend schema is dumped into a committed manifest, frontend and + backend value lists are compared in CI with an explicit allow-list for the + few legitimate compatibility divergences, and lifecycle fixtures prove a + config from the oldest supported era — or one from the future — loads + without silent loss ([#33](https://github.com/Matysh/houseplan-card/issues/33)). + - Old and future plan configs are now guarded by machinery instead of habit: the backend schema is dumped into a committed manifest, frontend and backend value lists are compared in CI with an explicit allow-list for the diff --git a/docs/CHANGELOG.ru.md b/docs/CHANGELOG.ru.md index 02d38e80..c377e959 100755 --- a/docs/CHANGELOG.ru.md +++ b/docs/CHANGELOG.ru.md @@ -8,6 +8,13 @@ ## Не выпущено +- Старые и будущие конфигурации плана теперь защищены механикой, а не + привычкой: схема бэкенда выгружается в закоммиченный манифест, списки + значений фронта и бэкенда сверяются в CI с явным allow-list'ом немногих + легитимных компат-расхождений, а lifecycle-фикстуры доказывают, что конфиг + старейшей поддерживаемой эпохи — или из будущего — загружается без тихих + потерь ([#33](https://github.com/Matysh/houseplan-card/issues/33)). + - Старые и будущие конфигурации плана теперь защищены механикой, а не привычкой: схема бэкенда выгружается в закоммиченный манифест, списки значений фронта и бэкенда сверяются в CI с явным allow-list'ом немногих