Architecture Decision Record · 0047

Vacancy-Application Submission via Personio-Inbox-Bridge mit Webhook-ACK (Pfad C+)

Status: superseded superseded by ADR-0050 customer-lens-reviewer: APPROVE-WITH-CAVEATS (2026-05-25)
⚠ Superseded am 2026-05-29 durch ADR-0050. Personio hat SOLCOM den Multiposting-Partner-Scope gewährt (P2503-191), wodurch der in dieser ADR als „Future-Refactor-Option“ dokumentierte Pfad A (direkter API-POST) erreichbar wurde. Die Email-Inbox-Bridge ist damit obsolet. Der untenstehende Inhalt bleibt als historischer Record erhalten.

TL;DR (historisch) — Drupal-zu-Personio-Application-Submit läuft im MVP via SMTP an die Personio-Inbox des SOLCOM-Tenants; der deterministische ACK kommt über den Personio-Webhook application.created zurück. Ein direkter HTTP-POST gegen die Personio Recruiting API ist mit SOLCOMs Standard-Recruiting-Credentials nicht erreichbar, weil der Endpoint hinter dem Personio-Multiposting-Partner-Scope gated ist (17 Live-Probes vom 2026-05-25 belegen das mit HTTP 401, nicht 404). Die Email-Inbox-Bridge ist damit der einzig durchgängig funktionierende Submit-Pfad und bleibt MVP-Architektur, sofern Personio den Multiposting-Scope nicht nachträglich aktiviert.

Kontext

F-100 / P2503-90 („Bewerber-Flow“) verlangt eine Drupal-native Bewerbungsseite pro Stelle. Karriere-Interessent:innen sollen vom Apply-CTA auf einer Vacancy-Detailseite (/karriere/<slug>) ohne Medienbruch direkt zu einer Bewerbungsseite auf der SOLCOM-Drupal-Site gelangen, das Formular ausfüllen, ihre Bewerbung absenden und im Personio-Recruiting-Backend wie eine über die Personio-Hosted-Page abgegebene Bewerbung erscheinen.

Die ursprüngliche Anforderung war: „Drupal-Webform sammelt Daten, schickt Submit per HTTP-POST direkt an die Personio Recruiting API, fertig.“ Diese Architektur (in dieser ADR Pfad A genannt) setzt voraus, dass der POST-Endpoint mit SOLCOMs vorhandenen papi--Recruiting-Credentials erreichbar ist. Ein Spike am 2026-05-25 hat das systematisch geprüft.

Spike-Befunde (17 Live-Probes gegen api.personio.de, 2026-05-25)

Stakeholder-Anforderungen aus F-100-Grilling

Entscheidung

Pfad C+ — Email-Inbox-Import + Webhook-ACK wird MVP-Architektur. Konkret:

  1. Drupal-Webform vacancy_application rendert pro Stelle unter /karriere/<slug>/bewerben. Vacancy-Kontext (Personio-Job-ID, Stellentitel, Vacancy-Node-ID) wird per Route-Parameter aufgelöst und als Hidden-Fields in die Form injiziert.
  2. Submit-Handler speichert die Submission und ihre Files in private://applications/<submission-uuid>/ und enqueued ein Queue-Item in solcom_personio_application_queue.
  3. Ein QueueWorker lädt das Item, ruft den deep module PersonioMailBuilder, der einen strukturierten Key-Value-Text-Body erzeugt, die Files als Attachments anhängt und einen Tracking-Hash ins Subject schreibt (Subject-Format: Bewerbung: <Stellentitel> (Personio-Job-ID <id>) · <Bewerbername> · trace:<hash>).
  4. Der Drupal-Mail-Manager versendet die Mail an die im Drupal-State hinterlegte Personio-Inbox-Adresse des SOLCOM-Tenants. Personio parst die Mail in eine Application im Recruiting-Posteingang und schickt die übliche Personio-Bestätigungsmail an die Bewerber:in.
  5. Personio feuert anschließend den Webhook application.created auf den Drupal-Receiver /personio/webhook/application-created. Drupal verifiziert die HMAC-Signatur via PersonioWebhookSignatureVerifier, matcht die Submission über den Tracking-Hash (oder hilfsweise über die Bewerber-Email), markiert die Submission als acked und speichert die Personio-Application-ID in Submission-Meta.
  6. Bei ACK wird die Conditional-Retention scharf: PII-Felder und Files werden aus dem SOLCOM-System gepurged.
  7. Failure-Pfade: max 5 Retry-Versuche mit Backoff (1 min/5 min/15 min/1 h/6 h); nach DLQ-Erschöpfung Mail an hr@solcom.de, Submission + Files bleiben persistent. Ein täglicher Cron-Job alarmiert HR, wenn eine Submission länger als 24 h ohne ACK im Status sent_pending_ack liegt.
  8. Eine HR-Recovery-Oberfläche unter /admin/karriere/dlq erlaubt Re-Queue, Files-Download und „Manuell erledigt“-Mark, nur für die HR-Rolle sichtbar.

Die Webhook-Subscription wird einmalig via Drush-Command solcom:personio:webhook-subscribe angelegt; Subscription-ID wird in Drupal-State persistiert. Ein Drush-Smoke-Test solcom:personio:smoke-test erzeugt regelmäßig eine markierte Test-Application gegen die Dummy-Stelle 2635453 und verifiziert den ACK via Personio v2 Read-back.

Rejected Alternatives

Pfad A — direkter HTTP-POST gegen POST /v1/recruiting/applications

Rejected, weil der Endpoint mit SOLCOMs Standard-Recruiting-Credentials nicht erreichbar ist. 17 Live-Probes mit fünf verschiedenen Auth-Pattern und zwei Content-Type-Variationen lieferten alle HTTP 401. Diagnose: Multiposting-Partner-Scope-Gate. Die Aktivierung dieses Scopes ist ein separater Personio-Vertrag, der von SOLCOMs Personio-Account-Manager neu verhandelt werden muss (Kosten, Vertragsdauer, Onboarding-SLA unbekannt). Diese Klärung läuft parallel als Sub-Task P2503-191 und ist explizit non-blocking für den MVP-Launch.

Future-Refactor-Option: Falls Personio den Multiposting-Scope für SOLCOM aktiviert, kann der QueueWorker-Body in einer Folge-Story von SMTP-Versand auf HTTP-POST gegen POST /v1/recruiting/applications umgestellt werden. Die Drupal-Webform-Architektur (Topology, Sub-Route, File-Upload, Queue-Schale, DLQ-UI) bleibt dabei unverändert; nur der innere Body des QueueWorker-Plugins (plus die PersonioApiClient-Methode) wechseln. Das ist ein 1-PR-Refactor, kein Architektur-Bruch.

Pfad B — Hosted-Page-Redirect (Status Quo)

Rejected, weil es das User-Story-Outcome „kein Medienbruch“ verletzt. Der heutige Apply-CTA leitet auf https://solcom-gmbh.jobs.personio.de/job/<id> weiter; Bewerber:innen verlassen die SOLCOM-Site und landen in einem visuell und URL-strukturell fremden Tool. Drop-Off im Apply-Flow ist höher als bei seitennativen Formularen, Brand-Konsistenz bricht, Drupal-Analytics werden nicht fortgeführt.

Behalten als Notfall-Fallback: Falls die Personio-Inbox-Konfiguration im SOLCOM-Tenant nicht in zumutbarer Zeit eingerichtet werden kann oder das Personio-Mail-Parsing in der initialen Smoke-Test-Phase strukturell scheitert (Felder werden nicht zuverlässig in Application-Felder gemappt), kann F-100 auf Pfad B zurückfallen. Diese Option wird nicht aktiv verfolgt, ist aber als Fallback dokumentiert.

Pfad D — Wechsel auf ein anderes Recruiting-Tool

Rejected, weil out-of-scope. Personio ist SOLCOMs vertraglich gebundenes Recruiting-Tool mit bestehender HR-Workflow-Integration. Ein Vendor-Switch wäre eine separate strategische Entscheidung mit deutlich größerem Scope (HR-Onboarding, Daten-Migration, Vertrags-Ende). Nicht Gegenstand dieser ADR.

Pfad E — Pipe-Through ohne persistente Drupal-Submission

Rejected, weil mit der Queue-Architektur inkompatibel. Pipe-Through (Submit-Request liest die Files direkt aus dem Upload-Stream und schickt sie unmittelbar an Personio, ohne Drupal-Persistierung) wurde initial in der Grilling-Session vorgeschlagen. Mit der HR-Recovery-Anforderung und dem damit erzwungenen Queue-Worker-Pattern ist Pipe-Through nicht möglich: der QueueWorker läuft zeitlich entkoppelt vom Submit-Request und braucht die Files im Filesystem. Persistente private://-Storage ist daher unausweichlich.

Consequences

Positive

Negative

Neutral / Folgeeffekte

Mitigation