Skip to content

Commit 860ca38

Browse files
committed
docs(forms): the submit's 403 row names the refusals that answer it, not a profile
The error table said `403 PERMISSION_DENIED` means "the resolved profile does not allow create on the target object". No permission set admits or refuses the public submit's create. Measured through the real route, it answers 403 when the security layer fails closed (permission sets or the object's security posture cannot be resolved), when a write under the submission's context leaves the grant (an afterInsert hook writing another object through ctx.api), or when a code-registered hook throws a 403 refusal; a declarative hook's throw answers 400. Text only; no behaviour changes. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QyoWKK9RwUNxBxmevy9Neb
1 parent 91ca7f3 commit 860ca38

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎content/docs/ui/forms.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ Errors:
222222
| `400 INVALID_REQUEST` | missing / blank slug (an empty body is coerced to `{}` and surfaces as `VALIDATION_FAILED` below, not here) |
223223
| `400 VALIDATION_ERROR` | the form's sections declare **no** fields, so it collects nothing — wire the fields and resubmit (#6920) |
224224
| `400 VALIDATION_FAILED` | object schema validators fail (`required`, `format`, `length`, …) |
225-
| `403 PERMISSION_DENIED` | the resolved profile does not allow create on the target object |
225+
| `403 PERMISSION_DENIED` | never a permission set refusing the create (section 2). It answers when the security layer fails closed: the permission sets for the submission could not be resolved ("permission subsystem unavailable"), or the target object's security posture could not be resolved. It also answers when a write made under the submission's context leaves the grant, such as an `afterInsert` hook writing a **different** object through `ctx.api` (the grant covers only the form's object), or when a hook registered in code throws a `403` refusal of its own (`PermissionDeniedError`). A declarative hook's `throw` answers `400`, not `403`. |
226226
| `404 FORM_NOT_FOUND` | slug not registered on any view whose form has `sharing.enabled: true` and `sharing.allowAnonymous: true` |
227227
| `5xx` (generic) | driver / hook threw — submit errors are mapped by `mapDataError`; there is no dedicated `FORM_SUBMIT_FAILED` code |
228228

0 commit comments

Comments
 (0)