/feeds/gulp.html + Legacy-Backlink-Redirectdevelop.
| Gate | Command | Ergebnis |
|---|---|---|
| PHPUnit (Sub-Modul) | phpunit -c web/core/phpunit.xml.dist .../solcom_project_offer_feeds/tests/ | 25/25 ✅ — 254 assertions |
| PHPCS Drupal/DrupalPractice | phpcs --standard=Drupal,DrupalPractice .../solcom_project_offer_feeds/ | 10/10 files ✅ — keine Findings |
| PHPStan | phpstan analyse -c phpstan.neon .../solcom_project_offer_feeds/ | 11/11 files ✅ — 0 errors |
Ausgangs-State der DDEV-DB: 2 Gulp-eligible Offers im Bundle project_offer (nid 257, sf-id a1WAU000002gTpF2AU; nid 273, sf-id a1WAU000002metF2AQ). Test-Setup: Offer 257 mit publish_end=2026-12-31, pub_status='Online', job_title='Senior Cloud Architect'.
| AK | Click-Pfad / Aktion | Erwartet | Beobachtet | Status |
|---|---|---|---|---|
| AK1 | GET /feeds/gulp.html |
HTML mit <a>-Tag pro Gulp-eligible Offer |
HTTP 200, 1 <a>-Tag, wohlgeformtes HTML |
✅ |
| AK2 | Linktext + href des <a>-Tags |
Linktext „Jobtitel (m/w/d)", href absolut auf /fuer-freiberufler/projektliste/<slug> (ADR-0032) |
Linktext „Senior Cloud Architect (m/w/d)" ✅; href absolute Drupal-URL ✅; URL-Pfad /projektpartnerportal/blacklist-analyst — siehe Deviation unten |
✅* |
| AK3 | Offer mit publish_end in der Vergangenheit |
Offer fehlt in der Linkliste | Covered via P7 PHPUnit GulpFeedBuilderTest::testBuildGulpExcludesExpiredOffer |
✅ |
| AK4 | Offer mit pub_status ≠ 'Online' |
Offer fehlt in der Linkliste | Covered via P7 PHPUnit GulpFeedBuilderTest::testBuildGulpExcludesOfflineOffer |
✅ |
| AK5a | GET /asp/robots/detail.aspx?mode=GULP&id=a1WAU000002gTpF2AU |
HTTP 301 mit Location auf kanonische Drupal-Detail-URL |
HTTP 301 + Location: https://solcom.ddev.site/projektpartnerportal/blacklist-analyst ✅ |
✅ |
| AK5b | GET /asp/robots/detail.aspx?mode=GULP&id=NO_SUCH_ID_XYZ |
HTTP 404 als CacheableResponse mit node_list:project_offer-Tag |
HTTP 404 ✅ (P6-Fix wirkt; Re-Cache-Invalidation bei späterer SF-Sync möglich) | ✅ |
| AK5 cutover | curl -H 'Host: www.solcom.de' …/asp/robots/detail.aspx?mode=GULP&id=<known> |
HTTP 301 wie AK5a, mit kanonischer www.solcom.de-Location | In DDEV nicht testbar — DDEV-Router lehnt unbekannten Vhost ab (Raw 404). Covered via P7 PHPUnit GulpLegacyRedirectTest + verbindlicher post-deploy verify in Staging |
⚠️* |
| AK6 | curl -I /feeds/gulp.html → Response-Header |
X-Robots-Tag: noindex, nofollow und Content-Type: text/html; charset=utf-8 |
Beide Header exakt ✅ (P3-Fix angewendet) | ✅ |
| AK7 | Edit Offer-Title via Node-Save, dann erneuter GET /feeds/gulp.html |
Geänderter Title erscheint sofort in nächster Response | Vor Save: „Java Backend Entwickler (m/w/d)"; nach Save: „Senior Cloud Architect (m/w/d)" — Cache-Tag node_list:project_offer invalidiert sofort ✅ |
✅ |
| AK8 | GET /feeds/gulp.html als anonymer User |
HTTP 200, keine Auth-Redirects | HTTP 200 ohne Location-Header ✅ |
✅ |
| AK9 | drush pm:uninstall → routes weg → module_installer.install → routes wieder da |
Beide Routen (HTML + F-340 XML) verschwinden bzw. erscheinen synchron | Nach Uninstall: /feeds/gulp.html = 404 ✅, /feeds/freelancermap.xml = 404 ✅. Nach Reinstall: beide 200 ✅, Feed-Body restored. Hinweis: drush pm:install via Drush hängt; Reinstall via \Drupal::service('module_installer')->install(...) erfolgreich |
✅ |
| AK10 | PHPUnit + PHPCS + PHPStan im Sub-Modul | Alle grün | P7-Test-Gate triple-green (siehe Sektion oben) | ✅ |
/projektpartnerportal/<slug> statt /fuer-freiberufler/projektliste/<slug>
Story-AK-2 verlangt kanonische URL unter /fuer-freiberufler/projektliste/<slug> (Memory project_projektliste_canonical_url, ADR-0032). Beobachtete Live-URL: /projektpartnerportal/<slug>.
Diagnose: Implementation ist korrekt — VendorFeedBuilder ruft $node->toUrl('canonical', ['absolute' => TRUE])->toString() auf. Die abweichende URL kommt aus dem Pathauto-Pattern in config/sync/pathauto.pattern.project_offer_content.yml, das auf /projektpartnerportal/[node:title] zeigt. Sobald dieses Pattern auf /fuer-freiberufler/projektliste/[node:title] geändert wird, ändert sich die Feed-URL automatisch — ohne Code-Change im Story-Sub-Modul.
Out-of-scope-Klassifikation: Goal §Posture beschränkt Edits auf solcom_project_offer_feeds/** + Story-Hub + Reports + LOG/INDEX. Pathauto-Pattern-Korrektur ist ein eigenständiges solcom_project_offer-Modul-/Config-Issue und gehört in einen separaten Folge-PR mit eigenem Jira-Issue.
Cutover-Impact: Konsistent mit dem Live-IA-Verhalten — Detail-Seiten unter /projektpartnerportal/<slug> sind erreichbar; /projektpartnerportal ist laut Memory ein Alias-Redirect, somit produziert die Feed-URL keinen toten Link.
Goal §Verification verlangt: curl -sI -H 'Host: www.solcom.de' …/asp/robots/detail.aspx?mode=GULP&id=<known-sf-id> → HTTP 301 mit kanonischer Location. In DDEV liefert dieser Aufruf jedoch HTTP 404 mit content-type: text/plain — das ist der Traefik-Default-404, weil der DDEV-Router den Vhost www.solcom.de nicht kennt.
Coverage: Der Code-Pfad (Symfony-Request mit beliebigem Host-Header → VendorFeedController::detailRedirect()) ist im P7-PHPUnit-Test GulpLegacyRedirectTest abgedeckt (Request via HTTP-Kernel ohne nginx-Vorfilter). Verbindlicher post-deploy verify in Staging gegen staging.solcom.de erforderlich.
feature/P2503-113 ab origin/develop, sauber für drei thematische Commits (P9).Nach Merge gegen develop + Mittwald-Deploy:
curl -sI https://<staging>/feeds/gulp.html → HTTP 200, Header korrektcurl -sI https://<staging>/asp/robots/detail.aspx?mode=GULP&id=<known-sf-id> → HTTP 301 mit Location auf /projektpartnerportal/<slug> (oder /fuer-freiberufler/projektliste/<slug> nach Pathauto-Fix)field_sf_id aus einer der 2 Live-Offers