feat(form-builder): add PersonProvisioner with race-safe firstOrCreate (WS-6)
PersonProvisioner reads bindings from schema_snapshot (RFC Q6) and provisions Persons via lockForUpdate + firstOrCreate (RFC Q8). Person is event-scoped (Person::$organisationScopeColumn = 'event_id'), so the lookup matches by (email, event_id) — cross-event submissions never collide. Throws PersonProvisioningException on misconfiguration (failsafe — publish guards should prevent these at config time): no_transaction, no_event, no_identity_key, identity_key_missing_value, no_crowd_type. Snapshot enrichment: FormFieldBindingService::toApplicatorShape + FormSubmissionService snapshot now adds a 'bindings' (plural) key with binding id, merge_strategy, trust_level, is_identity_key. Singular 'binding' key kept for legacy webhook / GDPR readers. Includes RFC V4 state-injection concurrency test asserting recovery semantics under lockForUpdate windows. Refs: RFC-WS-6.md §3 (Q6, Q8), §4 (V4) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -243,7 +243,13 @@ final class FormSubmissionService
|
||||
'is_required' => (bool) $f->is_required,
|
||||
'is_filterable' => (bool) $f->is_filterable,
|
||||
'is_pii' => (bool) $f->is_pii,
|
||||
'binding' => $this->bindingService->toJsonShape($f->bindings->first()),
|
||||
// WS-6 RFC Q6 — singular 'binding' kept for legacy webhook /
|
||||
// GDPR readers; plural 'bindings' carries every binding on
|
||||
// the field with id, merge_strategy, trust_level,
|
||||
// is_identity_key for PersonProvisioner / BindingConflictResolver
|
||||
// / FormBindingApplicator. Single helper to avoid duplicated
|
||||
// dynamic-property access inside this lambda.
|
||||
...$this->bindingService->snapshotShapesFor($f->bindings),
|
||||
'conditional_logic' => $this->conditionalLogicService->toJsonShape($f->rootConditionalLogicGroup()),
|
||||
'translations' => $this->stripOptionsFromTranslations($f->translations),
|
||||
'value_storage_hint' => $f->value_storage_hint instanceof \BackedEnum ? $f->value_storage_hint->value : $f->value_storage_hint,
|
||||
|
||||
Reference in New Issue
Block a user