|
1 | 1 | # @objectstack/example-showcase |
2 | 2 |
|
| 3 | +## 0.3.14-rc.6 |
| 4 | + |
| 5 | +### Patch Changes |
| 6 | + |
| 7 | +- 284e7d2: fix(rest): a crashing hook body answers the sanitised fault envelope, not a raw `TypeError` at 400 (#7543) |
| 8 | + |
| 9 | + `POST /api/v1/data/showcase_task` with `{"title": 12345}` answered |
| 10 | + |
| 11 | + ``` |
| 12 | + 400 { "error": "TypeError: not a function", "object": "showcase_task" } |
| 13 | + ``` |
| 14 | + |
| 15 | + — a JS runtime error as the client-facing message, in a body with no `code` at |
| 16 | + all. Two contract breaks in one response: an internal fault echoed verbatim to a |
| 17 | + caller, and an error body outside the ledgered envelope, so a client keying on |
| 18 | + `code` got nothing. |
| 19 | + |
| 20 | + **The seam.** `mapDataError` has two sandbox-unwrap branches, and they are the |
| 21 | + only ones in the file that emit `{ error, object }` with no `code` at 400. They |
| 22 | + exist for one shape: a hook or action body that runs |
| 23 | + `throw new Error('删除被阻断:仍有未结清的发票')` — an author writing a business |
| 24 | + rule whose message _is_ the remedy, which is answered verbatim at 400 and |
| 25 | + deliberately without a `code`. A body that instead **crashes** arrives as a |
| 26 | + thrown error too, so it took the same branch and its `TypeError` went out as if |
| 27 | + it were that author's message. |
| 28 | + |
| 29 | + **The fix.** Both branches now separate a body that _reported_ something from a |
| 30 | + body that _faulted_, by the thrown error's constructor name — the sandbox |
| 31 | + stringifies a throw as `<name>: <message>`, so a leading `TypeError:`, |
| 32 | + `ReferenceError:`, `RangeError:`, `SyntaxError:`, `URIError:`, `EvalError:`, |
| 33 | + `InternalError:` or `AggregateError:` is structural evidence of a crash rather |
| 34 | + than a keyword heuristic over prose. A crash answers the same sanitised |
| 35 | + `500 INTERNAL_ERROR` the mapper's terminal branch already gives — which is not |
| 36 | + new policy: that branch's own contract (#5489) names this exact case ("a plain |
| 37 | + handler bug (`TypeError: x is not a function`) … server faults that a caller |
| 38 | + cannot fix and a caller SHOULD retry"). The unwraps simply sat above it and |
| 39 | + intercepted the crash first. |
| 40 | + |
| 41 | + Both doors are guarded, not one. The `innerMessage` branch and the raw-message |
| 42 | + regex fallback produce byte-identical bodies, so classifying in only one would |
| 43 | + make the envelope depend on whether the `SandboxError` instance survived a |
| 44 | + rethrow. |
| 45 | + |
| 46 | + **Unchanged:** a deliberate refusal still reaches the caller verbatim at 400 |
| 47 | + with no `code`. The fix changes _which_ errors take that branch, not what it |
| 48 | + emits. A body that expresses a business rule as `throw new RangeError('…')` is |
| 49 | + now sanitised — an accepted cost, since that is not the documented authoring |
| 50 | + style and the fail-safe direction is the one that does not ship runtime faults to |
| 51 | + clients. The operator still gets the full text: 500 is outside |
| 52 | + `isExpectedDataStatus`, so `handleRouteError` logs `[REST] Unhandled error` with |
| 53 | + the whole error. |
| 54 | + |
| 55 | + **Showcase.** `NormalizeTaskTitleHook` guarded its trim with truthiness |
| 56 | + (`if (ctx.input.title)`), so the number `12345` passed the guard and had no |
| 57 | + `.trim`. It now checks `typeof … === 'string'`. That is the actual cause of the |
| 58 | + reported repro, and with it fixed the request **succeeds** rather than erroring: |
| 59 | + `record-validator` coerces a `text` value with `String(value)`, so a number in a |
| 60 | + text field breaks no declared contract. These hook bodies are read as |
| 61 | + documentation, so the type-safe shape is the one to show — a hook must not assume |
| 62 | + a field's runtime type just because its metadata declares one. |
| 63 | + |
| 64 | +- Updated dependencies [5823d59] |
| 65 | +- Updated dependencies [76d74ec] |
| 66 | +- Updated dependencies [86f7a20] |
| 67 | +- Updated dependencies [c546c89] |
| 68 | +- Updated dependencies [22df871] |
| 69 | +- Updated dependencies [9c82146] |
| 70 | +- Updated dependencies [744b8f5] |
| 71 | +- Updated dependencies [2c1988c] |
| 72 | +- Updated dependencies [211abdb] |
| 73 | +- Updated dependencies [b3de0dd] |
| 74 | +- Updated dependencies [35b36f2] |
| 75 | +- Updated dependencies [f505689] |
| 76 | +- Updated dependencies [08363a0] |
| 77 | +- Updated dependencies [6a9dec6] |
| 78 | +- Updated dependencies [baeb4f0] |
| 79 | +- Updated dependencies [199ec47] |
| 80 | +- Updated dependencies [08cd163] |
| 81 | +- Updated dependencies [7674859] |
| 82 | +- Updated dependencies [7a8476f] |
| 83 | +- Updated dependencies [518ca7a] |
| 84 | +- Updated dependencies [d063a96] |
| 85 | +- Updated dependencies [cf7c694] |
| 86 | +- Updated dependencies [603cab8] |
| 87 | +- Updated dependencies [591f675] |
| 88 | +- Updated dependencies [9051802] |
| 89 | +- Updated dependencies [2f8328c] |
| 90 | +- Updated dependencies [f293d45] |
| 91 | +- Updated dependencies [f067930] |
| 92 | +- Updated dependencies [97ace2a] |
| 93 | +- Updated dependencies [8f1851e] |
| 94 | +- Updated dependencies [61ea810] |
| 95 | +- Updated dependencies [66d99ec] |
| 96 | +- Updated dependencies [91eddca] |
| 97 | +- Updated dependencies [b61afc1] |
| 98 | +- Updated dependencies [97b6658] |
| 99 | +- Updated dependencies [814db6d] |
| 100 | +- Updated dependencies [8dd98bf] |
| 101 | +- Updated dependencies [8a9c079] |
| 102 | +- Updated dependencies [cc3555e] |
| 103 | +- Updated dependencies [ea936f3] |
| 104 | +- Updated dependencies [69ac82c] |
| 105 | +- Updated dependencies [c6a4eeb] |
| 106 | +- Updated dependencies [e124711] |
| 107 | +- Updated dependencies [f1544e2] |
| 108 | +- Updated dependencies [9d4dfc4] |
| 109 | +- Updated dependencies [1059965] |
| 110 | +- Updated dependencies [60b672e] |
| 111 | +- Updated dependencies [e654bfd] |
| 112 | +- Updated dependencies [c9b809f] |
| 113 | + - @objectstack/spec@17.0.0-rc.7 |
| 114 | + - @objectstack/runtime@17.0.0-rc.7 |
| 115 | + - @objectstack/service-datasource@17.0.0-rc.7 |
| 116 | + - @objectstack/driver-sql@17.0.0-rc.7 |
| 117 | + - @objectstack/cloud-connection@17.0.0-rc.7 |
| 118 | + - @objectstack/connector-mcp@17.0.0-rc.7 |
| 119 | + - @objectstack/connector-openapi@17.0.0-rc.7 |
| 120 | + - @objectstack/connector-rest@17.0.0-rc.7 |
| 121 | + - @objectstack/connector-slack@17.0.0-rc.7 |
| 122 | + |
3 | 123 | ## 0.3.14-rc.5 |
4 | 124 |
|
5 | 125 | ### Patch Changes |
|
0 commit comments