UNPKG

eve

Version:

Filesystem-first framework for durable backend AI agents that run anywhere.

1 lines • 1.68 kB
import{createHmac,timingSafeEqual}from"node:crypto";import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{resolveLinearWebhookSecret}from"#public/channels/linear/auth.js";const log=createLogger(`linear.verify`);async function verifyLinearRequest(e,t){let n=await e.text();if(t.webhookVerifier!==void 0){let r=await t.webhookVerifier(e,n);if(!r)throw Error(`linearChannel: inbound webhook verifier rejected the request.`);return typeof r==`string`?r:n}let r=await resolveLinearWebhookSecret(t.webhookSecret),i=e.headers.get(`linear-signature`)??``;if(!i)throw Error(`linearChannel: inbound request missing Linear-Signature.`);if(!constantTimeCompare(signLinearWebhookBody(n,r),i))throw Error(`linearChannel: inbound request signature mismatch.`);return verifyWebhookTimestamp(n,t.maxSkewMs??6e4),n}function signLinearWebhookBody(e,t){return createHmac(`sha256`,t).update(e).digest(`hex`)}function verifyWebhookTimestamp(e,t){if(!Number.isFinite(t)||t<0)throw Error(`linearChannel: maxSkewMs must be a non-negative finite number.`);let n;try{n=JSON.parse(e)}catch{throw Error(`linearChannel: inbound request body is not valid JSON.`)}let r=isObject(n)?n.webhookTimestamp:void 0;if(typeof r!=`number`||!Number.isFinite(r))throw Error(`linearChannel: inbound request missing webhookTimestamp.`);if(Math.abs(Date.now()-r)>t)throw Error(`linearChannel: inbound request timestamp outside allowed skew.`)}function constantTimeCompare(e,t){if(e.length!==t.length)return!1;try{return timingSafeEqual(Buffer.from(e),Buffer.from(t))}catch(e){return log.debug(`timingSafeEqual threw`,{error:e}),!1}}export{signLinearWebhookBody,verifyLinearRequest};