Files
orca/src/cli/remote-selection-flag-rejection.ts
T
Neil 9bed758e36 fix(cli): reject runtime selectors on host list and environment list (#18405)
`orca host list --environment m4air` was not ignoring the flag — it was applying
it to half the answer. `shouldIgnoreRemoteSelection` never pinned the `host`
family, so the SSH-target lookup was routed to m4air while paired servers were
still read from this machine's own pairing store, and the handler stamped the
envelope `_meta.runtimeId: "local"` regardless. The result was one listing
describing two hosts: the openclaw row silently disappeared, which reads as
"m4air has no SSH targets". `environment list --environment X` had the pin but
no guard, so the flag vanished with no signal at all.

Reject rather than route. `host list` answers "what can this machine target and
with what flag"; its paired-server half comes from a client-local store and
cannot be routed at all, so any routed answer is necessarily half-substituted —
rule 1 of docs/reference/ssh-execution-boundary.md. `environment list` is
entirely client-local, so there is no other host to ask. This matches the
`account` and `artifacts` precedent, the only two pinned families that already
paired the pin with a rejection guard.

- pin the `host` family so an ambient ORCA_ENVIRONMENT cannot produce the same
  two-machine listing with no flag to reject; `runtimeId: "local"` is now true
- extract the duplicated `rejectRemoteSelectionFlags` from account.ts and
  artifacts.ts into src/cli/remote-selection-flag-rejection.ts
- `environment show` / `environment rm` / `environment add` are untouched: there
  `--environment` and `--pairing-code` name the row to act on, not a route
2026-09-03 14:43:05 -07:00

30 lines
1.0 KiB
TypeScript

import { RuntimeClientError } from './runtime/types'
/**
* The flags that pick which runtime answers a command. `shouldIgnoreRemoteSelection`
* in `src/cli/index.ts` pins some command families to the local runtime, which drops
* these silently — so every pinned family pairs the pin with this rejection instead.
*/
export const REMOTE_SELECTION_FLAGS = ['environment', 'pairing-code'] as const
/**
* Fails a pinned command that was given a runtime selector, rather than answering
* for a machine the caller did not name. `suffix` completes "`--<flag>` does not
* retarget …" and should say what the command answers for and where to run it.
*/
export function rejectRemoteSelectionFlags(
flags: ReadonlyMap<string, string | boolean>,
suffix: string,
data?: Record<string, unknown>
): void {
for (const flag of REMOTE_SELECTION_FLAGS) {
if (flags.has(flag)) {
throw new RuntimeClientError(
'invalid_argument',
`\`--${flag}\` does not retarget ${suffix}`,
data
)
}
}
}