@ubiquity-os/plugin-sdk 1.0.9 → 1.0.11

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/index.d.mts CHANGED
@@ -36,6 +36,7 @@ interface Options$1 {
36
36
  postCommentOnError?: boolean;
37
37
  settingsSchema?: TAnySchema;
38
38
  envSchema?: TAnySchema;
39
+ bypassSignatureVerification?: boolean;
39
40
  }
40
41
  declare function createPlugin<TConfig = unknown, TEnv = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TSupportedEvents>) => Promise<Record<string, unknown> | undefined>, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
41
42
 
package/dist/index.d.ts CHANGED
@@ -36,6 +36,7 @@ interface Options$1 {
36
36
  postCommentOnError?: boolean;
37
37
  settingsSchema?: TAnySchema;
38
38
  envSchema?: TAnySchema;
39
+ bypassSignatureVerification?: boolean;
39
40
  }
40
41
  declare function createPlugin<TConfig = unknown, TEnv = unknown, TSupportedEvents extends EmitterWebhookEventName = EmitterWebhookEventName>(handler: (context: Context<TConfig, TEnv, TSupportedEvents>) => Promise<Record<string, unknown> | undefined>, manifest: Manifest, options?: Options$1): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
41
42
 
package/dist/index.js CHANGED
@@ -164,13 +164,19 @@ var inputSchema = import_typebox.Type.Object({
164
164
  authToken: import_typebox.Type.String(),
165
165
  settings: import_typebox.Type.Record(import_typebox.Type.String(), import_typebox.Type.Any()),
166
166
  ref: import_typebox.Type.String(),
167
- signature: import_typebox.Type.String()
167
+ signature: import_typebox.Type.String(),
168
+ bypassSignatureVerification: import_typebox.Type.Optional(
169
+ import_typebox.Type.Boolean({
170
+ default: false,
171
+ description: "Bypass signature verification (caution: only use this if you know what you're doing)"
172
+ })
173
+ )
168
174
  });
169
175
  function createPlugin(handler, manifest, options) {
170
176
  const pluginOptions = {
171
- kernelPublicKey: options?.kernelPublicKey || KERNEL_PUBLIC_KEY,
172
- logLevel: options?.logLevel || import_ubiquity_os_logger.LOG_LEVEL.INFO,
173
- postCommentOnError: options?.postCommentOnError || true,
177
+ kernelPublicKey: options?.kernelPublicKey ?? KERNEL_PUBLIC_KEY,
178
+ logLevel: options?.logLevel ?? import_ubiquity_os_logger.LOG_LEVEL.INFO,
179
+ postCommentOnError: options?.postCommentOnError ?? true,
174
180
  settingsSchema: options?.settingsSchema,
175
181
  envSchema: options?.envSchema
176
182
  };
@@ -190,7 +196,7 @@ function createPlugin(handler, manifest, options) {
190
196
  }
191
197
  const inputs = import_value.Value.Decode(inputSchema, body);
192
198
  const signature = inputs.signature;
193
- if (!await verifySignature(pluginOptions.kernelPublicKey, inputs, signature)) {
199
+ if (!options?.bypassSignatureVerification && !await verifySignature(pluginOptions.kernelPublicKey, inputs, signature)) {
194
200
  throw new import_http_exception.HTTPException(400, { message: "Invalid signature" });
195
201
  }
196
202
  let config2;
@@ -265,11 +271,11 @@ var inputSchema2 = import_typebox2.Type.Object({
265
271
  });
266
272
  async function createActionsPlugin(handler, options) {
267
273
  const pluginOptions = {
268
- logLevel: options?.logLevel || import_ubiquity_os_logger2.LOG_LEVEL.INFO,
269
- postCommentOnError: options?.postCommentOnError || true,
274
+ logLevel: options?.logLevel ?? import_ubiquity_os_logger2.LOG_LEVEL.INFO,
275
+ postCommentOnError: options?.postCommentOnError ?? true,
270
276
  settingsSchema: options?.settingsSchema,
271
277
  envSchema: options?.envSchema,
272
- kernelPublicKey: options?.kernelPublicKey || KERNEL_PUBLIC_KEY
278
+ kernelPublicKey: options?.kernelPublicKey ?? KERNEL_PUBLIC_KEY
273
279
  };
274
280
  const pluginGithubToken = process.env.PLUGIN_GITHUB_TOKEN;
275
281
  if (!pluginGithubToken) {
package/dist/index.mjs CHANGED
@@ -126,13 +126,19 @@ var inputSchema = T.Object({
126
126
  authToken: T.String(),
127
127
  settings: T.Record(T.String(), T.Any()),
128
128
  ref: T.String(),
129
- signature: T.String()
129
+ signature: T.String(),
130
+ bypassSignatureVerification: T.Optional(
131
+ T.Boolean({
132
+ default: false,
133
+ description: "Bypass signature verification (caution: only use this if you know what you're doing)"
134
+ })
135
+ )
130
136
  });
131
137
  function createPlugin(handler, manifest, options) {
132
138
  const pluginOptions = {
133
- kernelPublicKey: options?.kernelPublicKey || KERNEL_PUBLIC_KEY,
134
- logLevel: options?.logLevel || LOG_LEVEL.INFO,
135
- postCommentOnError: options?.postCommentOnError || true,
139
+ kernelPublicKey: options?.kernelPublicKey ?? KERNEL_PUBLIC_KEY,
140
+ logLevel: options?.logLevel ?? LOG_LEVEL.INFO,
141
+ postCommentOnError: options?.postCommentOnError ?? true,
136
142
  settingsSchema: options?.settingsSchema,
137
143
  envSchema: options?.envSchema
138
144
  };
@@ -152,7 +158,7 @@ function createPlugin(handler, manifest, options) {
152
158
  }
153
159
  const inputs = Value.Decode(inputSchema, body);
154
160
  const signature = inputs.signature;
155
- if (!await verifySignature(pluginOptions.kernelPublicKey, inputs, signature)) {
161
+ if (!options?.bypassSignatureVerification && !await verifySignature(pluginOptions.kernelPublicKey, inputs, signature)) {
156
162
  throw new HTTPException(400, { message: "Invalid signature" });
157
163
  }
158
164
  let config2;
@@ -227,11 +233,11 @@ var inputSchema2 = T2.Object({
227
233
  });
228
234
  async function createActionsPlugin(handler, options) {
229
235
  const pluginOptions = {
230
- logLevel: options?.logLevel || LOG_LEVEL2.INFO,
231
- postCommentOnError: options?.postCommentOnError || true,
236
+ logLevel: options?.logLevel ?? LOG_LEVEL2.INFO,
237
+ postCommentOnError: options?.postCommentOnError ?? true,
232
238
  settingsSchema: options?.settingsSchema,
233
239
  envSchema: options?.envSchema,
234
- kernelPublicKey: options?.kernelPublicKey || KERNEL_PUBLIC_KEY
240
+ kernelPublicKey: options?.kernelPublicKey ?? KERNEL_PUBLIC_KEY
235
241
  };
236
242
  const pluginGithubToken = process.env.PLUGIN_GITHUB_TOKEN;
237
243
  if (!pluginGithubToken) {
@@ -0,0 +1,12 @@
1
+ interface Inputs {
2
+ stateId: unknown;
3
+ eventName: unknown;
4
+ eventPayload: unknown;
5
+ authToken: unknown;
6
+ settings: unknown;
7
+ ref: unknown;
8
+ }
9
+ declare function verifySignature(publicKeyPem: string, inputs: Inputs, signature: string): Promise<boolean>;
10
+ declare function signPayload(payload: string, privateKey: string): Promise<string>;
11
+
12
+ export { signPayload, verifySignature };
@@ -0,0 +1,12 @@
1
+ interface Inputs {
2
+ stateId: unknown;
3
+ eventName: unknown;
4
+ eventPayload: unknown;
5
+ authToken: unknown;
6
+ settings: unknown;
7
+ ref: unknown;
8
+ }
9
+ declare function verifySignature(publicKeyPem: string, inputs: Inputs, signature: string): Promise<boolean>;
10
+ declare function signPayload(payload: string, privateKey: string): Promise<string>;
11
+
12
+ export { signPayload, verifySignature };
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/signature.ts
21
+ var signature_exports = {};
22
+ __export(signature_exports, {
23
+ signPayload: () => signPayload,
24
+ verifySignature: () => verifySignature
25
+ });
26
+ module.exports = __toCommonJS(signature_exports);
27
+ async function verifySignature(publicKeyPem, inputs, signature) {
28
+ try {
29
+ const inputsOrdered = {
30
+ stateId: inputs.stateId,
31
+ eventName: inputs.eventName,
32
+ eventPayload: inputs.eventPayload,
33
+ settings: inputs.settings,
34
+ authToken: inputs.authToken,
35
+ ref: inputs.ref
36
+ };
37
+ const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").trim();
38
+ const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));
39
+ const publicKey = await crypto.subtle.importKey(
40
+ "spki",
41
+ binaryDer,
42
+ {
43
+ name: "RSASSA-PKCS1-v1_5",
44
+ hash: "SHA-256"
45
+ },
46
+ true,
47
+ ["verify"]
48
+ );
49
+ const signatureArray = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
50
+ const dataArray = new TextEncoder().encode(JSON.stringify(inputsOrdered));
51
+ return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, signatureArray, dataArray);
52
+ } catch (error) {
53
+ console.error(error);
54
+ return false;
55
+ }
56
+ }
57
+ async function importRsaPrivateKey(pem) {
58
+ const pemContents = pem.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").trim();
59
+ const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));
60
+ return await crypto.subtle.importKey(
61
+ "pkcs8",
62
+ binaryDer.buffer,
63
+ {
64
+ name: "RSASSA-PKCS1-v1_5",
65
+ hash: "SHA-256"
66
+ },
67
+ true,
68
+ ["sign"]
69
+ );
70
+ }
71
+ async function signPayload(payload, privateKey) {
72
+ const data = new TextEncoder().encode(payload);
73
+ const _privateKey = await importRsaPrivateKey(privateKey);
74
+ const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", _privateKey, data);
75
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
76
+ }
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ signPayload,
80
+ verifySignature
81
+ });
@@ -0,0 +1,55 @@
1
+ // src/signature.ts
2
+ async function verifySignature(publicKeyPem, inputs, signature) {
3
+ try {
4
+ const inputsOrdered = {
5
+ stateId: inputs.stateId,
6
+ eventName: inputs.eventName,
7
+ eventPayload: inputs.eventPayload,
8
+ settings: inputs.settings,
9
+ authToken: inputs.authToken,
10
+ ref: inputs.ref
11
+ };
12
+ const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").trim();
13
+ const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));
14
+ const publicKey = await crypto.subtle.importKey(
15
+ "spki",
16
+ binaryDer,
17
+ {
18
+ name: "RSASSA-PKCS1-v1_5",
19
+ hash: "SHA-256"
20
+ },
21
+ true,
22
+ ["verify"]
23
+ );
24
+ const signatureArray = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
25
+ const dataArray = new TextEncoder().encode(JSON.stringify(inputsOrdered));
26
+ return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, signatureArray, dataArray);
27
+ } catch (error) {
28
+ console.error(error);
29
+ return false;
30
+ }
31
+ }
32
+ async function importRsaPrivateKey(pem) {
33
+ const pemContents = pem.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").trim();
34
+ const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));
35
+ return await crypto.subtle.importKey(
36
+ "pkcs8",
37
+ binaryDer.buffer,
38
+ {
39
+ name: "RSASSA-PKCS1-v1_5",
40
+ hash: "SHA-256"
41
+ },
42
+ true,
43
+ ["sign"]
44
+ );
45
+ }
46
+ async function signPayload(payload, privateKey) {
47
+ const data = new TextEncoder().encode(payload);
48
+ const _privateKey = await importRsaPrivateKey(privateKey);
49
+ const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", _privateKey, data);
50
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
51
+ }
52
+ export {
53
+ signPayload,
54
+ verifySignature
55
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubiquity-os/plugin-sdk",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "SDK for plugin support.",
5
5
  "author": "Ubiquity DAO",
6
6
  "license": "MIT",
@@ -18,6 +18,9 @@
18
18
  ],
19
19
  "constants": [
20
20
  "dist/constants.d.ts"
21
+ ],
22
+ "signature": [
23
+ "dist/signature.d.ts"
21
24
  ]
22
25
  }
23
26
  },
@@ -36,6 +39,11 @@
36
39
  "types": "./dist/constants.d.ts",
37
40
  "import": "./dist/constants.mjs",
38
41
  "require": "./dist/constants.js"
42
+ },
43
+ "./signature": {
44
+ "types": "./dist/signature.d.ts",
45
+ "import": "./dist/signature.mjs",
46
+ "require": "./dist/signature.js"
39
47
  }
40
48
  },
41
49
  "files": [
@@ -50,7 +58,7 @@
50
58
  "knip": "knip --config .github/knip.ts",
51
59
  "knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts",
52
60
  "prepare": "node .husky/install.mjs",
53
- "test": "jest --setupFiles dotenv/config --coverage"
61
+ "jest:test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest --setupFiles dotenv/config --coverage"
54
62
  },
55
63
  "keywords": [
56
64
  "typescript",
@@ -83,10 +91,10 @@
83
91
  "@cspell/dict-software-terms": "^3.3.18",
84
92
  "@cspell/dict-typescript": "^3.1.2",
85
93
  "@eslint/js": "^9.14.0",
86
- "@jest/globals": "29.7.0",
94
+ "@jest/globals": "^29.7.0",
87
95
  "@mswjs/data": "0.16.1",
88
- "@types/jest": "29.5.12",
89
96
  "@types/node": "^20.11.19",
97
+ "cross-env": "^7.0.3",
90
98
  "cspell": "^8.4.0",
91
99
  "eslint": "^9.14.0",
92
100
  "eslint-config-prettier": "^9.1.0",
@@ -94,13 +102,17 @@
94
102
  "eslint-plugin-prettier": "^5.2.1",
95
103
  "eslint-plugin-sonarjs": "^2.0.4",
96
104
  "husky": "^9.0.11",
97
- "jest": "29.7.0",
98
- "jest-junit": "16.0.0",
99
- "jest-md-dashboard": "0.8.0",
105
+ "jest": "^29.7.0",
106
+ "jest-junit": "^16.0.0",
107
+ "jest-md-dashboard": "^0.8.0",
100
108
  "knip": "^5.0.1",
101
109
  "lint-staged": "^15.2.2",
110
+ "msw": "^2.6.3",
111
+ "npm-run-all": "^4.1.5",
102
112
  "prettier": "^3.3.3",
103
- "ts-jest": "29.1.2",
113
+ "simple-git": "^3.27.0",
114
+ "ts-jest": "^29.2.5",
115
+ "ts-node": "^10.9.2",
104
116
  "tsup": "8.1.0",
105
117
  "typescript": "^5.5.4",
106
118
  "typescript-eslint": "^8.13.0"