From 533e9702591436810160dfb1cf8a42a222cfb7c7 Mon Sep 17 00:00:00 2001 From: Jarvis Date: Mon, 13 Jul 2026 03:43:50 -0500 Subject: [PATCH] fix(discord): report runtime agent binding denial --- apps/gateway/src/chat/chat.gateway.ts | 13 ++++++++++++- .../plugin/discord-ingress.security.spec.ts | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/apps/gateway/src/chat/chat.gateway.ts b/apps/gateway/src/chat/chat.gateway.ts index e8c9fc7..f3fd1b5 100644 --- a/apps/gateway/src/chat/chat.gateway.ts +++ b/apps/gateway/src/chat/chat.gateway.ts @@ -668,7 +668,18 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa ); const actorId = binding && resolveDiscordInteractionActorId(binding, ingress.userId); const agentName = process.env['MOSAIC_AGENT_NAME']?.trim(); - if (!actorId || !agentName || binding.instanceId !== agentName) return; + if (!actorId || !agentName || binding.instanceId !== agentName) { + this.logger.warn( + `Rejected Discord approval without a matching runtime agent from ${client.id}`, + ); + client.emit('discord:approval', { + correlationId: ingress.correlationId, + success: false, + approvalId: undefined, + expiresAt: undefined, + }); + return; + } const providerId = actionParts[1]!; const sessionId = actionParts[2]!; const approval = await this.commandAuthorization.createRuntimeTerminationApproval({ diff --git a/apps/gateway/src/plugin/discord-ingress.security.spec.ts b/apps/gateway/src/plugin/discord-ingress.security.spec.ts index 9efd067..3ceb840 100644 --- a/apps/gateway/src/plugin/discord-ingress.security.spec.ts +++ b/apps/gateway/src/plugin/discord-ingress.security.spec.ts @@ -271,6 +271,24 @@ describe('Discord ingress security', () => { ]); }); + it('rejects approval when the binding targets a different runtime agent', async () => { + configureDiscordEnv(); + process.env['MOSAIC_AGENT_NAME'] = 'Other'; + const { gateway, client } = discordGateway('admin'); + + await gateway.handleDiscordApproval( + client as never, + ingressEnvelope('/approve fleet runtime-1', 'mismatched-agent-approve'), + ); + + expect(client.emit).toHaveBeenCalledWith('discord:approval', { + correlationId: 'correlation-001', + success: false, + approvalId: undefined, + expiresAt: undefined, + }); + }); + it('rejects unpaired and non-admin Discord users for approval and stop', async () => { configureDiscordEnv(); const { gateway, client } = discordGateway('member');