/**
 * Trello webhook types and signature verification utilities.
 *
 * Provides pure-function signature verification for Trello webhook payloads
 * using HMAC-SHA1 with base64 encoding.
 *
 * Trello signs webhooks differently from GitHub and Stripe:
 * - The signature header is `X-Trello-Webhook` (base64-encoded HMAC-SHA1)
 * - The HMAC is computed over `${rawBody}${callbackURL}` (body + callback URL)
 * - The signing secret is the application's API secret (also the OAuth 1.0 secret)
 * - There is no timestamp-based replay protection
 *
 * @see https://developer.atlassian.com/cloud/trello/guides/rest-api/webhooks/
 */
import crypto from 'node:crypto';
// ── Trello webhook header name ──────────────────────────────────────────
/** Header containing the base64-encoded HMAC-SHA1 signature. */
export const TRELLO_SIGNATURE_HEADER = 'x-trello-webhook';
// ── Signature verification ──────────────────────────────────────────────
/**
 * Verify a Trello webhook signature (HMAC-SHA1, base64-encoded).
 *
 * Trello computes the signature over `${rawBody}${callbackURL}` using
 * the application's API secret as the HMAC key. The result is base64-encoded
 * and sent in the `X-Trello-Webhook` header.
 *
 * Uses timing-safe comparison to prevent timing attacks.
 *
 * @param rawBody - The raw request body as a Buffer.
 * @param signatureHeader - The value of the X-Trello-Webhook header (base64-encoded).
 * @param secret - The Trello application API secret.
 * @param callbackUrl - The callback URL exactly as provided during webhook creation.
 * @returns true if the signature is valid, false otherwise.
 */
export function verifyTrelloSignature(rawBody, signatureHeader, secret, callbackUrl) {
    // Trello signs: HMAC-SHA1(secret, body + callbackURL)
    const content = rawBody.toString('utf-8') + callbackUrl;
    const computedSig = crypto.createHmac('sha1', secret).update(content).digest('base64');
    // Timing-safe comparison on the raw base64 bytes
    try {
        const receivedBuf = Buffer.from(signatureHeader, 'base64');
        const computedBuf = Buffer.from(computedSig, 'base64');
        return (receivedBuf.length === computedBuf.length && crypto.timingSafeEqual(receivedBuf, computedBuf));
    }
    catch {
        // Invalid base64 or length mismatch
        return false;
    }
}
// ── Payload extraction helpers ──────────────────────────────────────────
/**
 * Extract the action type from a parsed Trello webhook body.
 *
 * Returns `body.action.type` (e.g., 'updateCard', 'createCard',
 * 'addMemberToBoard', 'commentCard'). Falls back to 'unknown' if the
 * expected structure is missing.
 */
export function extractTrelloActionType(body) {
    if (body && typeof body === 'object' && 'action' in body) {
        const action = body.action;
        if (action && typeof action === 'object' && 'type' in action) {
            return String(action.type);
        }
    }
    return 'unknown';
}
/**
 * Extract the action ID from a parsed Trello webhook body.
 *
 * Returns `body.action.id` or undefined if not present.
 */
export function extractTrelloActionId(body) {
    if (body && typeof body === 'object' && 'action' in body) {
        const action = body.action;
        if (action && typeof action === 'object' && 'id' in action) {
            return String(action.id);
        }
    }
    return undefined;
}
//# sourceMappingURL=trello-types.js.map