import test from 'brittle'
import fs from 'bare-fs'
import path from 'bare-path'
import os from 'bare-os'
import { SecureStorage } from '../../lib/identity/secure-storage.js'
function tmpVaultPath() {
const dir = path.join(os.tmpdir(), 'hypernote-test-' + Date.now() + '-' + Math.random().toString(36).slice(2))
fs.mkdirSync(dir, { recursive: true })
return path.join(dir, 'test-vault.enc')
}
test('SecureStorage - encrypt and decrypt round-trip', async (t) => {
const vaultPath = tmpVaultPath()
const storage = new SecureStorage(vaultPath)
const plaintext = Buffer.from('my secret mnemonic words here')
const password = Buffer.from('test-password-123')
await storage.encrypt(plaintext, password)
t.ok(storage.exists(), 'vault file exists after encrypt')
const decrypted = await storage.decrypt(password)
t.alike(decrypted, plaintext, 'decrypted matches original')
// Cleanup
fs.unlinkSync(vaultPath)
fs.rmdirSync(path.dirname(vaultPath))
})
test('SecureStorage - wrong password fails', async (t) => {
const vaultPath = tmpVaultPath()
const storage = new SecureStorage(vaultPath)
const plaintext = Buffer.from('secret data')
const password = Buffer.from('correct-password')
await storage.encrypt(plaintext, password)
try {
await storage.decrypt(Buffer.from('wrong-password'))
t.fail('should have thrown')
} catch (err) {
t.ok(err.message.includes('wrong password') || err.message.includes('Decryption failed'), 'error indicates wrong password')
}
// Cleanup
fs.unlinkSync(vaultPath)
fs.rmdirSync(path.dirname(vaultPath))
})
test('SecureStorage - change password', async (t) => {
const vaultPath = tmpVaultPath()
const storage = new SecureStorage(vaultPath)
const plaintext = Buffer.from('changeable secret')
const oldPass = Buffer.from('old-password')
const newPass = Buffer.from('new-password')
await storage.encrypt(plaintext, oldPass)
await storage.changePassword(oldPass, newPass)
// Old password should fail
try {
await storage.decrypt(oldPass)
t.fail('old password should fail')
} catch {
t.pass('old password correctly rejected')
}
// New password should work
const decrypted = await storage.decrypt(newPass)
t.alike(decrypted, plaintext, 'new password decrypts correctly')
// Cleanup
fs.unlinkSync(vaultPath)
fs.rmdirSync(path.dirname(vaultPath))
})
test('SecureStorage - exists() returns false for missing file', (t) => {
const storage = new SecureStorage('/tmp/nonexistent-vault-' + Date.now() + '.enc')
t.absent(storage.exists(), 'returns false for missing file')
})