Voller 3-Achsen-Review (post-reconcile) — mp/P2503-90 Pfad A
Vacancy Application · direkter Personio-Recruiting-API-POST · PR #165066 → develop · Fixed-Point origin/develop · 2026-05-30 · Source: ADR-0028
VERDICT: CLEAN — keine BLOCKERS, review-ready
Layer-Evals (verifiziert)
| Gate | Ergebnis |
|---|---|
| PHPUnit Kernel (gesamtes Modul) | OK 27 Tests / 217 Assertions, 0 Failures (15 bekannte Deprecations) |
| phpcs (pre-commit hook) | clean 0 Errors |
phpstan (phpstan.neon) | No errors |
| Live-Feature-Re-Test (Sandbox, Job 2635453) | PASS Submission+CV → queue:run → 2xx + Send-Token im Feld + GDPR-Purge + Submission gelöscht |
Standards
Keine HARD violations. DI durchgängig korrekt (Services, QueueWorker via ContainerFactoryPluginInterface, Drush-Commands, Controller); Routing — alle state-ändernden DLQ-Routen via ConfirmFormBase (POST + CSRF), Apply/Thank-You via _custom_access, DLQ-Listing via _permission; manage karriere dlq in permissions.yml; key:key in info.yml; Config-Schema deckt alle drei Settings-Felder; keine Superglobals; kein hook_update_N nötig (neues Modul).
| Klasse | Finding | Disposition |
|---|---|---|
| Judgement | @WebformHandler-Doc-Annotation statt PHP-Attribut | SKIP Webform-Contrib-Plugin-Manager ist selbst annotation-basiert; ein Attribut würde nicht registrieren — korrekt-by-convention bis Webform migriert |
| Advisory | key.key.solcom_personio_api_key.yml mit dependencies: {} | OK konsistent mit den 3 bestehenden key.key.solcom_sf_*-Configs (Site-Pattern) |
| Advisory | personio_send_documents-Kill-Switch ohne Inline-Rationale-Kommentar | WORKLOG in ADR-0050 + README dokumentiert; Inline-Comment minor |
Canvas-Korrektheit
Spec
Spec-treu zu F-100 + ADR-0050; kein Scope-Creep. Der C+-Stack (PersonioMailBuilder/PersonioWebhookController/PersonioWebhookCommands) ist sauber entfernt. „Keine Personio-Application-ID gespeichert" ist korrekt-per-Contract (live verifiziert: 201 leer, kein Read-back), kein Spec-Gap.
| Klasse | Finding | Disposition |
|---|---|---|
| Missing | AK-12 — DLQ zeigt File-Presence Ja/Nein, keinen CV-Download-Link → HR kann CV für fehlgeschlagene Bewerbung nicht abrufen | FOLLOW-UP echter Gap; bei Erfolg geht CV jetzt an Personio (files-live), aber DLQ-Recovery braucht Download → P90-Folge-Item |
| Missing | AK-1 — Apply-CTA (field_apply_url) nicht auf interne Sub-Route umverdrahtet | DEFERRED vorab-bekannt (Re-Grill G7, eigener Slice) |
| Missing | AK-17 — AVV-Context-Snapshot fehlt in docs/context/ | DEFERRED vorab-bekannte Vorbedingung |
| Wrong (minor) | AK-6 — upload_location ist flach private://applications/ (kein per-UUID-Token) → Files co-minglen; zudem private://-Stream-Wrapper im DDEV nicht konfiguriert (ApplicationPurger:99-Warning) | FOLLOW-UP P90-14; Purger-is_dir()-Guard macht Removal zum sicheren No-Op, Entity-Delete räumt Files |
| Wrong (minor) | C-3 — #access-Flag-Structural-Test prüft inline-Test-Webforms, nicht die installierte webform.webform.vacancy_application.yml | WORKLOG Config selbst korrekt (alle 5 Lifecycle-Elemente tragen den Flag); der vom ADR mandatierte Config-Load-Test fehlt |
Summary
Findings: standards=3 (0 hard, 1 judgement, 2 advisory), canvas=inaktiv, spec=5 (3 missing pre-disclosed/deferred, 0 scope-creep, 2 minor wrong-impl). Worst: AK-12 — DLQ ohne CV-Download, HR kann CV einer fehlgeschlagenen Bewerbung nicht abrufen.
Fazit
Der Contract-Reconcile ist sauber: 0 HARD violations, kein Scope-Creep, spec-treu, alle Layer-Evals grün, Live-Feature-Re-Test PASS. Die Findings sind allesamt vorab-bekannte Deferrals (AK-1/AK-17) oder File-Storage-Folge-Items (AK-12 DLQ-Download, flat upload_location + private://-Wrapper) — orthogonal zum reconcileden API-Contract. Der PR ist review-ready. Der Merge bleibt menschlich (Memory feedback_ki_merged_nicht_bis_mr).