fix(showcase): resolve self-pointing connector baseUrl from the environment instead of a hard-wired 127.0.0.1:3000 - #7621
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-help
marked this pull request as ready for review
August 11, 2026 09:40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7538
What was wrong
StatusApiConnectorandStatusOpenApiConnectorcarried the literalhttp://127.0.0.1:3000inproviderConfig.baseUrl(examples/app-showcase/src/system/connectors/index.ts:57/:89). Any instance not listening on 3000 — CI, QA, any dev boot on an isolated port — could not self-ping, and every flow dispatching through those connectors failed withfetch failed. That symptom is indistinguishable from a sandbox egress block, which is what made it expensive to diagnose.The premise held on
origin/main: both literals were present exactly as triage reported, plusstatus-openapi.json:8'sserversURL.The measured question: can connector metadata read env?
The old comment at
:55asserted "metadata files don't read env". That is false, and the PR removes it.src/system/connectors/index.tsis an ordinary Node module imported byobjectstack.config.ts(line 37), which itself already readsprocess.envat line 135 — same module graph, same process, same evaluation. Measured end to end below.There is a real timing caveat, now documented in the new module rather than left as folklore: the read happens in whichever process loads
objectstack.config.ts. On theos dev/os servepath (serveloads the config when present) that is the serving process, so the value follows the live environment. On the artifact-only path (os buildonce,os start --artifact) the connector metadata is serialized intodist/objectstack.json, so the value is frozen at build time. The plugin inplugins:is code and cannot be serialized at all, so it only exists on the config-load path.Shape chosen: one shared resolver, used by both self-URL sources
New
examples/app-showcase/src/system/self-url.tsexportsresolveShowcaseSelfUrl(), and both self-URL sources now call it — the declarative connector instances and theConnectorRestPluginatobjectstack.config.ts:135, which previously inlined its ownprocess.env.SHOWCASE_SELF_URL ?? '...'. That is what keeps the two from diverging, which was the point of triage's bonus lead.Resolution order, most explicit first:
SHOWCASE_SELF_URL— full base URL; the escape hatch for anything a port cannot express (different host, https, proxy prefix). Kept primary because the config already documented it.OS_PORT, then its deprecated aliasPORT— the same names, in the same order, that the CLI itself reads to pick the listen port (packages/cli/src/commands/serve.ts:204:readEnvWithDeprecation('OS_PORT', 'PORT') ?? '3000'). Following the CLI's own inputs is what makes the isolated-port boot in the issue's repro self-ping correctly with no extra configuration.http://127.0.0.1:3000— the historical literal, unchanged, so a plainpnpm devbehaves exactly as before.status-openapi.jsonkeeps its literalservers[0].url: a static document cannot follow a bound port, andcreateOpenApiConnectorresolvesconfig.baseUrl ?? document.servers[0].url(packages/connectors/connector-openapi/src/openapi-connector.ts:152), so the connector's env-resolvedbaseUrlalways wins. Itsinfo.descriptionnow says so instead of leaving the stale-looking literal unexplained.The showcase deliberately omits
@types/node, so the new module and test each declare a module-scoped ambientprocess— the same idiom (and same stated reason) asobjectstack.config.ts:55, rather than widening the sharedtest/node-shim.d.ts.Verification
Unit — new
examples/app-showcase/test/connector-self-url.test.ts(12 cases: precedence rungs, plus each connector under a non-3000 port, an explicit URL, and an empty environment).tsc --noEmitgreen.Reverse verification (predicted direction: RED on revert). Restoring the two literals via
git checkout origin/main -- .../connectors/index.ts:The four environment-following cases go red while the "still defaults to 3000" cases stay green — a literal is by construction still correct in the default case, so default-case assertions alone can never detect this bug. Both halves are required.
End-to-end through the real CLI compile (
node node_modules/@objectstack/cli/bin/run.js compile), reading the compiled artifact's connector metadata:Live self-ping — a throwaway probe script (kept out of the repo) boots an HTTP server on 4711 and dispatches through the real
createRestConnector/createOpenApiConnectorbuilt from the compiledproviderConfig:Counterfactual, same server on 4711 with the pre-fix literal — the issue's exact symptom:
That is the same before/after causality the QA run established with its TCP forwarder, obtained without one.
showcase-smoke.ymldoes NOT cover this. It is a Playwright console nav-render smoke, non-blocking, manual + nightly only, andexamples/app-showcase/playwright.config.tshard-codesconst PORT = 3000— so it exercises exactly the one port at which the bug is invisible, and it drives no connector dispatch.node scripts/check-nul-bytes.mjs: OK.origin/mainmerged before opening (batch-mate #7542 works insrc/automation/flows/, untouched here).Changeset
None —
examples/app-showcaseis"private": trueand publishes nothing, so no user-visible package releases. This PR takes theskip-changesetlabel route.Generated by Claude Code