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 samePOST /packages/:id/publish-drafts handler whose seedApplied field #8443 just fixed:
// ~line 537 — the ADR-0045 visibility flip(resultasany).unhideError=e?.message??'visibility flip failed';// ~line 568 — the 'metadata:reloaded' announce(resultasany).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 calls getMetaItems and saveMetaItem per unpublished app — a sys_metadata outage arrives there as a bare driver Error;rebindError's block calls announceKernelEvent, 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.
⚠️ One thing to measure rather than assume, because it decided the shape of both #8333 and #8443: whether either catch also receives an authored population that declares nothing and would be blanked by the withhold. 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
Found by the dev on #8443 while converting that route's
seedApplieddisclosure. 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 samePOST /packages/:id/publish-draftshandler whoseseedAppliedfield #8443 just fixed: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
trywraps 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: falsewith no PR is a legitimate deliverable if either turns out unreachable.Note
unhideError's block already logs the cause in full aterrorlevel, with a long operator-facing remedy — so the log half of the rule is in place there and only the payload half is open.rebindErrorhas 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:
clientFacingFailureTextfrom@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
seedAppliedfield on this same response) · #8333 · #8136 · #8086Generated by Claude Code