Follow-up from the docs pass for #1923 (documentation#605).
Problem
@hidden / hidden: true is documented as the way to keep a field out of the MCP tool descriptors and the OpenAPI document — the latter matters because /openapi.json has no per-user filtering, so anything reaching it is visible to anyone who can hit the HTTP port. That suppression is implemented only at the top level:
MCP — attributeVisible is consulted in the top-level loops (components/mcp/tools/schemas/derive.ts:166, :208, :319), but attributeToProperty recurses into attr.properties with no visibility check, so a hidden sub-property is emitted with its description.
OpenAPI — resources/openApi.ts:142 does if (hidden) continue; for top-level attributes only. The nested-object branch calls attributeToFragment, which does not suppress and instead emits the flag as a schema key:
// resources/jsonSchemaTypes.ts:119
if (attr.hidden) fragment.hidden = true;
So a hidden nested sub-property appears in the public OpenAPI document along with its description and a "hidden": true marker advertising that it was meant to be suppressed.
Why it matters
The docs tell authors to use @hidden for fields that should not surface publicly ("don't put secrets, internal-only commentary, or speculative prose in docstrings; use @hidden to suppress"). For a nested field that guidance currently does not hold. This is narrow — it needs a nested object whose sub-field is marked hidden — but the failure is silent and in the direction of disclosure.
Note the exposure is bounded: table-backed GraphQL nested types usually take the $ref branch in openApi.ts, so this mainly affects programmatic static properties objects and any table path that reaches the attr.properties branch.
Suggested fix
- Filter in the recursion: skip
hidden sub-attributes in attributeToProperty (derive.ts) and in attributeToFragment's properties loop (jsonSchemaTypes.ts), rather than only in the top-level loops.
- Stop emitting
hidden as a JSON Schema key at all — it is a Harper directive, not JSON Schema vocabulary, and it does not belong in an output document. (Check consumers first: Table.properties round-trips through fragmentToAttribute, which reads it back, so the key may need to stay in the canonical projection while being stripped on the MCP/OpenAPI emit paths.)
- Add unit coverage for a hidden sub-property on both surfaces — the existing tests only assert top-level suppression.
Once fixed, the "top-level only" caveats in reference/resources/resource-api.md need to come back out.
Issue generated by kAIle (Claude Opus 4.8).
Follow-up from the docs pass for #1923 (documentation#605).
Problem
@hidden/hidden: trueis documented as the way to keep a field out of the MCP tool descriptors and the OpenAPI document — the latter matters because/openapi.jsonhas no per-user filtering, so anything reaching it is visible to anyone who can hit the HTTP port. That suppression is implemented only at the top level:MCP —
attributeVisibleis consulted in the top-level loops (components/mcp/tools/schemas/derive.ts:166,:208,:319), butattributeToPropertyrecurses intoattr.propertieswith no visibility check, so a hidden sub-property is emitted with itsdescription.OpenAPI —
resources/openApi.ts:142doesif (hidden) continue;for top-level attributes only. The nested-object branch callsattributeToFragment, which does not suppress and instead emits the flag as a schema key:So a hidden nested sub-property appears in the public OpenAPI document along with its description and a
"hidden": truemarker advertising that it was meant to be suppressed.Why it matters
The docs tell authors to use
@hiddenfor fields that should not surface publicly ("don't put secrets, internal-only commentary, or speculative prose in docstrings; use@hiddento suppress"). For a nested field that guidance currently does not hold. This is narrow — it needs a nested object whose sub-field is marked hidden — but the failure is silent and in the direction of disclosure.Note the exposure is bounded: table-backed GraphQL nested types usually take the
$refbranch inopenApi.ts, so this mainly affects programmaticstatic propertiesobjects and any table path that reaches theattr.propertiesbranch.Suggested fix
hiddensub-attributes inattributeToProperty(derive.ts) and inattributeToFragment'spropertiesloop (jsonSchemaTypes.ts), rather than only in the top-level loops.hiddenas a JSON Schema key at all — it is a Harper directive, not JSON Schema vocabulary, and it does not belong in an output document. (Check consumers first:Table.propertiesround-trips throughfragmentToAttribute, which reads it back, so the key may need to stay in the canonical projection while being stripped on the MCP/OpenAPI emit paths.)Once fixed, the "top-level only" caveats in
reference/resources/resource-api.mdneed to come back out.Issue generated by kAIle (Claude Opus 4.8).