Architecture Decision Record · 0031

Personio-Vacancy-Sync via öffentlichem XML-Feed — anonymes Pulling als toleriertes Compliance-Risiko

Entscheidung. Der Personio-Vacancy-Sync bleibt auf dem öffentlichen XML-Feed solcom-gmbh.jobs.personio.de/xml via migrate_plus. Der für Mai 2026 erwogene Refactor auf einen authentifizierten v2-REST-Pfad wird verworfen, weil ein Live-Spike nachgewiesen hat, dass die v2-REST-API nur 8 Header-Felder liefert und alle Content-Felder ausschließlich im XML-Feed existieren. Anonymes Pulling wird als toleriertes Compliance-Risiko anerkannt: die Quelle ist Personio-seitig public publiziert, kein Privacy-Surface, keine PII.

Kontext

Der SOLCOM-Karriere-Bereich auf solcom.de spiegelt offene Stellenanzeigen aus Personio in den Drupal-Bundle node/vacancy. Das Modul web/modules/custom/solcom_vacancy zieht die Stellen stündlich via hook_cron aus dem öffentlichen XML-Feed solcom-gmbh.jobs.personio.de/xml; die Migration config/sync/migrate_plus.migration.solcom_vacancy.yml nutzt data_fetcher_plugin: http + data_parser_plugin: xml. Hard-Delete-Sweep über VacancyHardDeleteSubscriber (MigrateEvents::POST_IMPORT) inklusive Empty-Response-Schutz. Datenmodell, Vocabularies und Canvas-Templates sind seit Q2/2025 produktiv.

Im Mai 2026 wurde ein Refactor auf eine authentifizierte v2-REST-API-Spiegelung erwogen (PRD 2026-05-15-personio-rest-import-prd.html, Plan 2026-05-15-001-feat-personio-rest-import.html). Treiber waren Compliance- und IT-Security-seitige Anforderungen, externe Datenquellen mit Service-Identity anzusprechen, sowie ein vermuteter Pattern-Konsistenz-Gewinn mit künftigen externen REST-Syncs (Salesforce-Publication-Sync, ADR-0029).

Der Live-Spike am 2026-05-15 (vollständig dokumentiert in docs/stories/F-280-personio-rest-import.html#spike-findings) gegen Personios v2-REST-API hat die Grundannahme „authentifizierte REST = vollständige Spiegelung" über 2345 Responses und 429 distinct Jobs erschöpfend widerlegt:

QuelleAuthJob-SetFelder pro Job
POST /v1/auth + GET /v2/recruiting/jobs Bearer papi-…, opaque, TTL 24h 429 (inkl. archiviert + Drafts) 8 Header-Felder: id, name, category, company, department, hiring_team, created_at, updated_at (requirements_parsed_data + total_requirements waren in 0/2345 Samples non-null)
GET solcom-gmbh.jobs.personio.de/xml keine (public) 32 (nur Career-Site-live) 15 Content-Felder: id, subcompany, office, department, recruitingCategory, name, jobDescriptions, employmentType, seniority, schedule, yearsOfExperience, keywords, occupation, occupationCategory, salaryInformation

Damit ist eine vollständige Spiegelung über REST technisch nicht möglich. Die XML-Quelle liefert genau die 32 Career-Site-live-Stellen mit allen 11 Content-Feldern — exakt das, was die Anzeige-Schicht (Vacancy-Card-Listing, Vacancy-Full-Canvas-Template) braucht.

Entscheidung

Der Personio-Vacancy-Sync bleibt unverändert auf dem öffentlichen XML-Feed solcom-gmbh.jobs.personio.de/xml, geführt über das bestehende solcom_vacancy-Modul mit migrate_plus. Authentifizierter v2-REST-Pfad wird verworfen.

Anonymes Pulling wird als toleriertes Compliance-Risiko anerkannt, mit folgender Begründung:

Drupal-Best-Practice für recurring strukturierte XML-Feeds (data_fetcher_plugin: http + data_parser_plugin: xml + MigrateEvents-Sweep) trägt diesen Use-Case nativ; keiner der Trigger für einen Service+Queue-Refactor (komplexe Auth-Flows, instabiles Schema, Webhook-Ingestion, Transaktions-Side-Effects) ist erfüllt.

Rejected alternatives

Consequences