diff --git a/api/app/Exceptions/FormBuilder/FieldValidationException.php b/api/app/Exceptions/FormBuilder/FieldValidationException.php new file mode 100644 index 00000000..a0125506 --- /dev/null +++ b/api/app/Exceptions/FormBuilder/FieldValidationException.php @@ -0,0 +1,23 @@ +> $fieldErrors + */ + public function __construct(array $fieldErrors, string $message = 'The submitted values failed validation.') + { + parent::__construct('VALIDATION_FAILED', 422, $message); + $this->fieldErrors = $fieldErrors; + } +} diff --git a/api/app/Exceptions/FormBuilder/PublicFormApiException.php b/api/app/Exceptions/FormBuilder/PublicFormApiException.php new file mode 100644 index 00000000..45e59605 --- /dev/null +++ b/api/app/Exceptions/FormBuilder/PublicFormApiException.php @@ -0,0 +1,33 @@ +>|null */ + public ?array $fieldErrors = null; + + /** @var array */ + public array $headers = []; + + public function __construct( + public readonly string $publicCode, + public readonly int $status, + string $message, + ) { + parent::__construct($message); + } +} diff --git a/api/app/Exceptions/FormBuilder/RateLimitedException.php b/api/app/Exceptions/FormBuilder/RateLimitedException.php new file mode 100644 index 00000000..9d0bf025 --- /dev/null +++ b/api/app/Exceptions/FormBuilder/RateLimitedException.php @@ -0,0 +1,14 @@ +headers['Retry-After'] = (string) max($retryAfterSeconds, 0); + } +} diff --git a/api/app/Exceptions/FormBuilder/SchemaNotFoundException.php b/api/app/Exceptions/FormBuilder/SchemaNotFoundException.php new file mode 100644 index 00000000..31e669be --- /dev/null +++ b/api/app/Exceptions/FormBuilder/SchemaNotFoundException.php @@ -0,0 +1,13 @@ +withExceptions(function (Exceptions $exceptions): void { + // Public Form Builder standardised error envelope (S2c D6). + $exceptions->render(function (\App\Exceptions\FormBuilder\PublicFormApiException $e, Request $request) { + $body = [ + 'message' => $e->getMessage(), + 'code' => $e->publicCode, + ]; + if ($e->fieldErrors !== null) { + $body['errors'] = $e->fieldErrors; + } + + return response()->json($body, $e->status, $e->headers); + }); + // Database connection / query errors → 503 $exceptions->render(function (QueryException|PDOException $e, Request $request) { if ($request->expectsJson() || $request->is('api/*')) {