@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.
@@ -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-preview.126","commit":"807fffa3fcd34b9d1e080282743f22122e024c84"};
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-preview.126","commit":"807fffa3fcd34b9d1e080282743f22122e024c84"};
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
+ }
package/dist/cjs/index.js CHANGED
@@ -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";