import { describe, expect, it, vi } from 'vitest'; import type { RuntimeScope } from '@mosaicstack/types'; import { type FleetReadAuthority, type FleetWriteAuthority, TmuxFleetRuntimeProvider, } from './tmux-fleet-runtime-provider.js'; import type { FleetRuntimeProviderError, FleetRuntimeTarget, FleetRuntimeTransport, } from './tmux-fleet-runtime-provider.js'; const scope: RuntimeScope = { actorId: 'operator-1', tenantId: 'tenant-a', channelId: 'discord-1', correlationId: 'corr-1', }; const target: FleetRuntimeTarget = { id: 'coder0', runtimeId: 'codex', socketName: 'tess-fleet', }; function transport(): FleetRuntimeTransport { return { verifySession: vi.fn(async (): Promise => target), listSessions: vi.fn(async (): Promise => [target]), sendMessage: vi.fn(async (): Promise => undefined), terminate: vi.fn(async (): Promise => undefined), }; } function readAuthority(): FleetReadAuthority { return { canRead: vi.fn(async (): Promise => true) }; } describe('TmuxFleetRuntimeProvider security policy', (): void => { it('advertises only fleet operations it can safely implement', async (): Promise => { const provider = new TmuxFleetRuntimeProvider({ transport: transport() }); await expect(provider.capabilities(scope)).resolves.toEqual({ supported: [ 'session.list', 'session.tree', 'session.send', 'session.attach', 'session.terminate', ], }); }); it('rejects control attach without consulting the tmux transport', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet }); await expect(provider.attach('coder0', 'control', scope)).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); expect(fleet.verifySession).not.toHaveBeenCalled(); }); it('denies fleet listing without an exact-scope read authority decision', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet }); await expect(provider.listSessions(scope)).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); expect(fleet.listSessions).not.toHaveBeenCalled(); }); it('denies read attachment without an exact-scope read authority decision', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet }); await expect(provider.attach('coder0', 'read', scope)).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); expect(fleet.verifySession).not.toHaveBeenCalled(); }); it('creates a read-only attachment only after exact target verification', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet, readAuthority: readAuthority(), attachmentIdFactory: (): string => 'attachment-1', now: (): Date => new Date('2026-07-12T00:00:00.000Z'), }); await expect(provider.attach('coder0', 'read', scope)).resolves.toEqual({ attachmentId: 'attachment-1', sessionId: 'coder0', mode: 'read', expiresAt: '2026-07-12T00:05:00.000Z', }); expect(fleet.verifySession).toHaveBeenCalledWith('coder0'); }); it('denies attachment-handle replay from another immutable actor scope', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet, readAuthority: readAuthority(), attachmentIdFactory: (): string => 'attachment-1', now: (): Date => new Date('2026-07-12T00:00:00.000Z'), }); await provider.attach('coder0', 'read', scope); await expect( provider.detach('attachment-1', { ...scope, actorId: 'operator-2' }), ).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); }); it('keeps attachment scope immutable after caller-side scope mutation', async (): Promise => { const mutableScope = { ...scope }; const provider = new TmuxFleetRuntimeProvider({ transport: transport(), readAuthority: readAuthority(), attachmentIdFactory: (): string => 'attachment-1', now: (): Date => new Date('2026-07-12T00:00:00.000Z'), }); await provider.attach('coder0', 'read', mutableScope); mutableScope.actorId = 'operator-2'; await expect(provider.detach('attachment-1', scope)).resolves.toBeUndefined(); }); it('denies expired attachment handles and removes them', async (): Promise => { let now = new Date('2026-07-12T00:00:00.000Z'); const provider = new TmuxFleetRuntimeProvider({ transport: transport(), readAuthority: readAuthority(), attachmentIdFactory: (): string => 'attachment-1', now: (): Date => now, }); await provider.attach('coder0', 'read', scope); now = new Date('2026-07-12T00:05:00.001Z'); await expect(provider.detach('attachment-1', scope)).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); await expect(provider.detach('attachment-1', scope)).rejects.toMatchObject({ code: 'not_found', } satisfies Partial); }); it('prunes expired attachment handles before creating a new handle', async (): Promise => { let now = new Date('2026-07-12T00:00:00.000Z'); let attachmentSequence = 0; const provider = new TmuxFleetRuntimeProvider({ transport: transport(), readAuthority: readAuthority(), attachmentIdFactory: (): string => `attachment-${++attachmentSequence}`, now: (): Date => now, }); await provider.attach('coder0', 'read', scope); now = new Date('2026-07-12T00:05:00.001Z'); await provider.attach('coder0', 'read', scope); await expect(provider.detach('attachment-1', scope)).rejects.toMatchObject({ code: 'not_found', } satisfies Partial); }); it('rejects an empty message before consulting write authority or tmux', async (): Promise => { const fleet = transport(); const writeAuthority: FleetWriteAuthority = { canWrite: vi.fn(async (): Promise => true), assertAuthorized: vi.fn(async (): Promise => undefined), }; const provider = new TmuxFleetRuntimeProvider({ transport: fleet, writeAuthority }); await expect( provider.sendMessage('coder0', { content: '', idempotencyKey: 'message-1' }, scope), ).rejects.toMatchObject({ code: 'invalid_request', } satisfies Partial); expect(writeAuthority.canWrite).not.toHaveBeenCalled(); expect(writeAuthority.assertAuthorized).not.toHaveBeenCalled(); expect(fleet.verifySession).not.toHaveBeenCalled(); expect(fleet.sendMessage).not.toHaveBeenCalled(); }); it('denies fleet writes by default before probing the tmux transport', async (): Promise => { const fleet = transport(); const provider = new TmuxFleetRuntimeProvider({ transport: fleet }); await expect( provider.sendMessage('coder0', { content: 'hello', idempotencyKey: 'message-1' }, scope), ).rejects.toMatchObject({ code: 'forbidden' } satisfies Partial); await expect(provider.terminate('coder0', 'approval-1', scope)).rejects.toMatchObject({ code: 'forbidden', } satisfies Partial); expect(fleet.verifySession).not.toHaveBeenCalled(); expect(fleet.sendMessage).not.toHaveBeenCalled(); expect(fleet.terminate).not.toHaveBeenCalled(); }); it('rejects an unverified target before consulting Mos write authority', async (): Promise => { const fleet = transport(); fleet.verifySession = vi.fn(async (): Promise => { throw new Error('target identity mismatch'); }); const writeAuthority: FleetWriteAuthority = { canWrite: vi.fn(async (): Promise => true), assertAuthorized: vi.fn(async (): Promise => undefined), }; const provider = new TmuxFleetRuntimeProvider({ transport: fleet, writeAuthority }); await expect( provider.sendMessage('coder', { content: 'hello', idempotencyKey: 'message-1' }, scope), ).rejects.toThrow('target identity mismatch'); expect(writeAuthority.assertAuthorized).not.toHaveBeenCalled(); expect(fleet.sendMessage).not.toHaveBeenCalled(); }); it('passes an exact session ID to the fleet transport only through authorized Mos writes', async (): Promise => { const fleet = transport(); const writeAuthority: FleetWriteAuthority = { canWrite: vi.fn(async (): Promise => true), assertAuthorized: vi.fn(async (): Promise => undefined), }; const provider = new TmuxFleetRuntimeProvider({ transport: fleet, sourceLabel: 'tess', writeAuthority, }); await provider.sendMessage('coder0', { content: 'hello', idempotencyKey: 'message-1' }, scope); await provider.terminate('coder0', 'approval-1', scope); expect(writeAuthority.assertAuthorized).toHaveBeenCalledWith({ operation: 'session.send', sessionId: 'coder0', scope, }); expect(writeAuthority.assertAuthorized).toHaveBeenCalledWith({ operation: 'session.terminate', sessionId: 'coder0', scope, approvalRef: 'approval-1', }); expect(fleet.sendMessage).toHaveBeenCalledWith('coder0', 'hello', 'tess'); expect(fleet.terminate).toHaveBeenCalledWith('coder0'); }); it('fails closed when consumers ask for session streaming', async (): Promise => { const provider = new TmuxFleetRuntimeProvider({ transport: transport() }); const stream = provider.streamSession('coder0', undefined, scope)[Symbol.asyncIterator](); await expect(stream.next()).rejects.toMatchObject({ code: 'capability_unsupported', } satisfies Partial); }); });