Skip to content

Provider contract $ref does not resolve on receiver after sync #49

@thehabes

Description

@thehabes

Summary

The provider contract at openapi/contracts/tpen-services-to-tinypen.openapi.yaml uses relative $refs into the local TinyNode mirror. The refs resolve correctly inside TinyPen's directory layout but do not resolve on cubap/rerum_openapi after sync, because the receiver's directory layout places the TinyNode mirror at a sibling path that does not exist relative to the synced contract.

Where it occurs

openapi/contracts/tpen-services-to-tinypen.openapi.yaml lines 22-24:

  /query:
    $ref: ../external/tpen-services-to-tinynode.openapi.yaml#/paths/~1query
  /update:
    $ref: ../external/tpen-services-to-tinynode.openapi.yaml#/paths/~1update

How ../external/ resolves in each repo

Contract lives at ../external/ resolves to File exists?
TinyPen (local) openapi/contracts/ openapi/external/tpen-services-to-tinynode.openapi.yaml ✓ yes
cubap/rerum_openapi (receiver, after sync) seams/tpen-services-to-tinypen/openapi/ seams/tpen-services-to-tinypen/external/tpen-services-to-tinynode.openapi.yaml ✗ no

On the receiver, the TinyNode mirror lives at a sibling path — seams/tpen-services-to-tinynode/openapi/baseline.openapi.yaml — not under seams/tpen-services-to-tinypen/external/. Any OpenAPI-aware tool that dereferences $refs against the receiver copy gets a file-not-found for /query and /update.

What does and doesn't break

  • ✓ Local TinyPen npm test — passes (resolves under openapi/external/)
  • ✓ Receiver file storage — fine (YAML text lands; broken refs sit dormant)
  • __tests__/provider_contract_surface.test.js — passes (verifies the literal $ref string and that the local mirror exists; does not simulate receiver-side resolution)
  • ✗ Any $ref-resolving tool run against the receiver copy: Redocly bundle/lint, swagger-cli bundle, doc renderers, code generators

Surfaced when

The first cross-repo sync after #47 landed: cubap/rerum_openapi#7. The synced file has the broken refs visible in the diff.

Remediation — three options, all single-file commits in this repo

  1. Inline the imported operations in openapi/contracts/tpen-services-to-tinypen.openapi.yaml (recommended). Self-contained, survives any transport, matches how the other baselines on the receiver are structured. Costs a few lines of duplication.
  2. Use a receiver-relative path like ../../tpen-services-to-tinynode/openapi/baseline.openapi.yaml#/paths/~1query. Breaks local resolution unless we also reorganize TinyPen's openapi/external/ to match the receiver layout. Trades one breakage for another — not recommended.
  3. Bundle/dereference at sync time with redocly bundle or swagger-cli bundle added as a step in .github/workflows/sync_tinypen_provider_contract.yaml before the copy. Cleanest semantically, adds a tooling dependency.

Acceptance criteria

  • The receiver copy of seams/tpen-services-to-tinypen/openapi/baseline.openapi.yaml resolves cleanly with npx @redocly/cli bundle <file> (no missing-ref errors).
  • TinyPen's existing tests continue to pass.
  • A receiver-side bundle check could be added later to catch this class of regression in CI.

Context

Surfaced during the #47 static review. Out-of-scope for that PR by agreement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions