Skip to content

openapi: a preserved field supplied through a merge key or alias is dropped with no trace #384

Description

@OmarAlJarrah

Summary

Every site that keeps a construct verbatim under Unmodeled finds its payload with
annotation.RawChildNode (or RawPropertyNode), which scans a mapping's Content
pairs directly. That scan does not expand a YAML merge key and does not resolve an
alias, so a field the parsed model does see reaches the IR in no form at all — no
field, no Unmodeled entry, and no diagnostic.

PreserveNodeInto returns (false, nil) for a nil node, and every caller treats a
false as "nothing was declared" rather than "something was declared and lost".

Reproduction

Verified at 937ed02. A path item whose summary, description and servers all
arrive through a merge key:

openapi: 3.1.0
info: {title: T, version: "1"}
x-base: &base
  summary: merged path summary
  description: merged path description
  servers: [{url: 'https://merged.example.com'}]
paths:
  /a:
    <<: *base
    get:
      operationId: mergedGet
      responses: {"200": {description: ok}}

The model reads all three; the raw lookup finds none of them:

GetSummary()="merged path summary"
GetDescription()="merged path description"
len(GetServers())=1
RawChildNode(summary)=false
RawChildNode(servers)=false
RawChildNode(get)=true

Compiling it produces no openapi:pathItemSummary, no openapi:pathItemDescription,
no openapi:servers, and no diagnostic of any severity.

That speakeasy honours the merge key is not in doubt — a parameters entry supplied
the same way reaches the IR, because GetParameters() reads the model rather than the
node.

Scope

This is a property of the lookup, not of any one caller. There are 31 non-test call
sites of RawChildNode/RawPropertyNode across operation, content, params,
auth and annotation, and each keeps a different construct: path-item servers and
documentation, an operation's own servers, response links/headers/content,
allowEmptyValue, prefixEncoding/itemEncoding, security-scheme fields, and every
schema keyword kept verbatim.

applyPathServers has had it since #39; #310 extends it to path-item documentation.
Neither is the defect — the lookup is.

Notes

nodeview already expands merge keys and resolves aliases (MappingPairs), and is
what the cycle scan uses for exactly this reason, so the machinery exists. Making the
raw lookup view-aware would change what is preserved at all 31 sites at once, which is
why it wants its own change and its own golden review rather than being folded into a
caller's PR.

TestApplyPathItemDocs_WithoutRootNode currently pins the silent branch as correct
using a synthetic soa.PathItem the parser never produces; a merge-key document
reaches the same branch carrying real data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions