blockintel-gate-sdk 0.3.7 → 0.3.9

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/README.md CHANGED
@@ -13,6 +13,8 @@ npm install @blockintel/gate-sdk
13
13
  - Node.js >= 18.0.0 (uses global `fetch` API)
14
14
  - TypeScript >= 5.0.0 (optional, for type definitions)
15
15
 
16
+ **Optional – On-prem HSM (PKCS#11):** For `GenericHsmSigner` with a real HSM (Thales nShield, Utimaco, AWS CloudHSM, SoftHSM2, etc.), install the optional dependency: `npm install pkcs11js`. Without it, `Pkcs11SessionImpl` throws at runtime when used; you can still pass a custom `pkcs11Session` to `GenericHsmSigner` for testing or a different PKCS#11 stack.
17
+
16
18
  ### Hot Path compatibility
17
19
 
18
20
  - **Mode**: Default is `SHADOW` (Hot Path returns ALLOW with reason codes for would-block decisions). Set `mode: 'ENFORCE'` or `GATE_MODE=ENFORCE` for real BLOCK responses.
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Metrics Collector for SDK
3
+ *
4
+ * Collects counters and latency metrics for observability.
5
+ */
6
+ interface Metrics {
7
+ requestsTotal: number;
8
+ allowedTotal: number;
9
+ blockedTotal: number;
10
+ stepupTotal: number;
11
+ timeoutsTotal: number;
12
+ errorsTotal: number;
13
+ circuitBreakerOpenTotal: number;
14
+ wouldBlockTotal: number;
15
+ failOpenTotal: number;
16
+ latencyMs: number[];
17
+ }
18
+ type MetricsHook = (metrics: Metrics) => void | Promise<void>;
19
+ /**
20
+ * Metrics Collector
21
+ */
22
+ declare class MetricsCollector {
23
+ private requestsTotal;
24
+ private allowedTotal;
25
+ private blockedTotal;
26
+ private stepupTotal;
27
+ private timeoutsTotal;
28
+ private errorsTotal;
29
+ private circuitBreakerOpenTotal;
30
+ private wouldBlockTotal;
31
+ private failOpenTotal;
32
+ private latencyMs;
33
+ private readonly maxSamples;
34
+ private readonly hooks;
35
+ /**
36
+ * Record a request
37
+ */
38
+ recordRequest(decision: 'ALLOW' | 'BLOCK' | 'REQUIRE_STEP_UP' | 'WOULD_BLOCK' | 'FAIL_OPEN', latencyMs: number): void;
39
+ /**
40
+ * Record a timeout
41
+ */
42
+ recordTimeout(): void;
43
+ /**
44
+ * Record an error
45
+ */
46
+ recordError(): void;
47
+ /**
48
+ * Record circuit breaker open
49
+ */
50
+ recordCircuitBreakerOpen(): void;
51
+ /**
52
+ * Record soft-enforce override (app chose to sign despite BLOCK decision)
53
+ */
54
+ recordSoftBlockOverride(decision: 'ALLOW' | 'BLOCK'): void;
55
+ /**
56
+ * Get current metrics snapshot
57
+ */
58
+ getMetrics(): Metrics;
59
+ /**
60
+ * Register a metrics hook (e.g., for Prometheus/OpenTelemetry export)
61
+ */
62
+ registerHook(hook: MetricsHook): void;
63
+ /**
64
+ * Emit metrics to all registered hooks
65
+ */
66
+ private emitMetrics;
67
+ /**
68
+ * Reset all metrics
69
+ */
70
+ reset(): void;
71
+ }
72
+
73
+ /**
74
+ * BlockIntel Gate SDK - Type Contracts
75
+ *
76
+ * Type definitions for Gate Hot Path API v2 contracts.
77
+ * Internal SDK uses camelCase; mapping to/from API snake_case is handled internally.
78
+ */
79
+ /**
80
+ * Transaction intent structure for evaluate request
81
+ */
82
+ interface TransactionIntentV2 {
83
+ from: string;
84
+ to: string;
85
+ value?: string;
86
+ data?: string;
87
+ nonce?: number | string;
88
+ gasPrice?: string;
89
+ gasLimit?: string;
90
+ chainId?: number | string;
91
+ [key: string]: unknown;
92
+ }
93
+ /**
94
+ * Signing context metadata
95
+ */
96
+ interface SigningContext {
97
+ signerId?: string;
98
+ source?: {
99
+ repo?: string;
100
+ workflow?: string;
101
+ environment?: string;
102
+ [key: string]: unknown;
103
+ };
104
+ wallet?: {
105
+ address: string;
106
+ type?: string;
107
+ [key: string]: unknown;
108
+ };
109
+ [key: string]: unknown;
110
+ }
111
+ /**
112
+ * Defense evaluate request (v2)
113
+ */
114
+ interface DefenseEvaluateRequestV2 {
115
+ txIntent: TransactionIntentV2;
116
+ signingContext?: SigningContext;
117
+ requestId?: string;
118
+ timestampMs?: number;
119
+ /**
120
+ * Enable transaction simulation (optional, defaults to false)
121
+ *
122
+ * When true, Hot Path will simulate the transaction after static policy evaluation.
123
+ * Adds 300-800ms latency but provides additional security checks.
124
+ */
125
+ simulate?: boolean;
126
+ }
127
+ /**
128
+ * Gate decision types
129
+ */
130
+ type GateDecision = 'ALLOW' | 'BLOCK' | 'REQUIRE_STEP_UP';
131
+ /**
132
+ * Step-up metadata in evaluate response
133
+ */
134
+ interface StepUpMetadata {
135
+ requestId: string;
136
+ ttlSeconds?: number;
137
+ }
138
+ /**
139
+ * Defense evaluate response (v2)
140
+ */
141
+ interface DefenseEvaluateResponseV2 {
142
+ decision: GateDecision;
143
+ reasonCodes: string[];
144
+ policyVersion?: string;
145
+ correlationId?: string;
146
+ decisionId?: string;
147
+ stepUp?: StepUpMetadata;
148
+ /**
149
+ * Decision token (JWS HS256) binding decision to txDigest. Required in ENFORCE/HARD when requireDecisionToken.
150
+ */
151
+ decisionToken?: string;
152
+ /**
153
+ * Unix seconds when decision token expires.
154
+ */
155
+ expiresAt?: number;
156
+ /**
157
+ * SHA256(canonicalJson(txBinding)). Must match when signing.
158
+ */
159
+ txDigest?: string;
160
+ /**
161
+ * Whether the decision was enforced (false in SHADOW mode)
162
+ */
163
+ enforced?: boolean;
164
+ /**
165
+ * Whether shadow mode would have blocked (true if mode=SHADOW and decision=BLOCK)
166
+ */
167
+ shadowWouldBlock?: boolean;
168
+ /**
169
+ * Gate mode used for this evaluation
170
+ */
171
+ mode?: GateMode;
172
+ /**
173
+ * Metadata (evaluation latency, simulation, policy hash for pinning)
174
+ */
175
+ metadata?: {
176
+ evaluationLatencyMs?: number;
177
+ policyHash?: string;
178
+ snapshotVersion?: number;
179
+ [key: string]: unknown;
180
+ };
181
+ /** True when evaluationMode was FIRE_AND_FORGET (optimistic ALLOW, attestation in background) */
182
+ fireAndForget?: boolean;
183
+ /** Warning message (e.g. SOFT_ENFORCE override) */
184
+ warning?: string;
185
+ }
186
+ /**
187
+ * Step-up status types
188
+ */
189
+ type GateStepUpStatus = 'PENDING' | 'APPROVED' | 'DENIED' | 'EXPIRED';
190
+ /**
191
+ * Step-up status response
192
+ */
193
+ interface StepUpStatusResponse {
194
+ status: GateStepUpStatus;
195
+ tenantId: string;
196
+ requestId: string;
197
+ decision?: string;
198
+ reasonCodes?: string[];
199
+ correlationId?: string;
200
+ expiresAtMs?: number;
201
+ ttl?: number;
202
+ }
203
+ /**
204
+ * Final result from awaitStepUpDecision
205
+ */
206
+ interface StepUpFinalResult {
207
+ status: GateStepUpStatus;
208
+ requestId: string;
209
+ elapsedMs: number;
210
+ decision?: string;
211
+ reasonCodes?: string[];
212
+ correlationId?: string;
213
+ }
214
+ /**
215
+ * Fail-safe mode for SDK (deprecated - use onConnectionFailure instead)
216
+ */
217
+ type FailSafeMode = 'ALLOW_ON_TIMEOUT' | 'BLOCK_ON_TIMEOUT' | 'BLOCK_ON_ANOMALY';
218
+ /**
219
+ * Gate Mode
220
+ *
221
+ * SHADOW: Evaluate and log, but always allow (monitor-only)
222
+ * SOFT_ENFORCE: Evaluate and return BLOCK decisions but let app override (no throw)
223
+ * ENFORCE: Evaluate and enforce decisions (block if policy violation)
224
+ */
225
+ type GateMode = 'SHADOW' | 'SOFT_ENFORCE' | 'ENFORCE';
226
+ /**
227
+ * Evaluation mode (attestation pitch: "Gate attests in parallel")
228
+ *
229
+ * BLOCKING: await gate.evaluate() blocks until response (default)
230
+ * FIRE_AND_FORGET: evaluate() returns immediately with optimistic ALLOW; attestation in background
231
+ * PARALLEL: same as BLOCKING; caller can await the returned promise later after doing other work
232
+ */
233
+ type EvaluationMode = 'BLOCKING' | 'FIRE_AND_FORGET' | 'PARALLEL';
234
+ /**
235
+ * Connection Failure Strategy
236
+ *
237
+ * FAIL_OPEN: Allow transaction if hotpath is unreachable
238
+ * FAIL_CLOSED: Block transaction if hotpath is unreachable (security-first)
239
+ */
240
+ type ConnectionFailureStrategy = 'FAIL_OPEN' | 'FAIL_CLOSED';
241
+ /**
242
+ * Circuit breaker configuration
243
+ */
244
+ interface CircuitBreakerConfig {
245
+ tripAfterConsecutiveFailures?: number;
246
+ coolDownMs?: number;
247
+ }
248
+ /**
249
+ * SDK client configuration
250
+ */
251
+ interface GateClientConfig {
252
+ baseUrl: string;
253
+ tenantId: string;
254
+ auth: {
255
+ mode: 'hmac';
256
+ keyId: string;
257
+ secret: string;
258
+ } | {
259
+ mode: 'apiKey';
260
+ apiKey: string;
261
+ };
262
+ timeoutMs?: number;
263
+ userAgent?: string;
264
+ clockSkewMs?: number;
265
+ retries?: number;
266
+ failSafeMode?: FailSafeMode;
267
+ /**
268
+ * Gate mode (default: SHADOW for safety)
269
+ *
270
+ * SHADOW: Monitor-only - evaluate and log, but always allow
271
+ * ENFORCE: Enforce decisions - block if policy violation
272
+ */
273
+ mode?: GateMode;
274
+ /** Evaluation mode: BLOCKING (default), FIRE_AND_FORGET (return immediately, attest in background), PARALLEL */
275
+ evaluationMode?: EvaluationMode;
276
+ /**
277
+ * Connection failure strategy (default: based on mode)
278
+ *
279
+ * FAIL_OPEN: Allow on connection failure (default in SHADOW mode)
280
+ * FAIL_CLOSED: Block on connection failure (default in ENFORCE mode)
281
+ */
282
+ onConnectionFailure?: ConnectionFailureStrategy;
283
+ circuitBreaker?: CircuitBreakerConfig;
284
+ enableStepUp?: boolean;
285
+ stepUp?: {
286
+ pollingIntervalMs?: number;
287
+ maxWaitMs?: number;
288
+ treatRequireStepUpAsBlockWhenDisabled?: boolean;
289
+ };
290
+ onMetrics?: (metrics: Metrics) => void | Promise<void>;
291
+ signerId?: string;
292
+ heartbeatRefreshIntervalSeconds?: number;
293
+ /** API key for Control Plane heartbeat endpoint (x-gate-heartbeat-key). Required when not local. Fallback: GATE_HEARTBEAT_KEY env. */
294
+ heartbeatApiKey?: string;
295
+ /** When true or GATE_SDK_DEBUG=1, log sanitized request/response (no secrets, no body values). */
296
+ debug?: boolean;
297
+ /**
298
+ * Break-glass token (optional, for emergency override)
299
+ *
300
+ * JWT token issued by Control Plane for time-bound policy bypass.
301
+ * Only valid if explicitly activated via break-glass endpoint.
302
+ */
303
+ breakglassToken?: string;
304
+ /**
305
+ * Local development mode - disables auth, heartbeat, and break-glass
306
+ * Set to true when using gate-local emulator
307
+ */
308
+ local?: boolean;
309
+ /**
310
+ * Enforcement mode (default: SOFT)
311
+ *
312
+ * SOFT: Warns if IAM permission risk detected, but allows initialization
313
+ * HARD: Blocks initialization if IAM permission risk detected (unless override set)
314
+ */
315
+ enforcementMode?: 'SOFT' | 'HARD';
316
+ /**
317
+ * Allow initialization even if IAM permission risk detected
318
+ *
319
+ * Default: false in HARD mode, true in SOFT mode
320
+ *
321
+ * WARNING: Setting to true in HARD mode defeats the purpose of hard enforcement.
322
+ * Only use during migration periods.
323
+ */
324
+ allowInsecureKmsSignPermission?: boolean;
325
+ /**
326
+ * Optional: Specific KMS key IDs to check for permission risk
327
+ * If not provided, checks for any kms:Sign permission
328
+ */
329
+ kmsKeyIds?: string[];
330
+ /**
331
+ * Require decision token before sign (default: true when mode=ENFORCE or enforcementMode=HARD).
332
+ * When true, evaluate() must return decisionToken/txDigest for ALLOW; sign path verifies digest match.
333
+ * Override with GATE_REQUIRE_DECISION_TOKEN env.
334
+ */
335
+ requireDecisionToken?: boolean;
336
+ /**
337
+ * Optional policy pinning: if set, evaluate response must have matching policyHash (from metadata).
338
+ * Mismatch → treat as BLOCK locally (do not call signer). Defense against Control Plane compromise.
339
+ */
340
+ expectedPolicyHash?: string;
341
+ /**
342
+ * Optional snapshot version pinning: if set, evaluate response must have matching snapshotVersion (from metadata).
343
+ * Mismatch → treat as BLOCK locally.
344
+ */
345
+ expectedSnapshotVersion?: number;
346
+ /**
347
+ * Optional: public key (PEM) to verify RS256 decision tokens. When set, ALLOW responses with decisionToken
348
+ * are signature-verified; invalid or wrong-key tokens are treated as BLOCK.
349
+ */
350
+ decisionTokenPublicKey?: string;
351
+ }
352
+ /**
353
+ * Post-sign attestation request (zero-latency audit: attest after signing)
354
+ */
355
+ interface AttestCompletedRequest {
356
+ txIntent: TransactionIntentV2;
357
+ signature: {
358
+ signature: string;
359
+ signerId: string;
360
+ keyId: string;
361
+ algorithm: string;
362
+ };
363
+ signingContext?: SigningContext;
364
+ }
365
+ /**
366
+ * Post-sign attestation response
367
+ */
368
+ interface AttestCompletedResponse {
369
+ decision: 'ALLOW' | 'POLICY_VIOLATION_DETECTED';
370
+ decisionId: string;
371
+ correlationId: string;
372
+ reasonCodes: string[];
373
+ attestation: {
374
+ signatureHash: string;
375
+ attestedAt: number;
376
+ attestationToken?: string;
377
+ };
378
+ }
379
+
380
+ export { type AttestCompletedRequest as A, type DefenseEvaluateRequestV2 as D, type EvaluationMode as E, type GateClientConfig as G, MetricsCollector as M, type StepUpStatusResponse as S, type TransactionIntentV2 as T, type DefenseEvaluateResponseV2 as a, type StepUpFinalResult as b, type SigningContext as c, type AttestCompletedResponse as d, type GateDecision as e, type GateMode as f, type StepUpMetadata as g, type GateStepUpStatus as h };