fix(orchestration): defer local mutation identity

This commit is contained in:
Brennan Benson
2026-08-14 17:22:32 -07:00
parent 2da726bc42
commit 46a5694288
2 changed files with 63 additions and 6 deletions
@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { z } from 'zod'
import { RpcDispatcher } from './dispatcher'
import { defineMethod, InvalidArgumentError, type RpcRequest } from './core'
@@ -37,6 +37,20 @@ const METHODS = [
handler: () => {
throw new InvalidArgumentError('Async validation rejected payload')
}
}),
defineMethod({
name: 'orchestration.inspectCaller',
params: z.object({}),
handler: (_params, { authenticatedCallerFingerprint }) => ({
authenticatedCallerFingerprint
})
}),
defineMethod({
name: 'orchestration.federationInspectCaller',
params: z.object({}),
handler: (_params, { authenticatedCallerFingerprint }) => ({
authenticatedCallerFingerprint
})
})
]
@@ -109,12 +123,16 @@ describe('RpcDispatcher computer-use validation errors', () => {
})
})
it('maps async validation errors to invalid_argument without shadowing Zod formatting', async () => {
it('maps async validation errors over streaming transport without shadowing Zod formatting', async () => {
const messages: string[] = []
const dispatcher = new RpcDispatcher({ runtime: makeRuntime(), methods: METHODS })
const response = await dispatcher.dispatch(makeRequest('orchestration.invalidArgument', {}))
await dispatcher.dispatchStreaming(
makeRequest('orchestration.invalidArgument', {}),
(message) => messages.push(message)
)
expect(response).toMatchObject({
expect(JSON.parse(messages[0]!)).toMatchObject({
ok: false,
error: {
code: 'invalid_argument',
@@ -122,4 +140,35 @@ describe('RpcDispatcher computer-use validation errors', () => {
}
})
})
it('forwards a paired caller fingerprint without requiring local orchestration state', async () => {
const dispatcher = new RpcDispatcher({ runtime: makeRuntime(), methods: METHODS })
const response = await dispatcher.dispatch(makeRequest('orchestration.inspectCaller', {}), {
authenticatedCallerFingerprint: 'paired-caller'
})
expect(response).toMatchObject({
ok: true,
result: { authenticatedCallerFingerprint: 'paired-caller' }
})
})
it('provides local identity to read-only federation authorization', async () => {
const getOrCreateLocalMutationCallerFingerprint = vi.fn(() => 'local-caller')
const runtime = Object.assign(makeRuntime(), {
getOrchestrationDb: () => ({ getOrCreateLocalMutationCallerFingerprint })
})
const dispatcher = new RpcDispatcher({ runtime, methods: METHODS })
const response = await dispatcher.dispatch(
makeRequest('orchestration.federationInspectCaller', {})
)
expect(response).toMatchObject({
ok: true,
result: { authenticatedCallerFingerprint: 'local-caller' }
})
expect(getOrCreateLocalMutationCallerFingerprint).toHaveBeenCalledOnce()
})
})
+10 -2
View File
@@ -10,6 +10,7 @@ import {
} from './core'
import type { FeatureInteractionId } from '../../../shared/feature-interactions'
import { isOrchestrationMutation } from '../../../shared/orchestration-rpc-contract'
import { errorResponse, successResponse } from './errors'
import { ALL_RPC_METHODS } from './methods'
import { emulatorProbe, emulatorProbeError } from '../../emulator/emulator-probe'
@@ -93,7 +94,7 @@ export class RpcDispatcher {
)
const authenticatedCallerFingerprint =
options?.authenticatedCallerFingerprint ??
(request.method.startsWith('orchestration.')
(needsLocalCallerFingerprint(request, effectiveParams)
? this.orchestrationMutations.getLocalAuthenticatedCallerFingerprint()
: undefined)
const invoke = (mutation?: DurableMutationInvocation) => {
@@ -186,7 +187,7 @@ export class RpcDispatcher {
)
const authenticatedCallerFingerprint =
options?.authenticatedCallerFingerprint ??
(request.method.startsWith('orchestration.')
(needsLocalCallerFingerprint(request, effectiveParams)
? this.orchestrationMutations.getLocalAuthenticatedCallerFingerprint()
: undefined)
const invoke = (mutation?: DurableMutationInvocation) => {
@@ -303,3 +304,10 @@ export class RpcDispatcher {
return { runtimeId: this.runtime.getRuntimeId() }
}
}
function needsLocalCallerFingerprint(request: RpcRequest, params: unknown): boolean {
return (
request.method.startsWith('orchestration.federation') ||
(!!request.orchestrationRequestId && isOrchestrationMutation(request.method, params))
)
}