Architecture Decision Record · 0039

Canvas-Config-Drift-Heilung via solcom_editorial post_update Hooks

TL;DR — Wiederkehrende Canvas-Config-Drift-Klassen (Autosave-Drafts mit Orphan-Prop-Keys, prop_field_definitions mit Empty-Array-default_value für Non-Entity-Ref-Fields) werden via hook_post_update_N in solcom_editorial generisch und idempotent geheilt. Jeder Deploy via drush updb repariert; kein händlicher Eingriff pro Inzidenz.

Kontext

Drupal-Canvas hält für jedes SDC-Placement zwei Versions-bezogene Storage-Layer: (1) die Component-Config-Entity canvas.component.sdc.<theme>.<name> mit active_version + versioned_properties-Hash-Map; (2) die Page-Trees in canvas_page__components / node__field_component_tree mit components_component_version-Pin pro Placement. Beide Layer werden ergänzt durch:

Beide Schichten driften gegen die SDC-Schema-Wahrheit, sobald die SDC sich entwickelt:

  1. Orphan-Prop-Keys im Autosave. Beispiel: byte_theme/footer hatte mal einen align-Prop, der wurde später aus der SDC entfernt. Ein älterer Autosave-Draft trägt inputs: {"align": true} weiterhin. Beim Editor-Open für die betroffene Page wirft Canvas 'align' is not a prop on this version of the Component … und crasht den Editor mit 500.
  2. Falsche default_value-Inferenz. Beispiel: byte_theme/skills-pills deklariert skills als type: array | null. Die Canvas-Inferenz mapped das auf field_type: string mit default_value: [] (Empty-Array). Eine spätere Canvas-Update-Version führt die Assertion exampleValueRequiresEntity($shape) === ($default_value === []) in GeneratedFieldExplicitInputUxComponentSourceBase::getDefaultStaticPropSource() ein — bei Non-Entity-Ref-Field mit Empty-Array-Default ist die Assertion FALSE === TRUE → 500 beim Component-Picker-Fetch.

Beide Klassen sind vorhersagbare Folge-Drift, keine Bugs in der Schema-Schicht. Sie können auf jedem Environment (Dev, Staging, Prod) auftreten, sobald eine SDC sich entwickelt. ADR-0002 hat den ersten Drift-Fall (Page-Region-Versions-Pin gegen entfernten Slot) per einmaligem Repair-Script geheilt — aber pro-Inzidenz, nicht generisch.

Entscheidung

Zwei Drift-Klassen werden per hook_post_update_N im solcom_editorial-Modul generisch und idempotent geheilt. Datei: web/modules/custom/solcom_editorial/solcom_editorial.post_update.php. Lauf-Zeitpunkt: drush updb bei jedem Deploy. Schema-Version-Bump per Hook stellt sicher, dass jeder Hook genau einmal pro Environment ausgeführt wird; ein zweiter Lauf nach Re-Set der Schema-Version wäre no-op (Idempotenz im Hook-Body).

Hook 1 — prune_orphan_autosave_props

Durchläuft alle canvas.auto_save-Einträge im Key-Value-Store. Für jede SDC-Component im component_tree (Block-Components werden übersprungen, weil deren Inputs nicht schema-versioniert sind):

Hook 2 — repair_orphan_default_values

Durchläuft alle canvas.component.<id>-Configs. Pro Version, pro Prop-Field-Definition:

Operativer Workflow

# Dev-Environment (oder beliebige andere)
drush updb -y

# Output:
# > [notice] Update started: solcom_editorial_post_update_prune_orphan_autosave_props
# > [notice] Canvas-Autosave-Cleanup: 1 Draft-Eintrag/e beruehrt, 1 Orphan-Input-Key(s) entfernt.
# > [notice] Update started: solcom_editorial_post_update_repair_orphan_default_values
# > [notice] Canvas-Default-Value-Repair: 1 Component-Config(s) repariert.

Bei zukünftigen Drift-Klassen (z. B. versioned_properties-Eintrag fehlt, aber Page-Tree pinnt darauf) wird eine dritte Hook-Funktion mit eigenem Namen angehängt. Schema-Version wächst monoton, jeder Hook läuft genau einmal pro Environment.

Rejected alternatives

Consequences