From 1542d3a9c77f845354b3d421786eb51729666dac Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 4 Sep 2026 16:54:11 -0400 Subject: [PATCH] feat: Report BYOM worker readiness --- packages/code/src/protocol.ts | 11 +++++ service/src/bridge/router.test.ts | 73 +++++++++++++++++++++++++++++++ service/src/bridge/router.ts | 17 +++++++ service/src/bridge/store.test.ts | 28 ++++++++++++ service/src/bridge/store.ts | 66 ++++++++++++++++++++++++++++ 5 files changed, 195 insertions(+) diff --git a/packages/code/src/protocol.ts b/packages/code/src/protocol.ts index 3bbd83cb..37288d63 100644 --- a/packages/code/src/protocol.ts +++ b/packages/code/src/protocol.ts @@ -433,6 +433,17 @@ export interface BridgeWorkerRegistrationResponse { supportedWorkspaceListFileFeatures?: WorkspaceListFileFeature[]; } +/** Administrator-visible liveness for a configured worker. Credentials, + * bindings, host paths, and worker identity material are deliberately omitted. */ +export interface BridgeWorkerStatusResponse { + protocolVersion: BridgeProtocolVersion; + workerId: string; + online: boolean; + ready: boolean; + leaseExpiresInMs?: number; + capabilities?: BridgeWorkerCapabilities; +} + export interface BridgePairingRedemption { protocolVersion: BridgeProtocolVersion; workerId: string; diff --git a/service/src/bridge/router.test.ts b/service/src/bridge/router.test.ts index 11b0eb31..764613a5 100644 --- a/service/src/bridge/router.test.ts +++ b/service/src/bridge/router.test.ts @@ -25,6 +25,79 @@ afterEach(async () => { }); describe('paired bridge HTTP API', () => { + test('reports authenticated worker readiness without exposing identity or binding data', async () => { + const store = new RedisBridgeStore(redis); + const app = express(); + app.use(json()); + app.use( + '/v1/bridge', + createBridgeRouter({ + store, + pairings: new RedisBridgePairingStore(redis), + authMode: 'paired', + adminToken: 'strong-administrator-bootstrap-token', + allowDynamicWorkers: true, + }), + ); + server = createServer(app); + await new Promise((resolve) => server?.listen(0, '127.0.0.1', resolve)); + const address = server.address(); + if (address == null || typeof address === 'string') { + throw new Error('Expected TCP listener'); + } + const baseUrl = `http://127.0.0.1:${address.port}/v1/bridge`; + const headers = { Authorization: 'Bearer strong-administrator-bootstrap-token' }; + + const offline = await fetch(`${baseUrl}/workers/user-vm/status`, { headers }); + expect(offline.status).toBe(200); + await expect(offline.json()).resolves.toEqual({ + protocolVersion: BRIDGE_PROTOCOL_VERSION, + workerId: 'user-vm', + online: false, + ready: false, + }); + + const capabilities = { + statefulWorkspace: true, + sandboxProfile: 'native-srt', + runtimes: ['bash'], + requiresReadyConfirmation: true, + }; + const registrationGeneration = await store.register({ + protocolVersion: BRIDGE_PROTOCOL_VERSION, + workerId: 'user-vm', + incarnationId: 'incarnation-00000001', + capabilities, + binding: { + tenantId: 'tenant-1', + principal: { type: 'user', id: 'user-1' }, + }, + credentialId: 'secret-credential-id', + identityId: 'secret-identity-id', + }); + + const starting = await fetch(`${baseUrl}/workers/user-vm/status`, { headers }); + expect(starting.status).toBe(200); + await expect(starting.json()).resolves.toMatchObject({ + workerId: 'user-vm', + online: true, + ready: false, + capabilities, + }); + expect( + JSON.stringify(await (await fetch(`${baseUrl}/workers/user-vm/status`, { headers })).json()), + ).not.toMatch(/tenant-1|user-1|secret-credential-id|secret-identity-id/); + + await store.confirmReady('user-vm', 'incarnation-00000001', registrationGeneration); + const ready = await fetch(`${baseUrl}/workers/user-vm/status`, { headers }); + const status = (await ready.json()) as Record; + expect(status).toMatchObject({ workerId: 'user-vm', online: true, ready: true, capabilities }); + expect(status.leaseExpiresInMs).toBeNumber(); + + const unauthorized = await fetch(`${baseUrl}/workers/user-vm/status`); + expect(unauthorized.status).toBe(401); + }); + test('rejects a malformed optional binding for a configured worker', async () => { const app = express(); app.use(json()); diff --git a/service/src/bridge/router.ts b/service/src/bridge/router.ts index 7fa87b93..f428bdbe 100644 --- a/service/src/bridge/router.ts +++ b/service/src/bridge/router.ts @@ -312,6 +312,23 @@ export function createBridgeRouter(options: BridgeRouterOptions): Router { }), ); + router.get( + '/workers/:workerId/status', + adminAuth, + asyncRoute(async (req, res) => { + const workerId = req.params.workerId; + if (!validWorkerId(workerId) || !configuredWorker(workerId)) { + res.status(400).json({ error: 'Invalid bridge worker ID' }); + return; + } + const status = await options.store.workerStatus(workerId); + res.json({ + protocolVersion: BRIDGE_PROTOCOL_VERSION, + workerId, + ...status, + }); + }), + ); router.post( '/workers/register', diff --git a/service/src/bridge/store.test.ts b/service/src/bridge/store.test.ts index e08273f9..9d271551 100644 --- a/service/src/bridge/store.test.ts +++ b/service/src/bridge/store.test.ts @@ -27,6 +27,34 @@ afterEach(async () => { }); describe('RedisBridgeStore', () => { + test('reports an atomic, capability-limited worker status snapshot', async () => { + const store = new RedisBridgeStore(redis); + const capabilities = { + statefulWorkspace: true, + sandboxProfile: 'native-srt', + runtimes: ['bash'], + requiresReadyConfirmation: true, + }; + expect(await store.workerStatus('vm-status')).toEqual({ online: false, ready: false }); + + const generation = await store.register({ + protocolVersion: BRIDGE_PROTOCOL_VERSION, + workerId: 'vm-status', + incarnationId: 'incarnation-status-01', + capabilities, + }); + expect(await store.workerStatus('vm-status')).toMatchObject({ + online: true, + ready: false, + capabilities, + }); + + await store.confirmReady('vm-status', 'incarnation-status-01', generation); + const status = await store.workerStatus('vm-status'); + expect(status).toMatchObject({ online: true, ready: true, capabilities }); + expect(status.leaseExpiresInMs).toBeGreaterThan(0); + }); + test('rejects a registration whose authenticated identity was replaced', async () => { await redis.set( 'codeapi:bridge:v1:identity:fenced-worker', diff --git a/service/src/bridge/store.ts b/service/src/bridge/store.ts index 03694b1b..da3956d7 100644 --- a/service/src/bridge/store.ts +++ b/service/src/bridge/store.ts @@ -12,6 +12,8 @@ import type { import { BRIDGE_PROTOCOL_VERSION, + isValidBridgeWorkerCapabilities, + isValidBridgeWorkerId, isWorkspaceToolRequest, isWorkspaceToolResult, } from '../../../packages/code/src/protocol'; @@ -68,6 +70,13 @@ export interface RegisteredBridgeWorker extends BridgeWorkerRegistration { identityId?: string; } +export interface BridgeWorkerStatus { + online: boolean; + ready: boolean; + leaseExpiresInMs?: number; + capabilities?: BridgeWorkerRegistration['capabilities']; +} + function supportsWorkspaceTool( registration: RegisteredBridgeWorker, request: WorkspaceToolRequest, @@ -309,6 +318,63 @@ export class RedisBridgeStore { ); } + /** Returns only the worker's ephemeral registration state. The registration + * is the heartbeat: when its TTL expires the worker is offline. */ + async workerStatus(workerId: string): Promise { + const snapshot = (await boundedCommand( + this.redis.eval( + [ + "local registration = redis.call('GET', KEYS[1])", + "if not registration then return { false, false, false, -2 } end", + 'return {', + ' registration,', + " redis.call('GET', KEYS[2]) or false,", + " redis.call('GET', KEYS[3]) or false,", + " redis.call('PTTL', KEYS[1])", + '}', + ].join('\n'), + 3, + workerKey(workerId), + workerReadyKey(workerId), + workerRegistrationGenerationKey(workerId), + ), + this.redisCommandTimeoutMs, + 'Bridge worker status', + )) as [string | null, string | null, string | null, number]; + const [rawRegistration, readyToken, registrationGeneration, leaseExpiresInMs] = snapshot; + if (rawRegistration == null || rawRegistration === '' || leaseExpiresInMs <= 0) { + return { online: false, ready: false }; + } + + let registration: RegisteredBridgeWorker; + try { + registration = JSON.parse(rawRegistration) as RegisteredBridgeWorker; + } catch { + return { online: false, ready: false }; + } + if ( + registration.protocolVersion !== BRIDGE_PROTOCOL_VERSION || + !isValidBridgeWorkerId(registration.workerId) || + registration.workerId !== workerId || + typeof registration.incarnationId !== 'string' || + !isValidBridgeWorkerCapabilities(registration.capabilities) + ) { + return { online: false, ready: false }; + } + + const requiresConfirmation = registration.capabilities.requiresReadyConfirmation === true; + const ready = + !requiresConfirmation || + (registrationGeneration != null && + readyToken === workerReadyToken(registration.incarnationId, Number(registrationGeneration))); + return { + online: true, + ready, + leaseExpiresInMs, + capabilities: registration.capabilities, + }; + } + async register( registration: RegisteredBridgeWorker, authorization?: string | {