Skip to content

Commit 9b4e870

Browse files
xuyushun441-sysos-zhuangclaude
authored
fix(cloud-connection): never present env_local/proj_local as cloud environment ids (#1786)
The CLI's dev/serve default OS_ENVIRONMENT_ID=env_local names the LOCAL kernel, not a control-plane environment. Presenting it to the cloud 404s the bind and resurrects the phantom-environment confusion that ADR runtime-identity-binding removes. Filter the sentinels in resolveEnvironmentId — such runtimes are simply unbound until the device-code registration completes. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 9fea621 commit 9b4e870

3 files changed

Lines changed: 24 additions & 1 deletion

File tree

.changeset/local-env-sentinel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@objectstack/cloud-connection": patch
3+
---
4+
5+
`resolveEnvironmentId` no longer presents the CLI's local-dev sentinel ids (`env_local` / `proj_local`) to the control plane as cloud environment ids — they identify the local kernel only. A single-environment runtime started via `objectstack dev` now reads as cleanly unbound and binds environment-less (ADR runtime-identity-binding), instead of 404-ing the bind against a non-existent cloud environment.

packages/cloud-connection/src/cloud-connection-plugin.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ describe('single-environment mode (host auth, fixed env id)', () => {
220220
expect(res.payload.data.total).toBe(1);
221221
});
222222

223+
it("ignores the CLI's local sentinel env ids (env_local / proj_local)", async () => {
224+
process.env.OS_ENVIRONMENT_ID = 'env_local';
225+
const rawApp = makeRawApp();
226+
const { ctx, fireKernelReady } = makeCtx({ rawApp });
227+
await new CloudConnectionPlugin({ singleEnvironment: true, controlPlaneUrl: 'http://cloud.test' }).start(ctx as any);
228+
await fireKernelReady();
229+
const res = await rawApp.routes.get('GET /api/v1/cloud-connection/status')!(makeC('http://localhost:3000/x'));
230+
expect(res.status).toBe(200);
231+
// Treated as "no cloud environment", not presented to the control plane.
232+
expect(res.payload.data.environmentId).toBeNull();
233+
expect(res.payload.data.bound).toBe(false);
234+
});
235+
223236
it('falls back to OS_ENVIRONMENT_ID when no config id is given', async () => {
224237
process.env.OS_ENVIRONMENT_ID = 'env-from-env-var';
225238
const rawApp = makeRawApp();

packages/cloud-connection/src/cloud-connection-plugin.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,12 @@ export class CloudConnectionPlugin implements Plugin {
147147

148148
const resolveEnvironmentId = async (c: any): Promise<string | undefined> => {
149149
const fixed = (this.cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? '').trim();
150-
if (fixed) return fixed;
150+
// The CLI's local-dev defaults ('env_local' / 'proj_local')
151+
// identify the LOCAL kernel, not a cloud environment — never
152+
// present them to the control plane as one (they would 404
153+
// the bind and resurrect the phantom-environment confusion
154+
// ADR runtime-identity-binding removes).
155+
if (fixed && fixed !== 'env_local' && fixed !== 'proj_local') return fixed;
151156
if (this.cfg.singleEnvironment) {
152157
// A completed bind persisted the environment id — a
153158
// self-hosted runtime needs no OS_ENVIRONMENT_ID after it.

0 commit comments

Comments
 (0)