import { SecretCryptoService } from '../src/modules/netaclaw/service/secret_crypto.js'; describe('SecretCryptoService', () => { const originalNetaSecretKey = process.env.NETA_SECRET_KEY; const originalAppSecret = process.env.APP_SECRET; beforeEach(() => { process.env.NETA_SECRET_KEY = 'test-secret-key'; delete process.env.APP_SECRET; }); afterEach(() => { if (originalNetaSecretKey === undefined) { delete process.env.NETA_SECRET_KEY; } else { process.env.NETA_SECRET_KEY = originalNetaSecretKey; } if (originalAppSecret === undefined) { delete process.env.APP_SECRET; } else { process.env.APP_SECRET = originalAppSecret; } }); it('encrypts and decrypts text without embedding plaintext', () => { const service = new SecretCryptoService(); const encrypted = service.encryptText('mysql-password'); expect(encrypted).not.toContain('mysql-password'); expect(service.decryptText(encrypted)).toBe('mysql-password'); }); it('encrypts and decrypts JSON values', () => { const service = new SecretCryptoService(); const value = { username: 'readonly', scopes: ['order.read'], maxRows: 100 }; const encrypted = service.encryptJson(value); expect(encrypted).not.toContain('readonly'); expect(service.decryptJson(encrypted)).toEqual(value); }); it('uses configured jwt secret when secret env vars are absent', () => { delete process.env.NETA_SECRET_KEY; delete process.env.APP_SECRET; const service = new SecretCryptoService(); (service as any).jwtSecret = 'configured-jwt-secret'; const encrypted = service.encryptText('mysql-password'); expect(service.decryptText(encrypted)).toBe('mysql-password'); }); it('rejects tampered envelopes', () => { const service = new SecretCryptoService(); const encrypted = service.encryptText('mysql-password'); const envelope = JSON.parse(Buffer.from(encrypted, 'base64').toString('utf8')); envelope.ct = `${envelope.ct.slice(0, -2)}AA`; const tampered = Buffer.from(JSON.stringify(envelope), 'utf8').toString('base64'); expect(() => service.decryptText(tampered)).toThrow(); }); });