diff --git a/apps/gateway/src/chat/chat.gateway.ts b/apps/gateway/src/chat/chat.gateway.ts index 1cde3a7..e8c9fc7 100644 --- a/apps/gateway/src/chat/chat.gateway.ts +++ b/apps/gateway/src/chat/chat.gateway.ts @@ -667,7 +667,8 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa 'approve', ); const actorId = binding && resolveDiscordInteractionActorId(binding, ingress.userId); - if (!actorId) return; + const agentName = process.env['MOSAIC_AGENT_NAME']?.trim(); + if (!actorId || !agentName || binding.instanceId !== agentName) return; const providerId = actionParts[1]!; const sessionId = actionParts[2]!; const approval = await this.commandAuthorization.createRuntimeTerminationApproval({ @@ -682,7 +683,7 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa providerId, sessionId, ), - agentName: binding.instanceId, + agentName, }); client.emit('discord:approval', { correlationId: ingress.correlationId, diff --git a/apps/gateway/src/plugin/discord-ingress.security.spec.ts b/apps/gateway/src/plugin/discord-ingress.security.spec.ts index 87fed51..9efd067 100644 --- a/apps/gateway/src/plugin/discord-ingress.security.spec.ts +++ b/apps/gateway/src/plugin/discord-ingress.security.spec.ts @@ -8,6 +8,7 @@ import { resolveDiscordInteractionActorId, resolveDiscordInteractionBinding, } from '@mosaicstack/discord-plugin'; +import { RuntimeProviderService } from '../agent/runtime-provider-registry.service.js'; import { ChatGateway } from '../chat/chat.gateway.js'; import { CommandAuthorizationService } from '../commands/command-authorization.service.js'; import { validateDiscordServiceToken } from '../chat/chat.gateway-auth.js'; @@ -79,33 +80,21 @@ function discordGateway(role: 'admin' | 'member'): { } { const authorization = commandAuthorization(role); const consumedActions: Array<{ actorId: string; correlationId: string }> = []; - const runtimeRegistry = { - terminate: async ( - providerId: string, - sessionId: string, - approvalId: string, - context: { - actorScope: { userId: string; tenantId: string }; - channelId: string; - correlationId: string; + const runtimeRegistry = new RuntimeProviderService( + { + require: () => ({ + capabilities: async () => ({ supported: ['session.terminate'] }), + terminate: async () => undefined, + }), + } as never, + { record: async () => undefined } as never, + { + consume: async (approvalId, action) => { + consumedActions.push({ actorId: action.actorId, correlationId: action.correlationId }); + return authorization.consumeRuntimeTerminationApproval(approvalId, action); }, - ): Promise => { - consumedActions.push({ - actorId: context.actorScope.userId, - correlationId: context.correlationId, - }); - const approved = await authorization.consumeRuntimeTerminationApproval(approvalId, { - providerId, - sessionId, - actorId: context.actorScope.userId, - tenantId: context.actorScope.tenantId, - channelId: context.channelId, - correlationId: context.correlationId, - agentName: 'Nova', - }); - if (!approved) throw new Error('approval denied'); }, - }; + ); return { gateway: new ChatGateway( {} as never, @@ -115,7 +104,7 @@ function discordGateway(role: 'admin' | 'member'): { {} as never, {} as never, authorization, - runtimeRegistry as never, + runtimeRegistry, ), client: { data: { discordService: true }, emit: vi.fn() }, consumedActions,