import { describe, expect, it } from 'vitest' import { decryptIntegrationSecret, encryptIntegrationSecret, type SecretBinding, } from './secret-envelope' const binding: SecretBinding = { workspaceId: 'workspace-a', integrationId: 'integration-a', secretKind: 'gitea-token', } const oldKey = Buffer.alloc(32, 7) const activeKey = Buffer.alloc(32, 9) const ring = { activeVersion: 'v2', keys: { v1: oldKey, v2: activeKey } } describe('integration secret envelope', () => { it('round-trips without exposing plaintext in the envelope', () => { const plaintext = 'gitea-secret-token-value' const envelope = encryptIntegrationSecret(plaintext, binding, ring) expect(JSON.stringify(envelope)).not.toContain(plaintext) expect(envelope).toMatchObject({ algorithm: 'AES-256-GCM', envelopeVersion: 1, keyVersion: 'v2', }) expect(decryptIntegrationSecret(envelope, binding, ring)).toBe(plaintext) }) it('decrypts an old key version through the key ring', () => { const envelope = encryptIntegrationSecret('old-secret', binding, { activeVersion: 'v1', keys: { v1: oldKey }, }) expect(decryptIntegrationSecret(envelope, binding, ring)).toBe('old-secret') }) it('rejects tampering, wrong AAD and unavailable key versions', () => { const envelope = encryptIntegrationSecret('bound-secret', binding, ring) expect(() => decryptIntegrationSecret( { ...envelope, ciphertext: Buffer.from('tampered').toString('base64') }, binding, ring, ), ).toThrow('authentication failed') expect(() => decryptIntegrationSecret( envelope, { ...binding, workspaceId: 'workspace-b' }, ring, ), ).toThrow('authentication failed') expect(() => decryptIntegrationSecret(envelope, binding, { activeVersion: 'v3', keys: { v3: Buffer.alloc(32, 1) }, }), ).toThrow('key version is unavailable') }) })