VariableRef parses, validates and re-serializes every $variable(...)$ value (S1/S2/S12); AttrWriter routes strings by catalog kind incl. per-subName composite kinds and key-name URL fallback (S3/S3a), rejects odd value keys (S13) and Divi HTML/attribute fields without unfiltered_html (S7); ambiguous design-system labels fail with their ids (S13a); R2 finding recorded (S5). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
6.1 KiB
6.1 KiB
Etappe 2 – Entscheidungen der Planung
Getroffen bei der Planung von Etappe 2a/2b, 2026-09-26. Kosten, falls falsch, jeweils am Ende.
- D1 (Ruling P16):
rev=Rev::ofPost(ganzer Eintrag); Divi-Sperre =tree_rev=Rev::of(post_content). Divi-Lese-Tools liefern beide, Divi-Schreib-Tools verlangentree_revund liefern beide neu. – Kosten: keine. - D2: Direkte Tools nach Etappe 2 = 21 (Spec §4.3 ohne
lit/library-insert, pluslit/site-status,lit/media-download).lit/site-statusbleibt direkt (leeres Schema, Anker von mcp-smoke.sh),lit/media-downloadmuss direkt bleiben. Indirekt:lit/divi-duplicate-node,lit/divi-replace-text. – Kosten: etwas mehr Kontext je Unterhaltung; in Etappe 3 neu bewerten. - D3: BlockTree mit eigenem Tokenizer (Muster von
WP_Block_Parser), opake Knoten für globale Module/Layouts und undekodierbare Attribute, unbalanciertes Markup → Ablehnung. – Kosten: globale Module erst ab Etappe 3 bearbeitbar. - D4:
ExposurePolicy::DIRECT_ONLYbleibt eine Liste; Etappe 2 bringt keine Bild-/Ressourcen-Tools, einAbility::requiresDirect()wäre YAGNI. – Kosten: bei weiteren Bild-Tools die Liste ergänzen. - D5:
lit/page-render-summarygehört zur WordPress-Integration (funktioniert für jeden Eintrag) und rendert den Inhaltsbereich im Prozess (the_content), ohne HTTP-Loopback. – Kosten: Header/Footer/Theme Builder fehlen im Auszug. - D6:
lit/divi-dynamic-sourcesund die Warnung „ähnliche Abschnitte“ kommen mit Etappe 3 (Theme Builder,lit/library-find-similar). – Kosten: bis dahin keine Quellenliste;{{field:…}}nimmt jeden Meta-Schlüssel. - D7 (Ruling R1): Divi-Speichern ohne kses für Benutzer ohne
unfiltered_html(sonst re-serialisiert WordPress jeden Block) ist nur vertretbar, weil keine client-gelieferte Zeichenkette ungeprüft inpost_contentgelangt. Klartext-Werte werden je Feldtyp bereinigt (Text:sanitize_text_field; Rich-Text:wp_kses_post, abhängig vonunfiltered_html; URLs:esc_url_raw, geroutet über die Attribut-Metadaten des Katalogs, ersatzweise über den Schlüsselnamen). Werte mit$variable(...)$– ob aus Platzhaltern erzeugt oder unverändert auslit/divi-node-getzurückgegeben – werden geparst, streng geprüft (zulässiger Typ, existierende gcid-/gvid-/Dynamic-Content-Quellennamen, whitelisted Settings-Schlüssel, String-Settings bereinigt) und vom Plugin neu serialisiert; alles andere wird mitvalidation_failedabgelehnt. Code-Modul ungefiltert nur mitunfiltered_html. – Kosten: jeder neue Schreibpfad muss bereinigen, streng validieren und neu serialisieren (Review-Pflicht). - R2 (Ruling): Ob Divi das Dynamic-Content-
before/afterbei der Ausgabe selbst escaped, wird in Etappe 2b im Divi-Quellcode verifiziert; die Bereinigung aus D7 gilt unabhängig vom Ergebnis (Verteidigung in der Tiefe). – Kosten: keine (Verifikation, keine Abhängigkeit der Sicherheit vom Ergebnis). - R2 – Befund (Etappe 2b, Divi 5.2.1, Ruling S5): (1) Dynamic-Content-
before/afterwird bei der Ausgabe nur dann mitwp_ksesgefiltert, wenn der Autor des Beitrags keinunfiltered_htmlhat (DynamicContentElements::get_wrapper_element); auf Seiten eines Administrators gelangt es ungefiltert ins HTML – ein Redakteur könnte dort Skript platzieren. (2)enable_html: ongibt Meta-Werte mitwp_kses_poststattesc_htmlaus; Divi entferntenable_htmlbeim Speichern nur für Benutzer ohneunfiltered_html(Security::sanitize_dynamic_content_fields,wp_insert_post_dataPriorität 10). (3)custom_meta_<key>wird ohneis_protected_meta-Prüfung ausgegeben (DynamicContentOptionPostMetaKey). (4) Farbverweis-Namen gehen unescaped invar(--<name>)(StyleLibrary\Utils::resolve_dynamic_variable). (5) Divis eigenewp_insert_post_data-Filter sind kein kses und laufen auch bei unserem Speichern ohne kses:AttributeSecurity(Priorität 5, immer, sobald"decoration":{und"attributes":{vorkommen) undHtmlSecurity(Priorität 6, beihtmlBefore/htmlAfter/elementType) parsen und re-serialisieren die ganze Seite;DynamicContentFixes(Priorität 10). Folgen: die Plugin-Prüfung aus D7 ist die eigentliche Garantie (VariableRef: nur ganze, geprüfte, neu serialisierte Verweise;before/afterohne unzulässiges HTML, keinenable_html, keine Meta-Schlüssel mit_); Divis Filter bleiben aktiv (Verteidigung in der Tiefe) und werden nie entfernt; Schreiben auf*.decoration.attributesund*.advanced.htmlnur mitunfiltered_html(„nur im Divi-Builder“, Ruling S7), und auf Seiten mit diesen Feldern gilt die Byte-Invarianz nicht (Divi normalisiert beim Speichern). – Kosten: keine (Dokumentation; die Sicherheit hängt nicht von Divis Ausgabe ab). - D8: Spalten neuer Zeilen über
module.decoration.sizing.desktop.value.flexType("1_3,2_3"→8_24,16_24; Fünftel und 1/7, 1/9, 1/10, 1/11 nativ), wie Divi 5.2 (Flex-Layout ist Standard). – Kosten: falls der Builder anders speichert, nur Composer anpassen. - D9: Platzhalter stehen allein im Wert; Überschriften der Kurzform ohne
levelwerdenh2. – Kosten: eingebettete dynamische Texte nur über die Vollform. - D10:
lit/divi-replace-textje Inhaltstyp; Probelauf lieferttree_revje Seite, Ausführung nur auf diesentargetsmitconfirm: true; ersetzt nur sichtbaren Text (…innerContent, Schlüssel text/title/label/alt/titleText), nie URLs oder Stile. – Kosten: Text mit HTML-Entitäten muss so gesucht werden, wie er gespeichert ist. - D11:
lit/content-createmitdivispeichert überwp_insert_postmit WordPress' üblicher Filterung (nur neuer, selbst erzeugter Inhalt – nichts Unberührtes, das byte-identisch bleiben müsste). – Kosten: für Benutzer ohneunfiltered_htmlkann WordPress Entitäten normalisieren;tree_revin der Antwort beschreibt den gespeicherten Stand. - D12: Fixtures: handgeschriebene Grenzfälle (
synthetic-*.html), mit Divis eigener Konvertierung erzeugte Seiten (converted-*.html), echte Modul-Metadaten (metadata-sample.json); im Visual Builder gebaute Seiten exportiert Jan-Niclas später mittests/Integration/divi-export-page.phpalsbuilder-*.html– sie laufen automatisch im Roundtrip-Test mit.