import { describe, expect, it } from 'vitest'; import type { CommandDef, SlashCommandPayload } from '@mosaicstack/types'; import { CommandAuthorizationService } from './command-authorization.service.js'; const adminCommand: CommandDef = { name: 'gc', description: 'GC', aliases: [], scope: 'admin', execution: 'socket', available: true, }; const payload: SlashCommandPayload = { command: 'gc', conversationId: 'conversation-1' }; function createService( role: string, entries: Map = new Map(), ): CommandAuthorizationService { const db = { select: () => ({ from: () => ({ where: () => ({ limit: async () => [{ role }] }) }) }), }; const redis = { get: async (key: string) => entries.get(key) ?? null, set: async (key: string, value: string) => { entries.set(key, value); }, del: async (key: string) => Number(entries.delete(key)), }; return new CommandAuthorizationService(db as never, redis); } describe('CommandAuthorizationService', () => { it('consumes one exact actor-bound approval once', async (): Promise => { const service = createService('admin'); const approval = await service.createApproval(adminCommand, payload, 'admin-1'); expect(approval).not.toBeNull(); expect( (await service.authorize(adminCommand, payload, 'admin-1', approval!.approvalId)).allowed, ).toBe(true); expect( (await service.authorize(adminCommand, payload, 'admin-1', approval!.approvalId)).allowed, ).toBe(false); }); it('rejects an approval when the structured action is mutated', async (): Promise => { const service = createService('admin'); const approval = await service.createApproval(adminCommand, payload, 'admin-1'); const mutated = { ...payload, conversationId: 'other-conversation' }; expect(approval).not.toBeNull(); expect( (await service.authorize(adminCommand, mutated, 'admin-1', approval!.approvalId)).allowed, ).toBe(false); }); it('denies an admin command to a member before approval is considered', async (): Promise => { const service = createService('member'); const approval = await service.createApproval(adminCommand, payload, 'member-1'); expect(approval).toBeNull(); expect( (await service.authorize(adminCommand, payload, 'member-1', 'forged-approval-id')).allowed, ).toBe(false); }); it('denies non-admin scopes to a platform admin (contract 2 ยง1.1 bypass retirement)', async (): Promise => { const service = createService('admin'); for (const scope of ['core', 'agent', 'skill', 'plugin'] as const) { const command: CommandDef = { ...adminCommand, name: `probe-${scope}`, scope }; expect( (await service.authorize(command, { ...payload, command: command.name }, 'admin-1')) .allowed, ).toBe(false); } }); it('allows member core/agent scopes and denies skill/plugin (deny-by-default)', async (): Promise => { const service = createService('member'); for (const [scope, allowed] of [ ['core', true], ['agent', true], ['skill', false], ['plugin', false], ] as const) { const command: CommandDef = { ...adminCommand, name: `probe-${scope}`, scope }; expect( (await service.authorize(command, { ...payload, command: command.name }, 'member-1')) .allowed, ).toBe(allowed); } }); it('denies a malformed durable approval expiry instead of treating it as unexpired', async (): Promise => { const entries = new Map(); const action = { providerId: 'fleet', sessionId: 'nova', actorId: 'admin-1', tenantId: 'tenant-1', channelId: 'discord:operator', correlationId: 'correlation-malformed-expiry', agentName: 'Nova', }; const service = createService('admin', entries); const approval = await service.createRuntimeTerminationApproval(action); expect(approval).not.toBeNull(); const key = `agent:Nova:command-approval:${approval!.approvalId}`; const stored = entries.get(key); expect(stored).toBeDefined(); entries.set(key, JSON.stringify({ ...JSON.parse(stored!), expiresAt: 'not-a-date' })); expect(await service.consumeRuntimeTerminationApproval(approval!.approvalId, action)).toBe( false, ); }); it('persists and consumes one exact runtime termination approval across a service restart', async (): Promise => { const entries = new Map(); const action = { providerId: 'fleet', sessionId: 'nova', actorId: 'admin-1', tenantId: 'tenant-1', channelId: 'discord:operator', correlationId: 'correlation-1', agentName: 'Nova', }; const beforeRestart = createService('admin', entries); const approval = await beforeRestart.createRuntimeTerminationApproval(action); const afterRestart = createService('admin', entries); expect( await afterRestart.consumeRuntimeTerminationApproval(approval!.approvalId, { ...action, sessionId: 'forged-session', }), ).toBe(false); expect(await afterRestart.consumeRuntimeTerminationApproval(approval!.approvalId, action)).toBe( true, ); expect(await afterRestart.consumeRuntimeTerminationApproval(approval!.approvalId, action)).toBe( false, ); }); });