Files
orca/src/shared/runtime-source-env.ts
T
OrcaWinandm4air 7aa91f730a fix(cli): check the runtime source before sending (#27206)
* fix(cli): check the runtime source before sending

A terminal Orca launches now carries which Orca launched it
(ORCA_RUNTIME_SOURCE_ID = the profile's installation id,
ORCA_RUNTIME_SOURCE_INCARNATION = the launching runtime id). Before a
request is sent, the CLI compares that with the runtime the profile's
runtime record names. Same runtime: sent as before. Different runtime:
a read-only status.get asks which profile it serves; the same profile (a
restart or update) is accepted, anything else is refused before the
request reaches it.

The vars cross into WSL through WSLENV. The SSH bridge stamps the
bridging runtime itself rather than trusting the remote env. The
existing orchestration compatibility stamp is untouched.

* fix(orcad): drop an inherited runtime source at startup

* fix(cli): an explicit switch to another profile is not fenced

The stamp also carries the launching runtime's userData path. A CLI that
dials a different profile than the one that launched its terminal, and
not the platform default an unpinned terminal falls back to, was pointed
there on purpose (orca-dev from a packaged Orca's terminal), so the
fence does not apply.

* refactor(cli): reuse the shared userData path comparison

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-10 03:19:14 -07:00

51 lines
2.0 KiB
TypeScript

// Which Orca runtime launched a process. Kept separate from the orchestration compatibility stamp,
// whose WSL/SSH union carries caller attestation and must stay untouched.
export const RUNTIME_SOURCE_ID_ENV = 'ORCA_RUNTIME_SOURCE_ID'
export const RUNTIME_SOURCE_INCARNATION_ENV = 'ORCA_RUNTIME_SOURCE_INCARNATION'
export const RUNTIME_SOURCE_PROFILE_PATH_ENV = 'ORCA_RUNTIME_SOURCE_PROFILE_PATH'
export type RuntimeSourceStamp = {
/** The launching profile's installation id; survives restarts. */
sourceId: string
/** The launching runtime's per-process id; only a hint that skips the probe. */
incarnation: string
/** The launching runtime's userData path, so an explicit switch to another profile is not refused. */
profilePath?: string
}
const MAX_SOURCE_FIELD_LENGTH = 4_096
function boundedValue(value: string | undefined): string | undefined {
const trimmed = value?.trim()
return trimmed && trimmed.length <= MAX_SOURCE_FIELD_LENGTH ? trimmed : undefined
}
export function readRuntimeSourceStamp(
env: Readonly<Record<string, string | undefined>>
): RuntimeSourceStamp | null {
const sourceId = boundedValue(env[RUNTIME_SOURCE_ID_ENV])
const incarnation = boundedValue(env[RUNTIME_SOURCE_INCARNATION_ENV])
const profilePath = boundedValue(env[RUNTIME_SOURCE_PROFILE_PATH_ENV])
if (!sourceId || !incarnation) {
return null
}
return profilePath ? { sourceId, incarnation, profilePath } : { sourceId, incarnation }
}
/** Replaces any inherited stamp, so a nested Orca never passes on its parent's source. */
export function stampRuntimeSourceEnv(
env: Record<string, string | undefined>,
stamp: RuntimeSourceStamp | null
): void {
delete env[RUNTIME_SOURCE_ID_ENV]
delete env[RUNTIME_SOURCE_INCARNATION_ENV]
delete env[RUNTIME_SOURCE_PROFILE_PATH_ENV]
if (stamp) {
env[RUNTIME_SOURCE_ID_ENV] = stamp.sourceId
env[RUNTIME_SOURCE_INCARNATION_ENV] = stamp.incarnation
if (stamp.profilePath) {
env[RUNTIME_SOURCE_PROFILE_PATH_ENV] = stamp.profilePath
}
}
}