agent-vault-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/.cursor/skills/npm-publish/SKILL.md +58 -0
  2. package/.github/workflows/ci.yml +67 -0
  3. package/README.md +164 -0
  4. package/ROADMAP.md +986 -0
  5. package/dist/commands/config.d.ts +8 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +67 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/delete.d.ts +7 -0
  10. package/dist/commands/delete.d.ts.map +1 -0
  11. package/dist/commands/delete.js +30 -0
  12. package/dist/commands/delete.js.map +1 -0
  13. package/dist/commands/login.d.ts +7 -0
  14. package/dist/commands/login.d.ts.map +1 -0
  15. package/dist/commands/login.js +37 -0
  16. package/dist/commands/login.js.map +1 -0
  17. package/dist/commands/register.d.ts +13 -0
  18. package/dist/commands/register.d.ts.map +1 -0
  19. package/dist/commands/register.js +160 -0
  20. package/dist/commands/register.js.map +1 -0
  21. package/dist/core/audit.d.ts +15 -0
  22. package/dist/core/audit.d.ts.map +1 -0
  23. package/dist/core/audit.js +36 -0
  24. package/dist/core/audit.js.map +1 -0
  25. package/dist/core/browser.d.ts +7 -0
  26. package/dist/core/browser.d.ts.map +1 -0
  27. package/dist/core/browser.js +104 -0
  28. package/dist/core/browser.js.map +1 -0
  29. package/dist/core/config.d.ts +9 -0
  30. package/dist/core/config.d.ts.map +1 -0
  31. package/dist/core/config.js +80 -0
  32. package/dist/core/config.js.map +1 -0
  33. package/dist/core/crypto.d.ts +17 -0
  34. package/dist/core/crypto.d.ts.map +1 -0
  35. package/dist/core/crypto.js +90 -0
  36. package/dist/core/crypto.js.map +1 -0
  37. package/dist/core/fields.d.ts +5 -0
  38. package/dist/core/fields.d.ts.map +1 -0
  39. package/dist/core/fields.js +54 -0
  40. package/dist/core/fields.js.map +1 -0
  41. package/dist/core/keychain.d.ts +5 -0
  42. package/dist/core/keychain.d.ts.map +1 -0
  43. package/dist/core/keychain.js +97 -0
  44. package/dist/core/keychain.js.map +1 -0
  45. package/dist/core/origin.d.ts +25 -0
  46. package/dist/core/origin.d.ts.map +1 -0
  47. package/dist/core/origin.js +73 -0
  48. package/dist/core/origin.js.map +1 -0
  49. package/dist/core/ratelimit.d.ts +10 -0
  50. package/dist/core/ratelimit.d.ts.map +1 -0
  51. package/dist/core/ratelimit.js +70 -0
  52. package/dist/core/ratelimit.js.map +1 -0
  53. package/dist/core/secure-memory.d.ts +39 -0
  54. package/dist/core/secure-memory.d.ts.map +1 -0
  55. package/dist/core/secure-memory.js +68 -0
  56. package/dist/core/secure-memory.js.map +1 -0
  57. package/dist/index.d.ts +3 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +129 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/types/index.d.ts +27 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +2 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/package.json +58 -0
  66. package/src/commands/config.ts +84 -0
  67. package/src/commands/delete.ts +39 -0
  68. package/src/commands/login.ts +49 -0
  69. package/src/commands/register.ts +188 -0
  70. package/src/core/audit.ts +59 -0
  71. package/src/core/browser.ts +131 -0
  72. package/src/core/config.ts +91 -0
  73. package/src/core/crypto.ts +106 -0
  74. package/src/core/fields.ts +59 -0
  75. package/src/core/keychain.ts +110 -0
  76. package/src/core/origin.ts +90 -0
  77. package/src/core/ratelimit.ts +89 -0
  78. package/src/core/secure-memory.ts +78 -0
  79. package/src/index.ts +133 -0
  80. package/src/types/index.ts +31 -0
  81. package/tests/browser-password-manager.test.ts +1023 -0
  82. package/tests/crypto.test.ts +140 -0
  83. package/tests/e2e.test.ts +565 -0
  84. package/tests/fixtures/server.ts +59 -0
  85. package/tests/security.test.ts +113 -0
  86. package/tsconfig.json +20 -0
  87. package/vitest.config.ts +17 -0
@@ -0,0 +1,59 @@
1
+ import { createServer, IncomingMessage, ServerResponse, Server } from 'http';
2
+
3
+ const LOGIN_FORM_HTML = `
4
+ <!DOCTYPE html>
5
+ <html>
6
+ <head>
7
+ <title>Login</title>
8
+ <style>
9
+ body { font-family: sans-serif; max-width: 400px; margin: 50px auto; padding: 20px; }
10
+ form { display: flex; flex-direction: column; gap: 15px; }
11
+ input { padding: 10px; font-size: 16px; }
12
+ button { padding: 10px; font-size: 16px; cursor: pointer; }
13
+ .success { color: green; display: none; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <h1>Login</h1>
18
+ <form id="login-form">
19
+ <input type="email" id="email" name="email" placeholder="Email" autocomplete="email" />
20
+ <input type="password" id="password" name="password" placeholder="Password" autocomplete="current-password" />
21
+ <button type="submit" id="submit-btn">Sign In</button>
22
+ </form>
23
+ <p class="success" id="success">Login successful!</p>
24
+ <script>
25
+ document.getElementById('login-form').addEventListener('submit', (e) => {
26
+ e.preventDefault();
27
+ document.getElementById('success').style.display = 'block';
28
+ });
29
+ </script>
30
+ </body>
31
+ </html>
32
+ `;
33
+
34
+ export interface TestServer {
35
+ url: string;
36
+ port: number;
37
+ close: () => Promise<void>;
38
+ }
39
+
40
+ export async function startTestServer(port: number): Promise<TestServer> {
41
+ return new Promise((resolve, reject) => {
42
+ const server: Server = createServer((req: IncomingMessage, res: ServerResponse) => {
43
+ res.writeHead(200, { 'Content-Type': 'text/html' });
44
+ res.end(LOGIN_FORM_HTML);
45
+ });
46
+
47
+ server.on('error', reject);
48
+
49
+ server.listen(port, '127.0.0.1', () => {
50
+ resolve({
51
+ url: `http://127.0.0.1:${port}`,
52
+ port,
53
+ close: () => new Promise<void>((res, rej) => {
54
+ server.close((err) => (err ? rej(err) : res()));
55
+ }),
56
+ });
57
+ });
58
+ });
59
+ }
@@ -0,0 +1,113 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { SecureString, withSecureStrings } from '../src/core/secure-memory.js';
3
+ import {
4
+ isSecureProtocol,
5
+ isHttpProtocol,
6
+ } from '../src/core/origin.js';
7
+
8
+ describe('SecureString', () => {
9
+ it('stores and retrieves value', () => {
10
+ const secure = new SecureString('secret123');
11
+ expect(secure.getValue()).toBe('secret123');
12
+ });
13
+
14
+ it('reports correct length', () => {
15
+ const secure = new SecureString('secret123');
16
+ expect(secure.length).toBe(9);
17
+ });
18
+
19
+ it('can be cleared', () => {
20
+ const secure = new SecureString('secret123');
21
+ expect(secure.isCleared()).toBe(false);
22
+ secure.clear();
23
+ expect(secure.isCleared()).toBe(true);
24
+ });
25
+
26
+ it('throws when accessing cleared value', () => {
27
+ const secure = new SecureString('secret123');
28
+ secure.clear();
29
+ expect(() => secure.getValue()).toThrow('SecureString has been cleared');
30
+ });
31
+
32
+ it('length is 0 after clearing', () => {
33
+ const secure = new SecureString('secret123');
34
+ secure.clear();
35
+ expect(secure.length).toBe(0);
36
+ });
37
+
38
+ it('can be cleared multiple times safely', () => {
39
+ const secure = new SecureString('secret123');
40
+ secure.clear();
41
+ secure.clear();
42
+ expect(secure.isCleared()).toBe(true);
43
+ });
44
+ });
45
+
46
+ describe('withSecureStrings', () => {
47
+ it('provides secure values to callback', async () => {
48
+ const result = await withSecureStrings(
49
+ { username: 'user', password: 'pass' },
50
+ async (secure) => {
51
+ expect(secure.username.getValue()).toBe('user');
52
+ expect(secure.password.getValue()).toBe('pass');
53
+ return 'done';
54
+ }
55
+ );
56
+ expect(result).toBe('done');
57
+ });
58
+
59
+ it('clears values after callback completes', async () => {
60
+ let capturedSecure: { username: SecureString; password: SecureString } | null = null;
61
+
62
+ await withSecureStrings({ username: 'user', password: 'pass' }, async (secure) => {
63
+ capturedSecure = secure;
64
+ return 'done';
65
+ });
66
+
67
+ expect(capturedSecure!.username.isCleared()).toBe(true);
68
+ expect(capturedSecure!.password.isCleared()).toBe(true);
69
+ });
70
+
71
+ it('clears values even if callback throws', async () => {
72
+ let capturedSecure: { username: SecureString } | null = null;
73
+
74
+ await expect(
75
+ withSecureStrings({ username: 'user' }, async (secure) => {
76
+ capturedSecure = secure;
77
+ throw new Error('test error');
78
+ })
79
+ ).rejects.toThrow('test error');
80
+
81
+ expect(capturedSecure!.username.isCleared()).toBe(true);
82
+ });
83
+ });
84
+
85
+ describe('Origin Security', () => {
86
+ describe('isSecureProtocol', () => {
87
+ it('returns true for HTTPS', () => {
88
+ expect(isSecureProtocol('https://example.com')).toBe(true);
89
+ });
90
+
91
+ it('returns false for HTTP', () => {
92
+ expect(isSecureProtocol('http://example.com')).toBe(false);
93
+ });
94
+
95
+ it('returns false for invalid URLs', () => {
96
+ expect(isSecureProtocol('not-a-url')).toBe(false);
97
+ });
98
+ });
99
+
100
+ describe('isHttpProtocol', () => {
101
+ it('returns true for HTTP', () => {
102
+ expect(isHttpProtocol('http://example.com')).toBe(true);
103
+ });
104
+
105
+ it('returns false for HTTPS', () => {
106
+ expect(isHttpProtocol('https://example.com')).toBe(false);
107
+ });
108
+
109
+ it('returns false for invalid URLs', () => {
110
+ expect(isHttpProtocol('not-a-url')).toBe(false);
111
+ });
112
+ });
113
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist", "tests"]
20
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['tests/**/*.test.ts'],
8
+ testTimeout: 60000,
9
+ hookTimeout: 60000,
10
+ pool: 'forks',
11
+ poolOptions: {
12
+ forks: {
13
+ singleFork: true,
14
+ },
15
+ },
16
+ },
17
+ });