feat(form-builder): add BindingConflictResolver per RFC Q7 (WS-6)

Resolves bindings within a submission to one winner per (target_entity,
target_attribute) group. Candidate set = form_values rows present
(absence excludes; null value is explicit clear and IS a candidate).
Trust-precedence with sort_order tie-break. Section-filtering for
RFC Q10 stub future-readiness.

Pure-logic resolver — no DB writes, only reads form_values for the
candidate gate. Works against the 'bindings' (plural) snapshot key
introduced alongside PersonProvisioner.

Refs: RFC-WS-6.md §3 (Q7, Q10)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-26 12:48:11 +02:00
parent d257d64925
commit 47265e9d4f
3 changed files with 419 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Providers;
use App\FormBuilder\Bindings\BindingConflictResolver;
use App\FormBuilder\Bindings\BindingTypeRegistry;
use App\FormBuilder\Bindings\PersonProvisioner;
use App\FormBuilder\Purposes\PurposeRegistry;
@@ -92,6 +93,7 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton(PurposeRegistry::class);
$this->app->singleton(BindingTypeRegistry::class);
$this->app->singleton(PersonProvisioner::class);
$this->app->singleton(BindingConflictResolver::class);
// Telescope is a dev-only debugging dashboard. Three-layer
// defense keeps it out of production: composer `dont-discover`