Summary
The package root re-exports ~15 OpenAPI construct documents. Almost all of them
carry the construct version in the identifier, so a consumer can see which
edition they are getting at the import site:
CategoryDefinitionV1Beta1OpenApiSchema -> constructs/v1beta1/category/CategorySchema
ComponentDefinitionV1Beta2OpenApiSchema -> constructs/v1beta2/component/ComponentSchema
DesignDefinitionV1Beta2OpenApiSchema -> constructs/v1beta2/design/DesignSchema
RelationshipDefinitionV1Alpha3OpenApiSchema -> constructs/v1alpha3/relationship/RelationshipSchema
InvitationDefinitionV1Beta2OpenApiSchema -> constructs/v1beta2/invitation/InvitationSchema
...
Exactly two do not, and both silently resolve to v1beta1:
| Root export |
Resolves to |
Newer construct exists |
Go model consumers bind |
BadgeSchema |
constructs/v1beta1/badge/BadgeSchema |
v1beta2 |
models/v1beta2/badge |
InvitationSchema |
constructs/v1beta1/invitation/InvitationSchema |
v1beta2, v1beta3 |
models/v1beta3/invitation |
(Verified against @meshery/schemas@1.3.44 by deep-equality between each root
export and every file under dist/constructs/.)
Why it bites
In both cases the difference between the pinned edition and the current one is
the snake_case -> camelCase identifier rename, i.e. exactly the field names
a consumer addresses:
badge v1beta1: id, org_id, label, name, description, image_url, created_at, ...
v1beta2: id, orgId, label, name, description, imageUrl, createdAt, ...
invitation v1beta1: id, owner_id, is_default, org_id, expires_at, accepted_by, created_at, ...
v1beta3: id, owner, isDefault, orgId, expiresAt, acceptedBy, createdAt, ...
The Go models these constructs generate are what providers actually bind, and
they are camelCase — models/v1beta2/badge.Badge is tagged json:"imageUrl" /
json:"orgId", models/v1beta3/invitation.Invitation is tagged json:"owner" /
json:"expiresAt". The generated RTK operations agree (createOrUpdateBadge's
body declares imageUrl, orgId).
So an unsuffixed export name reads as the schema for that construct while
pinning the retired edition, and a consumer that addresses the live camelCase
field names inherits the mismatch with no error anywhere: _.pick /
property lookups against the document return nothing, and the failure surfaces
only as a form field that never renders.
That is not hypothetical — it shipped:
layer5io/meshery-cloud#5917.
The Recognitions create/edit modal projected its RJSF schema out of the root
BadgeSchema while addressing imageUrl. The image field never rendered, and
because required still named imageUrl, RJSF refused every submit against a
field the user could not see: "Create Recognition" sent no request at all. The
consumer's field names were correct throughout; only the import source was wrong.
Suggested fix
Either is fine, and either one makes the mistake impossible rather than merely
reviewable:
- Rename to match every sibling —
BadgeDefinitionV1Beta2OpenApiSchema,
InvitationDefinitionV1Beta3OpenApiSchema — keeping the old names as
deprecated aliases for a release; or
- Repoint the two unsuffixed exports at the current construct edition.
A packaging test asserting that no root export of a construct document is
version-ambiguous would keep it from recurring as new constructs are added.
Consumer-side note
meshery-cloud has repointed its badge consumer at the
constructs/v1beta2/badge/BadgeSchema subpath and added an architecture guard
(ui/__tests__/architecture/schema-construct-version-parity.test.ts) that
refuses any import of these two exports and asserts every construct the UI
imports matches the version its Go server binds. InvitationSchema is not
consumed from the barrel there — both consumers already use the v1beta3
subpath — so it is currently a latent trap rather than a live defect.
Summary
The package root re-exports ~15 OpenAPI construct documents. Almost all of them
carry the construct version in the identifier, so a consumer can see which
edition they are getting at the import site:
Exactly two do not, and both silently resolve to
v1beta1:BadgeSchemaconstructs/v1beta1/badge/BadgeSchemav1beta2models/v1beta2/badgeInvitationSchemaconstructs/v1beta1/invitation/InvitationSchemav1beta2,v1beta3models/v1beta3/invitation(Verified against
@meshery/schemas@1.3.44by deep-equality between each rootexport and every file under
dist/constructs/.)Why it bites
In both cases the difference between the pinned edition and the current one is
the snake_case -> camelCase identifier rename, i.e. exactly the field names
a consumer addresses:
The Go models these constructs generate are what providers actually bind, and
they are camelCase —
models/v1beta2/badge.Badgeis taggedjson:"imageUrl"/json:"orgId",models/v1beta3/invitation.Invitationis taggedjson:"owner"/json:"expiresAt". The generated RTK operations agree (createOrUpdateBadge'sbody declares
imageUrl,orgId).So an unsuffixed export name reads as the schema for that construct while
pinning the retired edition, and a consumer that addresses the live camelCase
field names inherits the mismatch with no error anywhere:
_.pick/property lookups against the document return nothing, and the failure surfaces
only as a form field that never renders.
That is not hypothetical — it shipped:
layer5io/meshery-cloud#5917.
The Recognitions create/edit modal projected its RJSF schema out of the root
BadgeSchemawhile addressingimageUrl. The image field never rendered, andbecause
requiredstill namedimageUrl, RJSF refused every submit against afield the user could not see: "Create Recognition" sent no request at all. The
consumer's field names were correct throughout; only the import source was wrong.
Suggested fix
Either is fine, and either one makes the mistake impossible rather than merely
reviewable:
BadgeDefinitionV1Beta2OpenApiSchema,InvitationDefinitionV1Beta3OpenApiSchema— keeping the old names asdeprecated aliases for a release; or
A packaging test asserting that no root export of a construct document is
version-ambiguous would keep it from recurring as new constructs are added.
Consumer-side note
meshery-cloudhas repointed its badge consumer at theconstructs/v1beta2/badge/BadgeSchemasubpath and added an architecture guard(
ui/__tests__/architecture/schema-construct-version-parity.test.ts) thatrefuses any import of these two exports and asserts every construct the UI
imports matches the version its Go server binds.
InvitationSchemais notconsumed from the barrel there — both consumers already use the
v1beta3subpath — so it is currently a latent trap rather than a live defect.