@fedpulse/sdk 1.0.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/LICENSE +21 -0
- package/README.md +331 -0
- package/dist/cjs/client.cjs +138 -0
- package/dist/cjs/errors.cjs +200 -0
- package/dist/cjs/http.cjs +449 -0
- package/dist/cjs/index.cjs +65 -0
- package/dist/cjs/resources/analytics.cjs +134 -0
- package/dist/cjs/resources/assistance.cjs +101 -0
- package/dist/cjs/resources/entities.cjs +149 -0
- package/dist/cjs/resources/exclusions.cjs +135 -0
- package/dist/cjs/resources/intelligence.cjs +96 -0
- package/dist/cjs/resources/opportunities.cjs +170 -0
- package/dist/cjs/resources/webhooks.cjs +262 -0
- package/dist/cjs/types/analytics.cjs +5 -0
- package/dist/cjs/types/assistance.cjs +5 -0
- package/dist/cjs/types/common.cjs +5 -0
- package/dist/cjs/types/entities.cjs +5 -0
- package/dist/cjs/types/exclusions.cjs +5 -0
- package/dist/cjs/types/index.cjs +5 -0
- package/dist/cjs/types/intelligence.cjs +5 -0
- package/dist/cjs/types/opportunities.cjs +5 -0
- package/dist/cjs/types/webhooks.cjs +5 -0
- package/dist/cjs/webhooks-verify.cjs +184 -0
- package/dist/esm/client.js +135 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.js +187 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/http.js +445 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/analytics.js +131 -0
- package/dist/esm/resources/analytics.js.map +1 -0
- package/dist/esm/resources/assistance.js +98 -0
- package/dist/esm/resources/assistance.js.map +1 -0
- package/dist/esm/resources/entities.js +146 -0
- package/dist/esm/resources/entities.js.map +1 -0
- package/dist/esm/resources/exclusions.js +132 -0
- package/dist/esm/resources/exclusions.js.map +1 -0
- package/dist/esm/resources/intelligence.js +93 -0
- package/dist/esm/resources/intelligence.js.map +1 -0
- package/dist/esm/resources/opportunities.js +167 -0
- package/dist/esm/resources/opportunities.js.map +1 -0
- package/dist/esm/resources/webhooks.js +259 -0
- package/dist/esm/resources/webhooks.js.map +1 -0
- package/dist/esm/types/analytics.js +5 -0
- package/dist/esm/types/analytics.js.map +1 -0
- package/dist/esm/types/assistance.js +5 -0
- package/dist/esm/types/assistance.js.map +1 -0
- package/dist/esm/types/common.js +5 -0
- package/dist/esm/types/common.js.map +1 -0
- package/dist/esm/types/entities.js +5 -0
- package/dist/esm/types/entities.js.map +1 -0
- package/dist/esm/types/exclusions.js +5 -0
- package/dist/esm/types/exclusions.js.map +1 -0
- package/dist/esm/types/index.js +5 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/intelligence.js +5 -0
- package/dist/esm/types/intelligence.js.map +1 -0
- package/dist/esm/types/opportunities.js +5 -0
- package/dist/esm/types/opportunities.js.map +1 -0
- package/dist/esm/types/webhooks.js +5 -0
- package/dist/esm/types/webhooks.js.map +1 -0
- package/dist/esm/webhooks-verify.js +179 -0
- package/dist/esm/webhooks-verify.js.map +1 -0
- package/dist/types/client.d.cts +136 -0
- package/dist/types/client.d.ts +136 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/errors.d.cts +139 -0
- package/dist/types/errors.d.ts +139 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/http.d.cts +137 -0
- package/dist/types/http.d.ts +137 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/index.d.cts +39 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/resources/analytics.d.cts +94 -0
- package/dist/types/resources/analytics.d.ts +94 -0
- package/dist/types/resources/analytics.d.ts.map +1 -0
- package/dist/types/resources/assistance.d.cts +66 -0
- package/dist/types/resources/assistance.d.ts +66 -0
- package/dist/types/resources/assistance.d.ts.map +1 -0
- package/dist/types/resources/entities.d.cts +101 -0
- package/dist/types/resources/entities.d.ts +101 -0
- package/dist/types/resources/entities.d.ts.map +1 -0
- package/dist/types/resources/exclusions.d.cts +84 -0
- package/dist/types/resources/exclusions.d.ts +84 -0
- package/dist/types/resources/exclusions.d.ts.map +1 -0
- package/dist/types/resources/intelligence.d.cts +66 -0
- package/dist/types/resources/intelligence.d.ts +66 -0
- package/dist/types/resources/intelligence.d.ts.map +1 -0
- package/dist/types/resources/opportunities.d.cts +116 -0
- package/dist/types/resources/opportunities.d.ts +116 -0
- package/dist/types/resources/opportunities.d.ts.map +1 -0
- package/dist/types/resources/webhooks.d.cts +180 -0
- package/dist/types/resources/webhooks.d.ts +180 -0
- package/dist/types/resources/webhooks.d.ts.map +1 -0
- package/dist/types/types/analytics.d.cts +85 -0
- package/dist/types/types/analytics.d.ts +85 -0
- package/dist/types/types/analytics.d.ts.map +1 -0
- package/dist/types/types/assistance.d.cts +55 -0
- package/dist/types/types/assistance.d.ts +55 -0
- package/dist/types/types/assistance.d.ts.map +1 -0
- package/dist/types/types/common.d.cts +58 -0
- package/dist/types/types/common.d.ts +58 -0
- package/dist/types/types/common.d.ts.map +1 -0
- package/dist/types/types/entities.d.cts +85 -0
- package/dist/types/types/entities.d.ts +85 -0
- package/dist/types/types/entities.d.ts.map +1 -0
- package/dist/types/types/exclusions.d.cts +81 -0
- package/dist/types/types/exclusions.d.ts +81 -0
- package/dist/types/types/exclusions.d.ts.map +1 -0
- package/dist/types/types/index.d.cts +12 -0
- package/dist/types/types/index.d.ts +12 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/intelligence.d.cts +104 -0
- package/dist/types/types/intelligence.d.ts +104 -0
- package/dist/types/types/intelligence.d.ts.map +1 -0
- package/dist/types/types/opportunities.d.cts +149 -0
- package/dist/types/types/opportunities.d.ts +149 -0
- package/dist/types/types/opportunities.d.ts.map +1 -0
- package/dist/types/types/webhooks.d.cts +106 -0
- package/dist/types/types/webhooks.d.ts +106 -0
- package/dist/types/types/webhooks.d.ts.map +1 -0
- package/dist/types/webhooks-verify.d.cts +102 -0
- package/dist/types/webhooks-verify.d.ts +102 -0
- package/dist/types/webhooks-verify.d.ts.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the Webhooks domain (/v1/webhooks).
|
|
3
|
+
*/
|
|
4
|
+
import type { PaginationParams } from './common.cjs';
|
|
5
|
+
import type { AiCategory, AiDifficulty } from './opportunities.cjs';
|
|
6
|
+
export type WebhookEvent = 'opportunity.new' | 'opportunity.modified' | 'opportunity.awarded' | 'opportunity.archived' | 'exclusion.new' | 'exclusion.terminated' | 'entity.new' | 'entity.updated' | 'entity.expired' | 'assistance.new' | 'assistance.updated';
|
|
7
|
+
export interface WebhookFilters {
|
|
8
|
+
/** NAICS codes to match (4–6 digit strings). Up to 50. */
|
|
9
|
+
naics?: string[];
|
|
10
|
+
/** Agency name substring filter (case-insensitive). */
|
|
11
|
+
agency?: string;
|
|
12
|
+
/** Set-aside type codes to match (e.g. '8A', 'WOSB'). Up to 20. */
|
|
13
|
+
setAside?: string[];
|
|
14
|
+
/** 2-letter US state code for place of performance. */
|
|
15
|
+
state?: string;
|
|
16
|
+
/** Minimum award amount in cents (inclusive). */
|
|
17
|
+
minAwardAmount?: number;
|
|
18
|
+
/** Maximum award amount in cents (inclusive). */
|
|
19
|
+
maxAwardAmount?: number;
|
|
20
|
+
/** AI-assigned category filter. */
|
|
21
|
+
aiCategory?: AiCategory;
|
|
22
|
+
/** AI-assigned difficulty filter. */
|
|
23
|
+
aiDifficulty?: AiDifficulty;
|
|
24
|
+
/** SAM.gov notice type codes to match. Up to 10. */
|
|
25
|
+
noticeType?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface Webhook {
|
|
28
|
+
id: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
url: string;
|
|
31
|
+
events: WebhookEvent[];
|
|
32
|
+
filters: WebhookFilters;
|
|
33
|
+
isActive: boolean;
|
|
34
|
+
pausedAt: string | null;
|
|
35
|
+
pauseReason: string | null;
|
|
36
|
+
consecutiveFailures: number;
|
|
37
|
+
lastTriggeredAt: string | null;
|
|
38
|
+
lastDeliveryStatus: string | null;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
}
|
|
42
|
+
export type DeliveryStatus = 'pending' | 'success' | 'failed' | 'abandoned';
|
|
43
|
+
export interface WebhookDelivery {
|
|
44
|
+
id: string;
|
|
45
|
+
webhookId: string;
|
|
46
|
+
eventType: WebhookEvent;
|
|
47
|
+
attempt: number;
|
|
48
|
+
status: DeliveryStatus;
|
|
49
|
+
httpStatus: number | null;
|
|
50
|
+
responseBody?: string | null;
|
|
51
|
+
failureReason: string | null;
|
|
52
|
+
durationMs: number | null;
|
|
53
|
+
nextRetryAt: string | null;
|
|
54
|
+
deliveredAt: string | null;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
/** Full payload envelope — only present on single-delivery detail response. */
|
|
57
|
+
payload?: WebhookPayload | null;
|
|
58
|
+
}
|
|
59
|
+
export interface WebhookPayload<T = unknown> {
|
|
60
|
+
event: WebhookEvent;
|
|
61
|
+
timestamp: string;
|
|
62
|
+
apiVersion: string;
|
|
63
|
+
data: T;
|
|
64
|
+
}
|
|
65
|
+
export interface WebhookVerifyOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Maximum age of a webhook delivery in seconds before it is considered a
|
|
68
|
+
* potential replay attack. Default: 300 (5 minutes).
|
|
69
|
+
*/
|
|
70
|
+
maxAgeSeconds?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface CreateWebhookParams {
|
|
73
|
+
/** Target URL — must be HTTPS and publicly reachable. */
|
|
74
|
+
url: string;
|
|
75
|
+
/** Event types to subscribe to (1–11). */
|
|
76
|
+
events: WebhookEvent[];
|
|
77
|
+
/** Optional delivery filters. Unset filters match all values. */
|
|
78
|
+
filters?: WebhookFilters;
|
|
79
|
+
}
|
|
80
|
+
export interface UpdateWebhookParams {
|
|
81
|
+
url?: string;
|
|
82
|
+
events?: WebhookEvent[];
|
|
83
|
+
filters?: WebhookFilters;
|
|
84
|
+
/** Set to false to pause the webhook. Set to true to resume. */
|
|
85
|
+
is_active?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Set to true to rotate the signing secret.
|
|
88
|
+
* The new raw secret is returned in the response — store it immediately.
|
|
89
|
+
*/
|
|
90
|
+
rotateSecret?: boolean;
|
|
91
|
+
}
|
|
92
|
+
export interface ListDeliveriesParams extends PaginationParams {
|
|
93
|
+
status?: DeliveryStatus;
|
|
94
|
+
event_type?: WebhookEvent;
|
|
95
|
+
}
|
|
96
|
+
export interface CreateWebhookResult {
|
|
97
|
+
webhook: Webhook;
|
|
98
|
+
/** Raw signing secret (64-char hex). Shown once — store immediately. */
|
|
99
|
+
secret: string;
|
|
100
|
+
}
|
|
101
|
+
export interface RotateSecretResult {
|
|
102
|
+
webhook: Webhook;
|
|
103
|
+
/** New raw signing secret (64-char hex). Shown once — store immediately. */
|
|
104
|
+
secret: string;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=webhooks.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the Webhooks domain (/v1/webhooks).
|
|
3
|
+
*/
|
|
4
|
+
import type { PaginationParams } from './common.js';
|
|
5
|
+
import type { AiCategory, AiDifficulty } from './opportunities.js';
|
|
6
|
+
export type WebhookEvent = 'opportunity.new' | 'opportunity.modified' | 'opportunity.awarded' | 'opportunity.archived' | 'exclusion.new' | 'exclusion.terminated' | 'entity.new' | 'entity.updated' | 'entity.expired' | 'assistance.new' | 'assistance.updated';
|
|
7
|
+
export interface WebhookFilters {
|
|
8
|
+
/** NAICS codes to match (4–6 digit strings). Up to 50. */
|
|
9
|
+
naics?: string[];
|
|
10
|
+
/** Agency name substring filter (case-insensitive). */
|
|
11
|
+
agency?: string;
|
|
12
|
+
/** Set-aside type codes to match (e.g. '8A', 'WOSB'). Up to 20. */
|
|
13
|
+
setAside?: string[];
|
|
14
|
+
/** 2-letter US state code for place of performance. */
|
|
15
|
+
state?: string;
|
|
16
|
+
/** Minimum award amount in cents (inclusive). */
|
|
17
|
+
minAwardAmount?: number;
|
|
18
|
+
/** Maximum award amount in cents (inclusive). */
|
|
19
|
+
maxAwardAmount?: number;
|
|
20
|
+
/** AI-assigned category filter. */
|
|
21
|
+
aiCategory?: AiCategory;
|
|
22
|
+
/** AI-assigned difficulty filter. */
|
|
23
|
+
aiDifficulty?: AiDifficulty;
|
|
24
|
+
/** SAM.gov notice type codes to match. Up to 10. */
|
|
25
|
+
noticeType?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface Webhook {
|
|
28
|
+
id: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
url: string;
|
|
31
|
+
events: WebhookEvent[];
|
|
32
|
+
filters: WebhookFilters;
|
|
33
|
+
isActive: boolean;
|
|
34
|
+
pausedAt: string | null;
|
|
35
|
+
pauseReason: string | null;
|
|
36
|
+
consecutiveFailures: number;
|
|
37
|
+
lastTriggeredAt: string | null;
|
|
38
|
+
lastDeliveryStatus: string | null;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
}
|
|
42
|
+
export type DeliveryStatus = 'pending' | 'success' | 'failed' | 'abandoned';
|
|
43
|
+
export interface WebhookDelivery {
|
|
44
|
+
id: string;
|
|
45
|
+
webhookId: string;
|
|
46
|
+
eventType: WebhookEvent;
|
|
47
|
+
attempt: number;
|
|
48
|
+
status: DeliveryStatus;
|
|
49
|
+
httpStatus: number | null;
|
|
50
|
+
responseBody?: string | null;
|
|
51
|
+
failureReason: string | null;
|
|
52
|
+
durationMs: number | null;
|
|
53
|
+
nextRetryAt: string | null;
|
|
54
|
+
deliveredAt: string | null;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
/** Full payload envelope — only present on single-delivery detail response. */
|
|
57
|
+
payload?: WebhookPayload | null;
|
|
58
|
+
}
|
|
59
|
+
export interface WebhookPayload<T = unknown> {
|
|
60
|
+
event: WebhookEvent;
|
|
61
|
+
timestamp: string;
|
|
62
|
+
apiVersion: string;
|
|
63
|
+
data: T;
|
|
64
|
+
}
|
|
65
|
+
export interface WebhookVerifyOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Maximum age of a webhook delivery in seconds before it is considered a
|
|
68
|
+
* potential replay attack. Default: 300 (5 minutes).
|
|
69
|
+
*/
|
|
70
|
+
maxAgeSeconds?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface CreateWebhookParams {
|
|
73
|
+
/** Target URL — must be HTTPS and publicly reachable. */
|
|
74
|
+
url: string;
|
|
75
|
+
/** Event types to subscribe to (1–11). */
|
|
76
|
+
events: WebhookEvent[];
|
|
77
|
+
/** Optional delivery filters. Unset filters match all values. */
|
|
78
|
+
filters?: WebhookFilters;
|
|
79
|
+
}
|
|
80
|
+
export interface UpdateWebhookParams {
|
|
81
|
+
url?: string;
|
|
82
|
+
events?: WebhookEvent[];
|
|
83
|
+
filters?: WebhookFilters;
|
|
84
|
+
/** Set to false to pause the webhook. Set to true to resume. */
|
|
85
|
+
is_active?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Set to true to rotate the signing secret.
|
|
88
|
+
* The new raw secret is returned in the response — store it immediately.
|
|
89
|
+
*/
|
|
90
|
+
rotateSecret?: boolean;
|
|
91
|
+
}
|
|
92
|
+
export interface ListDeliveriesParams extends PaginationParams {
|
|
93
|
+
status?: DeliveryStatus;
|
|
94
|
+
event_type?: WebhookEvent;
|
|
95
|
+
}
|
|
96
|
+
export interface CreateWebhookResult {
|
|
97
|
+
webhook: Webhook;
|
|
98
|
+
/** Raw signing secret (64-char hex). Shown once — store immediately. */
|
|
99
|
+
secret: string;
|
|
100
|
+
}
|
|
101
|
+
export interface RotateSecretResult {
|
|
102
|
+
webhook: Webhook;
|
|
103
|
+
/** New raw signing secret (64-char hex). Shown once — store immediately. */
|
|
104
|
+
secret: string;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=webhooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/types/webhooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook signature verification for FedPulse webhook deliveries.
|
|
3
|
+
*
|
|
4
|
+
* FedPulse signs every outgoing webhook POST with HMAC-SHA256.
|
|
5
|
+
* Use these utilities to verify that incoming requests are genuinely from
|
|
6
|
+
* FedPulse and have not been tampered with or replayed.
|
|
7
|
+
*
|
|
8
|
+
* ## Signing algorithm:
|
|
9
|
+
* signed_body = `${timestampSeconds}.${rawPayloadJson}`
|
|
10
|
+
* signature = HMAC-SHA256(rawSecret, signed_body) → hex
|
|
11
|
+
*
|
|
12
|
+
* ## Delivery headers (all present on every POST):
|
|
13
|
+
* X-FedPulse-Signature : `sha256={hex_hmac}`
|
|
14
|
+
* X-FedPulse-Timestamp : Unix epoch seconds (string)
|
|
15
|
+
* X-FedPulse-Event : Event type (e.g. "opportunity.new")
|
|
16
|
+
* X-FedPulse-Delivery-Id : UUIDv4 delivery identifier
|
|
17
|
+
*
|
|
18
|
+
* ## Replay protection:
|
|
19
|
+
* Reject deliveries where |now − timestamp| > maxAgeSeconds (default 300s).
|
|
20
|
+
*/
|
|
21
|
+
import type { WebhookPayload, WebhookVerifyOptions } from './types/webhooks.cjs';
|
|
22
|
+
import { FedPulseError } from './errors.cjs';
|
|
23
|
+
/** Thrown when webhook signature verification fails. */
|
|
24
|
+
export declare class WebhookVerificationError extends FedPulseError {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
export interface VerifyWebhookInput {
|
|
28
|
+
/**
|
|
29
|
+
* The raw request body as a string or Buffer.
|
|
30
|
+
* Must be the **exact** bytes received, before any JSON parsing.
|
|
31
|
+
*/
|
|
32
|
+
rawBody: string | Buffer;
|
|
33
|
+
/** Value of the `X-FedPulse-Signature` header (e.g. `sha256=abc...`). */
|
|
34
|
+
signatureHeader: string;
|
|
35
|
+
/** Value of the `X-FedPulse-Timestamp` header (Unix epoch seconds as string). */
|
|
36
|
+
timestampHeader: string;
|
|
37
|
+
/** The raw webhook secret you received at creation time (64-char hex string). */
|
|
38
|
+
secret: string;
|
|
39
|
+
/** Verification options. */
|
|
40
|
+
options?: WebhookVerifyOptions;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Verify a FedPulse webhook delivery and parse the payload.
|
|
44
|
+
*
|
|
45
|
+
* This function performs three checks:
|
|
46
|
+
* 1. **Format check** — headers are present and in the expected format.
|
|
47
|
+
* 2. **Timestamp check** — delivery is not older than `maxAgeSeconds`.
|
|
48
|
+
* 3. **Signature check** — HMAC-SHA256 matches using constant-time comparison.
|
|
49
|
+
*
|
|
50
|
+
* Throws `WebhookVerificationError` on any failure.
|
|
51
|
+
* Returns the parsed, verified `WebhookPayload<T>`.
|
|
52
|
+
*
|
|
53
|
+
* @param input Headers, raw body, and secret.
|
|
54
|
+
* @returns Parsed and verified webhook payload.
|
|
55
|
+
*
|
|
56
|
+
* @throws {WebhookVerificationError} If the signature is invalid, the timestamp
|
|
57
|
+
* is out of range, or the headers are malformed.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // Express.js example (use bodyParser.raw() to get the raw buffer):
|
|
62
|
+
* app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
63
|
+
* let payload;
|
|
64
|
+
* try {
|
|
65
|
+
* payload = FedPulse.verifyWebhook({
|
|
66
|
+
* rawBody: req.body,
|
|
67
|
+
* signatureHeader: req.headers['x-fedpulse-signature'] as string,
|
|
68
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'] as string,
|
|
69
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
70
|
+
* });
|
|
71
|
+
* } catch (err) {
|
|
72
|
+
* return res.status(400).send('Invalid signature');
|
|
73
|
+
* }
|
|
74
|
+
* console.log('Event:', payload.event, 'Data:', payload.data);
|
|
75
|
+
* res.status(200).send('OK');
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function verifyWebhook<T = unknown>(input: VerifyWebhookInput): WebhookPayload<T>;
|
|
80
|
+
/**
|
|
81
|
+
* Extract the FedPulse webhook headers from a plain headers object.
|
|
82
|
+
*
|
|
83
|
+
* Normalises both lowercase and original-casing variants so you don't
|
|
84
|
+
* have to worry about header casing differences between frameworks.
|
|
85
|
+
*
|
|
86
|
+
* @param headers A plain object or Map of request headers.
|
|
87
|
+
* @returns Extracted signature and timestamp values.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* // Works with Express, Fastify, Koa, Next.js API routes, etc.
|
|
92
|
+
* const { signatureHeader, timestampHeader } = extractWebhookHeaders(req.headers);
|
|
93
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function extractWebhookHeaders(headers: Record<string, string | string[] | undefined> | Headers): {
|
|
97
|
+
signatureHeader: string;
|
|
98
|
+
timestampHeader: string;
|
|
99
|
+
event: string;
|
|
100
|
+
deliveryId: string;
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=webhooks-verify.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook signature verification for FedPulse webhook deliveries.
|
|
3
|
+
*
|
|
4
|
+
* FedPulse signs every outgoing webhook POST with HMAC-SHA256.
|
|
5
|
+
* Use these utilities to verify that incoming requests are genuinely from
|
|
6
|
+
* FedPulse and have not been tampered with or replayed.
|
|
7
|
+
*
|
|
8
|
+
* ## Signing algorithm:
|
|
9
|
+
* signed_body = `${timestampSeconds}.${rawPayloadJson}`
|
|
10
|
+
* signature = HMAC-SHA256(rawSecret, signed_body) → hex
|
|
11
|
+
*
|
|
12
|
+
* ## Delivery headers (all present on every POST):
|
|
13
|
+
* X-FedPulse-Signature : `sha256={hex_hmac}`
|
|
14
|
+
* X-FedPulse-Timestamp : Unix epoch seconds (string)
|
|
15
|
+
* X-FedPulse-Event : Event type (e.g. "opportunity.new")
|
|
16
|
+
* X-FedPulse-Delivery-Id : UUIDv4 delivery identifier
|
|
17
|
+
*
|
|
18
|
+
* ## Replay protection:
|
|
19
|
+
* Reject deliveries where |now − timestamp| > maxAgeSeconds (default 300s).
|
|
20
|
+
*/
|
|
21
|
+
import type { WebhookPayload, WebhookVerifyOptions } from './types/webhooks.js';
|
|
22
|
+
import { FedPulseError } from './errors.js';
|
|
23
|
+
/** Thrown when webhook signature verification fails. */
|
|
24
|
+
export declare class WebhookVerificationError extends FedPulseError {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
export interface VerifyWebhookInput {
|
|
28
|
+
/**
|
|
29
|
+
* The raw request body as a string or Buffer.
|
|
30
|
+
* Must be the **exact** bytes received, before any JSON parsing.
|
|
31
|
+
*/
|
|
32
|
+
rawBody: string | Buffer;
|
|
33
|
+
/** Value of the `X-FedPulse-Signature` header (e.g. `sha256=abc...`). */
|
|
34
|
+
signatureHeader: string;
|
|
35
|
+
/** Value of the `X-FedPulse-Timestamp` header (Unix epoch seconds as string). */
|
|
36
|
+
timestampHeader: string;
|
|
37
|
+
/** The raw webhook secret you received at creation time (64-char hex string). */
|
|
38
|
+
secret: string;
|
|
39
|
+
/** Verification options. */
|
|
40
|
+
options?: WebhookVerifyOptions;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Verify a FedPulse webhook delivery and parse the payload.
|
|
44
|
+
*
|
|
45
|
+
* This function performs three checks:
|
|
46
|
+
* 1. **Format check** — headers are present and in the expected format.
|
|
47
|
+
* 2. **Timestamp check** — delivery is not older than `maxAgeSeconds`.
|
|
48
|
+
* 3. **Signature check** — HMAC-SHA256 matches using constant-time comparison.
|
|
49
|
+
*
|
|
50
|
+
* Throws `WebhookVerificationError` on any failure.
|
|
51
|
+
* Returns the parsed, verified `WebhookPayload<T>`.
|
|
52
|
+
*
|
|
53
|
+
* @param input Headers, raw body, and secret.
|
|
54
|
+
* @returns Parsed and verified webhook payload.
|
|
55
|
+
*
|
|
56
|
+
* @throws {WebhookVerificationError} If the signature is invalid, the timestamp
|
|
57
|
+
* is out of range, or the headers are malformed.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // Express.js example (use bodyParser.raw() to get the raw buffer):
|
|
62
|
+
* app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
63
|
+
* let payload;
|
|
64
|
+
* try {
|
|
65
|
+
* payload = FedPulse.verifyWebhook({
|
|
66
|
+
* rawBody: req.body,
|
|
67
|
+
* signatureHeader: req.headers['x-fedpulse-signature'] as string,
|
|
68
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'] as string,
|
|
69
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
70
|
+
* });
|
|
71
|
+
* } catch (err) {
|
|
72
|
+
* return res.status(400).send('Invalid signature');
|
|
73
|
+
* }
|
|
74
|
+
* console.log('Event:', payload.event, 'Data:', payload.data);
|
|
75
|
+
* res.status(200).send('OK');
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function verifyWebhook<T = unknown>(input: VerifyWebhookInput): WebhookPayload<T>;
|
|
80
|
+
/**
|
|
81
|
+
* Extract the FedPulse webhook headers from a plain headers object.
|
|
82
|
+
*
|
|
83
|
+
* Normalises both lowercase and original-casing variants so you don't
|
|
84
|
+
* have to worry about header casing differences between frameworks.
|
|
85
|
+
*
|
|
86
|
+
* @param headers A plain object or Map of request headers.
|
|
87
|
+
* @returns Extracted signature and timestamp values.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* // Works with Express, Fastify, Koa, Next.js API routes, etc.
|
|
92
|
+
* const { signatureHeader, timestampHeader } = extractWebhookHeaders(req.headers);
|
|
93
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function extractWebhookHeaders(headers: Record<string, string | string[] | undefined> | Headers): {
|
|
97
|
+
signatureHeader: string;
|
|
98
|
+
timestampHeader: string;
|
|
99
|
+
event: string;
|
|
100
|
+
deliveryId: string;
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=webhooks-verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks-verify.d.ts","sourceRoot":"","sources":["../../src/webhooks-verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAgB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,wDAAwD;AACxD,qBAAa,wBAAyB,SAAQ,aAAa;gBAC7C,OAAO,EAAE,MAAM;CAK5B;AAID,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,eAAe,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EACvC,KAAK,EAAE,kBAAkB,GACxB,cAAc,CAAC,CAAC,CAAC,CAyGnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,OAAO,GAC/D;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAuBzF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fedpulse/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official JavaScript/TypeScript SDK for the FedPulse API — federal contracts, exclusions, entities, assistance listings, and market intelligence.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fedpulse",
|
|
7
|
+
"sam.gov",
|
|
8
|
+
"federal-contracts",
|
|
9
|
+
"government",
|
|
10
|
+
"api-sdk",
|
|
11
|
+
"typescript"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://fedpulse.dev",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/fedpulse/sdk.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/fedpulse/sdk/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/cjs/index.cjs",
|
|
27
|
+
"module": "./dist/esm/index.js",
|
|
28
|
+
"types": "./dist/types/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/types/index.d.ts",
|
|
33
|
+
"default": "./dist/esm/index.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/types/index.d.cts",
|
|
37
|
+
"default": "./dist/cjs/index.cjs"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "npm run build:esm && npm run build:cjs && npm run build:types && node scripts/make-dcts.mjs",
|
|
48
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
49
|
+
"build:cjs": "tsc -p tsconfig.cjs.json && node scripts/rename-cjs.mjs",
|
|
50
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"lint": "tsc --noEmit",
|
|
55
|
+
"prepublishOnly": "npm run build && npm test"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@vitest/coverage-v8": "^2.0.0",
|
|
59
|
+
"typescript": "^5.5.0",
|
|
60
|
+
"vitest": "^2.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|