agentlock-shared 0.1.0 → 0.2.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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +57 -15
- package/dist/__tests__/crypto.test.js +137 -47
- package/dist/__tests__/crypto.test.js.map +1 -1
- package/dist/__tests__/messaging.test.d.ts +2 -0
- package/dist/__tests__/messaging.test.d.ts.map +1 -0
- package/dist/__tests__/messaging.test.js +75 -0
- package/dist/__tests__/messaging.test.js.map +1 -0
- package/dist/__tests__/policy.test.js +124 -7
- package/dist/__tests__/policy.test.js.map +1 -1
- package/dist/__tests__/signing.test (# Edit conflict 2026-04-01 z3etfmC #).js +51 -0
- package/dist/__tests__/signing.test.js (# Edit conflict 2026-04-01 4rndy9C #).map +1 -0
- package/dist/crypto.d.ts +36 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +150 -5
- package/dist/crypto.js.map +1 -1
- package/dist/plans.d.ts +4 -0
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +16 -0
- package/dist/plans.js.map +1 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +54 -29
- package/dist/policy.js.map +1 -1
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +21 -4
- package/dist/redact.js.map +1 -1
- package/dist/schemas.d.ts +72 -11
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +62 -10
- package/dist/schemas.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/crypto.test.ts +169 -0
- package/src/__tests__/messaging.test.ts +83 -0
- package/src/__tests__/policy.test.ts +141 -7
- package/src/crypto.ts +153 -5
- package/src/plans.ts +20 -0
- package/src/policy.ts +58 -28
- package/src/redact.ts +20 -3
- package/src/schemas.ts +121 -53
- package/src/types.ts +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const signing_js_1 = require("../signing.js");
|
|
5
|
+
(0, vitest_1.describe)('Ed25519 Signing', () => {
|
|
6
|
+
(0, vitest_1.it)('should generate valid keypair', () => {
|
|
7
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
8
|
+
(0, vitest_1.expect)(kp.publicKey).toBeTruthy();
|
|
9
|
+
(0, vitest_1.expect)(kp.privateKey).toBeTruthy();
|
|
10
|
+
(0, vitest_1.expect)(kp.publicKey.length).toBeGreaterThan(0);
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.it)('should sign and verify a request', () => {
|
|
13
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
14
|
+
const body = { action_type: 'write', tool: 'demo', payload: { key: 'value' } };
|
|
15
|
+
const headers = (0, signing_js_1.signRequest)(body, 'agent-123', kp.privateKey);
|
|
16
|
+
(0, vitest_1.expect)(() => (0, signing_js_1.verifyRequest)(body, headers, kp.publicKey)).not.toThrow();
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.it)('should reject tampered body (top-level field)', () => {
|
|
19
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
20
|
+
const body = { action_type: 'write', tool: 'demo', payload: { key: 'value' } };
|
|
21
|
+
const headers = (0, signing_js_1.signRequest)(body, 'agent-123', kp.privateKey);
|
|
22
|
+
const tampered = { ...body, tool: 'admin' };
|
|
23
|
+
(0, vitest_1.expect)(() => (0, signing_js_1.verifyRequest)(tampered, headers, kp.publicKey)).toThrow('Invalid signature');
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)('should reject tampered nested payload field', () => {
|
|
26
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
27
|
+
const body = { action_type: 'write', tool: 'demo', payload: { key: 'value', amount: 100 } };
|
|
28
|
+
const headers = (0, signing_js_1.signRequest)(body, 'agent-123', kp.privateKey);
|
|
29
|
+
const tampered = { ...body, payload: { key: 'value', amount: 999999 } };
|
|
30
|
+
(0, vitest_1.expect)(() => (0, signing_js_1.verifyRequest)(tampered, headers, kp.publicKey)).toThrow('Invalid signature');
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)('canonicalStringify should sort keys recursively at all nesting levels', () => {
|
|
33
|
+
const obj = { z: 1, a: { y: 2, b: 3 }, m: [{ q: 4, c: 5 }] };
|
|
34
|
+
const result = (0, signing_js_1.canonicalStringify)(obj);
|
|
35
|
+
// All object levels must have sorted keys
|
|
36
|
+
(0, vitest_1.expect)(result).toBe('{"a":{"b":3,"y":2},"m":[{"c":5,"q":4}],"z":1}');
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)('should reject missing headers', () => {
|
|
39
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
40
|
+
const body = { action_type: 'write', tool: 'demo', payload: {} };
|
|
41
|
+
(0, vitest_1.expect)(() => (0, signing_js_1.verifyRequest)(body, {}, kp.publicKey)).toThrow('Missing required signature headers');
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.it)('should reject stale timestamp', () => {
|
|
44
|
+
const kp = (0, signing_js_1.generateKeypair)();
|
|
45
|
+
const body = { action_type: 'write', tool: 'demo', payload: {} };
|
|
46
|
+
const headers = (0, signing_js_1.signRequest)(body, 'agent-123', kp.privateKey);
|
|
47
|
+
headers['x-timestamp'] = String(Date.now() - 10 * 60 * 1000);
|
|
48
|
+
(0, vitest_1.expect)(() => (0, signing_js_1.verifyRequest)(body, headers, kp.publicKey)).toThrow('Timestamp skew');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=signing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.test.js","sourceRoot":"","sources":["../../src/__tests__/signing.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,8CAAgG;AAEhG,IAAA,iBAAQ,EAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,IAAA,eAAM,EAAC,EAAE,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC;QAClC,IAAA,eAAM,EAAC,EAAE,CAAC,UAAU,CAAC,CAAC,UAAU,EAAE,CAAC;QACnC,IAAA,eAAM,EAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/E,MAAM,OAAO,GAAG,IAAA,wBAAW,EAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;QAC9D,IAAA,eAAM,EAAC,GAAG,EAAE,CAAC,IAAA,0BAAa,EAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/E,MAAM,OAAO,GAAG,IAAA,wBAAW,EAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC5C,IAAA,eAAM,EAAC,GAAG,EAAE,CAAC,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC;QAC5F,MAAM,OAAO,GAAG,IAAA,wBAAW,EAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QACxE,IAAA,eAAM,EAAC,GAAG,EAAE,CAAC,IAAA,0BAAa,EAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAA,+BAAkB,EAAC,GAAG,CAAC,CAAC;QACvC,0CAA0C;QAC1C,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACjE,IAAA,eAAM,EAAC,GAAG,EAAE,CAAC,IAAA,0BAAa,EAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,EAAE,GAAG,IAAA,4BAAe,GAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACjE,MAAM,OAAO,GAAG,IAAA,wBAAW,EAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;QAC9D,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC7D,IAAA,eAAM,EAAC,GAAG,EAAE,CAAC,IAAA,0BAAa,EAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/crypto.d.ts
CHANGED
|
@@ -1,9 +1,45 @@
|
|
|
1
1
|
export declare function generateKey(): Uint8Array;
|
|
2
|
+
/**
|
|
3
|
+
* Low-level symmetric encryption using a provided key.
|
|
4
|
+
* Callers that need envelope encryption (per-data DEK) should use
|
|
5
|
+
* envelopeEncrypt() instead.
|
|
6
|
+
*/
|
|
2
7
|
export declare function encrypt(data: string, key: Uint8Array): string;
|
|
8
|
+
/**
|
|
9
|
+
* Low-level symmetric decryption. Handles both envelope-encrypted data
|
|
10
|
+
* (prefixed with "env1:") and legacy direct-key encrypted data.
|
|
11
|
+
*
|
|
12
|
+
* For envelope data: unwraps the per-data DEK using the master key,
|
|
13
|
+
* then decrypts the payload with the DEK.
|
|
14
|
+
*
|
|
15
|
+
* For legacy data: decrypts directly with the provided key, falling
|
|
16
|
+
* back to MASTER_KEY_PREVIOUS for key rotation support.
|
|
17
|
+
*/
|
|
3
18
|
export declare function decrypt(encryptedData: string, key: Uint8Array): string;
|
|
19
|
+
/**
|
|
20
|
+
* Encrypt arbitrary data using a per-data DEK (envelope encryption).
|
|
21
|
+
* Generates a fresh 256-bit DEK, encrypts the data with it, then wraps
|
|
22
|
+
* the DEK with the provided master key. Returns a single string in the
|
|
23
|
+
* format "env1:<wrappedDEK>:<encryptedPayload>" so it fits in a single
|
|
24
|
+
* database column and is backward-compatible with decrypt().
|
|
25
|
+
*
|
|
26
|
+
* Use this instead of encrypt() for all data at rest. Each encrypted
|
|
27
|
+
* value gets its own DEK, so compromising one ciphertext does not
|
|
28
|
+
* expose other data -- the attacker still needs the master key to
|
|
29
|
+
* unwrap any individual DEK.
|
|
30
|
+
*/
|
|
31
|
+
export declare function envelopeEncrypt(data: string, masterKey: Uint8Array): string;
|
|
32
|
+
/**
|
|
33
|
+
* Decrypt data produced by envelopeEncrypt(). Expects the "env1:" prefixed
|
|
34
|
+
* format. For general use, call decrypt() which auto-detects the format.
|
|
35
|
+
*/
|
|
36
|
+
export declare function envelopeDecrypt(encryptedData: string, masterKey: Uint8Array): string;
|
|
4
37
|
export declare function encryptDEK(dek: Uint8Array, masterKey: Uint8Array): string;
|
|
5
38
|
export declare function decryptDEK(encryptedDEK: string, masterKey: Uint8Array): Uint8Array;
|
|
6
39
|
export declare function getMasterKey(): Uint8Array;
|
|
40
|
+
export declare function getPreviousMasterKey(): Uint8Array | null;
|
|
41
|
+
/** Zero and release cached master keys. Call on graceful shutdown. */
|
|
42
|
+
export declare function clearCachedKeys(): void;
|
|
7
43
|
export declare function generateMasterKey(): string;
|
|
8
44
|
export declare function encryptCredential(payload: Record<string, unknown>, masterKey: Uint8Array): {
|
|
9
45
|
encryptedDEK: string;
|
package/dist/crypto.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAYA,wBAAgB,WAAW,IAAI,UAAU,CAExC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAU7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CA0BtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAU3E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAKpF;AAkDD,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,MAAM,CAEzE;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAGlF;AAMD,wBAAgB,YAAY,IAAI,UAAU,CAMzC;AAMD,wBAAgB,oBAAoB,IAAI,UAAU,GAAG,IAAI,CAOxD;AAED,sEAAsE;AACtE,wBAAgB,eAAe,IAAI,IAAI,CAUtC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,SAAS,EAAE,UAAU,GACpB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAUpD;AAED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,UAAU,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB"}
|
package/dist/crypto.js
CHANGED
|
@@ -6,17 +6,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.generateKey = generateKey;
|
|
7
7
|
exports.encrypt = encrypt;
|
|
8
8
|
exports.decrypt = decrypt;
|
|
9
|
+
exports.envelopeEncrypt = envelopeEncrypt;
|
|
10
|
+
exports.envelopeDecrypt = envelopeDecrypt;
|
|
9
11
|
exports.encryptDEK = encryptDEK;
|
|
10
12
|
exports.decryptDEK = decryptDEK;
|
|
11
13
|
exports.getMasterKey = getMasterKey;
|
|
14
|
+
exports.getPreviousMasterKey = getPreviousMasterKey;
|
|
15
|
+
exports.clearCachedKeys = clearCachedKeys;
|
|
12
16
|
exports.generateMasterKey = generateMasterKey;
|
|
13
17
|
exports.encryptCredential = encryptCredential;
|
|
14
18
|
exports.decryptCredential = decryptCredential;
|
|
15
19
|
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
16
20
|
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
21
|
+
/**
|
|
22
|
+
* Envelope encryption prefix. Data encrypted with envelopeEncrypt() is
|
|
23
|
+
* stored as a single string: "env1:<base64-wrappedDEK>:<base64-payload>".
|
|
24
|
+
* The decrypt() function detects this prefix and automatically unwraps
|
|
25
|
+
* using the DEK, maintaining backward compatibility with legacy data
|
|
26
|
+
* encrypted directly with MASTER_KEY.
|
|
27
|
+
*/
|
|
28
|
+
const ENVELOPE_PREFIX = 'env1:';
|
|
17
29
|
function generateKey() {
|
|
18
30
|
return tweetnacl_1.default.randomBytes(32);
|
|
19
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Low-level symmetric encryption using a provided key.
|
|
34
|
+
* Callers that need envelope encryption (per-data DEK) should use
|
|
35
|
+
* envelopeEncrypt() instead.
|
|
36
|
+
*/
|
|
20
37
|
function encrypt(data, key) {
|
|
21
38
|
const nonce = tweetnacl_1.default.randomBytes(tweetnacl_1.default.secretbox.nonceLength);
|
|
22
39
|
const message = new TextEncoder().encode(data);
|
|
@@ -26,15 +43,118 @@ function encrypt(data, key) {
|
|
|
26
43
|
combined.set(box, nonce.length);
|
|
27
44
|
return (0, tweetnacl_util_1.encodeBase64)(combined);
|
|
28
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Low-level symmetric decryption. Handles both envelope-encrypted data
|
|
48
|
+
* (prefixed with "env1:") and legacy direct-key encrypted data.
|
|
49
|
+
*
|
|
50
|
+
* For envelope data: unwraps the per-data DEK using the master key,
|
|
51
|
+
* then decrypts the payload with the DEK.
|
|
52
|
+
*
|
|
53
|
+
* For legacy data: decrypts directly with the provided key, falling
|
|
54
|
+
* back to MASTER_KEY_PREVIOUS for key rotation support.
|
|
55
|
+
*/
|
|
29
56
|
function decrypt(encryptedData, key) {
|
|
57
|
+
// Detect envelope-encrypted format and handle transparently
|
|
58
|
+
if (encryptedData.startsWith(ENVELOPE_PREFIX)) {
|
|
59
|
+
return envelopeDecryptInternal(encryptedData, key);
|
|
60
|
+
}
|
|
61
|
+
// Legacy format: data encrypted directly with MASTER_KEY
|
|
30
62
|
const combined = (0, tweetnacl_util_1.decodeBase64)(encryptedData);
|
|
31
63
|
const nonce = combined.slice(0, tweetnacl_1.default.secretbox.nonceLength);
|
|
32
64
|
const box = combined.slice(tweetnacl_1.default.secretbox.nonceLength);
|
|
33
65
|
const message = tweetnacl_1.default.secretbox.open(box, nonce, key);
|
|
34
|
-
if (
|
|
35
|
-
|
|
66
|
+
if (message) {
|
|
67
|
+
return new TextDecoder().decode(message);
|
|
68
|
+
}
|
|
69
|
+
// Try previous master key for rotation support
|
|
70
|
+
const prevKey = getPreviousMasterKey();
|
|
71
|
+
if (prevKey) {
|
|
72
|
+
const message2 = tweetnacl_1.default.secretbox.open(box, nonce, prevKey);
|
|
73
|
+
if (message2) {
|
|
74
|
+
return new TextDecoder().decode(message2);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
throw new Error('Decryption failed: invalid key or corrupted data');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Encrypt arbitrary data using a per-data DEK (envelope encryption).
|
|
81
|
+
* Generates a fresh 256-bit DEK, encrypts the data with it, then wraps
|
|
82
|
+
* the DEK with the provided master key. Returns a single string in the
|
|
83
|
+
* format "env1:<wrappedDEK>:<encryptedPayload>" so it fits in a single
|
|
84
|
+
* database column and is backward-compatible with decrypt().
|
|
85
|
+
*
|
|
86
|
+
* Use this instead of encrypt() for all data at rest. Each encrypted
|
|
87
|
+
* value gets its own DEK, so compromising one ciphertext does not
|
|
88
|
+
* expose other data -- the attacker still needs the master key to
|
|
89
|
+
* unwrap any individual DEK.
|
|
90
|
+
*/
|
|
91
|
+
function envelopeEncrypt(data, masterKey) {
|
|
92
|
+
const dek = generateKey();
|
|
93
|
+
try {
|
|
94
|
+
const wrappedDEK = encrypt((0, tweetnacl_util_1.encodeBase64)(dek), masterKey);
|
|
95
|
+
const encryptedPayload = encrypt(data, dek);
|
|
96
|
+
return `${ENVELOPE_PREFIX}${wrappedDEK}:${encryptedPayload}`;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
// Zero DEK from memory after use (defense-in-depth against heap dumps)
|
|
100
|
+
dek.fill(0);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Decrypt data produced by envelopeEncrypt(). Expects the "env1:" prefixed
|
|
105
|
+
* format. For general use, call decrypt() which auto-detects the format.
|
|
106
|
+
*/
|
|
107
|
+
function envelopeDecrypt(encryptedData, masterKey) {
|
|
108
|
+
if (!encryptedData.startsWith(ENVELOPE_PREFIX)) {
|
|
109
|
+
throw new Error('Not an envelope-encrypted value (missing env1: prefix)');
|
|
110
|
+
}
|
|
111
|
+
return envelopeDecryptInternal(encryptedData, masterKey);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Internal envelope decryption. Parses the "env1:wrappedDEK:payload" format,
|
|
115
|
+
* unwraps the DEK, and decrypts the payload.
|
|
116
|
+
*/
|
|
117
|
+
function envelopeDecryptInternal(encryptedData, masterKey) {
|
|
118
|
+
// Format: "env1:<base64-wrappedDEK>:<base64-encryptedPayload>"
|
|
119
|
+
// The wrapped DEK itself is a base64 string produced by encrypt(), which
|
|
120
|
+
// can contain '+', '/', '=' but never ':'. So we split on ':' after the prefix.
|
|
121
|
+
const withoutPrefix = encryptedData.slice(ENVELOPE_PREFIX.length);
|
|
122
|
+
const separatorIndex = withoutPrefix.lastIndexOf(':');
|
|
123
|
+
if (separatorIndex <= 0) {
|
|
124
|
+
throw new Error('Invalid envelope format: missing DEK/payload separator');
|
|
125
|
+
}
|
|
126
|
+
const wrappedDEK = withoutPrefix.slice(0, separatorIndex);
|
|
127
|
+
const encryptedPayload = withoutPrefix.slice(separatorIndex + 1);
|
|
128
|
+
if (!wrappedDEK || !encryptedPayload) {
|
|
129
|
+
throw new Error('Invalid envelope format: empty DEK or payload');
|
|
130
|
+
}
|
|
131
|
+
// Unwrap the DEK using the master key (with key-rotation fallback)
|
|
132
|
+
let dekBase64;
|
|
133
|
+
try {
|
|
134
|
+
dekBase64 = decrypt(wrappedDEK, masterKey);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
throw new Error('Envelope decryption failed: could not unwrap DEK');
|
|
138
|
+
}
|
|
139
|
+
const dek = (0, tweetnacl_util_1.decodeBase64)(dekBase64);
|
|
140
|
+
try {
|
|
141
|
+
// Decrypt the payload using the per-data DEK
|
|
142
|
+
// Use low-level decryption here (not decrypt()) to avoid infinite
|
|
143
|
+
// recursion on the envelope prefix check -- the inner payload is
|
|
144
|
+
// always in legacy format.
|
|
145
|
+
const combined = (0, tweetnacl_util_1.decodeBase64)(encryptedPayload);
|
|
146
|
+
const nonce = combined.slice(0, tweetnacl_1.default.secretbox.nonceLength);
|
|
147
|
+
const box = combined.slice(tweetnacl_1.default.secretbox.nonceLength);
|
|
148
|
+
const message = tweetnacl_1.default.secretbox.open(box, nonce, dek);
|
|
149
|
+
if (!message) {
|
|
150
|
+
throw new Error('Envelope decryption failed: payload decryption failed');
|
|
151
|
+
}
|
|
152
|
+
return new TextDecoder().decode(message);
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
// Zero DEK from memory after use
|
|
156
|
+
dek.fill(0);
|
|
36
157
|
}
|
|
37
|
-
return new TextDecoder().decode(message);
|
|
38
158
|
}
|
|
39
159
|
function encryptDEK(dek, masterKey) {
|
|
40
160
|
return encrypt((0, tweetnacl_util_1.encodeBase64)(dek), masterKey);
|
|
@@ -48,12 +168,37 @@ function decryptDEK(encryptedDEK, masterKey) {
|
|
|
48
168
|
let _cachedMasterKey = null;
|
|
49
169
|
function getMasterKey() {
|
|
50
170
|
if (_cachedMasterKey)
|
|
51
|
-
return _cachedMasterKey;
|
|
171
|
+
return _cachedMasterKey.slice();
|
|
52
172
|
const key = process.env.MASTER_KEY;
|
|
53
173
|
if (!key)
|
|
54
174
|
throw new Error('MASTER_KEY environment variable not set');
|
|
55
175
|
_cachedMasterKey = (0, tweetnacl_util_1.decodeBase64)(key);
|
|
56
|
-
return _cachedMasterKey;
|
|
176
|
+
return _cachedMasterKey.slice();
|
|
177
|
+
}
|
|
178
|
+
// Support MASTER_KEY rotation: try previous key when current key fails
|
|
179
|
+
let _cachedPrevKey = null;
|
|
180
|
+
let _prevKeyChecked = false;
|
|
181
|
+
function getPreviousMasterKey() {
|
|
182
|
+
if (_prevKeyChecked)
|
|
183
|
+
return _cachedPrevKey ? _cachedPrevKey.slice() : null;
|
|
184
|
+
_prevKeyChecked = true;
|
|
185
|
+
const key = process.env.MASTER_KEY_PREVIOUS;
|
|
186
|
+
if (!key)
|
|
187
|
+
return null;
|
|
188
|
+
_cachedPrevKey = (0, tweetnacl_util_1.decodeBase64)(key);
|
|
189
|
+
return _cachedPrevKey.slice();
|
|
190
|
+
}
|
|
191
|
+
/** Zero and release cached master keys. Call on graceful shutdown. */
|
|
192
|
+
function clearCachedKeys() {
|
|
193
|
+
if (_cachedMasterKey) {
|
|
194
|
+
_cachedMasterKey.fill(0);
|
|
195
|
+
_cachedMasterKey = null;
|
|
196
|
+
}
|
|
197
|
+
if (_cachedPrevKey) {
|
|
198
|
+
_cachedPrevKey.fill(0);
|
|
199
|
+
_cachedPrevKey = null;
|
|
200
|
+
}
|
|
201
|
+
_prevKeyChecked = false;
|
|
57
202
|
}
|
|
58
203
|
function generateMasterKey() {
|
|
59
204
|
return (0, tweetnacl_util_1.encodeBase64)(generateKey());
|
package/dist/crypto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":";;;;;AAYA,kCAEC;AAOD,0BAUC;AAYD,0BA0BC;AAcD,0CAUC;AAMD,0CAKC;AAkDD,gCAEC;AAED,gCAGC;AAMD,oCAMC;AAMD,oDAOC;AAGD,0CAUC;AAED,8CAEC;AAED,8CAaC;AAED,8CAcC;AA1OD,0DAA6B;AAC7B,mDAA4D;AAE5D;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,SAAgB,WAAW;IACzB,OAAO,mBAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,SAAgB,OAAO,CAAC,IAAY,EAAE,GAAe;IACnD,MAAM,KAAK,GAAG,mBAAI,CAAC,WAAW,CAAC,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,mBAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3D,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEhC,OAAO,IAAA,6BAAY,EAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,OAAO,CAAC,aAAqB,EAAE,GAAe;IAC5D,4DAA4D;IAC5D,IAAI,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9C,OAAO,uBAAuB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,yDAAyD;IACzD,MAAM,QAAQ,GAAG,IAAA,6BAAY,EAAC,aAAa,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAEvD,MAAM,OAAO,GAAG,mBAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,+CAA+C;IAC/C,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,mBAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,eAAe,CAAC,IAAY,EAAE,SAAqB;IACjE,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,OAAO,CAAC,IAAA,6BAAY,EAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QACzD,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC5C,OAAO,GAAG,eAAe,GAAG,UAAU,IAAI,gBAAgB,EAAE,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,uEAAuE;QACvE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,aAAqB,EAAE,SAAqB;IAC1E,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,uBAAuB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,SAAS,uBAAuB,CAAC,aAAqB,EAAE,SAAqB;IAC3E,+DAA+D;IAC/D,yEAAyE;IACzE,gFAAgF;IAChF,MAAM,aAAa,GAAG,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtD,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,aAAa,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;IAEjE,IAAI,CAAC,UAAU,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,mEAAmE;IACnE,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,GAAG,GAAG,IAAA,6BAAY,EAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,6CAA6C;QAC7C,kEAAkE;QAClE,iEAAiE;QACjE,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,IAAA,6BAAY,EAAC,gBAAgB,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC5D,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,mBAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,mBAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;YAAS,CAAC;QACT,iCAAiC;QACjC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,GAAe,EAAE,SAAqB;IAC/D,OAAO,OAAO,CAAC,IAAA,6BAAY,EAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED,SAAgB,UAAU,CAAC,YAAoB,EAAE,SAAqB;IACpE,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACnD,OAAO,IAAA,6BAAY,EAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,4EAA4E;AAC5E,gFAAgF;AAChF,IAAI,gBAAgB,GAAsB,IAAI,CAAC;AAE/C,SAAgB,YAAY;IAC1B,IAAI,gBAAgB;QAAE,OAAO,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACrE,gBAAgB,GAAG,IAAA,6BAAY,EAAC,GAAG,CAAC,CAAC;IACrC,OAAO,gBAAgB,CAAC,KAAK,EAAE,CAAC;AAClC,CAAC;AAED,uEAAuE;AACvE,IAAI,cAAc,GAAsB,IAAI,CAAC;AAC7C,IAAI,eAAe,GAAG,KAAK,CAAC;AAE5B,SAAgB,oBAAoB;IAClC,IAAI,eAAe;QAAE,OAAO,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,eAAe,GAAG,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC5C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,cAAc,GAAG,IAAA,6BAAY,EAAC,GAAG,CAAC,CAAC;IACnC,OAAO,cAAc,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,sEAAsE;AACtE,SAAgB,eAAe;IAC7B,IAAI,gBAAgB,EAAE,CAAC;QACrB,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,gBAAgB,GAAG,IAAI,CAAC;IAC1B,CAAC;IACD,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,eAAe,GAAG,KAAK,CAAC;AAC1B,CAAC;AAED,SAAgB,iBAAiB;IAC/B,OAAO,IAAA,6BAAY,EAAC,WAAW,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,iBAAiB,CAC/B,OAAgC,EAChC,SAAqB;IAErB,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAC/D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,uEAAuE;QACvE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAC/B,YAAoB,EACpB,gBAAwB,EACxB,SAAqB;IAErB,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,iEAAiE;QACjE,qEAAqE;QACrE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/plans.d.ts
CHANGED
|
@@ -4,9 +4,13 @@ export interface PlanLimits {
|
|
|
4
4
|
agents: number;
|
|
5
5
|
credentials: number;
|
|
6
6
|
members: number;
|
|
7
|
+
policies: number;
|
|
7
8
|
timelineHistoryDays: number;
|
|
8
9
|
undoEnabled: boolean;
|
|
9
10
|
browserSessions: number;
|
|
11
|
+
messagesPerMonth: number;
|
|
12
|
+
messageHistoryDays: number;
|
|
13
|
+
threadsPerAgent: number;
|
|
10
14
|
}
|
|
11
15
|
export interface PlanDefinition extends PlanLimits {
|
|
12
16
|
id: PlanId;
|
package/dist/plans.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"plans.d.ts","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CA0DvC,CAAC;AAEX,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAgBtD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO9D"}
|
package/dist/plans.js
CHANGED
|
@@ -16,9 +16,13 @@ exports.PLANS = {
|
|
|
16
16
|
agents: 3,
|
|
17
17
|
credentials: 2,
|
|
18
18
|
members: 1,
|
|
19
|
+
policies: 3,
|
|
19
20
|
timelineHistoryDays: 14,
|
|
20
21
|
undoEnabled: false,
|
|
21
22
|
browserSessions: 0,
|
|
23
|
+
messagesPerMonth: 100,
|
|
24
|
+
messageHistoryDays: 7,
|
|
25
|
+
threadsPerAgent: 5,
|
|
22
26
|
},
|
|
23
27
|
pro: {
|
|
24
28
|
id: 'pro',
|
|
@@ -31,9 +35,13 @@ exports.PLANS = {
|
|
|
31
35
|
agents: 10,
|
|
32
36
|
credentials: 25,
|
|
33
37
|
members: 5,
|
|
38
|
+
policies: 10,
|
|
34
39
|
timelineHistoryDays: 90,
|
|
35
40
|
undoEnabled: true,
|
|
36
41
|
browserSessions: 2,
|
|
42
|
+
messagesPerMonth: 5000,
|
|
43
|
+
messageHistoryDays: 30,
|
|
44
|
+
threadsPerAgent: 50,
|
|
37
45
|
},
|
|
38
46
|
team: {
|
|
39
47
|
id: 'team',
|
|
@@ -46,9 +54,13 @@ exports.PLANS = {
|
|
|
46
54
|
agents: 50,
|
|
47
55
|
credentials: Infinity,
|
|
48
56
|
members: 25,
|
|
57
|
+
policies: 50,
|
|
49
58
|
timelineHistoryDays: 365,
|
|
50
59
|
undoEnabled: true,
|
|
51
60
|
browserSessions: 5,
|
|
61
|
+
messagesPerMonth: Infinity,
|
|
62
|
+
messageHistoryDays: 90,
|
|
63
|
+
threadsPerAgent: Infinity,
|
|
52
64
|
},
|
|
53
65
|
};
|
|
54
66
|
function getPlanLimits(plan) {
|
|
@@ -60,9 +72,13 @@ function getPlanLimits(plan) {
|
|
|
60
72
|
agents: def.agents,
|
|
61
73
|
credentials: def.credentials,
|
|
62
74
|
members: def.members,
|
|
75
|
+
policies: def.policies,
|
|
63
76
|
timelineHistoryDays: def.timelineHistoryDays,
|
|
64
77
|
undoEnabled: def.undoEnabled,
|
|
65
78
|
browserSessions: def.browserSessions,
|
|
79
|
+
messagesPerMonth: def.messagesPerMonth,
|
|
80
|
+
messageHistoryDays: def.messageHistoryDays,
|
|
81
|
+
threadsPerAgent: def.threadsPerAgent,
|
|
66
82
|
};
|
|
67
83
|
}
|
|
68
84
|
function canUndo(plan) {
|
package/dist/plans.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../src/plans.ts"],"names":[],"mappings":"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"}
|
package/dist/policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAUpB,eAAO,MAAM,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAUpB,eAAO,MAAM,oBAAoB,EAAE,WAiBlC,CAAC;AASF,wBAAgB,cAAc,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,WAAW,GACjB,sBAAsB,CAsHxB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CA6CA"}
|
package/dist/policy.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DEFAULT_POLICY_RULES = void 0;
|
|
4
4
|
exports.evaluatePolicy = evaluatePolicy;
|
|
5
5
|
exports.buildActionPreview = buildActionPreview;
|
|
6
|
-
const redact_js_1 = require("./redact.js");
|
|
7
6
|
const RISK_MAP = {
|
|
8
7
|
read: 'low',
|
|
9
8
|
write: 'medium',
|
|
@@ -17,6 +16,7 @@ exports.DEFAULT_POLICY_RULES = {
|
|
|
17
16
|
{ action_type: 'write', decision: 'REQUIRE_APPROVAL' },
|
|
18
17
|
{ action_type: 'financial', decision: 'REQUIRE_APPROVAL' },
|
|
19
18
|
{ action_type: 'admin', decision: 'BLOCK' },
|
|
19
|
+
{ tool: 'mcp.list_tools', decision: 'ALLOW' },
|
|
20
20
|
],
|
|
21
21
|
http: {
|
|
22
22
|
allowedDomains: [],
|
|
@@ -24,14 +24,27 @@ exports.DEFAULT_POLICY_RULES = {
|
|
|
24
24
|
blockList: [],
|
|
25
25
|
},
|
|
26
26
|
limits: {
|
|
27
|
-
maxActionsPerHour: 100,
|
|
27
|
+
maxActionsPerHour: 100, // Enforced in gateway via check_rate_limit RPC
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
|
+
// Default HTTP rules when rules.http is not configured
|
|
31
|
+
const DEFAULT_HTTP_RULES = {
|
|
32
|
+
allowedDomains: [],
|
|
33
|
+
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
34
|
+
blockList: [],
|
|
35
|
+
};
|
|
30
36
|
function evaluatePolicy(action, rules) {
|
|
37
|
+
// Block unknown action types (defense-in-depth)
|
|
38
|
+
if (!(action.action_type in RISK_MAP)) {
|
|
39
|
+
return { decision: 'BLOCK', risk_level: 'critical', reason: `Unknown action type: ${action.action_type}` };
|
|
40
|
+
}
|
|
41
|
+
// SECURITY: Normalize tool name to lowercase to prevent case-sensitivity
|
|
42
|
+
// bypasses (e.g., "Http.get" skipping HTTP domain allowlist checks).
|
|
43
|
+
const normalizedTool = action.tool.toLowerCase();
|
|
31
44
|
const risk_level = RISK_MAP[action.action_type] ?? 'medium';
|
|
32
45
|
// Browser tools: browser.open always requires approval
|
|
33
|
-
if (
|
|
34
|
-
if (
|
|
46
|
+
if (normalizedTool.startsWith('browser.')) {
|
|
47
|
+
if (normalizedTool === 'browser.open') {
|
|
35
48
|
return {
|
|
36
49
|
decision: 'REQUIRE_APPROVAL',
|
|
37
50
|
risk_level: 'medium',
|
|
@@ -47,26 +60,31 @@ function evaluatePolicy(action, rules) {
|
|
|
47
60
|
reason: 'Browser actions require an active session (use browser.open first)',
|
|
48
61
|
};
|
|
49
62
|
}
|
|
50
|
-
// MCP tools: list_tools
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
reason: 'MCP tool discovery is read-only',
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
if (action.tool.split('.')[0] === 'http' && rules.http) {
|
|
63
|
+
// MCP tools: list_tools handled via default rules (can be overridden by custom policies)
|
|
64
|
+
// HTTP tool checks: always enforce domain/method restrictions
|
|
65
|
+
const isHttpTool = normalizedTool.split('.')[0] === 'http';
|
|
66
|
+
if (isHttpTool) {
|
|
67
|
+
const httpRules = rules.http ?? DEFAULT_HTTP_RULES;
|
|
59
68
|
const url = action.payload.url;
|
|
69
|
+
if (!url) {
|
|
70
|
+
// SECURITY: HTTP actions without a URL must be blocked at the policy level.
|
|
71
|
+
// The connector would also reject it, but policy should be the first gate.
|
|
72
|
+
return { decision: 'BLOCK', risk_level: 'critical', reason: 'HTTP actions require a URL in payload' };
|
|
73
|
+
}
|
|
60
74
|
if (url) {
|
|
61
75
|
try {
|
|
62
|
-
const domain = new URL(url).hostname;
|
|
76
|
+
const domain = new URL(url).hostname.replace(/\.$/, '').toLowerCase();
|
|
63
77
|
// Use exact match or proper subdomain match (preceded by a dot)
|
|
64
78
|
// to prevent "not-trusted.com" from matching allowlist entry "trusted.com"
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
// Both sides are normalized: lowercase + trailing-dot stripped.
|
|
80
|
+
const matchesDomain = (d, pattern) => {
|
|
81
|
+
const normalizedPattern = pattern.replace(/\.$/, '').toLowerCase();
|
|
82
|
+
return d === normalizedPattern || d.endsWith('.' + normalizedPattern);
|
|
83
|
+
};
|
|
84
|
+
if (httpRules.blockList.some((b) => matchesDomain(domain, b))) {
|
|
67
85
|
return { decision: 'BLOCK', risk_level: 'critical', reason: `Domain ${domain} is in block list` };
|
|
68
86
|
}
|
|
69
|
-
if (
|
|
87
|
+
if (httpRules.allowedDomains.length === 0) {
|
|
70
88
|
// No allowlist configured: safe default is REQUIRE_APPROVAL, not ALLOW.
|
|
71
89
|
// This prevents agents from exfiltrating data to arbitrary domains.
|
|
72
90
|
return {
|
|
@@ -75,7 +93,7 @@ function evaluatePolicy(action, rules) {
|
|
|
75
93
|
reason: 'HTTP allowlist not configured — approval required for all HTTP calls',
|
|
76
94
|
};
|
|
77
95
|
}
|
|
78
|
-
if (!
|
|
96
|
+
if (!httpRules.allowedDomains.some((d) => matchesDomain(domain, d))) {
|
|
79
97
|
return { decision: 'BLOCK', risk_level, reason: `Domain ${domain} not in allowed list` };
|
|
80
98
|
}
|
|
81
99
|
}
|
|
@@ -84,7 +102,7 @@ function evaluatePolicy(action, rules) {
|
|
|
84
102
|
}
|
|
85
103
|
}
|
|
86
104
|
const method = action.payload.method?.toUpperCase();
|
|
87
|
-
if (method && !
|
|
105
|
+
if (method && !httpRules.allowedMethods.includes(method)) {
|
|
88
106
|
return { decision: 'BLOCK', risk_level, reason: `HTTP method ${method} not allowed` };
|
|
89
107
|
}
|
|
90
108
|
}
|
|
@@ -97,26 +115,36 @@ function evaluatePolicy(action, rules) {
|
|
|
97
115
|
reason: `Cost estimate ${action.cost_estimate} exceeds limit ${rules.limits.maxCostPerAction}`,
|
|
98
116
|
};
|
|
99
117
|
}
|
|
100
|
-
// Most specific: tool-specific rule
|
|
101
|
-
let matched = rules.rules.find((r) => r.tool
|
|
118
|
+
// Most specific: tool-specific rule (case-insensitive to prevent bypasses)
|
|
119
|
+
let matched = rules.rules.find((r) => r.tool !== undefined && r.tool.toLowerCase() === normalizedTool);
|
|
102
120
|
// Then action-type rule
|
|
103
121
|
if (!matched)
|
|
104
122
|
matched = rules.rules.find((r) => r.action_type === action.action_type);
|
|
105
123
|
if (matched) {
|
|
124
|
+
let finalDecision = matched.decision;
|
|
125
|
+
// SECURITY: Never auto-allow admin/financial actions even via explicit rules
|
|
126
|
+
if (finalDecision === 'ALLOW' && ['admin', 'financial'].includes(action.action_type)) {
|
|
127
|
+
finalDecision = 'REQUIRE_APPROVAL';
|
|
128
|
+
}
|
|
106
129
|
return {
|
|
107
|
-
decision:
|
|
130
|
+
decision: finalDecision,
|
|
108
131
|
risk_level,
|
|
109
132
|
reason: `Matched rule: ${matched.action_type ?? matched.tool}`,
|
|
110
133
|
matched_rule: matched,
|
|
111
134
|
};
|
|
112
135
|
}
|
|
113
136
|
const defaultDecision = rules.defaultMode === 'allow' ? 'ALLOW' : rules.defaultMode === 'block' ? 'BLOCK' : 'REQUIRE_APPROVAL';
|
|
137
|
+
// SECURITY: Never auto-allow high-risk actions via permissive default mode
|
|
138
|
+
if (defaultDecision === 'ALLOW' && ['admin', 'financial'].includes(action.action_type)) {
|
|
139
|
+
return { decision: 'REQUIRE_APPROVAL', risk_level, reason: 'High-risk action types always require approval even with permissive default policy' };
|
|
140
|
+
}
|
|
114
141
|
return { decision: defaultDecision, risk_level, reason: 'Default policy' };
|
|
115
142
|
}
|
|
116
143
|
function buildActionPreview(action) {
|
|
144
|
+
const normalizedTool = action.tool.toLowerCase();
|
|
117
145
|
let summary = `${action.action_type.toUpperCase()} via ${action.tool}`;
|
|
118
146
|
let target;
|
|
119
|
-
if (
|
|
147
|
+
if (normalizedTool.split('.')[0] === 'http') {
|
|
120
148
|
const url = action.payload.url;
|
|
121
149
|
const method = action.payload.method;
|
|
122
150
|
if (url) {
|
|
@@ -129,7 +157,7 @@ function buildActionPreview(action) {
|
|
|
129
157
|
summary = `${method?.toUpperCase() ?? 'HTTP'} request to ${target}`;
|
|
130
158
|
}
|
|
131
159
|
}
|
|
132
|
-
else if (
|
|
160
|
+
else if (normalizedTool === 'browser.open') {
|
|
133
161
|
const url = action.payload.url;
|
|
134
162
|
if (url) {
|
|
135
163
|
try {
|
|
@@ -144,20 +172,17 @@ function buildActionPreview(action) {
|
|
|
144
172
|
summary = 'Open browser session';
|
|
145
173
|
}
|
|
146
174
|
}
|
|
147
|
-
else if (
|
|
175
|
+
else if (normalizedTool === 'mcp.list_tools') {
|
|
148
176
|
const server = action.payload.server;
|
|
149
177
|
target = server;
|
|
150
178
|
summary = `List available tools on MCP server "${server ?? 'unknown'}"`;
|
|
151
179
|
}
|
|
152
|
-
else if (
|
|
180
|
+
else if (normalizedTool === 'mcp.call_tool') {
|
|
153
181
|
const server = action.payload.server;
|
|
154
182
|
const method = action.payload.method;
|
|
155
183
|
target = server;
|
|
156
184
|
summary = `Call "${method ?? 'unknown'}" on MCP server "${server ?? 'unknown'}"`;
|
|
157
185
|
}
|
|
158
|
-
else if (action.tool === 'demo') {
|
|
159
|
-
summary = `Write to demo table: ${JSON.stringify((0, redact_js_1.redact)(action.payload)).slice(0, 80)}`;
|
|
160
|
-
}
|
|
161
186
|
return {
|
|
162
187
|
summary,
|
|
163
188
|
target,
|
package/dist/policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|