Repository navigation
publish-drafts has two more undeclared-driver-text fields on the same 200 body: unhideError and rebindError #8516
Description
Found by the dev on #8443 while converting that route's seedApplied disclosure. Unassigned; nobody is on it. Deliberately left out of #8443's PR: those are different producers on the same response, and the card that names them should get the same reproduce-first treatment #8443 was held to, rather than riding along unmeasured.
The sites
Both in packages/runtime/src/domains/packages.ts, inside the same POST /packages/:id/publish-drafts handler whose seedApplied field #8443 just fixed:
// ~line 537 — the ADR-0045 visibility flip
(result as any).unhideError = e?.message ?? 'visibility flip failed';
// ~line 568 — the 'metadata:reloaded' announce
(result as any).rebindError = e?.message ?? 'metadata:reloaded announce failed';Both ride the same 200 publish response as data, in the same object as seedApplied, so the same argument applies verbatim: no HTTP boundary's 5xx message withhold can reach a field on a success body, and the disclosure can only be closed at the producer.
What each try wraps goes at the metadata store / the kernel bus:
unhideError's block callsgetMetaItemsandsaveMetaItemper unpublished app — asys_metadataoutage arrives there as a bare driverError;rebindError's block callsannounceKernelEvent, so whatever a subscriber throws is quoted verbatim to the caller.
The contract being violated is the same one: ADR-0112 — a caught error's sentence may be quoted to a caller only when that error declared itself a client-facing refusal (4xx status); anything undeclared is withheld and the original goes to the log.
Status of the evidence
Read from source, NOT reproduced end to end — the same honest state #8443 was filed in. They were found by grepping the runtime for the string shape #8443's site used, after that site was fixed. Whoever takes it should drive a real failure through each of the two blocks and record the actual 200 body first; premise_still_valid: false with no PR is a legitimate deliverable if either turns out unreachable.
Note unhideError's block already logs the cause in full at error level, with a long operator-facing remedy — so the log half of the rule is in place there and only the payload half is open. rebindError has no such log line; withholding without adding one would lose the diagnosis entirely.
The fix, if the premise holds
The rule now has one implementation and it is exported: clientFacingFailureText from @objectstack/metadata-protocol (exported by #8443's PR, which is also where the runtime-side precedent for calling it lives). Nothing new needs designing — quote only what declared 4xx, log the rest.
saveMetaItem's refusals do declare 4xx today; a subscriber's throw on the announce path declares nothing at all, and its message may or may not be worth anything to a caller.
Related
#8443 (the seedApplied field on this same response) · #8333 · #8136 · #8086
Generated by Claude Code
Activity
hotlong commentedon Aug 14, 2026
First-touch grade: promoted to
pm:queue. Premise re-verified onorigin/mainthis round:(result as any).unhideError = e?.message …is now atpackages/runtime/src/domains/packages.ts:544andrebindErrorat :575 — both still quote raw driver/subscriber text onto the 200 publish body — andclientFacingFailureTextis exported from@objectstack/metadata-protocol(protocol.ts:1681, re-exported inindex.ts), so the rule the card names is consumable. A concrete violation of the declared ADR-0112 contract with a named landing and a reproduce-first instruction already on the card ⇒ queue; nothing to ask.Notes for the claiming dev: line numbers drifted from the card's ~537/~568 (now 544/575); the card's reproduce-first requirement and the authored-population measurement (
rebindError's subscriber throws declare nothing) stand as written;rebindErrorhas no log line today, so the withhold must add one or the diagnosis is lost.本评论来自分诊座位 Routine。
Generated by Claude Code
fix(runtime): stop publish-drafts disclosing driver and subscriber te…