@particle-academy/fancy-connector-core 0.11.0 → 0.12.0

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/index.d.cts CHANGED
@@ -2468,7 +2468,7 @@ type HmacScheme = {
2468
2468
  * `v0:${timestamp}:${body}`, GitHub signs the body alone, and Svix signs
2469
2469
  * `${id}.${timestamp}.${body}` where `id` is the delivery's own id header.
2470
2470
  */
2471
- payload: (raw: string, timestamp?: string, id?: string) => string;
2471
+ payload: (raw: string, timestamp?: string, id?: string, request?: SignedRequestLine) => string;
2472
2472
  /** Seconds a delivery stays acceptable. */
2473
2473
  tolerance?: number;
2474
2474
  /** Encoding of the signature the provider sends. */
@@ -2483,7 +2483,37 @@ type HmacScheme = {
2483
2483
  secretEncoding?: "utf8" | "base64";
2484
2484
  /** A prefix to strip before decoding (`whsec_`). Its absence is a refusal, never a guess. */
2485
2485
  secretPrefix?: string;
2486
+ /**
2487
+ * The unit the timestamp header is in. Seconds unless said otherwise:
2488
+ * HubSpot sends MILLISECONDS, and comparing those with a window in seconds
2489
+ * refuses every delivery ever made.
2490
+ */
2491
+ timestampUnit?: "s" | "ms";
2492
+ /**
2493
+ * The provider signs the REQUEST LINE too (HubSpot v3:
2494
+ * method + uri + body + timestamp). A delivery the host passed without its
2495
+ * method or URL is refused by name, never signed with a gap.
2496
+ */
2497
+ signsRequestLine?: boolean;
2498
+ /** How the signed URI is spelled from the URL the request was sent to. */
2499
+ uri?: SignedUriRule;
2500
+ };
2501
+ /** The URI rules a provider's signature can follow. Closed: each is a decision. */
2502
+ declare const SIGNED_URI_RULES: readonly ["hubspot-v3"];
2503
+ type SignedUriRule = (typeof SIGNED_URI_RULES)[number];
2504
+ /** The request line as signed: the method, and the URI after the scheme's rule. */
2505
+ type SignedRequestLine = {
2506
+ method: string;
2507
+ uri: string;
2486
2508
  };
2509
+ /**
2510
+ * The URI a provider signs, from the URL the request arrived on.
2511
+ *
2512
+ * `hubspot-v3`: only the QUERY portion is percent-decoded, and only for twelve
2513
+ * escapes (case-insensitive); never its leading `?`; any `#fragment` dropped.
2514
+ * Everything else, `%26` and `%3D` included, stays as sent.
2515
+ */
2516
+ declare function normaliseSignedUri(url: string, rule: SignedUriRule): string;
2487
2517
  /** The HMAC key a scheme's secret spells, or the reason it cannot be one. */
2488
2518
  declare function secretKeyBytes(secret: string, options?: {
2489
2519
  secretEncoding?: "utf8" | "base64";
@@ -2516,6 +2546,11 @@ declare function verifyHmac(options: {
2516
2546
  timestamp?: string;
2517
2547
  /** The delivery's id, when the scheme signs one (Svix's `svix-id`). */
2518
2548
  id?: string;
2549
+ /** The request line as RECEIVED, when the scheme signs it (HubSpot v3). */
2550
+ request?: {
2551
+ method: string;
2552
+ url: string;
2553
+ };
2519
2554
  /** Seconds since the epoch. Injected so tests are not clock-dependent. */
2520
2555
  now?: number;
2521
2556
  }): Promise<WebhookVerification>;
@@ -2627,6 +2662,11 @@ declare function header(headers: Record<string, string | string[] | undefined>,
2627
2662
  * SSE, CometD).
2628
2663
  */
2629
2664
  type DeliveryMechanism = "webhook" | "subscription" | "poll" | "pubsub" | "stream";
2665
+ /** See `TriggerDescriptor.route`. `path` is dotted; `[]` means every element. */
2666
+ type DeliveryRoute = {
2667
+ by: string;
2668
+ path: string;
2669
+ };
2630
2670
  type TriggerDescriptor = {
2631
2671
  service: string;
2632
2672
  operation: string;
@@ -2655,6 +2695,15 @@ type TriggerDescriptor = {
2655
2695
  * it, over the same raw bytes the signature was checked against.
2656
2696
  */
2657
2697
  decode?: DeliveryDecode;
2698
+ /**
2699
+ * For a delivery that reaches ONE endpoint on behalf of many tenants
2700
+ * (HubSpot app webhooks, Gmail's Pub/Sub topic): the ONLY key a host may
2701
+ * route by, and where it sits in the verified payload. The rule that goes
2702
+ * with it is fixed, not configurable: route only AFTER verification, only
2703
+ * to a connection or watch the host minted, and drop an unmapped key with a
2704
+ * 2xx and a log line, creating nothing. The package declares; the HOST routes.
2705
+ */
2706
+ route?: DeliveryRoute;
2658
2707
  /** For `poll`: the provider's smallest sane interval, in seconds. */
2659
2708
  minPollSeconds?: number;
2660
2709
  /** A faked sample event, so the node is runnable before any of the above. */
@@ -2703,6 +2752,13 @@ type InboundDelivery = {
2703
2752
  /** The body EXACTLY as received. Not re-serialised. See `webhook.ts`. */
2704
2753
  raw: string;
2705
2754
  headers: Record<string, string | string[] | undefined>;
2755
+ /**
2756
+ * The request line as RECEIVED, for a provider that signs it (HubSpot v3).
2757
+ * Pass the full URL the provider called, scheme, host, path and query,
2758
+ * exactly as it arrived.
2759
+ */
2760
+ method?: string;
2761
+ url?: string;
2706
2762
  };
2707
2763
  /**
2708
2764
  * Verify an inbound delivery against a trigger's declared scheme.
@@ -2728,4 +2784,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
2728
2784
  */
2729
2785
  declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
2730
2786
 
2731
- export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, type JoinTarget, type JoinTargetKind, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
2787
+ export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, type JoinTarget, type JoinTargetKind, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
package/dist/index.d.ts CHANGED
@@ -2468,7 +2468,7 @@ type HmacScheme = {
2468
2468
  * `v0:${timestamp}:${body}`, GitHub signs the body alone, and Svix signs
2469
2469
  * `${id}.${timestamp}.${body}` where `id` is the delivery's own id header.
2470
2470
  */
2471
- payload: (raw: string, timestamp?: string, id?: string) => string;
2471
+ payload: (raw: string, timestamp?: string, id?: string, request?: SignedRequestLine) => string;
2472
2472
  /** Seconds a delivery stays acceptable. */
2473
2473
  tolerance?: number;
2474
2474
  /** Encoding of the signature the provider sends. */
@@ -2483,7 +2483,37 @@ type HmacScheme = {
2483
2483
  secretEncoding?: "utf8" | "base64";
2484
2484
  /** A prefix to strip before decoding (`whsec_`). Its absence is a refusal, never a guess. */
2485
2485
  secretPrefix?: string;
2486
+ /**
2487
+ * The unit the timestamp header is in. Seconds unless said otherwise:
2488
+ * HubSpot sends MILLISECONDS, and comparing those with a window in seconds
2489
+ * refuses every delivery ever made.
2490
+ */
2491
+ timestampUnit?: "s" | "ms";
2492
+ /**
2493
+ * The provider signs the REQUEST LINE too (HubSpot v3:
2494
+ * method + uri + body + timestamp). A delivery the host passed without its
2495
+ * method or URL is refused by name, never signed with a gap.
2496
+ */
2497
+ signsRequestLine?: boolean;
2498
+ /** How the signed URI is spelled from the URL the request was sent to. */
2499
+ uri?: SignedUriRule;
2500
+ };
2501
+ /** The URI rules a provider's signature can follow. Closed: each is a decision. */
2502
+ declare const SIGNED_URI_RULES: readonly ["hubspot-v3"];
2503
+ type SignedUriRule = (typeof SIGNED_URI_RULES)[number];
2504
+ /** The request line as signed: the method, and the URI after the scheme's rule. */
2505
+ type SignedRequestLine = {
2506
+ method: string;
2507
+ uri: string;
2486
2508
  };
2509
+ /**
2510
+ * The URI a provider signs, from the URL the request arrived on.
2511
+ *
2512
+ * `hubspot-v3`: only the QUERY portion is percent-decoded, and only for twelve
2513
+ * escapes (case-insensitive); never its leading `?`; any `#fragment` dropped.
2514
+ * Everything else, `%26` and `%3D` included, stays as sent.
2515
+ */
2516
+ declare function normaliseSignedUri(url: string, rule: SignedUriRule): string;
2487
2517
  /** The HMAC key a scheme's secret spells, or the reason it cannot be one. */
2488
2518
  declare function secretKeyBytes(secret: string, options?: {
2489
2519
  secretEncoding?: "utf8" | "base64";
@@ -2516,6 +2546,11 @@ declare function verifyHmac(options: {
2516
2546
  timestamp?: string;
2517
2547
  /** The delivery's id, when the scheme signs one (Svix's `svix-id`). */
2518
2548
  id?: string;
2549
+ /** The request line as RECEIVED, when the scheme signs it (HubSpot v3). */
2550
+ request?: {
2551
+ method: string;
2552
+ url: string;
2553
+ };
2519
2554
  /** Seconds since the epoch. Injected so tests are not clock-dependent. */
2520
2555
  now?: number;
2521
2556
  }): Promise<WebhookVerification>;
@@ -2627,6 +2662,11 @@ declare function header(headers: Record<string, string | string[] | undefined>,
2627
2662
  * SSE, CometD).
2628
2663
  */
2629
2664
  type DeliveryMechanism = "webhook" | "subscription" | "poll" | "pubsub" | "stream";
2665
+ /** See `TriggerDescriptor.route`. `path` is dotted; `[]` means every element. */
2666
+ type DeliveryRoute = {
2667
+ by: string;
2668
+ path: string;
2669
+ };
2630
2670
  type TriggerDescriptor = {
2631
2671
  service: string;
2632
2672
  operation: string;
@@ -2655,6 +2695,15 @@ type TriggerDescriptor = {
2655
2695
  * it, over the same raw bytes the signature was checked against.
2656
2696
  */
2657
2697
  decode?: DeliveryDecode;
2698
+ /**
2699
+ * For a delivery that reaches ONE endpoint on behalf of many tenants
2700
+ * (HubSpot app webhooks, Gmail's Pub/Sub topic): the ONLY key a host may
2701
+ * route by, and where it sits in the verified payload. The rule that goes
2702
+ * with it is fixed, not configurable: route only AFTER verification, only
2703
+ * to a connection or watch the host minted, and drop an unmapped key with a
2704
+ * 2xx and a log line, creating nothing. The package declares; the HOST routes.
2705
+ */
2706
+ route?: DeliveryRoute;
2658
2707
  /** For `poll`: the provider's smallest sane interval, in seconds. */
2659
2708
  minPollSeconds?: number;
2660
2709
  /** A faked sample event, so the node is runnable before any of the above. */
@@ -2703,6 +2752,13 @@ type InboundDelivery = {
2703
2752
  /** The body EXACTLY as received. Not re-serialised. See `webhook.ts`. */
2704
2753
  raw: string;
2705
2754
  headers: Record<string, string | string[] | undefined>;
2755
+ /**
2756
+ * The request line as RECEIVED, for a provider that signs it (HubSpot v3).
2757
+ * Pass the full URL the provider called, scheme, host, path and query,
2758
+ * exactly as it arrived.
2759
+ */
2760
+ method?: string;
2761
+ url?: string;
2706
2762
  };
2707
2763
  /**
2708
2764
  * Verify an inbound delivery against a trigger's declared scheme.
@@ -2728,4 +2784,4 @@ declare function verifyDelivery(trigger: TriggerDescriptor, delivery: InboundDel
2728
2784
  */
2729
2785
  declare function triggerEvent(trigger: TriggerDescriptor, connection: ResolvedConnection, injected: unknown, config: Record<string, unknown>): unknown;
2730
2786
 
2731
- export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, type JoinTarget, type JoinTargetKind, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
2787
+ export { AMBIGUOUS_REFUSAL, type ApiContract, type Attempt, type Attendee, type ByteRange, CANONICAL_METRICS, CONNECTOR_API_VERSION, CONNECTOR_MODES, CREDENTIAL_SCOPES, type CallOptions, type CallResult, type Capabilities, type Catalogue, type ChainLinks, type ChainOutcome, type ChainRef, type ChallengeHandshake, type Citation, type Classified, type ConnectionCredentials, type ConnectionHost, type ConnectionSpec, type Connector, ConnectorAmbiguous, ConnectorApiMismatch, ConnectorAuthError, ConnectorConfigError, ConnectorError, type ConnectorErrorContext, type ConnectorFaker, ConnectorIdempotencyExpiredError, type ConnectorMode, ConnectorModeError, ConnectorRateLimited, type ConnectorRequest, ConnectorRequestError, type ConnectorResult, ConnectorTransient, ConnectorUnreachable, type ContractOperation, type CredentialField, type CredentialScope, DEFAULT_IDEMPOTENCY_WINDOW_SECONDS, DEFAULT_RETRY, DELIVERY_DECODE_KINDS, type DeliveryDeclaration, type DeliveryDecode, type DeliveryMechanism, type DeliveryOutcome, type DeliveryRoute, type DriftFinding, type DriftReport, EXPIRES_AT_UNITS, type ExpiresAtUnit, FAKE_EPOCH, FORM_FIELD_JSON_REASONS, type FailureKind, type FakeRequest, type FakeValues, FormFieldJsonError, type FormFieldJsonReason, type HmacScheme, type HmacVerificationSpec, type HostEnvironment, type IdempotencyOptions, type InboundDelivery, type Invite, type InviteMethod, type JoinTarget, type JoinTargetKind, type LeaseAction, type LeaseDeclaration, type LeaseState, MAX_IDEMPOTENCY_KEY_LENGTH, type MetricDescriptor, type MetricSample, type MimeAttachment, type MimeHeader, type MimeMessage, type MimePart, type ModeInputs, NO_IDEMPOTENCY_KEY_WARNING, PROBLEM_SEVERITIES, type PreparedRequest, type ProbeOutcome, type ProbeReport, type ProbeResult, type ProbeSpec, type Problem, type ProviderAdapter, RENDERER_VERSION, REVIEW_STALE_DAYS, type RecordedShape, type RecurrenceRule, type RenderRules, type RenderedPayload, type RequestedMode, type ResolveOptions, type ResolvedConnection, type RetryPolicy, type RunIdentity, SANDBOX_KINDS, SIGNED_URI_RULES, SUPPORTED_CONNECTOR_API, type SandboxKind, type Segment, type ServiceDescriptor, type SetupStep, type ShapeMismatch, type SharedTokenScheme, type SharedTokenVerificationSpec, type SignedRequestLine, type SignedUriRule, type SpecSource, type SubscriptionLease, type TextUnit, type Transport, type TransportResponse, type TriggerDescriptor, type VerifyResult, type WebhookVerification, type WebhookVerificationSpec, assertConnectorApi, byteRangeOf, callConnector, capabilityProblems, checkAgainstOpenApi, checkAgainstRecordedShape, classifyError, classifyHttp, classifyStatus, classifyThrown, compareShape, connectionsFor, constantTimeEquals, decodeDelivery, decodeFormFieldJson, deliver, fakeRequest, fakeValues, getConnectionHost, graphemes, handshakeResponse, header, hmac, httpFailure, idempotencyKeyFor, isEmptyPayload, isRemote, isSharedTokenScheme, isSharedTokenSpec, isUnconditionallyRetryable, joinTargets, leaseAction, leaseFromResponse, leaseRenewAt, leaseState, linkRanges, measure, nextOccurrence, normaliseSignedUri, parseInvite, parseMime, payloadHash, postChain, probe, providerProblems, providerSandboxIsSelectable, registerConnectionHost, registerTransport, render, reported, resetRateState, resolveConnection, resolveConnectorMode, respectRate, runIdentityFrom, runKeyFrom, runProbes, sandboxIsSelectable, sandboxRefusal, satisfiesMinimum, secretKeyBytes, seedFrom, shapeOf, shouldRetry, sliceByteRange, splitToFit, subscriptionLease, triggerEvent, unchecked, utf8Length, verifyDelivery, verifyHmac, verifySharedToken, withResolvedLimit };
package/dist/index.js CHANGED
@@ -1953,6 +1953,29 @@ var PROBLEM_SEVERITIES = ["block", "warn"];
1953
1953
  var CANONICAL_METRICS = ["like", "share", "reply", "quote", "view"];
1954
1954
 
1955
1955
  // src/webhook.ts
1956
+ var SIGNED_URI_RULES = ["hubspot-v3"];
1957
+ var HUBSPOT_V3_DECODE = {
1958
+ "%3A": ":",
1959
+ "%2F": "/",
1960
+ "%3F": "?",
1961
+ "%40": "@",
1962
+ "%21": "!",
1963
+ "%24": "$",
1964
+ "%27": "'",
1965
+ "%28": "(",
1966
+ "%29": ")",
1967
+ "%2A": "*",
1968
+ "%2C": ",",
1969
+ "%3B": ";"
1970
+ };
1971
+ function normaliseSignedUri(url, rule) {
1972
+ if (rule !== "hubspot-v3") throw new Error(`unknown signed-uri rule ${JSON.stringify(rule)}`);
1973
+ const withoutFragment = url.split("#", 1)[0] ?? "";
1974
+ const q = withoutFragment.indexOf("?");
1975
+ if (q === -1) return withoutFragment;
1976
+ const query = withoutFragment.slice(q + 1).replace(/%[0-9A-Fa-f]{2}/g, (e) => HUBSPOT_V3_DECODE[e.toUpperCase()] ?? e);
1977
+ return `${withoutFragment.slice(0, q)}?${query}`;
1978
+ }
1956
1979
  function secretKeyBytes(secret, options = {}) {
1957
1980
  let material = secret;
1958
1981
  if (options.secretPrefix !== void 0) {
@@ -1987,13 +2010,26 @@ async function verifyHmac(options) {
1987
2010
  const sent = Number(timestamp);
1988
2011
  if (!Number.isFinite(sent)) return { ok: false, reason: "timestamp header is not a number" };
1989
2012
  const now = options.now ?? Math.floor(Date.now() / 1e3);
1990
- if (Math.abs(now - sent) > scheme.tolerance) {
2013
+ const sentSeconds = scheme.timestampUnit === "ms" ? sent / 1e3 : sent;
2014
+ if (Math.abs(now - sentSeconds) > scheme.tolerance) {
1991
2015
  return { ok: false, reason: `delivery is outside the ${scheme.tolerance}s replay window` };
1992
2016
  }
1993
2017
  }
1994
2018
  const key = secretKeyBytes(secret, scheme);
1995
2019
  if ("reason" in key) return { ok: false, reason: key.reason };
1996
- const expected = await hmac(secret, scheme.payload(raw, timestamp, id), scheme.algorithm, scheme.encoding ?? "hex", scheme);
2020
+ let line;
2021
+ if (scheme.signsRequestLine) {
2022
+ const { method, url } = options.request ?? {};
2023
+ if (!method || !url) return { ok: false, reason: "delivery carried no request method or url" };
2024
+ line = { method, uri: scheme.uri ? normaliseSignedUri(url, scheme.uri) : url };
2025
+ }
2026
+ const expected = await hmac(
2027
+ secret,
2028
+ scheme.payload(raw, timestamp, id, line),
2029
+ scheme.algorithm,
2030
+ scheme.encoding ?? "hex",
2031
+ scheme
2032
+ );
1997
2033
  return signatures.some((candidate) => constantTimeEquals(expected, candidate)) ? { ok: true } : { ok: false, reason: "signature did not match" };
1998
2034
  }
1999
2035
  async function hmac(secret, payload, algorithm, encoding = "hex", options = {}) {
@@ -2118,6 +2154,7 @@ async function verifyDelivery(trigger, delivery, secret, now) {
2118
2154
  scheme: spec.scheme,
2119
2155
  timestamp,
2120
2156
  id,
2157
+ ...delivery.method === void 0 && delivery.url === void 0 ? {} : { request: { method: delivery.method ?? "", url: delivery.url ?? "" } },
2121
2158
  ...now === void 0 ? {} : { now }
2122
2159
  });
2123
2160
  }
@@ -2169,6 +2206,7 @@ export {
2169
2206
  RENDERER_VERSION,
2170
2207
  REVIEW_STALE_DAYS,
2171
2208
  SANDBOX_KINDS,
2209
+ SIGNED_URI_RULES,
2172
2210
  SUPPORTED_CONNECTOR_API,
2173
2211
  assertConnectorApi,
2174
2212
  byteRangeOf,
@@ -2208,6 +2246,7 @@ export {
2208
2246
  linkRanges,
2209
2247
  measure,
2210
2248
  nextOccurrence,
2249
+ normaliseSignedUri,
2211
2250
  parseInvite,
2212
2251
  parseMime,
2213
2252
  payloadHash,