d70c7ea47b
Contract (capability incl. requiresFollowupFetch seam, verifySignature, normalize, fetch?, send), HMAC-SHA256 sign/verify (timing-safe), reference WebhookAdapter (normalize→IngestInteractionRequest), SandboxSink (no network), email/whatsapp fixtures. CJS build (consumed by the NestJS service). 4 tests; boundary updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
16 lines
601 B
TypeScript
16 lines
601 B
TypeScript
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
|
|
/** `sha256=<hex>` signature over the raw body (GitHub/Stripe style). */
|
|
export function hmacSign(body: string, secret: string): string {
|
|
return 'sha256=' + createHmac('sha256', secret).update(body).digest('hex');
|
|
}
|
|
|
|
export function hmacVerify(body: string, secret: string, signature: string | undefined): boolean {
|
|
if (!signature) return false;
|
|
const expected = hmacSign(body, secret);
|
|
const a = Buffer.from(expected);
|
|
const b = Buffer.from(signature);
|
|
if (a.length !== b.length) return false;
|
|
return timingSafeEqual(a, b);
|
|
}
|