Skip to content

Commit ef2a44d

Browse files
razor-xclaudeseambot
authored
Do not document undocumented APIs (#1266)
* fix: strip internal x-undocumented fields from Mintlify OpenAPI spec The transform pipeline only filtered operation-level x-undocumented, removing whole undocumented paths. Schema-level markers leaked through: the internal `sync` field (tagged `x-undocumented: "Only used internally."`) shipped into the published spec as both a request-body property and a query parameter on delete endpoints. Add a recursive pass over the whole spec that removes any property or parameter bearing x-undocumented (and drops it from sibling `required`), covering request bodies, parameters, and response schemas across all HTTP methods -- not just the `post` operations the existing loop touches. Policy for x-draft: keep the annotated node, consistent with the existing operation-level policy of keeping x-draft paths in the navigation, but strip the x-draft marker key so internal notes ("Early access.", "Needs review.") do not ship. No downstream code reads either marker. Verified against the current generated openapi.json: 88 x-undocumented and 18 x-draft markers reduced to 0, the internal `sync` field removed from both bodies and params, and unmarked siblings preserved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5RzvZ86DxrMzBKyhhEDaW * ci: Generate docs --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Seam Bot <seambot@getseam.com>
1 parent 7909baa commit ef2a44d

3 files changed

Lines changed: 86 additions & 1034 deletions

File tree

mintlify-codegen/lib/report.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export const report: Metalsmith.Plugin = (_files, metalsmith) => {
1010

1111
console.log(`\nDone!`)
1212
console.log(` Removed undocumented paths: ${stats.removedPaths}`)
13+
console.log(
14+
` Removed undocumented fields/params: ${stats.removedInternalFields}`,
15+
)
1316
console.log(` Total documented endpoints: ${stats.totalEndpoints}`)
1417
console.log(` With code samples: ${stats.withCodeSamples}`)
1518
console.log(` With scoped action_attempts: ${stats.withActionAttempts}`)

mintlify-codegen/lib/transform-spec.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,66 @@ function rewriteAllDescriptions(obj: any): void {
273273
}
274274
}
275275

276+
/**
277+
* Recursively strip internal-only and preview markers from schema fragments.
278+
*
279+
* transformSpec() removes whole operations flagged `x-undocumented`, but the
280+
* marker also appears on individual request parameters, request-body
281+
* properties, and response properties (e.g. the internal `sync` field, tagged
282+
* `x-undocumented: "Only used internally."`). Those leak into the published
283+
* spec unless stripped here.
284+
*
285+
* Policy, mirroring the operation-level handling above:
286+
* - `x-undocumented` — internal-only. Remove the annotated property or
287+
* parameter outright, and drop it from any sibling `required` list.
288+
* - `x-draft` — early-access/preview. Keep the annotated node (consistent
289+
* with keeping x-draft paths in the navigation), but delete the marker key
290+
* so its internal note ("Early access.", "Needs review.") does not ship.
291+
*/
292+
function stripInternalSchemaFragments(obj: any, stats: TransformStats): void {
293+
if (obj == null || typeof obj !== 'object') return
294+
295+
if (Array.isArray(obj)) {
296+
for (const item of obj) stripInternalSchemaFragments(item, stats)
297+
return
298+
}
299+
300+
// Drop object-schema properties flagged x-undocumented. Check before
301+
// recursing, since recursion deletes the marker from surviving nodes.
302+
if (obj.properties != null && typeof obj.properties === 'object') {
303+
for (const [name, propSchema] of Object.entries(obj.properties) as any) {
304+
if (propSchema?.['x-undocumented'] != null) {
305+
delete obj.properties[name]
306+
if (Array.isArray(obj.required)) {
307+
obj.required = obj.required.filter((r: string) => r !== name)
308+
if (obj.required.length === 0) delete obj.required
309+
}
310+
stats.removedInternalFields++
311+
}
312+
}
313+
}
314+
315+
// Drop operation parameters flagged x-undocumented. The marker can sit on the
316+
// parameter object itself or on its nested schema.
317+
if (Array.isArray(obj.parameters)) {
318+
const before = obj.parameters.length
319+
obj.parameters = obj.parameters.filter(
320+
(param: any) =>
321+
param?.['x-undocumented'] == null &&
322+
param?.schema?.['x-undocumented'] == null,
323+
)
324+
stats.removedInternalFields += before - obj.parameters.length
325+
}
326+
327+
// Recurse into whatever remains, then drop residual markers on this node.
328+
for (const value of Object.values(obj)) {
329+
stripInternalSchemaFragments(value, stats)
330+
}
331+
332+
delete obj['x-undocumented']
333+
delete obj['x-draft']
334+
}
335+
276336
/**
277337
* Truncate a description to the first paragraph or ~500 chars.
278338
* Avoids cutting inside markdown links, which would produce broken
@@ -353,6 +413,7 @@ export function transformSpec(
353413
withActionAttempts: 0,
354414
withoutCodeSamples: [] as string[],
355415
removedPaths: 0,
416+
removedInternalFields: 0,
356417
}
357418

358419
// Remove only undocumented paths to reduce spec size
@@ -485,6 +546,11 @@ export function transformSpec(
485546
// Transform component schemas
486547
transformComponents(spec)
487548

549+
// Strip internal-only ("x-undocumented") properties and parameters that the
550+
// operation-level path filter above does not reach (e.g. the internal `sync`
551+
// field), and drop preview ("x-draft") markers from surviving nodes.
552+
stripInternalSchemaFragments(spec, stats)
553+
488554
// Recursively rewrite all description fields in the entire spec.
489555
// This catches deeply nested descriptions that the per-operation and
490556
// per-component passes above don't reach (e.g., parameter descriptions,
@@ -571,4 +637,5 @@ export interface TransformStats {
571637
withActionAttempts: number
572638
withoutCodeSamples: string[]
573639
removedPaths: number
640+
removedInternalFields: number
574641
}

0 commit comments

Comments
 (0)