import { describe, expect, it, vi } from 'vitest'; import type { ConnectorExecutionContext, ConnectorExecutionGrant, ConnectorLease, ConnectorLeaseAuditEvent, ConnectorLeaseStore, FencedConnectorAdapter, LogicalAgentBinding, } from '@mosaicstack/types'; import { ConnectorLeaseCoordinator, MAX_CONNECTOR_GRANT_TTL_MS, MAX_CONNECTOR_LEASE_TTL_MS, } from './connector-lease.js'; import type { ConnectorLeaseError } from './connector-lease.js'; const identity = { tenantId: 'tenant-a', logicalAgentId: 'mos' } as const; const binding: LogicalAgentBinding = { identity, bindingId: 'operator-chat' }; const activeLease: ConnectorLease = { ...binding, leaseId: '00000000-0000-4000-8000-000000000001', connectorId: 'connector-a', scopes: ['runtime.send', 'tool.execute'], leaseEpoch: '3', acquiredAt: '2026-07-14T17:00:00.000Z', heartbeatAt: '2026-07-14T17:00:00.000Z', expiresAt: '2026-07-14T17:10:00.000Z', }; class FakeLeaseStore implements ConnectorLeaseStore { lease: ConnectorLease | null = activeLease; readonly audits: ConnectorLeaseAuditEvent[] = []; async acquire(): Promise { if (!this.lease) throw new Error('fixture has no lease'); return this.lease; } async takeover(): Promise { if (!this.lease) throw new Error('fixture has no lease'); return this.lease; } async heartbeat(): Promise { if (!this.lease) throw new Error('fixture has no lease'); return this.lease; } async release(): Promise {} async findCurrent(): Promise { return this.lease; } async recordAudit(event: ConnectorLeaseAuditEvent): Promise { this.audits.push(event); } } describe('ConnectorLeaseCoordinator fencing', (): void => { it('validates a server-minted grant immediately before invoking an adapter side effect', async (): Promise => { const store = new FakeLeaseStore(); const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => new Date('2026-07-14T17:01:00.000Z'), }); const grant = await coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: 30_000, correlationId: 'correlation-1', }); const execute = vi.fn(async (_input: string, context: ConnectorExecutionContext) => context); const adapter: FencedConnectorAdapter = { execute }; const context = await coordinator.executeGrant(grant, 'runtime.send', 'hello', adapter); expect(execute).toHaveBeenCalledOnce(); expect(context).toMatchObject({ identity, bindingId: 'operator-chat', connectorId: 'connector-a', leaseEpoch: '3', scopes: ['runtime.send'], }); }); it('caps grant expiry to the durable current lease instead of submitted metadata', async (): Promise => { const store = new FakeLeaseStore(); store.lease = { ...activeLease, expiresAt: '2026-07-14T17:01:05.000Z' }; const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => new Date('2026-07-14T17:01:00.000Z'), }); const grant = await coordinator.issueGrant({ lease: { ...activeLease, expiresAt: '2026-07-14T18:00:00.000Z' }, scopes: ['runtime.send'], ttlMs: 30_000, correlationId: 'correlation-durable-expiry', }); expect(grant.expiresAt).toBe('2026-07-14T17:01:05.000Z'); }); it.each([ ['forged clone', (grant: ConnectorExecutionGrant): ConnectorExecutionGrant => ({ ...grant })], [ 'cross-tenant clone', (grant: ConnectorExecutionGrant): ConnectorExecutionGrant => ({ ...grant, identity: { ...grant.identity, tenantId: 'tenant-b' }, }), ], [ 'cross-agent clone', (grant: ConnectorExecutionGrant): ConnectorExecutionGrant => ({ ...grant, identity: { ...grant.identity, logicalAgentId: 'other-agent' }, }), ], [ 'cross-binding clone', (grant: ConnectorExecutionGrant): ConnectorExecutionGrant => ({ ...grant, bindingId: 'other-binding', }), ], [ 'cross-connector clone', (grant: ConnectorExecutionGrant): ConnectorExecutionGrant => ({ ...grant, connectorId: 'connector-b', }), ], ])('denies and audits a %s before adapter invocation', async (_label, forge): Promise => { const store = new FakeLeaseStore(); const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => new Date('2026-07-14T17:01:00.000Z'), }); const grant = await coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: 30_000, correlationId: 'correlation-forged', }); const adapter = { execute: vi.fn().mockResolvedValue(undefined) }; await expect( coordinator.executeGrant(forge(grant), 'runtime.send', undefined, adapter), ).rejects.toMatchObject({ code: 'forged_grant' } satisfies Partial); expect(adapter.execute).not.toHaveBeenCalled(); expect(store.audits.at(-1)).toMatchObject({ event: 'reject', outcome: 'denied', reason: 'forged_grant', correlationId: 'correlation-forged', }); }); it('denies malformed forged grants with sanitized audit metadata', async (): Promise => { const store = new FakeLeaseStore(); const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => new Date('2026-07-14T17:01:00.000Z'), }); const adapter = { execute: vi.fn().mockResolvedValue(undefined) }; await expect( coordinator.executeGrant( // @ts-expect-error Deliberately exercise malformed runtime input at the trust boundary. {}, 'runtime.send', undefined, adapter, ), ).rejects.toMatchObject({ code: 'forged_grant' } satisfies Partial); expect(adapter.execute).not.toHaveBeenCalled(); expect(store.audits).toContainEqual( expect.objectContaining({ identity: { tenantId: 'untrusted', logicalAgentId: 'untrusted' }, bindingId: 'untrusted', connectorId: 'untrusted', correlationId: 'untrusted', reason: 'forged_grant', }), ); }); it('rejects lease and grant TTLs above server-side safety caps', async (): Promise => { const store = new FakeLeaseStore(); const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => new Date('2026-07-14T17:01:00.000Z'), }); expect( () => new ConnectorLeaseCoordinator(store, { maxLeaseTtlMs: MAX_CONNECTOR_LEASE_TTL_MS + 1, }), ).toThrow(/no greater than/); await expect( coordinator.acquire({ identity, bindingId: 'operator-chat', connectorId: 'connector-a', scopes: ['runtime.send'], ttlMs: MAX_CONNECTOR_LEASE_TTL_MS + 1, correlationId: 'correlation-ttl', }), ).rejects.toThrow(/no greater than/); await expect( coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: MAX_CONNECTOR_GRANT_TTL_MS + 1, correlationId: 'correlation-ttl', }), ).rejects.toThrow(/no greater than/); }); it('denies stale epoch, expired grant, and unauthorized scope before side effects', async (): Promise => { let now = new Date('2026-07-14T17:01:00.000Z'); const store = new FakeLeaseStore(); const coordinator = new ConnectorLeaseCoordinator(store, { now: (): Date => now }); const stale = await coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: 30_000, correlationId: 'correlation-stale', }); store.lease = { ...activeLease, leaseEpoch: '4', connectorId: 'connector-b' }; const adapter = { execute: vi.fn().mockResolvedValue(undefined) }; await expect( coordinator.executeGrant(stale, 'runtime.send', undefined, adapter), ).rejects.toMatchObject({ code: 'stale_epoch' } satisfies Partial); store.lease = activeLease; const expiring = await coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: 1_000, correlationId: 'correlation-expired', }); now = new Date('2026-07-14T17:01:02.000Z'); await expect( coordinator.executeGrant(expiring, 'runtime.send', undefined, adapter), ).rejects.toMatchObject({ code: 'grant_expired' } satisfies Partial); now = new Date('2026-07-14T17:01:00.000Z'); const scoped = await coordinator.issueGrant({ lease: activeLease, scopes: ['runtime.send'], ttlMs: 30_000, correlationId: 'correlation-scope', }); await expect( coordinator.executeGrant(scoped, 'tool.execute', undefined, adapter), ).rejects.toMatchObject({ code: 'scope_denied' } satisfies Partial); expect(adapter.execute).not.toHaveBeenCalled(); }); });