Skip to content

Commit 6d399e7

Browse files
committed
fix(rest): throw the version-token refusal into the route's catch, the envelope the protocol's own refusal gets
Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
1 parent b763612 commit 6d399e7

1 file changed

Lines changed: 19 additions & 26 deletions

File tree

‎packages/rest/src/rest-server.ts‎

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,10 +1762,16 @@ function sendMetaItemAbsent(res: any): void {
17621762
* unguarded too.
17631763
*
17641764
* Returns the refusal's sentence, or `undefined` when the token is absent or
1765-
* judged. The runtime dispatcher's `/data` domain carries this function
1766-
* statement for statement (`versionTokenRefusal` in
1767-
* `packages/runtime/src/domains/data.ts`), so the two doors answer every token
1768-
* alike; `data-update-expected-version.test.ts` and
1765+
* judged. Both doors build the refusal with the one constructor,
1766+
* `validationFailure(sentence, [])` (`@objectstack/types`), and render it with
1767+
* their own classifier: this file THROWS it into the route's catch
1768+
* (`mapDataError`, the envelope the protocol's `""` refusal gets here), and the
1769+
* dispatcher hands it to `deps.errorFromThrown` and RETURNS the answer (a throw
1770+
* out of `dispatch()` reaches a `createHonoApp` host's catch-all, which reads
1771+
* only `statusCode` and would answer `500`). The runtime dispatcher's `/data`
1772+
* domain carries this function statement for statement (`versionTokenRefusal`
1773+
* in `packages/runtime/src/domains/data.ts`), so the two doors answer every
1774+
* token alike; `data-update-expected-version.test.ts` and
17691775
* `data-delete-expected-version.test.ts` hold them to it.
17701776
*/
17711777
function versionTokenRefusal(token: unknown, spelling: string): string | undefined {
@@ -9118,20 +9124,15 @@ export class RestServer {
91189124
// [#23492] A token that can never carry a version is
91199125
// refused here, before anything is asked, and every
91209126
// other present token is forwarded below: no token the
9121-
// caller sent is read as "no token".
9127+
// caller sent is read as "no token". THROWN as
9128+
// `validationFailure`, so this route's catch answers it
9129+
// through `mapDataError`, in the envelope it already
9130+
// gives the protocol's own refusal of `""`.
91229131
const versionRefusal = versionTokenRefusal(
91239132
expectedVersion,
91249133
bodyVersion != null ? 'The body\'s `expectedVersion`' : 'The `If-Match` header',
91259134
);
9126-
if (versionRefusal) {
9127-
res.status(400).json({
9128-
error: versionRefusal,
9129-
code: 'VALIDATION_FAILED',
9130-
fields: [],
9131-
object: req.params?.object,
9132-
});
9133-
return;
9134-
}
9135+
if (versionRefusal) throw validationFailure(versionRefusal, []);
91359136
if (await this.enforceApiAccess(req, res, p, environmentId, 'update')) return;
91369137
// [#3899] Same gate as create: the wire body is the bare
91379138
// field patch (`expectedVersion` already stripped above),
@@ -9207,22 +9208,14 @@ export class RestServer {
92079208
? (req.query as any).expectedVersion
92089209
: undefined;
92099210
const expectedVersion = queryVersion ?? ifMatchHeader;
9210-
// [#23492] The `PATCH` above's rule: a token that can
9211-
// never carry a version is refused, every other present
9212-
// token is forwarded.
9211+
// [#23492] The `PATCH` above's rule, thrown the same
9212+
// way: a token that can never carry a version is
9213+
// refused, every other present token is forwarded.
92139214
const versionRefusal = versionTokenRefusal(
92149215
expectedVersion,
92159216
queryVersion != null ? 'The `expectedVersion` query parameter' : 'The `If-Match` header',
92169217
);
9217-
if (versionRefusal) {
9218-
res.status(400).json({
9219-
error: versionRefusal,
9220-
code: 'VALIDATION_FAILED',
9221-
fields: [],
9222-
object: req.params?.object,
9223-
});
9224-
return;
9225-
}
9218+
if (versionRefusal) throw validationFailure(versionRefusal, []);
92269219
if (await this.enforceApiAccess(req, res, p, environmentId, 'delete')) return;
92279220
const deleteRequest: ServerScopedDataRequest<DeleteDataRequest> = {
92289221
object: req.params.object,

0 commit comments

Comments
 (0)