Skip to content

Commit 19db5fa

Browse files
qq9340100claude
andauthored
fix(runtime): stop publish-drafts disclosing driver and subscriber text on unhideError and rebindError (#8816)
* fix(runtime): withhold undeclared driver/subscriber text from publish-drafts' unhideError and rebindError (#8516) * docs(changeset): #8516 * test(runtime): re-spell the three publish-drafts flip pins for the ADR-0112 withhold (#8516) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a495ad5 commit 19db5fa

4 files changed

Lines changed: 496 additions & 5 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
"@objectstack/runtime": patch
3+
---
4+
5+
fix(runtime): `publish-drafts` no longer discloses driver or subscriber text on `unhideError` / `rebindError` (#8516)
6+
7+
`POST /api/v1/packages/:id/publish-drafts` answered, on a **200**:
8+
9+
```json
10+
{ "success": true, "data": {
11+
"unhideError": "SQLITE_ERROR: no such table: sys_metadata",
12+
"rebindError": "TypeError: Cannot read properties of undefined (reading 'triggers') at AutomationPlugin.rebind (/srv/objectstack/packages/services/service-automation/dist/index.js:412:31)" } }
13+
```
14+
15+
These are the two remaining producers on the response whose `seedApplied` field
16+
#8443 converted — the ADR-0045 visibility flip and the `metadata:reloaded`
17+
announce. Both ride a success body as **data**, so no HTTP boundary's 5xx
18+
message withhold can reach them; the disclosure had to be closed at the
19+
producer. Both were driven for real before being changed, and both reproduced.
20+
21+
Both now follow the rule already in force next door: a caught sentence is
22+
quoted only when the error **declared** itself a client-facing refusal (4xx
23+
`status`, ADR-0112); anything else gets the stable sentence the field could
24+
already carry, and the original goes to the server log. The rule is imported
25+
from `@objectstack/metadata-protocol` (`clientFacingFailureText`), not restated
26+
locally.
27+
28+
**Both halves of the rule, because the two sites started in different states.**
29+
The flip already logged its cause in full at `error` with an operator remedy, so
30+
only its payload changed. The announce had **no log line at all** — withholding
31+
alone would have converted an over-disclosure into a silent failure, so it gains
32+
one at `warn`, naming the cause, the concrete consequence (a newly published
33+
record-triggered flow does not bind its trigger until the process restarts) and
34+
the fix (re-run the idempotent publish, or restart). `warn` rather than `error`
35+
because nothing that claimed to persist failed to: the drafts are published and
36+
the flip is stored, and an unbound trigger is AGENTS.md's own worked example of
37+
a functional degradation — the level the sibling announce of this same event
38+
already uses.
39+
40+
**Authoring feedback is preserved, not blanked.** The flip's authored refusals
41+
all declare 4xx (`ITEM_LOCKED`, `NOT_OVERRIDABLE`,
42+
`OBJECT_OVERLAY_PACKAGE_MISMATCH`, …), so a locked or non-overridable app still
43+
tells its publisher which app and why, verbatim — and the `unhiddenApps`
44+
half-flip report beside it is untouched. A subscriber that declares a 4xx
45+
refusal is quoted by the same positive list.

0 commit comments

Comments
 (0)