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
[finding] the served openapi.json overrides the info.version that packages/spec owns, so the published artifact says 17.2.0 and the served document says v1 #11646
Raised by the dev seat on #11546 / PR #11641 as an open question, and routed here rather than
answered: it is a public-document contract shape, which sits on the manual floor. ⛔ Not graded
and not decided by the routing seat. Filed unassigned.
PR #11641 corrected the comment on this line and removed a fallback; it deliberately did not
change the served value. This card is the question it left open.
The split, measured
info.version
the published artifact — @objectstack/spec's ./openapi.json export, set by packages/spec/scripts/build-openapi.ts to SPEC_VERSION, pinned by openapi-self-consistency.test.ts
17.2.0
the served document — GET {base}/openapi.json, overridden at serve time with config.api.version
v1
Same field name, same package family, two different kinds of fact. The route's own test twin already
asserts that the info block is "the half packages/spec owns" and that "serve-time enrichment
must not touch it" — with the assertion narrowed to info.title alone, precisely because version is overridden. So the invariant is stated and then excepted, in the same file.
The three shapes
option
what it costs
A
leave the override (what #11641 shipped) — served info.version stays the declared API version identifier
zero behaviour change on every working config; the two faces keep saying different things
B
remove the override — served info.version becomes SPEC_VERSION, matching the published artifact and the twin's stated invariant
a real behaviour change on a public document ⇒ Clause-② yes, contract review
C
put info.version behind an explicit config key so a deployment states which fact it publishes
new public surface for a demand nobody has expressed
What is already measured, so nobody re-derives it
Consumer survey — zero. No consumer reads this document's info.version by value in objectstack, objectui, cloud, or cloud-v1. The one v{info.version} render in cloud-v1
(apps/cloud/components/api-docs/api-docs-viewer.tsx) reads cloud's own generateOpenAPISpec() document, not this one. So there is no consumer pull in either direction.
The static artifact carries no paths. It is the contract half rather than a usable document,
which is the strongest argument that the two faces are allowed to differ.
The axis the dev seat named as the weakest point of its own choice
Recorded verbatim rather than smoothed over, because it is the honest half of an A recommendation:
Long-term soundness: contract-first genuinely favours B (a consumer-side override rewriting a
producer-owned contract field is the shape the rule warns about), and this is the one axis where A
is the weaker answer — I am flagging that rather than smoothing it.
Against that: with a measured zero consumer pull, changing a served value on a public document is
the speculative widening the startup-scope axis exists to refuse, and #11546 was split out precisely
to avoid it.
Routing note
If this is graded as work, note that the field is owned by packages/spec's build
(build-openapi.ts, openapi-self-consistency.test.ts) while the override lives in packages/rest
— so the landing package depends on which option is chosen, and B in particular reads as a domain:spec change rather than the domain:cli lane that filed it.
Raised by the dev seat on #11546 / PR #11641 as an open question, and routed here rather than
answered: it is a public-document contract shape, which sits on the manual floor. ⛔ Not graded
and not decided by the routing seat. Filed unassigned.
PR #11641 corrected the comment on this line and removed a fallback; it deliberately did not
change the served value. This card is the question it left open.
The split, measured
info.version@objectstack/spec's./openapi.jsonexport, set bypackages/spec/scripts/build-openapi.tstoSPEC_VERSION, pinned byopenapi-self-consistency.test.ts17.2.0GET {base}/openapi.json, overridden at serve time withconfig.api.versionv1Same field name, same package family, two different kinds of fact. The route's own test twin already
asserts that the
infoblock is "the halfpackages/specowns" and that "serve-time enrichmentmust not touch it" — with the assertion narrowed to
info.titlealone, precisely becauseversionis overridden. So the invariant is stated and then excepted, in the same file.The three shapes
info.versionstays the declared API version identifierinfo.versionbecomesSPEC_VERSION, matching the published artifact and the twin's stated invariantinfo.versionbehind an explicit config key so a deployment states which fact it publishesWhat is already measured, so nobody re-derives it
info.versionby value inobjectstack,objectui,cloud, orcloud-v1. The onev{info.version}render incloud-v1(
apps/cloud/components/api-docs/api-docs-viewer.tsx) reads cloud's owngenerateOpenAPISpec()document, not this one. So there is no consumer pull in either direction.versionis "theversion of the OpenAPI document (which is distinct from the OpenAPI Specification version or the
API implementation version)". That text excludes the runtime/implementation version — which is
what settled
@objectstack/restopenapi.json setsinfo.versiontoconfig.api.version('v1') under a comment promising "the runtime version" — the comment is falsified by the line it introduces #11546's original fork — but it does not choose betweenv1and17.2.0.paths. It is the contract half rather than a usable document,which is the strongest argument that the two faces are allowed to differ.
The axis the dev seat named as the weakest point of its own choice
Recorded verbatim rather than smoothed over, because it is the honest half of an A recommendation:
Against that: with a measured zero consumer pull, changing a served value on a public document is
the speculative widening the startup-scope axis exists to refuse, and #11546 was split out precisely
to avoid it.
Routing note
If this is graded as work, note that the field is owned by
packages/spec's build(
build-openapi.ts,openapi-self-consistency.test.ts) while the override lives inpackages/rest— so the landing package depends on which option is chosen, and B in particular reads as a
domain:specchange rather than thedomain:clilane that filed it.