Skip to content

fix(api-catalog): resolve discriminator.mapping refs to #/$defs pointers (DEVX-548)#96

Merged
jpage-godaddy merged 3 commits into
godaddy:rust-portfrom
smukherjee-godaddy:DEVX-548-catalog-ref-deref
Jul 14, 2026
Merged

fix(api-catalog): resolve discriminator.mapping refs to #/$defs pointers (DEVX-548)#96
jpage-godaddy merged 3 commits into
godaddy:rust-portfrom
smukherjee-godaddy:DEVX-548-catalog-ref-deref

Conversation

@smukherjee-godaddy

@smukherjee-godaddy smukherjee-godaddy commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Problem

gddy api describe returned broken, unresolvable schema references for polymorphic commerce types (Amount, Fee, FundingSource, Channel, PricingModel, CallbackAuthentication).

The API catalog resolves $ref objects into local #/$defs/... entries, but OpenAPI discriminator.mapping carries schema references as plain strings, not $ref objects — so the dereferencer never rewrote them. The generated catalog kept external file paths like:

"discriminator": {
  "mapping": {
    "DEFAULT": "./BasicChannel.yaml",
    "APPLE_PAY": "../payment-token/ApplePayPaymentToken.yaml"
  }
}

A developer inspecting a commerce schema via api describe got a dead file path instead of a resolvable pointer. 52 such leaks existed across channels, payment-requests, payments, subscriptions, and transactions.

Fix

  • Generator (rust/tools/generate-api-catalog): added rewrite_discriminator_mappings, run after ref-lifting in load_and_dereference. It rewrites each external mapping value to the matching #/$defs/<key> using the same key derivation as $ref lifting — and only when that def exists, so a mapping is never pointed at a missing schema.
  • Build guard: extended the unresolved-reference check to treat external discriminator.mapping values as build-failing, exactly like an external $ref. Future spec drift now fails generation instead of silently shipping a broken pointer.
  • Catalog: rewrote 52 mappings across the 5 affected domains. (Full regeneration requires source-spec repo access unavailable in this environment, so the committed catalog was rewritten with the identical, verified transform; the generator change keeps it correct on the next regen.)
  • Tests: added mapping-rewrite and drift-guard unit tests.

Impact

  • gddy api describe now returns fully-resolvable schemas for all polymorphic commerce types.
  • The catalog contains zero unresolvable discriminator.mapping values (verified: 0 remaining leaks, 0 dangling #/$defs pointers, all catalog files valid JSON).
  • Generation now fails fast on any future external mapping leak.

Scope / follow-ups

The original ticket cited 587 unresolved external $refs — that was already fixed on rust-port; all 1787 $refs now resolve internally. This change addresses the residual plain-string leaks. Two remaining external references are intentionally out of scope:

  • GraphQL schemaRef (./graphql/schema.graphql) in catalog-products and taxes — tracked with the GraphQL commerce work (DEVX-546).
  • JSON-Schema $id URIs — valid identifiers, not broken references; left as-is.

Testing

  • cargo test -p generate-api-catalog — 10/10 pass (incl. 2 new)
  • cargo test api_explorer — pass with rewritten catalogs embedded
  • cargo clippy -p generate-api-catalog -- -D warnings — clean
  • cargo fmt --check — clean

Notes for reviewers

Includes a small unrelated chore commit gitignoring legacy TS build artifacts (node_modules/, dist/, .pnpm-store/, .npmrc) that surface as untracked noise in the rust-port tree. Happy to split it out if preferred.

smukherjee-godaddy and others added 3 commits July 13, 2026 18:38
…ers (DEVX-548)

The API catalog left external file paths inside OpenAPI `discriminator.mapping`
blocks (e.g. "./BasicChannel.yaml", "../payment-token/ApplePayPaymentToken.yaml").
Unlike `$ref` objects, mapping values are plain strings, so the dereferencer never
rewrote them — and `api describe` surfaced broken, unresolvable schema references
for polymorphic commerce types (Amount, Fee, FundingSource, Channel, PricingModel).

The referenced subschemas are already lifted into `$defs` via the same key
derivation, so rewrite each external mapping value to the matching `#/$defs/<key>`
pointer (only when the def exists, so a mapping is never pointed at a missing
schema). Also extend the unresolved-ref guard to treat external mapping values as
build-failing, same as an external `$ref`, so future drift is caught in CI.

- generator: add rewrite_discriminator_mappings, run it after lifting in
  load_and_dereference; extend collect_unresolved_refs to scan mappings
- regenerate-equivalent: rewrite 52 mappings across channels, payment-requests,
  payments, subscriptions, transactions catalogs
- tests: mapping rewrite + drift-guard unit tests

Note: two residual external references remain and are scoped as follow-ups:
GraphQL `schemaRef` ("./graphql/schema.graphql") in catalog-products/taxes
(tied to the GraphQL work in DEVX-546), and JSON-Schema `$id` URIs (valid
identifiers, not broken refs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
node_modules/, dist/, .pnpm-store/, and .npmrc are artifacts of the legacy TS
CLI and are not part of the Rust port. They surface as untracked noise when
switching into the rust-port working tree; ignore them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (DEVX-548)

Adds the negative-path test for the safety guard: a discriminator.mapping value
whose target is never lifted into $defs is left external (not pointed at a missing
key), and collect_unresolved_refs then flags it so the build fails. Locks in the
`def_keys.contains` guard behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jpage-godaddy
jpage-godaddy merged commit 0b9d565 into godaddy:rust-port Jul 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants