agentlock-shared 0.1.0 → 0.3.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 (171) hide show
  1. package/dist/__tests__/billing.test.d.ts +2 -0
  2. package/dist/__tests__/billing.test.d.ts.map +1 -0
  3. package/dist/__tests__/billing.test.js +31 -0
  4. package/dist/__tests__/billing.test.js.map +1 -0
  5. package/dist/__tests__/crypto.test.js +137 -47
  6. package/dist/__tests__/crypto.test.js.map +1 -1
  7. package/dist/__tests__/dns-pinning.test.d.ts +2 -0
  8. package/dist/__tests__/dns-pinning.test.d.ts.map +1 -0
  9. package/dist/__tests__/dns-pinning.test.js +33 -0
  10. package/dist/__tests__/dns-pinning.test.js.map +1 -0
  11. package/dist/__tests__/llm-classifier-cache-store.test.d.ts +2 -0
  12. package/dist/__tests__/llm-classifier-cache-store.test.d.ts.map +1 -0
  13. package/dist/__tests__/llm-classifier-cache-store.test.js +65 -0
  14. package/dist/__tests__/llm-classifier-cache-store.test.js.map +1 -0
  15. package/dist/__tests__/llm-classifier-cache.test.d.ts +2 -0
  16. package/dist/__tests__/llm-classifier-cache.test.d.ts.map +1 -0
  17. package/dist/__tests__/llm-classifier-cache.test.js +44 -0
  18. package/dist/__tests__/llm-classifier-cache.test.js.map +1 -0
  19. package/dist/__tests__/llm-classifier.test.d.ts +2 -0
  20. package/dist/__tests__/llm-classifier.test.d.ts.map +1 -0
  21. package/dist/__tests__/llm-classifier.test.js +167 -0
  22. package/dist/__tests__/llm-classifier.test.js.map +1 -0
  23. package/dist/__tests__/messaging.test.d.ts +2 -0
  24. package/dist/__tests__/messaging.test.d.ts.map +1 -0
  25. package/dist/__tests__/messaging.test.js +75 -0
  26. package/dist/__tests__/messaging.test.js.map +1 -0
  27. package/dist/__tests__/plans-classifier-limits.test.d.ts +2 -0
  28. package/dist/__tests__/plans-classifier-limits.test.d.ts.map +1 -0
  29. package/dist/__tests__/plans-classifier-limits.test.js +22 -0
  30. package/dist/__tests__/plans-classifier-limits.test.js.map +1 -0
  31. package/dist/__tests__/policy-category-floor.test.d.ts +2 -0
  32. package/dist/__tests__/policy-category-floor.test.d.ts.map +1 -0
  33. package/dist/__tests__/policy-category-floor.test.js +46 -0
  34. package/dist/__tests__/policy-category-floor.test.js.map +1 -0
  35. package/dist/__tests__/policy-claude-bash.test.d.ts +2 -0
  36. package/dist/__tests__/policy-claude-bash.test.d.ts.map +1 -0
  37. package/dist/__tests__/policy-claude-bash.test.js +401 -0
  38. package/dist/__tests__/policy-claude-bash.test.js.map +1 -0
  39. package/dist/__tests__/policy-llm-floor.test.d.ts +2 -0
  40. package/dist/__tests__/policy-llm-floor.test.d.ts.map +1 -0
  41. package/dist/__tests__/policy-llm-floor.test.js +107 -0
  42. package/dist/__tests__/policy-llm-floor.test.js.map +1 -0
  43. package/dist/__tests__/policy-ssh-e2e.test.d.ts +2 -0
  44. package/dist/__tests__/policy-ssh-e2e.test.d.ts.map +1 -0
  45. package/dist/__tests__/policy-ssh-e2e.test.js +89 -0
  46. package/dist/__tests__/policy-ssh-e2e.test.js.map +1 -0
  47. package/dist/__tests__/policy-ssh-sessions.test.d.ts +2 -0
  48. package/dist/__tests__/policy-ssh-sessions.test.d.ts.map +1 -0
  49. package/dist/__tests__/policy-ssh-sessions.test.js +139 -0
  50. package/dist/__tests__/policy-ssh-sessions.test.js.map +1 -0
  51. package/dist/__tests__/policy-ssh.test.d.ts +2 -0
  52. package/dist/__tests__/policy-ssh.test.d.ts.map +1 -0
  53. package/dist/__tests__/policy-ssh.test.js +180 -0
  54. package/dist/__tests__/policy-ssh.test.js.map +1 -0
  55. package/dist/__tests__/policy.test.js +522 -7
  56. package/dist/__tests__/policy.test.js.map +1 -1
  57. package/dist/__tests__/redact.test.js +76 -0
  58. package/dist/__tests__/redact.test.js.map +1 -1
  59. package/dist/__tests__/signing.test.js +89 -0
  60. package/dist/__tests__/signing.test.js.map +1 -1
  61. package/dist/__tests__/ssh-fingerprint.test.d.ts +2 -0
  62. package/dist/__tests__/ssh-fingerprint.test.d.ts.map +1 -0
  63. package/dist/__tests__/ssh-fingerprint.test.js +19 -0
  64. package/dist/__tests__/ssh-fingerprint.test.js.map +1 -0
  65. package/dist/__tests__/vpn-route.test.d.ts +2 -0
  66. package/dist/__tests__/vpn-route.test.d.ts.map +1 -0
  67. package/dist/__tests__/vpn-route.test.js +72 -0
  68. package/dist/__tests__/vpn-route.test.js.map +1 -0
  69. package/dist/__tests__/wireguard.test.d.ts +2 -0
  70. package/dist/__tests__/wireguard.test.d.ts.map +1 -0
  71. package/dist/__tests__/wireguard.test.js +114 -0
  72. package/dist/__tests__/wireguard.test.js.map +1 -0
  73. package/dist/billing.d.ts +12 -0
  74. package/dist/billing.d.ts.map +1 -0
  75. package/dist/billing.js +41 -0
  76. package/dist/billing.js.map +1 -0
  77. package/dist/crypto.d.ts +41 -0
  78. package/dist/crypto.d.ts.map +1 -1
  79. package/dist/crypto.js +208 -6
  80. package/dist/crypto.js.map +1 -1
  81. package/dist/dns-pinning.d.ts +28 -0
  82. package/dist/dns-pinning.d.ts.map +1 -0
  83. package/dist/dns-pinning.js +113 -0
  84. package/dist/dns-pinning.js.map +1 -0
  85. package/dist/index.d.ts +6 -0
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +9 -0
  88. package/dist/index.js.map +1 -1
  89. package/dist/llm-classifier-cache-store.d.ts +49 -0
  90. package/dist/llm-classifier-cache-store.d.ts.map +1 -0
  91. package/dist/llm-classifier-cache-store.js +63 -0
  92. package/dist/llm-classifier-cache-store.js.map +1 -0
  93. package/dist/llm-classifier-cache.d.ts +6 -0
  94. package/dist/llm-classifier-cache.d.ts.map +1 -0
  95. package/dist/llm-classifier-cache.js +52 -0
  96. package/dist/llm-classifier-cache.js.map +1 -0
  97. package/dist/llm-classifier.d.ts +29 -0
  98. package/dist/llm-classifier.d.ts.map +1 -0
  99. package/dist/llm-classifier.js +191 -0
  100. package/dist/llm-classifier.js.map +1 -0
  101. package/dist/observability.d.ts +36 -0
  102. package/dist/observability.d.ts.map +1 -0
  103. package/dist/observability.js +75 -0
  104. package/dist/observability.js.map +1 -0
  105. package/dist/plans.d.ts +21 -0
  106. package/dist/plans.d.ts.map +1 -1
  107. package/dist/plans.js +52 -14
  108. package/dist/plans.js.map +1 -1
  109. package/dist/policy.d.ts +173 -3
  110. package/dist/policy.d.ts.map +1 -1
  111. package/dist/policy.js +951 -58
  112. package/dist/policy.js.map +1 -1
  113. package/dist/redact.d.ts.map +1 -1
  114. package/dist/redact.js +104 -7
  115. package/dist/redact.js.map +1 -1
  116. package/dist/regex-safety.d.ts +21 -0
  117. package/dist/regex-safety.d.ts.map +1 -0
  118. package/dist/regex-safety.js +49 -0
  119. package/dist/regex-safety.js.map +1 -0
  120. package/dist/sanitize.d.ts +31 -0
  121. package/dist/sanitize.d.ts.map +1 -0
  122. package/dist/sanitize.js +54 -0
  123. package/dist/sanitize.js.map +1 -0
  124. package/dist/schemas.d.ts +267 -14
  125. package/dist/schemas.d.ts.map +1 -1
  126. package/dist/schemas.js +152 -10
  127. package/dist/schemas.js.map +1 -1
  128. package/dist/signing.d.ts +15 -0
  129. package/dist/signing.d.ts.map +1 -1
  130. package/dist/signing.js +53 -4
  131. package/dist/signing.js.map +1 -1
  132. package/dist/ssh-fingerprint.d.ts +10 -0
  133. package/dist/ssh-fingerprint.d.ts.map +1 -0
  134. package/dist/ssh-fingerprint.js +52 -0
  135. package/dist/ssh-fingerprint.js.map +1 -0
  136. package/dist/ssrf.d.ts +36 -0
  137. package/dist/ssrf.d.ts.map +1 -0
  138. package/dist/ssrf.js +140 -0
  139. package/dist/ssrf.js.map +1 -0
  140. package/dist/types.d.ts +131 -0
  141. package/dist/types.d.ts.map +1 -1
  142. package/dist/wireguard.d.ts +63 -0
  143. package/dist/wireguard.d.ts.map +1 -0
  144. package/dist/wireguard.js +226 -0
  145. package/dist/wireguard.js.map +1 -0
  146. package/package.json +42 -29
  147. package/.turbo/turbo-build.log +0 -4
  148. package/.turbo/turbo-test.log +0 -34
  149. package/dist/__tests__/content-crypto.test.d.ts +0 -2
  150. package/dist/__tests__/content-crypto.test.d.ts.map +0 -1
  151. package/dist/__tests__/content-crypto.test.js +0 -117
  152. package/dist/__tests__/content-crypto.test.js.map +0 -1
  153. package/dist/content-crypto.d.ts +0 -24
  154. package/dist/content-crypto.d.ts.map +0 -1
  155. package/dist/content-crypto.js +0 -58
  156. package/dist/content-crypto.js.map +0 -1
  157. package/src/__tests__/policy.test.ts +0 -88
  158. package/src/__tests__/redact.test.ts +0 -41
  159. package/src/__tests__/signing.test.ts +0 -55
  160. package/src/crypto.ts +0 -87
  161. package/src/index.ts +0 -8
  162. package/src/mcp-catalog.ts +0 -181
  163. package/src/plans.ts +0 -96
  164. package/src/policy.ts +0 -186
  165. package/src/redact.ts +0 -114
  166. package/src/schemas.ts +0 -53
  167. package/src/signing.ts +0 -120
  168. package/src/types.ts +0 -212
  169. package/test-gateway.mjs +0 -47
  170. package/tsconfig.json +0 -10
  171. package/vitest.config.ts +0 -8
@@ -1 +0,0 @@
1
- {"version":3,"file":"content-crypto.js","sourceRoot":"","sources":["../src/content-crypto.ts"],"names":[],"mappings":";;;;;;AAUA,kCAEC;AAGD,0BAOC;AAGD,8BAYC;AAGD,8BAMC;AAGD,wCAQC;AAGD,8CASC;AArED,0DAA6B;AAC7B,mDAA4D;AAC5D,iDAA8C;AAE9C,iDAAiD;AACpC,QAAA,sBAAsB,GAAG,CAAC,CAAC;AACxC,+CAA+C;AAClC,QAAA,mBAAmB,GAAG,CAAC,CAAC;AAErC,sDAAsD;AACtD,SAAgB,WAAW;IACzB,OAAO,mBAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,4FAA4F;AAC5F,SAAgB,OAAO,CACrB,GAAe,EACf,WAAuB;IAEvB,MAAM,KAAK,GAAG,mBAAI,CAAC,WAAW,CAAC,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,mBAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IACpD,OAAO,EAAE,UAAU,EAAE,IAAA,6BAAY,EAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAA,6BAAY,EAAC,KAAK,CAAC,EAAE,CAAC;AACvE,CAAC;AAED,sEAAsE;AACtE,SAAgB,SAAS,CACvB,UAAkB,EAClB,KAAa,EACb,WAAuB;IAEvB,MAAM,GAAG,GAAG,IAAA,6BAAY,EAAC,UAAU,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,IAAA,6BAAY,EAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,mBAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kEAAkE;AAClE,SAAgB,SAAS,CACvB,UAAkB,EAClB,IAAgB;IAEhB,MAAM,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO,IAAA,eAAM,EAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,4EAA4E;AAC5E,SAAgB,cAAc,CAC5B,GAAe,EACf,UAAkB;IAElB,MAAM,IAAI,GAAG,mBAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,IAAA,6BAAY,EAAC,IAAI,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,2EAA2E;AAC3E,SAAgB,iBAAiB,CAC/B,UAAkB,EAClB,KAAa,EACb,IAAY,EACZ,UAAkB;IAElB,MAAM,SAAS,GAAG,IAAA,6BAAY,EAAC,IAAI,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7C,OAAO,SAAS,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC"}
@@ -1,88 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { evaluatePolicy, DEFAULT_POLICY_RULES } from '../policy.js';
3
- import type { AgentActionRequest } from '../types.js';
4
-
5
- describe('Policy Engine', () => {
6
- it('should ALLOW read actions by default', () => {
7
- const action: AgentActionRequest = { action_type: 'read', tool: 'http', payload: {} };
8
- expect(evaluatePolicy(action, DEFAULT_POLICY_RULES).decision).toBe('ALLOW');
9
- });
10
-
11
- it('should REQUIRE_APPROVAL for write actions', () => {
12
- const action: AgentActionRequest = { action_type: 'write', tool: 'demo', payload: {} };
13
- expect(evaluatePolicy(action, DEFAULT_POLICY_RULES).decision).toBe('REQUIRE_APPROVAL');
14
- });
15
-
16
- it('should BLOCK admin actions', () => {
17
- const action: AgentActionRequest = { action_type: 'admin', tool: 'system', payload: {} };
18
- expect(evaluatePolicy(action, DEFAULT_POLICY_RULES).decision).toBe('BLOCK');
19
- });
20
-
21
- it('should REQUIRE_APPROVAL for financial actions', () => {
22
- const action: AgentActionRequest = { action_type: 'financial', tool: 'stripe', payload: {} };
23
- expect(evaluatePolicy(action, DEFAULT_POLICY_RULES).decision).toBe('REQUIRE_APPROVAL');
24
- });
25
-
26
- it('should BLOCK disallowed HTTP domains', () => {
27
- const action: AgentActionRequest = {
28
- action_type: 'read',
29
- tool: 'http',
30
- payload: { url: 'https://evil.com/data', method: 'GET' },
31
- };
32
- const rules = {
33
- ...DEFAULT_POLICY_RULES,
34
- http: { allowedDomains: ['trusted.com'], allowedMethods: ['GET'], blockList: [] },
35
- };
36
- expect(evaluatePolicy(action, rules).decision).toBe('BLOCK');
37
- });
38
-
39
- it('should BLOCK explicitly blocklisted domains', () => {
40
- const action: AgentActionRequest = {
41
- action_type: 'read',
42
- tool: 'http',
43
- payload: { url: 'https://evil.com/data', method: 'GET' },
44
- };
45
- const rules = {
46
- ...DEFAULT_POLICY_RULES,
47
- http: { allowedDomains: [], allowedMethods: ['GET'], blockList: ['evil.com'] },
48
- };
49
- expect(evaluatePolicy(action, rules).decision).toBe('BLOCK');
50
- });
51
-
52
- it('should ALLOW admin actions when defaultMode is allow and no matching rule', () => {
53
- const action: AgentActionRequest = { action_type: 'admin', tool: 'system', payload: {} };
54
- const rules = { ...DEFAULT_POLICY_RULES, defaultMode: 'allow' as const, rules: [] };
55
- const result = evaluatePolicy(action, rules);
56
- expect(result.decision).toBe('ALLOW');
57
- expect(result.reason).toBe('Default policy');
58
- });
59
-
60
- it('should ALLOW financial actions when defaultMode is allow and no matching rule', () => {
61
- const action: AgentActionRequest = { action_type: 'financial', tool: 'stripe', payload: {} };
62
- const rules = { ...DEFAULT_POLICY_RULES, defaultMode: 'allow' as const, rules: [] };
63
- const result = evaluatePolicy(action, rules);
64
- expect(result.decision).toBe('ALLOW');
65
- expect(result.reason).toBe('Default policy');
66
- });
67
-
68
- it('should still respect explicit rules for admin even with defaultMode allow', () => {
69
- const action: AgentActionRequest = { action_type: 'admin', tool: 'system', payload: {} };
70
- const rules = {
71
- ...DEFAULT_POLICY_RULES,
72
- defaultMode: 'allow' as const,
73
- rules: [{ action_type: 'admin' as const, decision: 'BLOCK' as const }],
74
- };
75
- expect(evaluatePolicy(action, rules).decision).toBe('BLOCK');
76
- });
77
-
78
- it('should BLOCK when cost exceeds limit', () => {
79
- const action: AgentActionRequest = {
80
- action_type: 'financial',
81
- tool: 'stripe',
82
- payload: {},
83
- cost_estimate: 1000,
84
- };
85
- const rules = { ...DEFAULT_POLICY_RULES, limits: { maxCostPerAction: 100 } };
86
- expect(evaluatePolicy(action, rules).decision).toBe('BLOCK');
87
- });
88
- });
@@ -1,41 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { redact, redactHeaders } from '../redact.js';
3
-
4
- describe('Redaction', () => {
5
- it('should redact api_key fields', () => {
6
- const obj = { name: 'test', api_key: 'super-secret-123', data: { token: 'abc' } };
7
- const result = redact(obj) as Record<string, unknown>;
8
- expect(result.api_key).toBe('[REDACTED]');
9
- expect((result.data as Record<string, unknown>).token).toBe('[REDACTED]');
10
- expect(result.name).toBe('test');
11
- });
12
-
13
- it('should redact Authorization headers', () => {
14
- const headers = { Authorization: 'Bearer secret', 'Content-Type': 'application/json' };
15
- const result = redactHeaders(headers);
16
- expect(result['Authorization']).toBe('[REDACTED]');
17
- expect(result['Content-Type']).toBe('application/json');
18
- });
19
-
20
- it('should handle nested objects', () => {
21
- const obj = { level1: { level2: { password: 'secret', safe: 'ok' } } };
22
- const result = redact(obj) as { level1: { level2: { password: string; safe: string } } };
23
- expect(result.level1.level2.password).toBe('[REDACTED]');
24
- expect(result.level1.level2.safe).toBe('ok');
25
- });
26
-
27
- it('should handle arrays', () => {
28
- const obj = { items: [{ token: 'secret1' }, { token: 'secret2' }] };
29
- const result = redact(obj) as { items: { token: string }[] };
30
- expect(result.items[0].token).toBe('[REDACTED]');
31
- expect(result.items[1].token).toBe('[REDACTED]');
32
- });
33
-
34
- it('should not redact safe fields', () => {
35
- const obj = { name: 'test', url: 'https://example.com', status: 200 };
36
- const result = redact(obj) as typeof obj;
37
- expect(result.name).toBe('test');
38
- expect(result.url).toBe('https://example.com');
39
- expect(result.status).toBe(200);
40
- });
41
- });
@@ -1,55 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateKeypair, signRequest, verifyRequest, canonicalStringify } from '../signing.js';
3
-
4
- describe('Ed25519 Signing', () => {
5
- it('should generate valid keypair', () => {
6
- const kp = generateKeypair();
7
- expect(kp.publicKey).toBeTruthy();
8
- expect(kp.privateKey).toBeTruthy();
9
- expect(kp.publicKey.length).toBeGreaterThan(0);
10
- });
11
-
12
- it('should sign and verify a request', () => {
13
- const kp = generateKeypair();
14
- const body = { action_type: 'write', tool: 'demo', payload: { key: 'value' } };
15
- const headers = signRequest(body, 'agent-123', kp.privateKey);
16
- expect(() => verifyRequest(body, headers, kp.publicKey)).not.toThrow();
17
- });
18
-
19
- it('should reject tampered body (top-level field)', () => {
20
- const kp = generateKeypair();
21
- const body = { action_type: 'write', tool: 'demo', payload: { key: 'value' } };
22
- const headers = signRequest(body, 'agent-123', kp.privateKey);
23
- const tampered = { ...body, tool: 'admin' };
24
- expect(() => verifyRequest(tampered, headers, kp.publicKey)).toThrow('Invalid signature');
25
- });
26
-
27
- it('should reject tampered nested payload field', () => {
28
- const kp = generateKeypair();
29
- const body = { action_type: 'write', tool: 'demo', payload: { key: 'value', amount: 100 } };
30
- const headers = signRequest(body, 'agent-123', kp.privateKey);
31
- const tampered = { ...body, payload: { key: 'value', amount: 999999 } };
32
- expect(() => verifyRequest(tampered, headers, kp.publicKey)).toThrow('Invalid signature');
33
- });
34
-
35
- it('canonicalStringify should sort keys recursively at all nesting levels', () => {
36
- const obj = { z: 1, a: { y: 2, b: 3 }, m: [{ q: 4, c: 5 }] };
37
- const result = canonicalStringify(obj);
38
- // All object levels must have sorted keys
39
- expect(result).toBe('{"a":{"b":3,"y":2},"m":[{"c":5,"q":4}],"z":1}');
40
- });
41
-
42
- it('should reject missing headers', () => {
43
- const kp = generateKeypair();
44
- const body = { action_type: 'write', tool: 'demo', payload: {} };
45
- expect(() => verifyRequest(body, {}, kp.publicKey)).toThrow('Missing required signature headers');
46
- });
47
-
48
- it('should reject stale timestamp', () => {
49
- const kp = generateKeypair();
50
- const body = { action_type: 'write', tool: 'demo', payload: {} };
51
- const headers = signRequest(body, 'agent-123', kp.privateKey);
52
- headers['x-timestamp'] = String(Date.now() - 10 * 60 * 1000);
53
- expect(() => verifyRequest(body, headers, kp.publicKey)).toThrow('Timestamp skew');
54
- });
55
- });
package/src/crypto.ts DELETED
@@ -1,87 +0,0 @@
1
- import nacl from 'tweetnacl';
2
- import { encodeBase64, decodeBase64 } from 'tweetnacl-util';
3
-
4
- export function generateKey(): Uint8Array {
5
- return nacl.randomBytes(32);
6
- }
7
-
8
- export function encrypt(data: string, key: Uint8Array): string {
9
- const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
10
- const message = new TextEncoder().encode(data);
11
- const box = nacl.secretbox(message, nonce, key);
12
-
13
- const combined = new Uint8Array(nonce.length + box.length);
14
- combined.set(nonce);
15
- combined.set(box, nonce.length);
16
-
17
- return encodeBase64(combined);
18
- }
19
-
20
- export function decrypt(encryptedData: string, key: Uint8Array): string {
21
- const combined = decodeBase64(encryptedData);
22
- const nonce = combined.slice(0, nacl.secretbox.nonceLength);
23
- const box = combined.slice(nacl.secretbox.nonceLength);
24
-
25
- const message = nacl.secretbox.open(box, nonce, key);
26
- if (!message) {
27
- throw new Error('Decryption failed: invalid key or corrupted data');
28
- }
29
-
30
- return new TextDecoder().decode(message);
31
- }
32
-
33
- export function encryptDEK(dek: Uint8Array, masterKey: Uint8Array): string {
34
- return encrypt(encodeBase64(dek), masterKey);
35
- }
36
-
37
- export function decryptDEK(encryptedDEK: string, masterKey: Uint8Array): Uint8Array {
38
- const dekBase64 = decrypt(encryptedDEK, masterKey);
39
- return decodeBase64(dekBase64);
40
- }
41
-
42
- // Cache the decoded master key to avoid creating multiple copies in memory.
43
- // A single copy is preferable to many short-lived copies scattered on the heap.
44
- let _cachedMasterKey: Uint8Array | null = null;
45
-
46
- export function getMasterKey(): Uint8Array {
47
- if (_cachedMasterKey) return _cachedMasterKey;
48
- const key = process.env.MASTER_KEY;
49
- if (!key) throw new Error('MASTER_KEY environment variable not set');
50
- _cachedMasterKey = decodeBase64(key);
51
- return _cachedMasterKey;
52
- }
53
-
54
- export function generateMasterKey(): string {
55
- return encodeBase64(generateKey());
56
- }
57
-
58
- export function encryptCredential(
59
- payload: Record<string, unknown>,
60
- masterKey: Uint8Array
61
- ): { encryptedDEK: string; encryptedPayload: string } {
62
- const dek = generateKey();
63
- try {
64
- const encryptedDEK = encryptDEK(dek, masterKey);
65
- const encryptedPayload = encrypt(JSON.stringify(payload), dek);
66
- return { encryptedDEK, encryptedPayload };
67
- } finally {
68
- // Zero DEK from memory after use (defense-in-depth against heap dumps)
69
- dek.fill(0);
70
- }
71
- }
72
-
73
- export function decryptCredential(
74
- encryptedDEK: string,
75
- encryptedPayload: string,
76
- masterKey: Uint8Array
77
- ): Record<string, unknown> {
78
- const dek = decryptDEK(encryptedDEK, masterKey);
79
- try {
80
- const json = decrypt(encryptedPayload, dek);
81
- return JSON.parse(json);
82
- } finally {
83
- // Best-effort: zero DEK from memory to minimize exposure window.
84
- // Not guaranteed by JS runtime, but reduces risk of heap-dump leaks.
85
- dek.fill(0);
86
- }
87
- }
package/src/index.ts DELETED
@@ -1,8 +0,0 @@
1
- export * from './types.js';
2
- export * from './crypto.js';
3
- export * from './signing.js';
4
- export * from './policy.js';
5
- export * from './redact.js';
6
- export * from './schemas.js';
7
- export * from './plans.js';
8
- export * from './mcp-catalog.js';
@@ -1,181 +0,0 @@
1
- export interface McpServerTemplate {
2
- id: string;
3
- name: string;
4
- description: string;
5
- serverUrl: string;
6
- authType: 'bearer' | 'none';
7
- authLabel?: string;
8
- authPlaceholder?: string;
9
- authHelpUrl?: string;
10
- category: string;
11
- }
12
-
13
- export const MCP_CATALOG: McpServerTemplate[] = [
14
- // --- Developer Tools ---
15
- {
16
- id: 'github',
17
- name: 'GitHub',
18
- description: 'Manage repos, issues, PRs, and code search',
19
-
20
- serverUrl: 'https://api.githubcopilot.com/mcp/',
21
- authType: 'bearer',
22
- authLabel: 'Personal Access Token',
23
- authPlaceholder: 'ghp_...',
24
- authHelpUrl: 'https://github.com/settings/tokens',
25
- category: 'Developer Tools',
26
- },
27
- {
28
- id: 'gitlab',
29
- name: 'GitLab',
30
- description: 'Projects, merge requests, pipelines, and issues',
31
-
32
- serverUrl: 'https://gitlab.com/-/mcp',
33
- authType: 'bearer',
34
- authLabel: 'Personal Access Token',
35
- authPlaceholder: 'glpat-...',
36
- authHelpUrl: 'https://gitlab.com/-/user_settings/personal_access_tokens',
37
- category: 'Developer Tools',
38
- },
39
- {
40
- id: 'linear',
41
- name: 'Linear',
42
- description: 'Issue tracking, projects, and team workflows',
43
-
44
- serverUrl: 'https://mcp.linear.app/sse',
45
- authType: 'bearer',
46
- authLabel: 'API Key',
47
- authPlaceholder: 'lin_api_...',
48
- authHelpUrl: 'https://linear.app/settings/api',
49
- category: 'Developer Tools',
50
- },
51
- {
52
- id: 'sentry',
53
- name: 'Sentry',
54
- description: 'Error tracking, performance monitoring, and alerts',
55
-
56
- serverUrl: 'https://mcp.sentry.dev/sse',
57
- authType: 'bearer',
58
- authLabel: 'Auth Token',
59
- authPlaceholder: 'sntrys_...',
60
- authHelpUrl: 'https://sentry.io/settings/account/api/auth-tokens/',
61
- category: 'Developer Tools',
62
- },
63
-
64
- // --- Cloud & Infrastructure ---
65
- {
66
- id: 'cloudflare',
67
- name: 'Cloudflare',
68
- description: 'Workers, KV, D1, R2, and DNS management',
69
- serverUrl: 'https://workers-mcp.cloudflare.com/mcp',
70
- authType: 'bearer',
71
- authLabel: 'API Token',
72
- authPlaceholder: '',
73
- authHelpUrl: 'https://dash.cloudflare.com/profile/api-tokens',
74
- category: 'Cloud & Infrastructure',
75
- },
76
-
77
- // --- Communication ---
78
- {
79
- id: 'slack',
80
- name: 'Slack',
81
- description: 'Send messages, manage channels, and search conversations',
82
- serverUrl: 'https://slack.com/api/mcp',
83
- authType: 'bearer',
84
- authLabel: 'Bot Token',
85
- authPlaceholder: 'xoxb-...',
86
- authHelpUrl: 'https://api.slack.com/apps',
87
- category: 'Communication',
88
- },
89
-
90
- // --- Search & Data ---
91
- {
92
- id: 'brave-search',
93
- name: 'Brave Search',
94
- description: 'Web search, news, and local results',
95
- serverUrl: 'https://mcp.brave.com/sse',
96
- authType: 'bearer',
97
- authLabel: 'API Key',
98
- authPlaceholder: 'BSA...',
99
- authHelpUrl: 'https://brave.com/search/api/',
100
- category: 'Search & Data',
101
- },
102
-
103
- // --- Productivity ---
104
- {
105
- id: 'notion',
106
- name: 'Notion',
107
- description: 'Pages, databases, and workspace content',
108
- serverUrl: 'https://mcp.notion.so/sse',
109
- authType: 'bearer',
110
- authLabel: 'Integration Token',
111
- authPlaceholder: 'ntn_...',
112
- authHelpUrl: 'https://www.notion.so/my-integrations',
113
- category: 'Productivity',
114
- },
115
-
116
- // --- AI & LLMs ---
117
- {
118
- id: 'context7',
119
- name: 'Context7',
120
- description: 'Up-to-date documentation and code examples for any library',
121
- serverUrl: 'https://mcp.context7.com/sse',
122
- authType: 'none',
123
- category: 'AI & LLMs',
124
- },
125
-
126
- // --- Databases ---
127
- {
128
- id: 'supabase',
129
- name: 'Supabase',
130
- description: 'Database queries, auth, storage, and edge functions',
131
- serverUrl: 'https://mcp.supabase.com/sse',
132
- authType: 'bearer',
133
- authLabel: 'Access Token',
134
- authPlaceholder: 'sbp_...',
135
- authHelpUrl: 'https://supabase.com/dashboard/account/tokens',
136
- category: 'Databases',
137
- },
138
- {
139
- id: 'neon',
140
- name: 'Neon',
141
- description: 'Serverless Postgres — branches, queries, and management',
142
- serverUrl: 'https://mcp.neon.tech/sse',
143
- authType: 'bearer',
144
- authLabel: 'API Key',
145
- authPlaceholder: '',
146
- authHelpUrl: 'https://console.neon.tech/app/settings/api-keys',
147
- category: 'Databases',
148
- },
149
-
150
- // --- Payments ---
151
- {
152
- id: 'stripe',
153
- name: 'Stripe',
154
- description: 'Payments, subscriptions, customers, and invoices',
155
- serverUrl: 'https://mcp.stripe.com/sse',
156
- authType: 'bearer',
157
- authLabel: 'Secret Key',
158
- authPlaceholder: 'sk_...',
159
- authHelpUrl: 'https://dashboard.stripe.com/apikeys',
160
- category: 'Payments',
161
- },
162
-
163
- // --- Monitoring ---
164
- {
165
- id: 'grafana',
166
- name: 'Grafana',
167
- description: 'Dashboards, alerts, and observability data',
168
- serverUrl: 'https://mcp.grafana.com/sse',
169
- authType: 'bearer',
170
- authLabel: 'Service Account Token',
171
- authPlaceholder: 'glsa_...',
172
- authHelpUrl: 'https://grafana.com/docs/grafana/latest/administration/service-accounts/',
173
- category: 'Monitoring',
174
- },
175
- ];
176
-
177
- export const MCP_CATEGORIES = [...new Set(MCP_CATALOG.map((s) => s.category))];
178
-
179
- export function getMcpTemplate(id: string): McpServerTemplate | undefined {
180
- return MCP_CATALOG.find((s) => s.id === id);
181
- }
package/src/plans.ts DELETED
@@ -1,96 +0,0 @@
1
- export type PlanId = 'free' | 'pro' | 'team';
2
-
3
- export interface PlanLimits {
4
- actionsPerMonth: number;
5
- agents: number;
6
- credentials: number;
7
- members: number;
8
- timelineHistoryDays: number;
9
- undoEnabled: boolean;
10
- browserSessions: number;
11
- }
12
-
13
- export interface PlanDefinition extends PlanLimits {
14
- id: PlanId;
15
- name: string;
16
- monthlyPrice: number; // USD cents
17
- yearlyPrice: number; // USD cents (total per year)
18
- stripePriceMonthly: string;
19
- stripePriceYearly: string;
20
- }
21
-
22
- export const PLANS: Record<PlanId, PlanDefinition> = {
23
- free: {
24
- id: 'free',
25
- name: 'Free',
26
- monthlyPrice: 0,
27
- yearlyPrice: 0,
28
- stripePriceMonthly: '',
29
- stripePriceYearly: '',
30
- actionsPerMonth: 1000,
31
- agents: 3,
32
- credentials: 2,
33
- members: 1,
34
- timelineHistoryDays: 14,
35
- undoEnabled: false,
36
- browserSessions: 0,
37
- },
38
- pro: {
39
- id: 'pro',
40
- name: 'Pro',
41
- monthlyPrice: 900,
42
- yearlyPrice: 7900,
43
- stripePriceMonthly: 'price_1T6b3m2NRlIkxMrBZ9bmEDYE',
44
- stripePriceYearly: 'price_1T6b3m2NRlIkxMrBo2yx01sJ',
45
- actionsPerMonth: Infinity,
46
- agents: 10,
47
- credentials: 25,
48
- members: 5,
49
- timelineHistoryDays: 90,
50
- undoEnabled: true,
51
- browserSessions: 2,
52
- },
53
- team: {
54
- id: 'team',
55
- name: 'Team',
56
- monthlyPrice: 4900,
57
- yearlyPrice: 41000,
58
- stripePriceMonthly: 'price_1T6b3n2NRlIkxMrBstkfVECC',
59
- stripePriceYearly: 'price_1T6b3o2NRlIkxMrBzHoQKPjz',
60
- actionsPerMonth: Infinity,
61
- agents: 50,
62
- credentials: Infinity,
63
- members: 25,
64
- timelineHistoryDays: 365,
65
- undoEnabled: true,
66
- browserSessions: 5,
67
- },
68
- } as const;
69
-
70
- export function getPlanLimits(plan: string): PlanLimits {
71
- const def = PLANS[plan as PlanId];
72
- if (!def) return PLANS.free;
73
- return {
74
- actionsPerMonth: def.actionsPerMonth,
75
- agents: def.agents,
76
- credentials: def.credentials,
77
- members: def.members,
78
- timelineHistoryDays: def.timelineHistoryDays,
79
- undoEnabled: def.undoEnabled,
80
- browserSessions: def.browserSessions,
81
- };
82
- }
83
-
84
- export function canUndo(plan: string): boolean {
85
- return getPlanLimits(plan).undoEnabled;
86
- }
87
-
88
- /** Map a Stripe price ID back to a plan ID */
89
- export function planFromPriceId(priceId: string): PlanId | null {
90
- for (const plan of Object.values(PLANS)) {
91
- if (plan.stripePriceMonthly === priceId || plan.stripePriceYearly === priceId) {
92
- return plan.id;
93
- }
94
- }
95
- return null;
96
- }