feat(core): initial release with 3-tier secret storage

Implements SmartSecret with macOS Keychain, Linux secret-tool, and AES-256-GCM encrypted file fallback backends. Zero runtime dependencies.
This commit is contained in:
2026-02-24 15:40:14 +00:00
commit 7a19f01def
18 changed files with 10842 additions and 0 deletions

94
test/test.ts Normal file
View File

@@ -0,0 +1,94 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as smartsecret from '../ts/index.js';
import * as path from 'path';
import * as fs from 'fs';
import * as os from 'os';
let testDir: string;
let instance: smartsecret.SmartSecret;
tap.test('setup - create temp directory', async () => {
testDir = path.join(os.tmpdir(), `smartsecret-test-${Date.now()}`);
fs.mkdirSync(testDir, { recursive: true });
instance = new smartsecret.SmartSecret({
service: 'smartsecret-test',
vaultPath: path.join(testDir, 'vault.json'),
});
});
tap.test('should report file-encrypted backend type', async () => {
const backendType = await instance.getBackendType();
// On CI/test environments without keychain, should fall back to file
expect(backendType).toEqual('file-encrypted');
});
tap.test('should set and get a secret', async () => {
await instance.setSecret('test-account', 'my-secret-value');
const result = await instance.getSecret('test-account');
expect(result).toEqual('my-secret-value');
});
tap.test('should return null for non-existent secret', async () => {
const result = await instance.getSecret('nonexistent');
expect(result).toBeNull();
});
tap.test('should overwrite an existing secret', async () => {
await instance.setSecret('test-account', 'updated-secret');
const result = await instance.getSecret('test-account');
expect(result).toEqual('updated-secret');
});
tap.test('should handle special characters in secrets', async () => {
const specialSecret = '!@#$%^&*()_+-=[]{}|;:\'",.<>?/\\`~\n\ttabs and newlines';
await instance.setSecret('special-chars', specialSecret);
const result = await instance.getSecret('special-chars');
expect(result).toEqual(specialSecret);
});
tap.test('should handle empty string secrets', async () => {
await instance.setSecret('empty-secret', '');
const result = await instance.getSecret('empty-secret');
expect(result).toEqual('');
});
tap.test('should list accounts', async () => {
const accounts = await instance.listAccounts();
expect(accounts).toContain('test-account');
expect(accounts).toContain('special-chars');
expect(accounts).toContain('empty-secret');
});
tap.test('should delete a secret', async () => {
const deleted = await instance.deleteSecret('test-account');
expect(deleted).toBeTrue();
const result = await instance.getSecret('test-account');
expect(result).toBeNull();
});
tap.test('should return false when deleting non-existent secret', async () => {
const deleted = await instance.deleteSecret('nonexistent');
expect(deleted).toBeFalse();
});
tap.test('should isolate secrets by service', async () => {
const otherInstance = new smartsecret.SmartSecret({
service: 'other-service',
vaultPath: path.join(testDir, 'vault.json'),
});
await otherInstance.setSecret('shared-name', 'other-value');
await instance.setSecret('shared-name', 'original-value');
const otherResult = await otherInstance.getSecret('shared-name');
const originalResult = await instance.getSecret('shared-name');
expect(otherResult).toEqual('other-value');
expect(originalResult).toEqual('original-value');
});
tap.test('cleanup - remove temp directory', async () => {
fs.rmSync(testDir, { recursive: true, force: true });
});
export default tap.start();