@blaxel/core 0.2.52-preview.126 → 0.2.52
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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs/common/webhook.js +101 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/types/client/types.gen.d.ts +12 -0
- package/dist/cjs/types/common/webhook.d.ts +89 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/cjs-browser/common/webhook.js +101 -0
- package/dist/cjs-browser/index.js +1 -0
- package/dist/cjs-browser/types/client/types.gen.d.ts +12 -0
- package/dist/cjs-browser/types/common/webhook.d.ts +89 -0
- package/dist/cjs-browser/types/index.d.ts +1 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm/common/webhook.js +97 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/settings.js +2 -2
- package/dist/esm-browser/common/webhook.js +97 -0
- package/dist/esm-browser/index.js +1 -0
- package/package.json +2 -2
|
@@ -10,7 +10,7 @@ function getPackageVersion() {
|
|
|
10
10
|
if (typeof require !== "undefined") {
|
|
11
11
|
// Try to require package.json (Node.js only, gracefully fails in browser)
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
|
-
const packageJson = {"version":"0.2.52
|
|
13
|
+
const packageJson = {"version":"0.2.52","commit":"4acd7b5efa6c9e04c5131f55e7a87029c4889b1d"};
|
|
14
14
|
return packageJson.version || "unknown";
|
|
15
15
|
}
|
|
16
16
|
else {
|
|
@@ -62,7 +62,7 @@ function getCommitHash() {
|
|
|
62
62
|
if (typeof require !== "undefined") {
|
|
63
63
|
// Try to require package.json and look for commit field (set during build)
|
|
64
64
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
65
|
-
const packageJson = {"version":"0.2.52
|
|
65
|
+
const packageJson = {"version":"0.2.52","commit":"4acd7b5efa6c9e04c5131f55e7a87029c4889b1d"};
|
|
66
66
|
// Check for commit in various possible locations
|
|
67
67
|
const commit = packageJson.commit || packageJson.buildInfo?.commit;
|
|
68
68
|
if (commit) {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
4
|
+
exports.verifyWebhookFromRequest = verifyWebhookFromRequest;
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
/**
|
|
7
|
+
* Verify the HMAC-SHA256 signature of a webhook callback from async-sidecar
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { verifyWebhookSignature } from '@blaxel/core';
|
|
12
|
+
*
|
|
13
|
+
* // In your Express endpoint
|
|
14
|
+
* app.post('/webhook', express.text({ type: 'application/json' }), (req, res) => {
|
|
15
|
+
* const isValid = verifyWebhookSignature({
|
|
16
|
+
* body: req.body,
|
|
17
|
+
* signature: req.headers['x-blaxel-signature'] as string,
|
|
18
|
+
* secret: process.env.CALLBACK_SECRET!
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* if (!isValid) {
|
|
22
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* const data = JSON.parse(req.body);
|
|
26
|
+
* // Process callback...
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param options - Verification options
|
|
31
|
+
* @returns true if the signature is valid, false otherwise
|
|
32
|
+
*/
|
|
33
|
+
function verifyWebhookSignature(options) {
|
|
34
|
+
const { body, signature, secret, timestamp, maxAge = 300 } = options;
|
|
35
|
+
if (!body || !signature || !secret) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
// Verify timestamp if provided (prevents replay attacks)
|
|
40
|
+
if (timestamp) {
|
|
41
|
+
const requestTime = parseInt(timestamp, 10);
|
|
42
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
43
|
+
const age = Math.abs(currentTime - requestTime);
|
|
44
|
+
if (isNaN(requestTime) || age > maxAge) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Extract hex signature from "sha256=<hex>" format
|
|
49
|
+
const expectedSignature = signature.replace('sha256=', '');
|
|
50
|
+
// Compute HMAC-SHA256 signature
|
|
51
|
+
const hmac = (0, crypto_1.createHmac)('sha256', secret);
|
|
52
|
+
hmac.update(body);
|
|
53
|
+
const computedSignature = hmac.digest('hex');
|
|
54
|
+
// Timing-safe comparison to prevent timing attacks
|
|
55
|
+
return (0, crypto_1.timingSafeEqual)(Buffer.from(expectedSignature, 'hex'), Buffer.from(computedSignature, 'hex'));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Invalid signature format or other error
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper to verify webhook from Express request object
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { verifyWebhookFromRequest } from '@blaxel/core';
|
|
68
|
+
* import express from 'express';
|
|
69
|
+
*
|
|
70
|
+
* app.use(express.text({ type: 'application/json' }));
|
|
71
|
+
*
|
|
72
|
+
* app.post('/webhook', (req, res) => {
|
|
73
|
+
* if (!verifyWebhookFromRequest(req, process.env.CALLBACK_SECRET!)) {
|
|
74
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* const data = JSON.parse(req.body);
|
|
78
|
+
* console.log('Received callback:', data);
|
|
79
|
+
* res.json({ received: true });
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @param request - Express request object (must use express.text() middleware)
|
|
84
|
+
* @param secret - The callback secret
|
|
85
|
+
* @param maxAge - Optional maximum age in seconds (default: 300)
|
|
86
|
+
* @returns true if the signature is valid, false otherwise
|
|
87
|
+
*/
|
|
88
|
+
function verifyWebhookFromRequest(request, secret, maxAge) {
|
|
89
|
+
const signature = request.headers['x-blaxel-signature'];
|
|
90
|
+
const timestamp = request.headers['x-blaxel-timestamp'];
|
|
91
|
+
if (typeof signature !== 'string') {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return verifyWebhookSignature({
|
|
95
|
+
body: request.body,
|
|
96
|
+
signature,
|
|
97
|
+
secret,
|
|
98
|
+
timestamp: typeof timestamp === 'string' ? timestamp : undefined,
|
|
99
|
+
maxAge
|
|
100
|
+
});
|
|
101
|
+
}
|
|
@@ -24,6 +24,7 @@ __exportStar(require("./common/errors.js"), exports);
|
|
|
24
24
|
__exportStar(require("./common/internal.js"), exports);
|
|
25
25
|
__exportStar(require("./common/logger.js"), exports);
|
|
26
26
|
__exportStar(require("./common/settings.js"), exports);
|
|
27
|
+
__exportStar(require("./common/webhook.js"), exports);
|
|
27
28
|
__exportStar(require("./jobs/index.js"), exports);
|
|
28
29
|
__exportStar(require("./mcp/index.js"), exports);
|
|
29
30
|
__exportStar(require("./models/index.js"), exports);
|
|
@@ -2779,6 +2779,14 @@ export type TriggerConfiguration = {
|
|
|
2779
2779
|
* The authentication type of the trigger
|
|
2780
2780
|
*/
|
|
2781
2781
|
authenticationType?: string;
|
|
2782
|
+
/**
|
|
2783
|
+
* The callback secret for async triggers (auto-generated, encrypted)
|
|
2784
|
+
*/
|
|
2785
|
+
callbackSecret?: string;
|
|
2786
|
+
/**
|
|
2787
|
+
* The callback URL for async triggers (optional)
|
|
2788
|
+
*/
|
|
2789
|
+
callbackUrl?: string;
|
|
2782
2790
|
/**
|
|
2783
2791
|
* The path of the trigger
|
|
2784
2792
|
*/
|
|
@@ -2795,6 +2803,10 @@ export type TriggerConfiguration = {
|
|
|
2795
2803
|
* The tasks configuration of the cronjob
|
|
2796
2804
|
*/
|
|
2797
2805
|
tasks?: Array<TriggerConfigurationTask>;
|
|
2806
|
+
/**
|
|
2807
|
+
* The timeout in seconds for async triggers (max 900s, MK3 only)
|
|
2808
|
+
*/
|
|
2809
|
+
timeout?: number;
|
|
2798
2810
|
};
|
|
2799
2811
|
/**
|
|
2800
2812
|
* The tasks configuration of the cronjob
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook signature verification for async-sidecar callbacks
|
|
3
|
+
*/
|
|
4
|
+
export interface WebhookVerificationOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The raw request body as a string
|
|
7
|
+
*/
|
|
8
|
+
body: string;
|
|
9
|
+
/**
|
|
10
|
+
* The X-Blaxel-Signature header value (format: "sha256=<hex_digest>")
|
|
11
|
+
*/
|
|
12
|
+
signature: string;
|
|
13
|
+
/**
|
|
14
|
+
* The secret key used to sign the webhook (same as CALLBACK_SECRET in async-sidecar)
|
|
15
|
+
*/
|
|
16
|
+
secret: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional: The X-Blaxel-Timestamp header value for replay attack prevention
|
|
19
|
+
*/
|
|
20
|
+
timestamp?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Optional: Maximum age of the webhook in seconds (default: 300 = 5 minutes)
|
|
23
|
+
*/
|
|
24
|
+
maxAge?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface AsyncSidecarCallback {
|
|
27
|
+
status_code: number;
|
|
28
|
+
response_body: string;
|
|
29
|
+
response_length: number;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verify the HMAC-SHA256 signature of a webhook callback from async-sidecar
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { verifyWebhookSignature } from '@blaxel/core';
|
|
38
|
+
*
|
|
39
|
+
* // In your Express endpoint
|
|
40
|
+
* app.post('/webhook', express.text({ type: 'application/json' }), (req, res) => {
|
|
41
|
+
* const isValid = verifyWebhookSignature({
|
|
42
|
+
* body: req.body,
|
|
43
|
+
* signature: req.headers['x-blaxel-signature'] as string,
|
|
44
|
+
* secret: process.env.CALLBACK_SECRET!
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* if (!isValid) {
|
|
48
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* const data = JSON.parse(req.body);
|
|
52
|
+
* // Process callback...
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param options - Verification options
|
|
57
|
+
* @returns true if the signature is valid, false otherwise
|
|
58
|
+
*/
|
|
59
|
+
export declare function verifyWebhookSignature(options: WebhookVerificationOptions): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Helper to verify webhook from Express request object
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { verifyWebhookFromRequest } from '@blaxel/core';
|
|
66
|
+
* import express from 'express';
|
|
67
|
+
*
|
|
68
|
+
* app.use(express.text({ type: 'application/json' }));
|
|
69
|
+
*
|
|
70
|
+
* app.post('/webhook', (req, res) => {
|
|
71
|
+
* if (!verifyWebhookFromRequest(req, process.env.CALLBACK_SECRET!)) {
|
|
72
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* const data = JSON.parse(req.body);
|
|
76
|
+
* console.log('Received callback:', data);
|
|
77
|
+
* res.json({ received: true });
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @param request - Express request object (must use express.text() middleware)
|
|
82
|
+
* @param secret - The callback secret
|
|
83
|
+
* @param maxAge - Optional maximum age in seconds (default: 300)
|
|
84
|
+
* @returns true if the signature is valid, false otherwise
|
|
85
|
+
*/
|
|
86
|
+
export declare function verifyWebhookFromRequest(request: {
|
|
87
|
+
body: string;
|
|
88
|
+
headers: Record<string, string | string[] | undefined>;
|
|
89
|
+
}, secret: string, maxAge?: number): boolean;
|
|
@@ -8,6 +8,7 @@ export * from "./common/errors.js";
|
|
|
8
8
|
export * from "./common/internal.js";
|
|
9
9
|
export * from "./common/logger.js";
|
|
10
10
|
export * from "./common/settings.js";
|
|
11
|
+
export * from "./common/webhook.js";
|
|
11
12
|
export * from "./jobs/index.js";
|
|
12
13
|
export * from "./mcp/index.js";
|
|
13
14
|
export * from "./models/index.js";
|