Skip to content

16.2 — Flatten $ref and allOf so shared sub-schemas are not opaque #164

Description

@vrabbi

Phase: Phase 16 — Engine and strategy expansion
Proposal: docs/proposals/next-phases.md §16
Priority: P3 · Size: L


Problem

$ref and allOf nodes are treated as opaque, all-or-nothing units. A rule must claim the whole subtree, and the engine does not reason about the fields inside.

This is a real constraint for XRDs generated from shared type definitions, where allOf composition and $ref reuse are the normal output of a schema generator rather than something the author chose.

Goal

A field inside a composed or referenced sub-schema is an ordinary field.

Non-goals

  • Remote $ref resolution. Kubernetes structural schemas do not permit it, and attempting it would be a security problem as well as a correctness one.
  • oneOf/anyOf — that is 16.1 — oneOf / anyOf branch mapping #163.

Design

A normalisation pass ahead of flattenSchema:

  • allOf — merge the subschemas into the parent. Conflicting constraints on the same property (two different types, incompatible enums) must be a compile error, not a silent last-writer-wins, because the apiserver's own behaviour there is not something to guess at.
  • $ref — resolve local references (#/...) against the document root, with cycle detection that errors rather than recursing.

Kubernetes structural schemas already restrict what is legal here (no $ref to anything but metadata in practice, allOf permitted with restrictions), so the achievable scope may be narrower than general JSON Schema — establish exactly what the apiserver accepts in a CRD before designing for more than that. That investigation is the first task.

Normalisation must be a separate, testable pass whose output is an ordinary JSONSchemaProps, so nothing downstream — flattenSchema, the resolvers, the leftover scan, the passthrough tree — needs to know it happened.

Acceptance criteria

  • Investigation of what apiextensions actually permits, recorded in this issue
  • Normalisation is a standalone pass with its own unit tests
  • Local $ref resolved; remote $ref rejected with a clear error
  • Cycles detected and reported, never hung
  • Conflicting allOf constraints are a compile error naming both sides
  • Every existing test passes unchanged (normalisation is a no-op for schemas without these constructs)
  • Passthrough's known-tree is built from the normalised schema, so composed fields are not mistaken for undeclared ones
  • docs/limitations.md narrowed accordingly

Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    phase-16Phase 16 - Engine and strategy expansionpriority/P3Nice to have; may slip a phasesize/L1-2 weeksstrategiespkg/engine conversion strategy work

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions