fix(app-shell): read the provisioned env from the nested environment row - #6706
Merged
Merged
Conversation
…` row
`POST /api/v1/cloud/environments` answers `{ success, data: { environment,
warnings, durationMs, hostnameAssignment? } }` — the created row is one level
down. `provisionProductionEnvironment` read `data` flat and returned it as a
`ProvisionedEnvironment`, so `id` and `hostname` were always `undefined` and
the envelope's siblings rode along in their place.
Silent by construction: both fields are optional, the call is best-effort by
contract (403/409 resolves to `alreadyProvisioned`) and the caller swallows
genuine failures — so the function reported a successful provision carrying no
environment at all, the exact outcome the strict envelope check in that file
was written to prevent. That check verifies `data` is an object and nothing
about its shape; it is left unchanged here.
The row is now projected to `{ id, hostname }`. One dialect only: no
`data.environment ?? data` alias, and a wrong-shaped `data` still resolves
rather than throws.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-sales
marked this pull request as ready for review
August 28, 2026 18:03
This was referenced Aug 28, 2026
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 #6629
POST /api/v1/cloud/environmentsanswers{ success, data: { environment, warnings, durationMs, hostnameAssignment? } }— the created row sits one level down, underenvironment.provisionProductionEnvironmentreaddataFLAT and returned it as aProvisionedEnvironment, soidandhostnamewere alwaysundefinedand the envelope's siblings rode along in their place.The row is now projected to
{ id, hostname }.Which half is measured, which is inherited
Consumer half — MEASURED here, on merge-base
5967be095, inpackages/app-shell/src/console/organizations/provisionEnvironment.ts:ProvisionedEnvironmentis declared{ id?: string; hostname?: string; alreadyProvisioned?: boolean }, withiddocumented as the control-planesys_environmentrow id;{ data?: ProvisionedEnvironment }, and the envelope check isif (!data || typeof data !== 'object') throw;return data— the wrapper itself.So the card's claim is confirmed against the actual code: the check verifies
datais an object and nothing about its shape. A payload of{ environment, warnings, durationMs }passes it unchanged and is returned whole as a value typedProvisionedEnvironment.Producer half — INHERITED, not measured. The producer evidence is
packages/service-cloud/src/routes/environment-lifecycle.tsinobjectstack-ai/cloud, which this repo cannot read. I searched this repo for a second source of the wire shape and found none: no fixture, no recorded response, and no typed client declares the create-environment response (hostnameAssignmentappears nowhere innode_modules/@objectstack/**). The only in-repo artifact that pinned the success-payload shape was this suite's own hand-written mock — and it pinned the FLAT shape, i.e. it pinned the bug. The fix is therefore pinned against the card's stated wire shape, declared as inherited.Anti-vacuity: RED before, GREEN after
This bug is quiet by construction — both fields optional, the call best-effort by contract, 403/409 resolving to
alreadyProvisioned: true, the caller swallowing genuine failures — so a test that merely asserts the fixed path is green would have been green before the fix too. The tests were therefore written and run against the unmodified merge-base implementation first.RED on
5967be095, implementation untouched, test file only —Tests 3 failed | 4 passed (7):environmentrow, not from the wrapperexpected { …(4) } to deeply equal { id: 'env-1', …(1) }datashape whenenvironmentis absentexpected 'flat-1' to be undefinedexpected { environment: { id: 'env-1', …(1) } } to match object { id: 'env-1', …(1) }GREEN after the fix —
Test Files 18 passed (18)/Tests 116 passed (116), run at35fe8741b.The second row is the anti-alias pin: it asserts a flat
datais not picked up (nodata.environment ?? data), and it is red pre-fix precisely because the old code did read it. The third was an existing fixture that pinned the wrong wire shape; retriaged rather than deleted.Deliberately NOT folded in: tightening the envelope check
A wrong-shaped
datastill resolves (withid/hostnameundefined) rather than throwing. Rejecting it is a tempting adjacent fix and may well be right, but it is a behaviour change on an error path that currently resolves best-effort. Blast radius as measured in this repo: the sole caller isCreateWorkspaceDialog.tsx, which wraps the call intry/catchand on throw logs a warning and falls through to the lazy onboarding gate — so a tightened check would convert a silent no-op into a logged failure plus a lazy re-provision on first navigation. That is a real user-visible path change and belongs in its own card, not here.The ADR-0006 D2 rename is not being raced
The cloud control plane is mid-rename under ADR-0006 D2 (epic objectstack-ai/objectstack#12865), where response payload keys
project/projectsbecomeenvironment/environmentson the OTHER control-plane routes.POST /cloud/environmentsis not part of that rename — it has always answeredenvironment— so this change is stable against that work rather than racing it. Reviewers should not have to rediscover this. Originally found while implementing the producer-half rename in objectstack-ai/cloud#1691.Changeset
Scored
patchin.changeset/6629-provision-env-nested-envelope.md. Reasoning: this is shipped runtime code in a released package whose return value is now different, not a comment or a test-only change, so an empty "no release" frontmatter would assert something false. Notminor— no new capability and no API surface change;ProvisionedEnvironmentis unchanged. The blast radius is small today (the sole in-repo caller discards the return value, and the symbol is not on the package barrel), but small is not unreleased.Verification
All heavy runs went through the shared verify lock. Union run at
35fe8741b; the working tree was clean at that commit, so the lint and type-check readings below are on the identical bytes.pnpm exec vitest run packages/app-shell/src/console/organizations/plus the six app-shell ratchet suites —Test Files 18 passed (18),Tests 116 passed (116), lockVERDICT command-exit 0.pnpm --filter "@object-ui/app-shell" run type-check—VERDICT command-exit 0. Both passes ran (tsc --noEmit && tsc -p tsconfig.test.json); the second is what covers test files, sincetsconfig.jsonexcludes them.pnpm --filter "@object-ui/app-shell" run lint— whole-packageeslint .,0 errors, 2779 warnings(all pre-existing; neither changed file appears). Scoped to app-shell because it is the only package this diff touches, and the rooteslint.config.jsdeclares noparserOptions.project/projectService, so no untouched file's verdict can move.pnpm --filter "@object-ui/app-shell^..." run build, 29 projects, exit 0) — the pre-existingdist/was from an older base.check-changeset-presence,check-changeset-fixed,check-changeset-no-major,check-changeset-overwrite,check-control-bytes,check-vi-mock-specifiers— all exit 0 with their own OK lines.Generated by Claude Code
Generated by Claude Code