Uh oh!
There was an error while loading. Please reload this page.
fix(runtime): derive /health and discovery version instead of a hardcoded '1.0.0' literal - #11242
Conversation
…, not a hardcoded '1.0.0' literal (#10993) Resolve `version` once at HttpDispatcher construction from an injected OS_RUNTIME_VERSION stamp, falling back to the resolved @objectstack/runtime package version -- reusing the env var cloud-connection-plugin.ts already reads for the same purpose. Fixes the identical defect on both the /health handler and the discovery payload (getDiscoveryInfo()), which share the same "System Identity" field in DiscoverySchema.
📓 Docs Drift CheckThis PR changes 1 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin cff0c051ce549614a25adabd77b4d02b321382fb && git checkout cff0c051ce549614a25adabd77b4d02b321382fb
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin df287e652862f92cd1f7e40846a494bb031aaac1 10a5a453d21db07afde4cc17dd8d863e1e36134f && git checkout -B drift-repro df287e652862f92cd1f7e40846a494bb031aaac1 && git merge --no-ff 10a5a453d21db07afde4cc17dd8d863e1e36134f
node scripts/docs-audit/affected-docs.mjs --json df287e652862f92cd1f7e40846a494bb031aaac1
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#10993
Premise check
Confirmed at
origin/main(dd84ddd796):packages/runtime/src/http-dispatcher.tscarried the hardcodedversion: '1.0.0'literal at both sites — the/healthhandler and the discovery payload built bygetDiscoveryInfo(). Premise holds.Second site — measured in scope
DiscoverySchema.version(packages/spec/src/api/discovery.zod.ts:681,z.string()) sits under the schema's "System Identity" section alongsidename, distinct fromServiceInfoSchema's separately-documented per-SERVICEversionfield ("Semantic version of the service implementation"). Three measurements:connect()(packages/client/src/index.ts:567) logsdata.versionalongsideapiNameandservicesunder "Connected to ObjectStack server" — read as artifact identity, not a protocol/API version.DiscoverySchemahas noprotocolfield at all — the "protocol 17" numbering nearGetDiscoveryResponseSchemais a documentation-only convention, not a contracted value.DiscoverySchemaproducer,getDiscovery()in@objectstack/metadata-protocol(packages/metadata-protocol/src/protocol.ts:5095), fills the SAME field with a DIFFERENT unrelated literal ('1.0', not even'1.0.0') — itself evidence neither producer ever treated the value as a meaningful contract.So this is the identical defect, not a separately-contracted value — fixed here, in the same file, alongside
/health. Filed the third producer (a different package) as its own unassigned card: #11235.Design
packages/runtime/src/runtime-version.ts,resolveRuntimeVersion(), called once inHttpDispatcher's constructor and stored onthis.runtimeVersion:OS_RUNTIME_VERSION, if the host injects one. Not a new env var —packages/cloud-connection/src/cloud-connection-plugin.tsalready reads this exact name (with a per-plugin literal fallback) to name the runtime in a device-bind approval URL; reused rather than inventing a second name for the same value (AGENTS.md [WIP] Create a new release version #9'sOS_{DOMAIN}_{NAME}config-value shape —RUNTIMEdomain,VERSIONvalue).@objectstack/runtime's own resolvedpackage.jsonversion, viacreateRequire(import.meta.url)('../package.json').'unknown'only if both are unavailable — never a plausible-looking literal.Resolved once at construction (per triage), not per-request — it names the process, which cannot change over the dispatcher's lifetime.
A build trap this surfaced
createRequire(import.meta.url)is correct for the ESM output, but esbuild EMPTIESimport.metain tsup's CJS build (measured:packages/lint's own builtdist/runtime.jsalready carries an[empty-import-meta]warning on a bundled dependency doing exactly this, unguarded).packages/runtime/tsup.config.tsnow setsshims: true, which makes tsup rewriteimport.meta.urlin the CJS bundle to a real__filename-derived value (itsassets/cjs_shims.js). Confirmed both ways by requiring the builtdist/index.cjsand importing the builtdist/index.jsdirectly and constructing a realHttpDispatcher: both correctly resolve the package version. Need-based injection — nothing else in the package references__dirname/__filename, so the ESM shim path is unused (no effect on the ESM build).Pin design + anti-vacuity
packages/runtime/src/http-dispatcher.runtime-version.test.tsdrives the realHttpDispatcher.dispatch()path (never source text or the resolver in isolation):'1.0.0'or the package version and asserts BOTH/healthand/discoveryreturn it verbatim — proves one derived source serves both callers.resolveRuntimeVersion()reads it, so the assertion tracks production code rather than an independently guessed string) — not'1.0.0', notundefined.Two pre-existing tests pinned the literal directly (
http-dispatcher.root.test.ts, both viagetDiscoveryInfo()on the root""and/discoveryroutes) — fixed at the source: they now assert against the real resolved package version instead of'1.0.0'.Reverse verification (fix committed first; both
version: this.runtimeVersion,sites reverted in the working tree to the literalversion: '1.0.0',; restored viagit checkout HEAD --): the literal turned exactly the intended 6 assertions red — 2 inhttp-dispatcher.root.test.ts, 4 in the new pin file — each naming the mismatch (expected '1.0.0' to be '17.1.0'/ the injected stamp), nothing else in the package moved. Restored, re-ran, green.Boot + curl (real process, not a unit test)
Booted a real
LiteKernel+HonoServerPlugin(port 0) +createDispatcherPluginserver against the built@objectstack/runtimeand fetched over real HTTP:Liveness contract — unchanged
/healthstill checks nothing beyond "this process is executing code" (framework#3756) — only the VALUE of one existing field changed. No schema widening:DiscoverySchema.version: z.string()was already declared.Gate verdicts (all local, quoted verbatim)
pnpm --filter '@objectstack/runtime' typecheck— exit 0, clean.pnpm --filter '@objectstack/runtime' build— ESM + CJS + DTS all succeed, noempty-import-metawarning on our own code.pnpm --filter '@objectstack/runtime' test(full package) —Test Files 184 passed (184)/Tests 2710 passed (2710).pnpm check:changeset-gate-self-tests— 3 self-tests OK.pnpm check:cross-package-test-inputs—OK: 13 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.pnpm check:objectui-changeset— self-tests OK.pnpm check:published-files—69 publishable package(s) of 78 workspace member(s) declare a files whitelist...pnpm check:slot-lookup—slot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none new... baseline key set verified against dd84ddd: no files added.pnpm check:test-source-alias—check-test-source-alias OK — 72 packages with tests scanned...pnpm check:type-source-resolution—check-type-source-resolution OK — 77 packages with a tsconfig.json scanned...node scripts/check-ci-filter-parity.mjs—OK: all 86 declared cross-package glob(s) (74 unique) are covered...node scripts/check-plugin-teardown-shape.mjs—63 Plugin implementation(s) across 4503 source(s)... 0 known-unreached, SHRINK-ONLY, baseline fully burned down.node scripts/docs-audit/check-affected-docs.mjs—affected-docs self-test: 339 cases pass.pnpm check:query-options-erasure—query-options-erasure ratchet holds: 67 unswept non-test site(s) in 17 file(s), none new... baseline key set verified against dd84ddd: no files added.pnpm check:engine-double-contract—OK — 384 pinned, 133 in the DEBT ledger, 2 exempt.pnpm check:where-matcher—where-matcher conformance holds: 282 matcher(s) discovered, 282 answer the combinator battery correctly or refuse it loudly... 0 silently-wrong and 0 unjudged... baseline key set verified against dd84ddd: no files added.pnpm check:nul-bytes—check-nul-bytes: OK (scanned 6513 text file(s) -- 6513 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).pnpm check:type-check-debt(real re-measure, full workspace closure built first viapnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*', 70/70 tasks) —check-type-check-coverage --re-measure: OK — 33 ledger entr(ies) re-measured in 254.0s, 1897 raw tsc error(s) total, none above its recorded number.@objectstack/runtime's own TEST_DEBT entry went DOWN (227 recorded → 226 measured), not up.All of the above were run at
10a5a453d2(this PR's current head).Out of scope
versionliteral —getDiscovery()inpackages/metadata-protocol/src/protocol.ts, identical defect to #10993, different producer/package #11235 — a third hardcoded discoveryversionliteral,packages/metadata-protocol/src/protocol.ts:5095('1.0'), a different package/producer.Generated by Claude Code