solcom · solcom-review · in-session · 3 Achsen (Canvas-Achse inaktiv)

solcom-review: feature/P2503-113 — Gulp HTML-Feed unter /feeds/gulp.html + Legacy-Backlink-Redirect

feature/P2503-113origin/develop Datum: 2026-05-25 3 Commits · 12 Files · +1192/-9 LOC Spec-Refs: P2503-113, P2503-169, P2503-170, F-360
Findings: standards=5 (2 hard, 3 judgement) · spec=3 (1 partial, 1 scope creep, 1 spec-vs-diff) · canvas=skipped (kein Diff-Match). Worst: Hard 1TrustedRedirectResponse 301 ohne addCacheableDependency(); gecachter 301 wird nicht invalidiert wenn Offer in Salesforce nachträglich gelöscht/unpublished wird.

Standards

hard 1 — VendorFeedController::detailRedirect() 301 ohne Cache-Tags

web/modules/custom/solcom_project_offer/modules/solcom_project_offer_feeds/src/Controller/VendorFeedController.php:61:

return new TrustedRedirectResponse($url, 301);

Die 404-Pfade in derselben Methode wurden im P6-Fix als CacheableResponse mit Cache-Tag node_list:project_offer versehen. Die 301-Antwort bleibt aber ohne Cache-Metadata. TrustedRedirectResponse implementiert CacheableResponseInterface und akzeptiert addCacheableDependency() — wird hier nicht genutzt.

Cutover-Impact: wird ein Offer in Salesforce gelöscht oder auf Offline gesetzt, bleibt die gecachte 301-Antwort gegen die alte SF-ID stehen. Bot folgt der Weiterleitung, kanonische URL liefert dann 404. Inkonsistent, aber kein Klick-Loop.

Fix-Vorschlag (3 Zeilen):

$response = new TrustedRedirectResponse($url, 301);
$response->addCacheableDependency($node);
$response->addCacheableDependency((new CacheableMetadata())->setCacheTags(['node_list:project_offer']));
return $response;

Rule-Quelle: .claude/skills/drupal-module-development/SKILL.md §Controller-Pattern (CacheableResponse-Hygiene für Public-Routen).

false-positive 2 — configFactory->get() dreifach in VendorFeedBuilder

Sub-Agent markierte VendorFeedBuilder.php:195,206,222 als Standards-Verstoss (mehrfacher configFactory->get()-Lookup). Verifikation per git diff develop...HEAD: 0 Matches auf configFactory im Diff. Die Zeilen sind F-340-UTM-Logik aus der develop-Base, nicht in diesem PR geändert. Kein Standards-Issue für diesen Review.

judgement Tests in tests/src/Kernel/ mit http_kernel-Pattern

GulpFeedRouteTest.php und GulpFeedBuilderTest.php nutzen KernelTestBase + http_kernel-Service für echte HTTP-Request-Cycles — faktisch ein Functional-Test-Pattern. Worklog dokumentiert die Abweichung als Precedent von VendorFeedRouteTest aus F-340. Aus drupal-testing-Skill-Perspektive akzeptabel; eine spätere Konsolidierung könnte beide Files in tests/src/Functional/ verschieben.

judgement Meta-Tag-Schema docs/reports/

QA-Report nutzt solcom:-Präfix-Meta-Tags (solcom:type, solcom:title, …). html-doc-authoring-Skill definiert für den Report-Strand doc--Präfix. Alle existierenden Review/QA-Reports im Strand nutzen aber konsistent solcom:. De-facto-Standard im Strand etabliert; Skill-Doku könnte das angleichen.

judgement Twig title ohne expliziten escape-Filter

solcom-feed-gulp.html.twig rendert {{ position.title }} ohne |escape oder |e. Drupal-Auto-Escape ist für Modul-Templates aktiv (kein autoescape: false). Defensive Praxis wäre {{ position.title|e }}; aktuelle Form sicher solange Auto-Escape greift. Kein Modul-Template-Issue für SDC-Regeln (Twig-Template, kein SDC).

Spec

partial P2503-169 AK-2 — Test-Assertion-Gap

GulpFeedBuilderTest.php assertet href-Format gegen /node/<id>, nicht gegen /fuer-freiberufler/projektliste/<slug> (ADR-0032, Memory project_projektliste_canonical_url). Implementation via toUrl('canonical') ist korrekt; der Test verifiziert aber nicht den Pathauto-Alias-Pfad, weil KernelTestBase kein Pathauto-Modul aktiviert. Worklog dokumentiert das als bewussten Tradeoff (Sub-Task P2503-169 Implementation Notes, „med — spec — AK-2 href-Format"). Live-QA P8 zeigt die kanonische URL korrekt vom Pathauto resolved (/projektpartnerportal/<slug> — aktuelle Pattern-Konfig).

scope creep .hooks/pre-commit Twig-Mapping-Fix

Commit 640b3c7 erweitert .hooks/pre-commit für Twig-Files in Custom-Modulen (vorher nur byte_theme). Nicht in P2503-113/169/170 oder PRD/Plan spezifiziert. Pragmatisch nötig zum Commit (Pre-Commit-Hook blockte ohne diesen Fix), daher als eigener chore(hooks)-Commit getrennt. Funktional unschädlich, sollte nach Merge in `scripts/ralph.sh`-Update-Run reflektiert werden.

spec ≠ diff P2503-170 AK-1 — Test-Assertion analog AK-2

GulpLegacyRedirectTest.php:110 assertet Location-Header gegen /node/<id>, Spec verlangt kanonische Detail-URL /fuer-freiberufler/projektliste/<slug>. Implementation via toUrl('canonical') korrekt; Test-Assertion verifiziert nicht, was die Spec fordert. Analog zu AK-2 dokumentierter Tradeoff.

behoben aus Vorrunde

Canvas-Korrektheit

Achse inaktiv — Diff enthält keine config/sync/canvas.*- oder *.component.yml-Files.

Empfehlung

Hard 1 sollte vor PR-Open gefixt werden — 3-Zeilen-Patch, kein neuer Test nötig (Bestehender GulpLegacyRedirectTest deckt den 301-Pfad bereits ab; Cache-Tag-Assertion könnte ergänzt werden, ist aber nicht spezifiziert in Story-AKs).

Spec-Findings (Test-Assertion-Gaps) sind dokumentierte Tradeoffs im Worklog. Eine spätere Konsolidierung würde eine Functional-Test-Suite mit Pathauto installieren — eigener Folge-PR chore/feeds-functional-tests.

Scope-Creep (Hook-Fix) ist als separater Commit isoliert und unschädlich für die Story.

Judgements sind alle akzeptabel; kein Handlungsbedarf vor PR-Open.