From acfa90ff506d6ba8bf3d9fde5bcc05af181bd6fa Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Sun, 26 Apr 2026 13:27:54 +0200 Subject: [PATCH] fix(form-builder): post-WS-6 trim of TriggerPersonIdentityMatch dead path (WS-6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per RFC Q2: the 'no subject โ†’ pending' path becomes unreachable for event_registration submissions because ApplyBindingsOnFormSubmit provisions the Person before this listener fires. Path preserved as failsafe with explicit warning log so misconfigurations and silent ApplyBindings failures surface mechanically. Existing test updated to spy on Log facade and assert the warning fires. Refs: RFC-WS-6.md ยง3 (Q2) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../TriggerPersonIdentityMatchOnFormSubmit.php | 18 +++++++++++++++--- ...ggerPersonIdentityMatchOnFormSubmitTest.php | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php b/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php index 43f816c4..da006082 100644 --- a/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php +++ b/api/app/Listeners/FormBuilder/TriggerPersonIdentityMatchOnFormSubmit.php @@ -80,10 +80,22 @@ final class TriggerPersonIdentityMatchOnFormSubmit private function resolveStatus(FormSubmission $submission): string { - // Public submission without a person subject โ€” mark pending so the - // portal shows the "we koppelen je gegevens zodra..." message. - // Real matching happens when the organiser attaches a person. if ($submission->subject_type !== 'person' || $submission->subject_id === null) { + // Post-WS-6 (RFC Q2): this path should be unreachable for + // event_registration submissions because ApplyBindingsOnFormSubmit + // provisions the Person synchronously before this listener fires. + // If we reach here, either: + // - ApplyBindings failed silently (check form_submission_action_failures) + // - Schema is misconfigured (no email binding, no identity-key) + // - Different purpose where subject genuinely is null + // Failsafe: preserve the existing 'pending' state so portal banner + // still renders sensibly, and surface the misconfiguration in logs. + Log::warning('form-builder.identity-match.no_person_subject_post_apply', [ + 'submission_id' => (string) $submission->id, + 'schema_id' => (string) $submission->form_schema_id, + 'subject_type' => $submission->subject_type, + ]); + return 'pending'; } diff --git a/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php b/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php index 236a0cd5..5123834a 100644 --- a/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php +++ b/api/tests/Feature/FormBuilder/Listeners/TriggerPersonIdentityMatchOnFormSubmitTest.php @@ -84,9 +84,23 @@ final class TriggerPersonIdentityMatchOnFormSubmitTest extends TestCase public function test_public_event_registration_submission_is_marked_pending(): void { + // RFC Q2: this path is now a logged-warning failsafe. The pending + // state is preserved for portal banner rendering, but a misconfigured + // schema or silently-failed ApplyBindings should surface in logs. + // Spy mode (not strict mock) so other listeners' Log calls don't + // interfere โ€” ApplyBindingsOnFormSubmit may also log error here. + $logSpy = \Illuminate\Support\Facades\Log::spy(); + $submission = $this->submit(); $this->assertSame('pending', $submission->identity_match_status); + + /** @var \Mockery\Expectation $expectation */ + $expectation = $logSpy->shouldHaveReceived('warning'); + $expectation->with( + 'form-builder.identity-match.no_person_subject_post_apply', + \Mockery::type('array'), + ); } public function test_linked_person_is_marked_matched(): void