/** * Field encryption singleton for NoteLett backend. * * Toggle precedence: * 1. Admin panel `encryption_enabled` flag (polled at startup via initEncryption) * 2. FIELD_ENCRYPT_ENABLED env var (fallback if platform-service unreachable) */ import { createFieldEncryptor, type FieldEncryptor } from '@bytelyst/field-encrypt'; import { config } from './config.js'; let _encryptor: FieldEncryptor | null = null; let _enabled: boolean = config.FIELD_ENCRYPT_ENABLED; /** Poll encryption_enabled flag from platform-service at startup. */ export async function initEncryption(productId: string, logger?: { info: (msg: string) => void }): Promise { const log = logger ?? { info: () => {} }; try { const url = `${config.PLATFORM_SERVICE_URL}/flags/poll?platform=backend`; const res = await fetch(url, { signal: AbortSignal.timeout(3000), headers: { 'x-product-id': productId }, }); if (res.ok) { const data = (await res.json()) as { flags: Record }; if (typeof data.flags?.encryption_enabled === 'boolean') { _enabled = data.flags.encryption_enabled; log.info(`Encryption flag from admin panel: ${_enabled ? 'ON' : 'OFF'}`); return; } } } catch { // platform-service unreachable — use env var } log.info(`Encryption from env var FIELD_ENCRYPT_ENABLED: ${_enabled ? 'ON' : 'OFF'}`); } export function getEncryptor(): FieldEncryptor { if (_encryptor) return _encryptor; _encryptor = createFieldEncryptor({ enabled: _enabled, keyProvider: config.FIELD_ENCRYPT_KEY_PROVIDER, encryptionKey: config.FIELD_ENCRYPT_KEY || undefined, keyVaultUrl: config.AZURE_KEYVAULT_URL || undefined, mekName: config.FIELD_ENCRYPT_MEK_NAME || undefined, }); return _encryptor; } /** @internal — for testing only. */ export function _resetEncryptor(): void { _encryptor = null; _enabled = config.FIELD_ENCRYPT_ENABLED; }