Kibana version
OpenAPI spec digest 25fd084766fe43b01ec0db0eccde55ad80542799 (current main as of 2026-05-28).
Last known good: 16a5962f072868f5dde786a2dab91de2c23f068d (parent of the offending commit).
Summary
Commit f8da12e93c73 ("[Fleet] Add meta:{id} to fleet schemas", PR #270560) added meta: { id: ... } annotations to a number of Fleet @kbn/config-schema definitions so they would be extracted as named OpenAPI components. During that extraction, three of the resulting components silently dropped fields that the same operations had exposed in the previous spec — and which are still read by the route handlers.
This appears to be a bug in the @kbn/config-schema → OpenAPI generator when meta: { id } is combined with .extends() (or otherwise composed) schemas: certain field shapes (nullable strings via oneOf([literal(null), string()]), arrays of strings, nested objects defined on a base schema) are dropped when the schema is flattened into the named component.
Affected components and missing fields
| Component |
Operation |
Missing properties |
Kibana_HTTP_APIs_simplified_create_package_policy_request |
POST /api/fleet/package_policies (simplified anyOf branch) |
output_id, policy_id, policy_ids, supports_agentless |
Kibana_HTTP_APIs_update_package_policy_request |
PUT /api/fleet/package_policies/{packagePolicyId} |
id |
Kibana_HTTP_APIs_package_policy_status_response |
POST /api/fleet/package_policies/delete (response item) |
output_id, policy_id, policy_ids, package |
For comparison, the other five Fleet schemas the same PR annotated (create_package_policy_request, package_policy_response, dry_run_package_policy, deprecation_info, package_policy_package) all extracted cleanly with their original property sets intact.
Evidence
Reproduce the diffs directly from the published specs:
PRE=16a5962f072868f5dde786a2dab91de2c23f068d
POST=f8da12e93c73
curl -sSf "https://raw.githubusercontent.com/elastic/kibana/$PRE/oas_docs/output/kibana.yaml" -o /tmp/pre.yaml
curl -sSf "https://raw.githubusercontent.com/elastic/kibana/$POST/oas_docs/output/kibana.yaml" -o /tmp/post.yaml
1. simplified_create_package_policy_request
Pre-PR, the simplified anyOf branch of POST /api/fleet/package_policies exposed all four fields:
$ awk '/post-fleet-package-policies$/,/responses:/' /tmp/pre.yaml \
| grep -cE '^ (output_id|policy_id|policy_ids|supports_agentless):$'
8 # = 4 fields × 2 anyOf branches
Post-PR, the named component drops them:
$ awk '/Kibana_HTTP_APIs_simplified_create_package_policy_request:/{f=1;next}
f && /^ Kibana_HTTP_APIs_/ {exit} f' /tmp/post.yaml \
| grep -E '^ (output_id|policy_id|policy_ids|supports_agentless):$'
# (no output)
The TypeScript definition in x-pack/platform/plugins/shared/fleet/common/types/models/package_policy_schema.ts still defines all four (e.g. output_id: schema.maybe(schema.oneOf([schema.literal(null), schema.string()])), supports_agentless: schema.maybe(schema.nullable(schema.boolean()))).
2. update_package_policy_request
Pre-PR PUT /api/fleet/package_policies/{packagePolicyId} body had an id property:
id:
description: Policy unique identifier.
type: string
Post-PR Kibana_HTTP_APIs_update_package_policy_request no longer has it (the field is defined on the base typed package_policy schema that update_package_policy extends).
3. package_policy_status_response
Pre-PR POST /api/fleet/package_policies/delete response items had:
body: { … }
id: { type: string }
name: { type: string }
output_id: { nullable: true, type: string }
package: { … nested object … }
policy_id: { deprecated: true, nullable: true, type: string }
policy_ids: { items: { type: string }, type: array }
statusCode: { type: number }
success: { type: boolean }
Post-PR Kibana_HTTP_APIs_package_policy_status_response has only body, id, name, statusCode, success — dropping output_id, policy_id, policy_ids, and the entire nested package object.
Pattern
The dropped fields share characteristics:
- nullable strings declared via
schema.oneOf([schema.literal(null), schema.string()]) — e.g. output_id, policy_id
- arrays of strings (
schema.arrayOf(schema.string())) — e.g. policy_ids
- nullable booleans via
schema.nullable(schema.boolean()) — e.g. supports_agentless
- nested objects inherited via
.extends() — e.g. package on the status response, id on update_package_policy_request
…all defined on a base schema that the now-meta.id-annotated schema extends. The generator appears to lose these fields when flattening base + extension into the named component.
Impact
Downstream OpenAPI-driven clients (e.g. the Terraform provider for Elastic Stack, which generates a Go client with oapi-codegen) lose the ability to set or read these fields:
simplified_create_package_policy_request — most painful. Users can no longer associate an integration policy with an agent policy (policy_ids) or override the output (output_id) on create via the simplified shape. The typed shape still exposes them, but switching shape requires converting mapped (map[string]input) inputs into typed ([]input with discriminators) inputs — a non-trivial rewrite. We have already had to add a FIXME and skip a regression test (TestOutputIdHandling/toAPIModel) in the provider until upstream is fixed.
update_package_policy_request — minor (id is normally taken from the URL path), but the generated client no longer exposes the field, which is observable in API contracts.
package_policy_status_response — bulk-delete response is less informative; callers can no longer learn the agent policy / output / package associated with the deleted policy.
Expected behaviour
The three affected named components should expose the same property sets the pre-PR inline schemas did. If any of these fields are intentionally being deprecated, please:
- Add explicit
deprecated: true (or x-deprecated/x-deprecated-reason) markers,
- Keep the non-deprecated alternatives (
policy_ids, output_id, supports_agentless, package) on the simplified / status schemas,
- And include a migration note.
If the root cause is the @kbn/config-schema → OpenAPI generator dropping fields on extends() + meta.id, then the fix is at the generator layer (and the same bug likely affects other plugins that adopt meta.id on extended schemas in the future).
Steps to reproduce
PRE=16a5962f072868f5dde786a2dab91de2c23f068d
POST=f8da12e93c73
curl -sSf "https://raw.githubusercontent.com/elastic/kibana/$PRE/oas_docs/output/kibana.yaml" -o /tmp/pre.yaml
curl -sSf "https://raw.githubusercontent.com/elastic/kibana/$POST/oas_docs/output/kibana.yaml" -o /tmp/post.yaml
# 1. simplified body
diff \
<(awk '/post-fleet-package-policies$/,/responses:/' /tmp/pre.yaml \
| grep -oE '(output_id|policy_id|policy_ids|supports_agentless)' | sort -u) \
<(awk '/Kibana_HTTP_APIs_simplified_create_package_policy_request:/{f=1;next}
f && /^ Kibana_HTTP_APIs_/ {exit} f' /tmp/post.yaml \
| grep -oE '(output_id|policy_id|policy_ids|supports_agentless)' | sort -u)
# 2. update body
diff \
<(awk '/put-fleet-package-policies-packagepolicyid/,/^ responses:/' /tmp/pre.yaml \
| grep -E '^ id:$') \
<(awk '/Kibana_HTTP_APIs_update_package_policy_request:/{f=1;next}
f && /^ Kibana_HTTP_APIs_/ {exit} f' /tmp/post.yaml \
| grep -E '^ id:$')
# 3. delete response item
diff \
<(awk '/post-fleet-package-policies-delete/,/post-fleet-package-policies-upgrade$/' /tmp/pre.yaml \
| grep -oE '(output_id|policy_id|policy_ids|package):' | sort -u) \
<(awk '/Kibana_HTTP_APIs_package_policy_status_response:/{f=1;next}
f && /^ Kibana_HTTP_APIs_/ {exit} f' /tmp/post.yaml \
| grep -oE '(output_id|policy_id|policy_ids|package):' | sort -u)
/cc @elastic/fleet
Kibana version
OpenAPI spec digest
25fd084766fe43b01ec0db0eccde55ad80542799(currentmainas of 2026-05-28).Last known good:
16a5962f072868f5dde786a2dab91de2c23f068d(parent of the offending commit).Summary
Commit
f8da12e93c73("[Fleet] Addmeta:{id}to fleet schemas", PR #270560) addedmeta: { id: ... }annotations to a number of Fleet@kbn/config-schemadefinitions so they would be extracted as named OpenAPI components. During that extraction, three of the resulting components silently dropped fields that the same operations had exposed in the previous spec — and which are still read by the route handlers.This appears to be a bug in the
@kbn/config-schema→ OpenAPI generator whenmeta: { id }is combined with.extends()(or otherwise composed) schemas: certain field shapes (nullable strings viaoneOf([literal(null), string()]), arrays of strings, nested objects defined on a base schema) are dropped when the schema is flattened into the named component.Affected components and missing fields
Kibana_HTTP_APIs_simplified_create_package_policy_requestPOST /api/fleet/package_policies(simplifiedanyOfbranch)output_id,policy_id,policy_ids,supports_agentlessKibana_HTTP_APIs_update_package_policy_requestPUT /api/fleet/package_policies/{packagePolicyId}idKibana_HTTP_APIs_package_policy_status_responsePOST /api/fleet/package_policies/delete(response item)output_id,policy_id,policy_ids,packageFor comparison, the other five Fleet schemas the same PR annotated (
create_package_policy_request,package_policy_response,dry_run_package_policy,deprecation_info,package_policy_package) all extracted cleanly with their original property sets intact.Evidence
Reproduce the diffs directly from the published specs:
1.
simplified_create_package_policy_requestPre-PR, the simplified
anyOfbranch ofPOST /api/fleet/package_policiesexposed all four fields:Post-PR, the named component drops them:
The TypeScript definition in
x-pack/platform/plugins/shared/fleet/common/types/models/package_policy_schema.tsstill defines all four (e.g.output_id: schema.maybe(schema.oneOf([schema.literal(null), schema.string()])),supports_agentless: schema.maybe(schema.nullable(schema.boolean()))).2.
update_package_policy_requestPre-PR
PUT /api/fleet/package_policies/{packagePolicyId}body had anidproperty:Post-PR
Kibana_HTTP_APIs_update_package_policy_requestno longer has it (the field is defined on the base typedpackage_policyschema thatupdate_package_policyextends).3.
package_policy_status_responsePre-PR
POST /api/fleet/package_policies/deleteresponse items had:Post-PR
Kibana_HTTP_APIs_package_policy_status_responsehas onlybody,id,name,statusCode,success— droppingoutput_id,policy_id,policy_ids, and the entire nestedpackageobject.Pattern
The dropped fields share characteristics:
schema.oneOf([schema.literal(null), schema.string()])— e.g.output_id,policy_idschema.arrayOf(schema.string())) — e.g.policy_idsschema.nullable(schema.boolean())— e.g.supports_agentless.extends()— e.g.packageon the status response,idonupdate_package_policy_request…all defined on a base schema that the now-
meta.id-annotated schema extends. The generator appears to lose these fields when flattening base + extension into the named component.Impact
Downstream OpenAPI-driven clients (e.g. the Terraform provider for Elastic Stack, which generates a Go client with
oapi-codegen) lose the ability to set or read these fields:simplified_create_package_policy_request— most painful. Users can no longer associate an integration policy with an agent policy (policy_ids) or override the output (output_id) on create via the simplified shape. The typed shape still exposes them, but switching shape requires converting mapped (map[string]input) inputs into typed ([]inputwith discriminators) inputs — a non-trivial rewrite. We have already had to add aFIXMEand skip a regression test (TestOutputIdHandling/toAPIModel) in the provider until upstream is fixed.update_package_policy_request— minor (idis normally taken from the URL path), but the generated client no longer exposes the field, which is observable in API contracts.package_policy_status_response— bulk-delete response is less informative; callers can no longer learn the agent policy / output / package associated with the deleted policy.Expected behaviour
The three affected named components should expose the same property sets the pre-PR inline schemas did. If any of these fields are intentionally being deprecated, please:
deprecated: true(orx-deprecated/x-deprecated-reason) markers,policy_ids,output_id,supports_agentless,package) on the simplified / status schemas,If the root cause is the
@kbn/config-schema→ OpenAPI generator dropping fields onextends()+meta.id, then the fix is at the generator layer (and the same bug likely affects other plugins that adoptmeta.idon extended schemas in the future).Steps to reproduce
/cc @elastic/fleet