fix(orchestration): route the legacy coordinator gate at the caller's own Run (#11745)

* fix(orchestration): route the legacy gate at the caller's own Run

The retained-legacy-coordinator gate treated an unnamed Run as the adopted
Run, so callers with no relation to it were fenced with legacy_read_only,
and the adopted Run's NULL coordinator made the owner escape hatch
unreachable.

Resolve the caller's bound Run first and keep the adopted Run only as the
unbound fallback, and treat an unclaimed adopted Run as free — the same
rule bindingMatches() already applies 100 lines down.

* refactor(orchestration): pass the open db handle into boundRunId

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-07-31 02:48:07 -07:00
committed by GitHub
co-authored by Orca
parent f936e7fc9c
commit d34bbd7917
2 changed files with 166 additions and 3 deletions
@@ -1,4 +1,5 @@
import type { OrcaRuntimeService, OrchestrationCompatibilityCallerAuthority } from '../orca-runtime'
import type { OrchestrationDb } from '../orchestration/db'
import type { LegacyCompatibilityPrincipalRow } from '../orchestration/types'
import type { LegacyCoordinatorAuthorityProof, RpcRequest } from './core'
import {
@@ -20,8 +21,12 @@ export class LegacyCoordinatorAuthority {
): LegacyCoordinatorAuthorityProof | undefined {
const db = this.runtime.getOrchestrationDb()
const adoption = db.getLegacyAdoption()
const requestedRun = requestedRunId ?? adoption?.adopted_run_id
if (!adoption || requestedRun !== adoption.adopted_run_id) {
if (!adoption) {
return undefined
}
// Why: an unnamed Run means the caller's own binding; only an unbound caller can still mean the adopted Run.
const requestedRun = requestedRunId ?? boundRunId(db, request) ?? adoption.adopted_run_id
if (requestedRun !== adoption.adopted_run_id) {
return undefined
}
const candidate = db.resolveLegacyCoordinatorCandidate({
@@ -31,10 +36,17 @@ export class LegacyCoordinatorAuthority {
})
if (!candidate) {
if (request.orchestrationCompatibilityEvidence) {
const run = db.getRun(adoption.adopted_run_id)
// Why: an unclaimed adopted Run has no coordinator to fence — same rule as bindingMatches below.
if (
!run?.coordinator_pane_key &&
!db.getLegacyCoordinatorPrincipal(adoption.adopted_run_id)
) {
return undefined
}
const caller = this.runtime.verifyOrchestrationCompatibilityCaller(
request.orchestrationCompatibilityEvidence
)
const run = db.getRun(adoption.adopted_run_id)
if (
caller &&
run?.coordinator_handle === caller.terminalHandle &&
@@ -168,3 +180,8 @@ export class LegacyCoordinatorAuthority {
)
}
}
function boundRunId(db: OrchestrationDb, request: RpcRequest): string | undefined {
const paneKey = request.orchestrationCompatibilityEvidence?.paneKey
return paneKey ? db.getCurrentRunForPane(paneKey)?.id : undefined
}
@@ -0,0 +1,146 @@
import { afterEach, describe, expect, it } from 'vitest'
import {
cleanupLegacyCompatibilityDispatcherHarnesses,
COORDINATOR_HANDLE,
createHarness,
currentEvidence,
CURRENT_COORDINATOR_HANDLE,
CURRENT_COORDINATOR_PANE,
evidence,
invoke,
request
} from './orchestration-legacy-compatibility-dispatcher-test-fixture'
afterEach(() => {
cleanupLegacyCompatibilityDispatcherHarnesses()
})
describe('legacy coordinator gate run routing', () => {
it.each(['dispatch', 'websocket'] as const)(
'%s asks an unbound caller to bind a Run instead of fencing it as a legacy coordinator',
async (transport) => {
const harness = createHarness()
const response = await invoke(
harness.dispatcher,
request(
'orchestration.taskCreate',
{
spec: 'fresh assignment',
callerTerminalHandle: CURRENT_COORDINATOR_HANDLE
},
currentEvidence('coordinator'),
`unbound-task-create-${transport}`
),
transport
)
expect(response).toMatchObject({
ok: false,
error: { code: 'run_required' }
})
expect(harness.db.listTasks({ runId: harness.adoptedRunId })).toHaveLength(1)
}
)
it('routes an unnamed Run to the caller binding even when attestation fails', async () => {
const harness = createHarness()
const run = harness.db.createRun({
objective: 'current work',
coordinatorHandle: CURRENT_COORDINATOR_HANDLE,
coordinatorPaneKey: CURRENT_COORDINATOR_PANE
})
const response = await harness.dispatcher.dispatch(
request(
'orchestration.taskCreate',
{
spec: 'fresh assignment',
callerTerminalHandle: CURRENT_COORDINATOR_HANDLE
},
{ ...currentEvidence('coordinator'), launchToken: '' },
'unattested-bound-task-create'
)
)
expect(response).toMatchObject({
ok: true,
result: { task: { run_id: run.id, spec: 'fresh assignment' } }
})
})
it('lets a current coordinator rebind the unclaimed adopted Run with actionable guidance', async () => {
const harness = createHarness()
const response = await harness.dispatcher.dispatch(
request(
'orchestration.runUse',
{ id: harness.adoptedRunId, from: CURRENT_COORDINATOR_HANDLE },
currentEvidence('coordinator'),
'unclaimed-adopted-run-use'
)
)
expect(response).toMatchObject({
ok: false,
error: {
code: 'consumer_fenced',
data: {
recoveryCommand: `orca orchestration run-use --id ${harness.adoptedRunId} --takeover-legacy`
}
}
})
})
it('still routes the retained legacy coordinator to the adopted Run without --run', async () => {
const harness = createHarness()
const response = await harness.dispatcher.dispatch(
request(
'orchestration.taskCreate',
{
spec: 'retained assignment',
callerTerminalHandle: COORDINATOR_HANDLE
},
evidence('coordinator'),
'retained-adopted-task-create'
)
)
expect(response).toMatchObject({
ok: true,
result: {
task: { run_id: harness.adoptedRunId, spec: 'retained assignment' }
}
})
})
it('still fences a stale legacy coordinator once the adopted Run is claimed', async () => {
const harness = createHarness()
harness.db.bindRun({
runId: harness.adoptedRunId,
coordinatorHandle: CURRENT_COORDINATOR_HANDLE,
coordinatorPaneKey: CURRENT_COORDINATOR_PANE,
takeoverLegacy: true
})
const response = await harness.dispatcher.dispatch(
request(
'orchestration.taskCreate',
{
spec: 'stale assignment',
run: harness.adoptedRunId,
callerTerminalHandle: COORDINATOR_HANDLE
},
evidence('coordinator'),
'claimed-adopted-task-create'
)
)
expect(response).toMatchObject({
ok: false,
error: { code: 'legacy_read_only' }
})
expect(harness.db.listTasks({ runId: harness.adoptedRunId })).toHaveLength(1)
})
})