blockintel-gate-sdk 0.1.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 ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 BlockIntel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,386 @@
1
+ # BlockIntel Gate SDK
2
+
3
+ Production-grade TypeScript/Node.js SDK for [BlockIntel Gate](https://blockintel.ai) Hot Path API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @blockintel/gate-sdk
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ - Node.js >= 18.0.0 (uses global `fetch` API)
14
+ - TypeScript >= 5.0.0 (optional, for type definitions)
15
+
16
+ ## Quick Start
17
+
18
+ ### HMAC Authentication
19
+
20
+ ```typescript
21
+ import { GateClient } from '@blockintel/gate-sdk';
22
+
23
+ const gate = new GateClient({
24
+ baseUrl: process.env.GATE_BASE_URL!,
25
+ tenantId: process.env.GATE_TENANT_ID!,
26
+ auth: {
27
+ mode: 'hmac',
28
+ keyId: process.env.GATE_KEY_ID!,
29
+ secret: process.env.GATE_HMAC_SECRET!,
30
+ },
31
+ enableStepUp: true,
32
+ });
33
+
34
+ // Evaluate a transaction
35
+ const response = await gate.evaluate({
36
+ txIntent: {
37
+ from: '0x1234567890123456789012345678901234567890',
38
+ to: '0x0987654321098765432109876543210987654321',
39
+ value: '1000000000000000000', // 1 ETH in wei
40
+ data: '0x...',
41
+ nonce: 42,
42
+ gasPrice: '20000000000',
43
+ gasLimit: '21000',
44
+ chainId: 1,
45
+ },
46
+ signingContext: {
47
+ signerId: 'my-signer-id',
48
+ source: {
49
+ repo: 'myorg/myrepo',
50
+ workflow: 'deploy-production',
51
+ environment: 'production',
52
+ },
53
+ wallet: {
54
+ address: '0x1234...',
55
+ type: 'hardware',
56
+ },
57
+ },
58
+ });
59
+
60
+ if (response.decision === 'ALLOW') {
61
+ // Proceed with transaction
62
+ console.log('Transaction approved:', response.correlationId);
63
+ } else if (response.decision === 'REQUIRE_STEP_UP') {
64
+ // Poll for step-up decision
65
+ const final = await gate.awaitStepUpDecision({
66
+ requestId: response.stepUp!.requestId,
67
+ });
68
+
69
+ if (final.status === 'APPROVED') {
70
+ // Proceed with transaction
71
+ console.log('Step-up approved:', final.correlationId);
72
+ } else {
73
+ // Block transaction
74
+ console.log('Step-up denied or expired:', final.status);
75
+ }
76
+ } else {
77
+ // BLOCK
78
+ console.log('Transaction blocked:', response.reasonCodes);
79
+ }
80
+ ```
81
+
82
+ ### API Key Authentication
83
+
84
+ ```typescript
85
+ import { GateClient } from '@blockintel/gate-sdk';
86
+
87
+ const gate = new GateClient({
88
+ baseUrl: process.env.GATE_BASE_URL!,
89
+ tenantId: process.env.GATE_TENANT_ID!,
90
+ auth: {
91
+ mode: 'apiKey',
92
+ apiKey: process.env.GATE_API_KEY!,
93
+ },
94
+ });
95
+
96
+ const response = await gate.evaluate({
97
+ txIntent: {
98
+ from: '0x123...',
99
+ to: '0x456...',
100
+ value: '1000000000000000000',
101
+ },
102
+ });
103
+ ```
104
+
105
+ ### Step-Up Polling
106
+
107
+ ```typescript
108
+ // Manual polling
109
+ const status = await gate.getStepUpStatus({
110
+ requestId: 'stepup-request-id',
111
+ });
112
+
113
+ console.log('Status:', status.status); // PENDING | APPROVED | DENIED | EXPIRED
114
+
115
+ // Automatic polling with timeout
116
+ const result = await gate.awaitStepUpDecision({
117
+ requestId: 'stepup-request-id',
118
+ maxWaitMs: 15000, // 15 seconds
119
+ intervalMs: 250, // Poll every 250ms
120
+ });
121
+
122
+ console.log('Final status:', result.status);
123
+ console.log('Elapsed time:', result.elapsedMs, 'ms');
124
+ ```
125
+
126
+ **Polling behavior:**
127
+ - `404 NOT_FOUND` → request ID does not exist OR does not belong to the tenant
128
+ - `EXPIRED` → TTL exceeded (deterministic), even if DynamoDB TTL has not deleted the item yet
129
+ - `PENDING` → waiting for external approval
130
+ - `APPROVED | DENIED` → terminal states
131
+
132
+ ## Configuration
133
+
134
+ ### `GateClientConfig`
135
+
136
+ ```typescript
137
+ interface GateClientConfig {
138
+ baseUrl: string; // Gate Hot Path API base URL
139
+ tenantId: string; // Your tenant ID
140
+ auth: // Authentication
141
+ | { mode: 'hmac'; keyId: string; secret: string }
142
+ | { mode: 'apiKey'; apiKey: string };
143
+ timeoutMs?: number; // Request timeout (default: 15000ms)
144
+ userAgent?: string; // User agent (default: '@blockintel/gate-sdk/<version>')
145
+ clockSkewMs?: number; // Clock skew tolerance (default: 120000ms)
146
+ enableStepUp?: boolean; // Enable step-up support (default: false)
147
+ stepUp?: {
148
+ pollingIntervalMs?: number; // Polling interval (default: 250ms)
149
+ maxWaitMs?: number; // Max wait time (default: 15000ms)
150
+ treatRequireStepUpAsBlockWhenDisabled?: boolean; // Transform REQUIRE_STEP_UP to BLOCK (default: true)
151
+ };
152
+ ```
153
+
154
+ When step-up is disabled, the SDK treats `REQUIRE_STEP_UP` as `BLOCK` by default to preserve Gate-only safety, unless the caller explicitly overrides this behavior.
155
+ }
156
+ ```
157
+
158
+ ### Environment Variables
159
+
160
+ ```bash
161
+ # Required
162
+ GATE_BASE_URL=https://gate.blockintelai.net
163
+ GATE_TENANT_ID=your-tenant-id
164
+
165
+ # HMAC Authentication
166
+ GATE_KEY_ID=your-key-id
167
+ GATE_HMAC_SECRET=your-secret
168
+
169
+ # OR API Key Authentication
170
+ GATE_API_KEY=your-api-key
171
+ ```
172
+
173
+ ## API Reference
174
+
175
+ ### `GateClient.evaluate(req, opts?)`
176
+
177
+ Evaluate a transaction defense request.
178
+
179
+ **Parameters:**
180
+ - `req: DefenseEvaluateRequestV2` - Transaction and signing context
181
+ - `opts?: { requestId?: string }` - Optional request ID (auto-generated if not provided)
182
+
183
+ **Returns:** `Promise<DefenseEvaluateResponseV2>`
184
+
185
+ **Response:**
186
+ ```typescript
187
+ {
188
+ decision: 'ALLOW' | 'BLOCK' | 'REQUIRE_STEP_UP';
189
+ reasonCodes: string[];
190
+ policyVersion?: string;
191
+ correlationId?: string;
192
+ stepUp?: {
193
+ requestId: string;
194
+ ttlSeconds?: number;
195
+ };
196
+ }
197
+ ```
198
+
199
+ ### `GateClient.getStepUpStatus(args)`
200
+
201
+ Get current step-up status.
202
+
203
+ **Parameters:**
204
+ - `args: { requestId: string; tenantId?: string }`
205
+
206
+ **Returns:** `Promise<StepUpStatusResponse>`
207
+
208
+ **Status Types:**
209
+ - `PENDING` - Waiting for decision
210
+ - `APPROVED` - Step-up approved
211
+ - `DENIED` - Step-up denied
212
+ - `EXPIRED` - Step-up expired (TTL exceeded)
213
+
214
+ **Polling behavior:**
215
+ - Returns `404 NOT_FOUND` if request ID does not exist OR does not belong to the tenant
216
+ - Returns `EXPIRED` deterministically if TTL exceeded, even if DynamoDB TTL has not deleted the item yet
217
+
218
+ ### `GateClient.awaitStepUpDecision(args)`
219
+
220
+ Poll step-up status until decision is reached or timeout.
221
+
222
+ **Parameters:**
223
+ - `args: { requestId: string; maxWaitMs?: number; intervalMs?: number }`
224
+
225
+ **Returns:** `Promise<StepUpFinalResult>`
226
+
227
+ ## Error Handling
228
+
229
+ The SDK uses custom error types:
230
+
231
+ ```typescript
232
+ import { GateError, GateErrorCode, StepUpNotConfiguredError } from '@blockintel/gate-sdk';
233
+
234
+ try {
235
+ const response = await gate.evaluate({ ... });
236
+ } catch (error) {
237
+ if (error instanceof GateError) {
238
+ console.error('Error code:', error.code);
239
+ console.error('Status:', error.status);
240
+ console.error('Request ID:', error.requestId);
241
+ console.error('Correlation ID:', error.correlationId);
242
+ }
243
+ }
244
+ ```
245
+
246
+ **Error Codes:**
247
+ - `NETWORK_ERROR` - Network connection failed
248
+ - `TIMEOUT` - Request timeout
249
+ - `NOT_FOUND` - Resource not found (404)
250
+ - `UNAUTHORIZED` - Authentication failed (401)
251
+ - `FORBIDDEN` - Access denied (403)
252
+ - `RATE_LIMITED` - Rate limit exceeded (429)
253
+ - `SERVER_ERROR` - Server error (5xx)
254
+ - `INVALID_RESPONSE` - Invalid response format
255
+ - `STEP_UP_NOT_CONFIGURED` - Step-up required but not enabled
256
+ - `STEP_UP_TIMEOUT` - Step-up polling timeout
257
+
258
+ ## Authentication
259
+
260
+ ### HMAC v1 Signing
261
+
262
+ The SDK implements HMAC v1 signing for secure authentication:
263
+
264
+ **Signing String:**
265
+ ```
266
+ <HTTP_METHOD>\n
267
+ <PATH>\n
268
+ <TENANT_ID>\n
269
+ <TIMESTAMP_MS>\n
270
+ <REQUEST_ID>\n
271
+ <SHA256_HEX_OF_BODY>\n
272
+ ```
273
+
274
+ **Signature:**
275
+ ```
276
+ HMAC-SHA256(secret, signingString) as hex
277
+ ```
278
+
279
+ **Headers:**
280
+ - `X-GATE-TENANT-ID`
281
+ - `X-GATE-KEY-ID`
282
+ - `X-GATE-TIMESTAMP-MS`
283
+ - `X-GATE-REQUEST-ID`
284
+ - `X-GATE-SIGNATURE`
285
+
286
+ ### API Key
287
+
288
+ For simpler onboarding, use API key authentication:
289
+
290
+ **Headers:**
291
+ - `X-API-KEY`
292
+ - `X-GATE-TENANT-ID`
293
+ - `X-GATE-REQUEST-ID`
294
+ - `X-GATE-TIMESTAMP-MS`
295
+
296
+ ## Step-Up Flow
297
+
298
+ Step-up is a feature-flagged capability that allows Gate to defer decisions to an external approval system.
299
+
300
+ **Flow:**
301
+ 1. SDK calls `evaluate()` → Gate returns `REQUIRE_STEP_UP`
302
+ 2. SDK polls `/defense/stepup/status` until decision is reached
303
+ 3. External system (Control Plane) approves/denies via separate API
304
+ 4. SDK receives final decision: `APPROVED`, `DENIED`, or `EXPIRED`
305
+
306
+ **Important:**
307
+ - Hot Path **never** approves/denies step-up
308
+ - Approve/deny happens **only** on Control Plane
309
+ - SDK only polls status from Hot Path
310
+ - **The SDK never performs approve/deny actions. Step-up resolution is handled exclusively by the Control Plane.**
311
+
312
+ Gate-only deployments should leave step-up disabled; the SDK will never "wait" unless step-up is enabled.
313
+
314
+ **TTL Guardrails:**
315
+ - Default: 600 seconds
316
+ - Min: 300 seconds
317
+ - Max: 900 seconds
318
+
319
+ ## Retry Logic
320
+
321
+ The SDK automatically retries failed requests:
322
+
323
+ - **Max Attempts:** 3
324
+ - **Retry On:** Network errors, timeouts, 429, 5xx
325
+ - **Never Retry On:** 4xx (except 429)
326
+ - **Backoff:** Exponential with jitter (100ms base, 2x factor, 800ms max)
327
+
328
+ **Request ID Stability:**
329
+ - Same `requestId` is used across all retries
330
+ - Ensures idempotency on Gate server
331
+
332
+ ## Secret Rotation
333
+
334
+ For HMAC authentication, secret rotation is the customer's responsibility:
335
+
336
+ 1. Update environment variable with new secret
337
+ 2. SDK reads from config at runtime (no caching)
338
+ 3. Restart application to use new secret
339
+
340
+ The SDK does not cache secrets across process restarts unless the user explicitly does so.
341
+
342
+ ## Security
343
+
344
+ - **HTTPS Required:** SDK validates HTTPS in production (localhost exception)
345
+ - **Secret Protection:** Never logs secrets or API keys
346
+ - **Clock Skew:** Configurable tolerance for timestamp validation
347
+ - **Replay Protection:** Request ID + timestamp prevent replay attacks
348
+
349
+ ## TypeScript Support
350
+
351
+ Full TypeScript definitions are included:
352
+
353
+ ```typescript
354
+ import type {
355
+ DefenseEvaluateRequestV2,
356
+ DefenseEvaluateResponseV2,
357
+ GateDecision,
358
+ StepUpStatusResponse,
359
+ GateStepUpStatus,
360
+ StepUpFinalResult,
361
+ } from '@blockintel/gate-sdk';
362
+ ```
363
+
364
+ ## Examples
365
+
366
+ See [examples](./examples) directory for complete examples:
367
+ - [HMAC Authentication](./examples/hmac-auth.ts)
368
+ - [API Key Authentication](./examples/api-key-auth.ts)
369
+ - [Step-Up Flow](./examples/step-up-flow.ts)
370
+
371
+ ## Publishing
372
+
373
+ - Package versions are immutable once published (NPM does not allow overwriting a released version). Always bump the version before tagging a release.
374
+
375
+ See [PUBLISHING.md](./PUBLISHING.md) for detailed publishing instructions.
376
+
377
+ ## License
378
+
379
+ MIT License - see [LICENSE](./LICENSE) file.
380
+
381
+ ## Support
382
+
383
+ - **Documentation:** https://docs.blockintel.ai
384
+ - **Issues:** https://github.com/4KInc/blockintel-ai/issues
385
+ - **Email:** support@blockintel.ai
386
+