@stackable-labs/sdk-extension-react 1.20.0 → 1.22.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/dist/rpc-client.d.ts +9 -0
- package/dist/rpc-client.js +49 -1
- package/dist/rpc-client.js.map +1 -1
- package/package.json +4 -2
package/dist/rpc-client.d.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RPC Client — sends capability requests from sandbox to host via postMessage.
|
|
3
|
+
* Handles transparent AES-256-GCM encryption for data.fetch payloads when
|
|
4
|
+
* an encryption key is provided by the host.
|
|
3
5
|
*/
|
|
4
6
|
import type { CapabilityType } from '@stackable-labs/sdk-extension-contracts';
|
|
7
|
+
/**
|
|
8
|
+
* Set the encryption key from a base64-encoded string.
|
|
9
|
+
* Called when the host sends an 'extension-encryption-key' message.
|
|
10
|
+
*/
|
|
11
|
+
export declare const setEncryptionKey: (keyBase64: string) => Promise<void>;
|
|
5
12
|
/**
|
|
6
13
|
* Initialize the RPC listener for responses from the host.
|
|
7
14
|
*/
|
|
8
15
|
export declare const initRpcListener: (extensionId: string) => void;
|
|
9
16
|
/**
|
|
10
17
|
* Send a capability request to the host and await the response.
|
|
18
|
+
* For data.fetch, transparently encrypts the request payload and
|
|
19
|
+
* decrypts the response when an encryption key is available.
|
|
11
20
|
*/
|
|
12
21
|
export declare const callCapability: <T = unknown>(capability: CapabilityType, payload?: unknown) => Promise<T>;
|
package/dist/rpc-client.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* RPC Client — sends capability requests from sandbox to host via postMessage.
|
|
3
|
+
* Handles transparent AES-256-GCM encryption for data.fetch payloads when
|
|
4
|
+
* an encryption key is provided by the host.
|
|
3
5
|
*/
|
|
6
|
+
import { WebCrypto } from '@agnostack/verifyd';
|
|
7
|
+
import { importKeyForEncryption } from '@stackable-labs/lib-utils-js';
|
|
8
|
+
// Lazy-init to avoid accessing globalThis.crypto at module load time.
|
|
9
|
+
// Uses native crypto to ensure CryptoKey compatibility with importKeyForEncryption.
|
|
10
|
+
let _webCrypto = null;
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
const getWebCrypto = () => (_webCrypto ??= new WebCrypto({ crypto: globalThis.crypto }));
|
|
4
13
|
let requestCounter = 0;
|
|
5
14
|
let registeredExtensionId = 'unknown';
|
|
15
|
+
let encryptionKey = null;
|
|
6
16
|
const pendingRequests = new Map();
|
|
7
17
|
const generateRequestId = () => `req_${++requestCounter}_${Date.now()}`;
|
|
18
|
+
/**
|
|
19
|
+
* Set the encryption key from a base64-encoded string.
|
|
20
|
+
* Called when the host sends an 'extension-encryption-key' message.
|
|
21
|
+
*/
|
|
22
|
+
export const setEncryptionKey = async (keyBase64) => {
|
|
23
|
+
encryptionKey = await importKeyForEncryption(keyBase64);
|
|
24
|
+
};
|
|
8
25
|
/**
|
|
9
26
|
* Initialize the RPC listener for responses from the host.
|
|
10
27
|
*/
|
|
@@ -12,6 +29,11 @@ export const initRpcListener = (extensionId) => {
|
|
|
12
29
|
registeredExtensionId = extensionId;
|
|
13
30
|
window.addEventListener('message', (event) => {
|
|
14
31
|
const msg = event.data;
|
|
32
|
+
// Handle encryption key distribution from host
|
|
33
|
+
if (msg?.type === 'extension-encryption-key') {
|
|
34
|
+
setEncryptionKey(msg.encryptionKey);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
15
37
|
if (msg?.type === 'capability-response') {
|
|
16
38
|
const response = msg;
|
|
17
39
|
const pending = pendingRequests.get(response.id);
|
|
@@ -27,10 +49,36 @@ export const initRpcListener = (extensionId) => {
|
|
|
27
49
|
}
|
|
28
50
|
});
|
|
29
51
|
};
|
|
52
|
+
const isEncryptedPayload = (value) => typeof value === 'object' && value !== null && value.encrypted === true && Array.isArray(value.data);
|
|
30
53
|
/**
|
|
31
54
|
* Send a capability request to the host and await the response.
|
|
55
|
+
* For data.fetch, transparently encrypts the request payload and
|
|
56
|
+
* decrypts the response when an encryption key is available.
|
|
57
|
+
*/
|
|
58
|
+
export const callCapability = async (capability, payload) => {
|
|
59
|
+
let actualPayload = payload;
|
|
60
|
+
// Encrypt data.fetch payloads if we have an encryption key
|
|
61
|
+
if (capability === 'data.fetch' && encryptionKey) {
|
|
62
|
+
const encrypted = await getWebCrypto().encryptMessage(JSON.stringify(payload), encryptionKey);
|
|
63
|
+
if (!encrypted)
|
|
64
|
+
throw new Error('Failed to encrypt data.fetch payload');
|
|
65
|
+
actualPayload = { encrypted: true, data: encrypted };
|
|
66
|
+
}
|
|
67
|
+
const result = await sendCapabilityRequest(capability, actualPayload);
|
|
68
|
+
// Decrypt data.fetch response if it came back encrypted
|
|
69
|
+
if (capability === 'data.fetch' && encryptionKey) {
|
|
70
|
+
const fetchResult = result;
|
|
71
|
+
if (isEncryptedPayload(fetchResult.data)) {
|
|
72
|
+
const decrypted = await getWebCrypto().decryptMessage(fetchResult.data.data, encryptionKey);
|
|
73
|
+
fetchResult.data = JSON.parse(decrypted);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Low-level: send a capability request to the host and await the response via postMessage.
|
|
32
80
|
*/
|
|
33
|
-
|
|
81
|
+
const sendCapabilityRequest = (capability, payload) => (new Promise((resolve, reject) => {
|
|
34
82
|
const id = generateRequestId();
|
|
35
83
|
pendingRequests.set(id, {
|
|
36
84
|
resolve: resolve,
|
package/dist/rpc-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rpc-client.js","sourceRoot":"","sources":["../src/rpc-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rpc-client.js","sourceRoot":"","sources":["../src/rpc-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackable-labs/sdk-extension-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@
|
|
15
|
+
"@agnostack/verifyd": "2.x",
|
|
16
|
+
"@stackable-labs/lib-utils-js": "workspace:*",
|
|
17
|
+
"@stackable-labs/sdk-extension-contracts": "1.22.0",
|
|
16
18
|
"@remote-dom/core": "1.x",
|
|
17
19
|
"@remote-dom/react": "1.x"
|
|
18
20
|
},
|