You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Generator and typecheck failures in this repo are **report-only** because those failures are the compatibility data. Fixture validity and generated spec freshness are the CI gates.
12
12
13
+
## Adoption Strategy
14
+
15
+
This project currently tests SDK generators and type emitters, but `$dynamicRef` adoption requires work across the OpenAPI ecosystem: SDK generators, parsers/bundlers, runtime validators, spec producers, and documentation renderers.
16
+
17
+
SDK generators are the first priority because they are where users see broken output directly. Spec producers such as `@nx/swagger` should start adding `$dynamicRef` emission support, but behind explicit opt-in flags until downstream SDK generator support is reliable.
18
+
19
+
See [State of the Union](state-of-the-union.md) for the detailed strategy.
|`api-envelope.yaml`| Valid wrapped-user page fails; invalid item cases fail | Not tested | Not tested | Expected same gap as pagination fixtures; AJV PR #2615 should fix this |
|`nested-workspace-resources.yaml`| Valid nested workspace passes; AJV accepts invalid nested folder data (missing `permissions` field) | Fails: "resolves to more than one schema" for multiple same-name `$dynamicAnchor` in the same document (`FolderTemplate.$defs.folderType` and `WorkspaceFolder.$defs.folderType` share an anchor name) — this is an AJV limitation, not a fixture bug | Not tested | AJV does not correctly resolve the multi-parameter generic template pattern; the fixture is semantically sound |
99
+
|`nested-workspace-resources.yaml`| Valid nested workspace passes; invalid nested folder missing permissions is accepted as a known gap because AJV resolves the generic `$dynamicRef` slot to the `not: {}` fallback | Fails: "resolves to more than one schema" for same-name `$dynamicAnchor`s in the generic binding path — this is an AJV limitation, not a fixture bug | Not tested | AJV does not correctly resolve the multi-parameter generic template pattern; the fixture is semantically sound |
|`spec-semantics/ambiguous-sibling-anchors.yaml`| Not tested | Not tested | Not tested | OpenAPI-valid research fixture for static-scan limitations |
102
102
|`spec-semantics/dynamicref-core-semantics.yaml`|`$ref` to `$dynamicAnchor` passes; several `$dynamicRef` core cases are known gaps, including non-fragment URI refs | Not tested | Core cases, non-fragment URI refs, allOf order, and multi-parameter generic cases pass | Semantics fixture tier; AJV gaps are documented by case output |
103
103
|`spec-semantics/external-dynamic-ref.yaml`| Not tested | Not tested | Valid external node passes; invalid external node fails | External resource semantics fixture for parser/bundler research |
104
104
105
-
AJV PR [#2615](https://github.com/ajv-validator/ajv/pull/2615) fixes the generic pagination dynamic binding pattern. The nested workspace fixture exposes a separate AJV limitation: multiple schemas declaring the same `$dynamicAnchor` name in a single document causes an ambiguous reference error. This is a limitation of AJV PR #2615, not a bug in the fixture — `nested-workspace-resources.yaml` is semantically correct (both anchor declarations are scoped to different schemas in the `allOf` chain).
105
+
AJV PR [#2615](https://github.com/ajv-validator/ajv/pull/2615) fixes the generic pagination dynamic binding pattern. The nested workspace fixture exposes a separate AJV limitation around same-name`$dynamicAnchor`s in a multi-parameter generic binding path. This is a limitation of AJV PR #2615, not a bug in the fixture — `nested-workspace-resources.yaml` is semantically correct because the declarations are scoped by the dynamic evaluation path.
Copy file name to clipboardExpand all lines: state-of-the-union.md
+21-2Lines changed: 21 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -50,7 +50,7 @@ JSON Schema runtime validation:
50
50
| Paginated response (inline) | Fails valid user/group pages | Passes valid/invalid user and group pages | Passes valid/invalid user and group pages | AJV PR #2615 fixes this |
51
51
| API envelope | Not yet tested | Not yet tested | Not yet tested | Expected same gap as pagination fixtures |
52
52
| Recursive category tree | Pass | Pass | Not tested | Pass |
53
-
| Nested workspace resources |PASS (valid workspace); FAIL (invalid nested folder — AJV does not enforce constraints through `$dynamicRef`generic template binding, same gap as pagination fixtures) | Fails: "resolves to more than one schema" — AJV limitation when multiple schemas share a `$dynamicAnchor` name in the same document; fixture is semantically correct | Not tested | AJV does not resolve `$dynamicRef`generics pattern; fallback `not: {}` accepts invalid data|
53
+
| Nested workspace resources |Valid workspace passes; invalid nested folder is accepted as a known gap because AJV resolves the generic `$dynamicRef`slot to the `not: {}` fallback | Fails: "resolves to more than one schema" — AJV limitation when same-name `$dynamicAnchor`s appear in the generic binding path; fixture is semantically correct | Not tested | AJV does not resolve the multi-parameter `$dynamicRef`generic template pattern|
| Spec semantics fixtures | Mixed known gaps | Not tested | Pass where runtime assertions exist | Research tier; see `fixtures/README.md`|
56
56
@@ -80,10 +80,26 @@ PaginatedUserResponse:
80
80
81
81
Hyperjump evaluates this as intended: user pages require `User[]`, group pages require `Group[]`, and invalid item shapes fail. AJV PR [#2615](https://github.com/ajv-validator/ajv/pull/2615) also now evaluates this correctly — valid user/group pages pass and invalid item shapes fail. This PR has not yet been merged.
82
82
83
-
The nested workspace fixture was restructured from sibling `$dynamicAnchor` declarations to a multi-parameter generic template pattern (`FolderTemplate` with `folderType` and `resourceType` slots). AJV now parses and partially validates the fixture but does not correctly enforce constraints through `$dynamicRef` generic template binding — the same gap that affects the pagination fixtures. The previous "ambiguous reference" error for same-name `$dynamicAnchor` declarations no longer applies to this fixture.
83
+
The nested workspace fixture was restructured from sibling `$dynamicAnchor` declarations to a multi-parameter generic template pattern (`FolderTemplate` with `folderType` and `resourceType` slots). AJV now parses and partially validates the fixture but does not correctly enforce constraints through `$dynamicRef` generic template binding — the same gap that affects the pagination fixtures. AJV PR #2615 still exposes a separate same-name `$dynamicAnchor` limitation in this generic binding path; the fixture remains semantically correct.
84
84
85
85
This means the claim that `$dynamicRef` can model generic wrappers is supported by the OAI discussion and by Hyperjump, but tool support is mixed. Upstream generator issues should include the validator matrix rather than relying on one validator.
86
86
87
+
## Ecosystem Workstreams
88
+
89
+
`$dynamicRef`adoption depends on several OpenAPI tool categories, not just SDK generators.
90
+
91
+
| Category | Role | Examples | Recommended work |
92
+
|---|---|---|---|
93
+
| SDK generators / type emitters | Generate application-facing clients and types | OpenAPI Generator, Orval, openapi-typescript, @hey-api/openapi-ts, Kiota, NSwag | Highest priority: preserve dynamic scope and emit reusable parameterized types where supported |
| Runtime validators | Validate data against schemas | AJV, Hyperjump | Close validator gaps and document disagreements |
96
+
| Spec producers | Generate OpenAPI specs from source code | `@nx/swagger`, `@nestjs/swagger`, tsoa, FastAPI, springdoc-openapi, poem-openapi, swaggo/swag | Add opt-in `$dynamicRef` emission while keeping duplicated-schema output as the default |
97
+
| Documentation renderers | Render OpenAPI docs | Swagger UI, Redoc, Stoplight Elements | Render valid specs containing `$dynamicRef` without crashing or hiding schemas |
98
+
99
+
SDK generators and type emitters are the first practical priority because broken generated types immediately affect application developers. A spec producer that emits `$dynamicRef` before downstream tools preserve the semantics can cause generation failures or degraded output such as `unknown`, `any`, `Object`, or duplicate non-generic wrappers.
100
+
101
+
Spec producers should still start implementing support now, but they should expose it as an explicit opt-in. Default output should remain compatibility-safe duplicated schemas until major SDK generators and parser/bundler stacks reliably preserve dynamic reference semantics.
This section is a compatibility snapshot from the initial focused run against Orval, OpenAPI Generator, and Swagger Codegen v3. The live CI matrix now covers additional TypeScript-oriented tools; use GitHub Actions artifacts and tracking issues for current per-tool status.
- Use duplicated concrete wrappers or a hybrid compatibility strategy for production SDK pipelines today.
155
+
- Prioritize SDK generators and type emitters first; they are the practical bottleneck for application adoption.
139
156
- Use validator-backed recursive and complex nested fixtures for upstream `$dynamicRef` parser/codegen work.
140
157
- Use the pagination/generic-wrapper fixture with the documented validator caveat: Hyperjump validates it; AJV currently does not.
141
158
- **Generic fixtures must produce parameterized types (generics) when the target language supports them.** Concrete materialization of generic wrappers — duplicating the template structure for each item type — does not pass validation. The purpose of `$dynamicRef` for generics is type reuse; producing duplicates defeats that purpose. For languages without generics, concrete wrappers are acceptable as a documented fallback.
159
+
- Spec producers such as `@nx/swagger` should add `$dynamicRef` emission behind explicit opt-in flags, not as default output, until downstream SDK generator support is reliable.
160
+
- Track spec producer work separately from SDK generator work; this repo does not need producer CI automation yet.
142
161
- Treat OAS `3.2.0` as experimental for generator compatibility until parser support improves.
143
162
- OpenAPI Generator has the most severe gap: it cannot parse specs containing `$dynamicAnchor` at all. Start upstream work there.
0 commit comments