feat(form-builder): schema drift detection + PUT auto_save_count
S2c D5 completion: schema_version_at_open column + drift semantics. - Migration 2026_04_22_100002 adds unsignedInteger schema_version_at_open. Recorded by FormSubmissionService::createDraft at the moment the portal first renders the form. - PublicFormSubmissionResource.schema_drift now compares schema_version_at_open vs schema_version_at_submit (or schema.version for active drafts) so organiser edits during an open draft surface as drift on subsequent PUT/submit responses. - PublicFormSubmissionController::update routes through FormSubmissionService::saveDraft so auto_save_count increments and the FormSubmissionDraftUpdated event fires per PUT. - bootstrap/app.php: FormRequest ValidationException on /api/v1/public/forms/* is now re-wrapped into the D6 envelope with code=VALIDATION_FAILED, so public endpoints emit one consistent error shape regardless of layer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,21 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
return response()->json($body, $e->status, $e->headers);
|
||||
});
|
||||
|
||||
// FormRequest validation on /api/v1/public/forms/* → rewrap into
|
||||
// the D6 envelope so every public endpoint error looks identical
|
||||
// regardless of which layer surfaced it.
|
||||
$exceptions->render(function (ValidationException $e, Request $request) {
|
||||
if (! $request->is('api/v1/public/forms/*')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => $e->getMessage(),
|
||||
'code' => 'VALIDATION_FAILED',
|
||||
'errors' => $e->errors(),
|
||||
], $e->status);
|
||||
});
|
||||
|
||||
// Database connection / query errors → 503
|
||||
$exceptions->render(function (QueryException|PDOException $e, Request $request) {
|
||||
if ($request->expectsJson() || $request->is('api/*')) {
|
||||
|
||||
Reference in New Issue
Block a user