optropic 1.0.0 → 2.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/dist/index.d.cts CHANGED
@@ -21,6 +21,11 @@ interface OptropicConfig {
21
21
  * Format: optr_live_xxx (production) or optr_test_xxx (test)
22
22
  */
23
23
  readonly apiKey: string;
24
+ /**
25
+ * Explicitly set sandbox mode. When omitted, auto-detected from
26
+ * the API key prefix: `optr_test_*` → sandbox, `optr_live_*` → live.
27
+ */
28
+ readonly sandbox?: boolean;
24
29
  /**
25
30
  * Base URL override (for self-hosted deployments).
26
31
  * If not provided, uses Optropic's managed infrastructure.
@@ -67,60 +72,93 @@ interface RetryConfig {
67
72
  */
68
73
  type ErrorCode = 'INVALID_API_KEY' | 'EXPIRED_API_KEY' | 'INSUFFICIENT_PERMISSIONS' | 'INVALID_GTIN' | 'INVALID_SERIAL' | 'INVALID_CODE_FORMAT' | 'INVALID_BATCH_CONFIG' | 'CODE_NOT_FOUND' | 'BATCH_NOT_FOUND' | 'PRODUCT_NOT_FOUND' | 'CODE_REVOKED' | 'CODE_EXPIRED' | 'BATCH_ALREADY_EXISTS' | 'RATE_LIMITED' | 'QUOTA_EXCEEDED' | 'NETWORK_ERROR' | 'TIMEOUT' | 'SERVICE_UNAVAILABLE' | 'INTERNAL_ERROR' | 'UNKNOWN_ERROR';
69
74
 
75
+ /**
76
+ * Assets Resource
77
+ *
78
+ * CRUD operations for digitally signed assets.
79
+ */
80
+
70
81
  interface Asset {
71
82
  readonly id: string;
72
- readonly short_id: string;
73
- readonly gtin: string;
74
- readonly serial: string;
83
+ readonly shortId: string;
84
+ readonly tenantId: string;
85
+ readonly keysetId: string;
86
+ readonly externalId: string | null;
87
+ readonly vertical: string;
88
+ readonly securityLevel: 'signed' | 'provenance';
89
+ readonly assetConfig: Record<string, unknown>;
90
+ readonly signatureHex: string;
75
91
  readonly status: 'active' | 'revoked';
76
- readonly security_level: 'signed' | 'provenance';
77
- readonly metadata?: Record<string, string>;
78
- readonly created_at: string;
79
- readonly revoked_at?: string;
92
+ readonly isSandbox: boolean;
93
+ readonly verificationCount: number;
94
+ readonly metadata: Record<string, unknown> | null;
95
+ readonly createdAt: string;
96
+ readonly updatedAt: string;
80
97
  }
81
98
  interface CreateAssetParams {
82
- readonly gtin: string;
83
- readonly serial: string;
84
- readonly metadata?: Record<string, string>;
99
+ readonly keysetId: string;
100
+ readonly externalId?: string;
101
+ readonly vertical?: string;
102
+ readonly securityLevel?: 'signed' | 'provenance';
103
+ readonly assetConfig?: Record<string, unknown>;
104
+ readonly metadata?: Record<string, unknown>;
85
105
  }
86
106
  interface ListAssetsParams {
87
- readonly limit?: number;
88
- readonly offset?: number;
107
+ readonly page?: number;
108
+ readonly per_page?: number;
89
109
  readonly status?: 'active' | 'revoked';
90
- readonly gtin?: string;
110
+ readonly vertical?: string;
111
+ /** Filter by sandbox status. Auto-set when using a test API key. */
112
+ readonly is_sandbox?: boolean;
113
+ }
114
+ interface ListAssetsResponse {
115
+ readonly data: Asset[];
116
+ readonly pagination: {
117
+ readonly total: number;
118
+ readonly page: number;
119
+ readonly perPage: number;
120
+ readonly totalPages: number;
121
+ };
91
122
  }
92
123
  interface VerifyResult {
93
124
  readonly id: string;
94
125
  readonly status: string;
95
- readonly security_level: string;
96
- readonly signature_valid: boolean;
97
- readonly verification_count: number;
98
- readonly last_verified_at: string;
99
- readonly revocation_status: 'active' | 'revoked';
100
- readonly verification_mode: 'online' | 'offline';
101
- readonly provenance_valid?: boolean;
102
- readonly evidence?: VerificationEvidence;
103
- }
104
- interface VerificationEvidence {
105
- readonly signature_valid: boolean;
106
- readonly revocation_status: string;
107
- readonly verification_mode: string;
108
- readonly provenance_valid?: boolean;
109
- readonly security_level?: string;
110
- readonly verification_count?: number;
126
+ readonly securityLevel: string;
127
+ readonly signatureValid: boolean;
128
+ readonly provenanceValid?: boolean;
129
+ readonly revocationStatus: 'active' | 'revoked';
130
+ readonly verificationMode: 'online' | 'offline';
131
+ readonly verificationCount: number;
132
+ readonly lastVerifiedAt: string;
111
133
  }
112
134
  interface BatchCreateParams {
113
- readonly assets: CreateAssetParams[];
135
+ readonly keysetId: string;
136
+ readonly assets: Array<{
137
+ readonly externalId?: string;
138
+ readonly vertical?: string;
139
+ readonly securityLevel?: 'signed' | 'provenance';
140
+ readonly assetConfig?: Record<string, unknown>;
141
+ readonly metadata?: Record<string, unknown>;
142
+ }>;
114
143
  }
115
144
  interface BatchCreateResult {
116
145
  readonly created: number;
117
- readonly asset_ids: string[];
146
+ readonly requested: number;
147
+ readonly assets: Asset[];
118
148
  }
119
149
  declare class AssetsResource {
120
150
  private readonly request;
121
- constructor(request: RequestFn);
151
+ private readonly client;
152
+ constructor(request: RequestFn, client: OptropicClient);
122
153
  create(params: CreateAssetParams): Promise<Asset>;
123
- list(params?: ListAssetsParams): Promise<Asset[]>;
154
+ /**
155
+ * List assets with optional filtering and pagination.
156
+ *
157
+ * When the client uses a sandbox/test API key, `is_sandbox` is
158
+ * automatically set to `true` so sandbox clients only see sandbox
159
+ * assets. Pass an explicit `is_sandbox` value to override.
160
+ */
161
+ list(params?: ListAssetsParams): Promise<ListAssetsResponse>;
124
162
  get(assetId: string): Promise<Asset>;
125
163
  verify(assetId: string): Promise<VerifyResult>;
126
164
  revoke(assetId: string, reason?: string): Promise<Asset>;
@@ -128,21 +166,169 @@ declare class AssetsResource {
128
166
  private buildQuery;
129
167
  }
130
168
 
169
+ /**
170
+ * Audit Resource
171
+ *
172
+ * Immutable audit log operations — list, get, and create custom audit events.
173
+ * Mirrors the Python SDK's `optropic.resources.audit` module.
174
+ */
175
+
176
+ interface AuditEvent {
177
+ readonly id: string;
178
+ readonly tenantId: string;
179
+ readonly eventType: string;
180
+ readonly actor: string;
181
+ readonly createdAt: string;
182
+ readonly resourceId?: string;
183
+ readonly resourceType?: string;
184
+ readonly details?: Record<string, unknown>;
185
+ readonly eventHash?: string;
186
+ readonly chainSequence?: number;
187
+ }
188
+ interface ListAuditParams {
189
+ readonly page?: number;
190
+ readonly limit?: number;
191
+ readonly event_type?: string;
192
+ readonly resource_id?: string;
193
+ readonly from_date?: string;
194
+ readonly to_date?: string;
195
+ }
196
+ interface ListAuditResponse {
197
+ readonly data: AuditEvent[];
198
+ readonly pagination: {
199
+ readonly total: number;
200
+ readonly page: number;
201
+ readonly perPage: number;
202
+ readonly totalPages: number;
203
+ };
204
+ }
205
+ interface CreateAuditEventParams {
206
+ readonly eventType: string;
207
+ readonly resourceId?: string;
208
+ readonly resourceType?: string;
209
+ readonly details?: Record<string, unknown>;
210
+ }
211
+ declare class AuditResource {
212
+ private readonly request;
213
+ constructor(request: RequestFn);
214
+ /**
215
+ * List audit events with optional filtering and pagination.
216
+ */
217
+ list(params?: ListAuditParams): Promise<ListAuditResponse>;
218
+ /**
219
+ * Retrieve a single audit event by ID.
220
+ */
221
+ get(eventId: string): Promise<AuditEvent>;
222
+ /**
223
+ * Record a custom audit event.
224
+ */
225
+ create(params: CreateAuditEventParams): Promise<AuditEvent>;
226
+ private buildQuery;
227
+ }
228
+
229
+ /**
230
+ * Compliance Resource
231
+ *
232
+ * Chain verification, Merkle proofs, audit export, and compliance configuration.
233
+ * Mirrors the Python SDK's `optropic.resources.compliance` module.
234
+ */
235
+
236
+ interface ChainVerifyResult {
237
+ readonly tenantId: string;
238
+ readonly chainValid: boolean;
239
+ readonly eventsChecked: number;
240
+ readonly verifiedAt: string;
241
+ readonly brokenAtSequence?: number;
242
+ }
243
+ interface MerkleRoot {
244
+ readonly id: string;
245
+ readonly rootHash: string;
246
+ readonly eventCount: number;
247
+ readonly periodStart: string;
248
+ readonly periodEnd: string;
249
+ readonly createdAt: string;
250
+ }
251
+ interface MerkleProof {
252
+ readonly eventId: string;
253
+ readonly eventHash: string;
254
+ readonly merkleRoot: string;
255
+ readonly proof: string[];
256
+ readonly verified: boolean;
257
+ readonly period: string;
258
+ }
259
+ interface ExportParams {
260
+ readonly from_date?: string;
261
+ readonly to_date?: string;
262
+ readonly limit?: number;
263
+ }
264
+ interface ExportResult {
265
+ readonly filename: string;
266
+ readonly eventCount: number;
267
+ readonly csv: string;
268
+ readonly signature?: string;
269
+ readonly publicKeyHex?: string;
270
+ readonly keyId?: string;
271
+ readonly algorithm?: string;
272
+ }
273
+ interface ComplianceConfig {
274
+ readonly complianceMode: string;
275
+ readonly retentionPolicy: Record<string, unknown>;
276
+ }
277
+ declare class ComplianceResource {
278
+ private readonly request;
279
+ constructor(request: RequestFn);
280
+ /**
281
+ * Verify the integrity of the full audit chain.
282
+ */
283
+ verifyChain(): Promise<ChainVerifyResult>;
284
+ /**
285
+ * Return all Merkle roots.
286
+ */
287
+ listMerkleRoots(): Promise<MerkleRoot[]>;
288
+ /**
289
+ * Return a Merkle inclusion proof for a specific audit event.
290
+ */
291
+ getMerkleProof(eventId: string): Promise<MerkleProof>;
292
+ /**
293
+ * Export audit data as a signed CSV.
294
+ */
295
+ exportAudit(params?: ExportParams): Promise<ExportResult>;
296
+ /**
297
+ * Retrieve the current compliance configuration.
298
+ */
299
+ getConfig(): Promise<ComplianceConfig>;
300
+ /**
301
+ * Update the compliance mode.
302
+ */
303
+ updateConfig(mode: string): Promise<ComplianceConfig>;
304
+ private buildQuery;
305
+ }
306
+
307
+ /**
308
+ * Keys Resource
309
+ *
310
+ * API key management operations.
311
+ */
312
+
131
313
  interface ApiKey {
132
314
  readonly id: string;
133
- readonly name: string;
134
- readonly key_prefix: string;
315
+ readonly label: string;
316
+ readonly prefix: string;
135
317
  readonly environment: string;
136
- readonly permissions: string[];
137
318
  readonly created_at: string;
138
319
  readonly last_used_at?: string;
139
320
  }
140
321
  interface CreateKeyParams {
141
- readonly name?: string;
142
- readonly environment?: 'production' | 'test';
322
+ readonly label?: string;
323
+ readonly environment?: 'live' | 'test';
143
324
  }
144
- interface CreateKeyResult extends ApiKey {
325
+ interface CreateKeyResult {
145
326
  readonly key: string;
327
+ readonly prefix: string;
328
+ readonly id: string;
329
+ readonly label: string;
330
+ readonly environment: string;
331
+ readonly created_at: string;
146
332
  }
147
333
  declare class KeysResource {
148
334
  private readonly request;
@@ -152,6 +338,134 @@ declare class KeysResource {
152
338
  revoke(keyId: string): Promise<void>;
153
339
  }
154
340
 
341
+ /**
342
+ * Keysets Resource
343
+ *
344
+ * Signing keyset management operations.
345
+ */
346
+
347
+ interface Keyset {
348
+ readonly id: string;
349
+ readonly name: string;
350
+ readonly publicKey: string;
351
+ readonly tenantId: string;
352
+ readonly isActive: boolean;
353
+ readonly createdAt: string;
354
+ }
355
+ interface CreateKeysetParams {
356
+ readonly name?: string;
357
+ }
358
+ interface ListKeysetsParams {
359
+ readonly page?: number;
360
+ readonly per_page?: number;
361
+ }
362
+ interface ListKeysetsResponse {
363
+ readonly data: Keyset[];
364
+ readonly pagination: {
365
+ readonly total: number;
366
+ readonly page: number;
367
+ readonly perPage: number;
368
+ readonly totalPages: number;
369
+ };
370
+ }
371
+ declare class KeysetsResource {
372
+ private readonly request;
373
+ constructor(request: RequestFn);
374
+ create(params?: CreateKeysetParams): Promise<Keyset>;
375
+ list(params?: ListKeysetsParams): Promise<ListKeysetsResponse>;
376
+ private buildQuery;
377
+ }
378
+
379
+ /**
380
+ * Schemas Resource
381
+ *
382
+ * Schema Registry operations — register and manage vertical config schemas.
383
+ * Mirrors the Python SDK's `optropic.resources.schemas` module.
384
+ */
385
+
386
+ interface VerticalSchema {
387
+ readonly id: string;
388
+ readonly tenantId: string;
389
+ readonly verticalId: string;
390
+ readonly version: string;
391
+ readonly metadataSchema: Record<string, unknown>;
392
+ readonly exportFormats: string[];
393
+ readonly isActive: boolean;
394
+ readonly createdAt: string;
395
+ readonly updatedAt: string;
396
+ readonly description?: string;
397
+ }
398
+ interface CreateSchemaParams {
399
+ readonly verticalId: string;
400
+ readonly metadataSchema: Record<string, unknown>;
401
+ readonly version?: string;
402
+ readonly exportFormats?: string[];
403
+ readonly description?: string;
404
+ }
405
+ interface UpdateSchemaParams {
406
+ readonly version?: string;
407
+ readonly metadataSchema?: Record<string, unknown>;
408
+ readonly exportFormats?: string[];
409
+ readonly description?: string;
410
+ readonly isActive?: boolean;
411
+ }
412
+ interface ListSchemasParams {
413
+ readonly page?: number;
414
+ readonly per_page?: number;
415
+ readonly include_inactive?: boolean;
416
+ }
417
+ interface ListSchemasResponse {
418
+ readonly data: VerticalSchema[];
419
+ readonly pagination: {
420
+ readonly total: number;
421
+ readonly page: number;
422
+ readonly perPage: number;
423
+ readonly totalPages: number;
424
+ };
425
+ }
426
+ interface SchemaValidationResult {
427
+ readonly valid: boolean;
428
+ readonly errors: Array<{
429
+ field: string;
430
+ message: string;
431
+ received?: string;
432
+ }>;
433
+ }
434
+ declare class SchemasResource {
435
+ private readonly request;
436
+ constructor(request: RequestFn);
437
+ /**
438
+ * Register or update a vertical config schema.
439
+ * If a schema already exists for the verticalId, it will be updated.
440
+ */
441
+ create(params: CreateSchemaParams): Promise<VerticalSchema>;
442
+ /**
443
+ * List registered vertical schemas with pagination.
444
+ */
445
+ list(params?: ListSchemasParams): Promise<ListSchemasResponse>;
446
+ /**
447
+ * Get the active schema for a specific vertical.
448
+ */
449
+ get(verticalId: string): Promise<VerticalSchema>;
450
+ /**
451
+ * Update an existing vertical schema.
452
+ */
453
+ update(verticalId: string, params: UpdateSchemaParams): Promise<VerticalSchema>;
454
+ /**
455
+ * Deactivate a vertical schema (soft delete).
456
+ */
457
+ delete(verticalId: string): Promise<void>;
458
+ /**
459
+ * Pre-flight validation: check if assetConfig matches the registered schema.
460
+ *
461
+ * This is a client-side convenience that fetches the schema and validates locally.
462
+ * The server also validates on asset creation.
463
+ */
464
+ validate(verticalId: string, assetConfig: Record<string, unknown>): Promise<SchemaValidationResult>;
465
+ private buildQuery;
466
+ private stripUndefined;
467
+ }
468
+
155
469
  /**
156
470
  * optropic - OptropicClient
157
471
  *
@@ -193,9 +507,20 @@ declare class OptropicClient {
193
507
  private readonly config;
194
508
  private readonly baseUrl;
195
509
  private readonly retryConfig;
510
+ private readonly _sandbox;
196
511
  readonly assets: AssetsResource;
512
+ readonly audit: AuditResource;
513
+ readonly compliance: ComplianceResource;
197
514
  readonly keys: KeysResource;
515
+ readonly keysets: KeysetsResource;
516
+ readonly schemas: SchemasResource;
198
517
  constructor(config: OptropicConfig);
518
+ /** True when the client is in sandbox mode (test API key or explicit override). */
519
+ get isSandbox(): boolean;
520
+ /** True when the client is in live/production mode. */
521
+ get isLive(): boolean;
522
+ /** Returns 'sandbox' or 'live'. */
523
+ get environment(): 'sandbox' | 'live';
199
524
  private isValidApiKey;
200
525
  private request;
201
526
  private executeRequest;
@@ -218,6 +543,51 @@ declare class OptropicClient {
218
543
  */
219
544
  declare function createClient(config: OptropicConfig): OptropicClient;
220
545
 
546
+ /**
547
+ * Webhook Signature Verification
548
+ *
549
+ * Verifies that incoming webhook payloads were signed by Optropic.
550
+ * Uses the endpoint secret provided when the webhook was registered.
551
+ *
552
+ * @module optropic/webhooks
553
+ */
554
+ interface WebhookVerifyOptions {
555
+ /** Raw request body (string). Must not be parsed JSON. */
556
+ readonly payload: string;
557
+ /** Value of the `X-Optropic-Signature` header. Format: `sha256=<hex>` */
558
+ readonly signature: string;
559
+ /** Value of the `X-Optropic-Timestamp` header (unix seconds). */
560
+ readonly timestamp: string;
561
+ /** The endpoint secret from webhook registration. */
562
+ readonly secret: string;
563
+ /** Maximum allowed age of the timestamp in seconds. @default 300 (5 minutes) */
564
+ readonly tolerance?: number;
565
+ }
566
+ interface WebhookVerifyResult {
567
+ readonly valid: boolean;
568
+ readonly reason?: string;
569
+ }
570
+ /**
571
+ * Verify a webhook payload signature.
572
+ *
573
+ * @example
574
+ * ```typescript
575
+ * import { verifyWebhookSignature } from 'optropic';
576
+ *
577
+ * const result = await verifyWebhookSignature({
578
+ * payload: req.body, // raw string body
579
+ * signature: req.headers['x-optropic-signature'],
580
+ * timestamp: req.headers['x-optropic-timestamp'],
581
+ * secret: process.env.WEBHOOK_SECRET!,
582
+ * });
583
+ *
584
+ * if (!result.valid) {
585
+ * return res.status(401).json({ error: result.reason });
586
+ * }
587
+ * ```
588
+ */
589
+ declare function verifyWebhookSignature(options: WebhookVerifyOptions): Promise<WebhookVerifyResult>;
590
+
221
591
  /**
222
592
  * optropic - Error Classes
223
593
  *
@@ -473,6 +843,6 @@ declare class ServiceUnavailableError extends OptropicError {
473
843
  });
474
844
  }
475
845
 
476
- declare const SDK_VERSION = "1.0.0";
846
+ declare const SDK_VERSION = "2.0.0";
477
847
 
478
- export { type ApiKey, type Asset, AssetsResource, AuthenticationError, type BatchCreateParams, type BatchCreateResult, BatchNotFoundError, CodeNotFoundError, type CreateAssetParams, type CreateKeyParams, type CreateKeyResult, type ErrorCode, InvalidCodeError, InvalidGTINError, InvalidSerialError, KeysResource, type ListAssetsParams, NetworkError, OptropicClient, type OptropicConfig, OptropicError, QuotaExceededError, RateLimitedError, type RequestFn, type RetryConfig, RevokedCodeError, SDK_VERSION, ServiceUnavailableError, TimeoutError, type VerificationEvidence, type VerifyResult, createClient };
848
+ export { type ApiKey, type Asset, AssetsResource, type AuditEvent, AuditResource, AuthenticationError, type BatchCreateParams, type BatchCreateResult, BatchNotFoundError, type ChainVerifyResult, CodeNotFoundError, type ComplianceConfig, ComplianceResource, type CreateAssetParams, type CreateAuditEventParams, type CreateKeyParams, type CreateKeyResult, type CreateKeysetParams, type CreateSchemaParams, type ErrorCode, type ExportParams, type ExportResult, InvalidCodeError, InvalidGTINError, InvalidSerialError, KeysResource, type Keyset, KeysetsResource, type ListAssetsParams, type ListAssetsResponse, type ListAuditParams, type ListAuditResponse, type ListKeysetsParams, type ListKeysetsResponse, type ListSchemasParams, type ListSchemasResponse, type MerkleProof, type MerkleRoot, NetworkError, OptropicClient, type OptropicConfig, OptropicError, QuotaExceededError, RateLimitedError, type RequestFn, type RetryConfig, RevokedCodeError, SDK_VERSION, type SchemaValidationResult, SchemasResource, ServiceUnavailableError, TimeoutError, type UpdateSchemaParams, type VerifyResult, type VerticalSchema, type WebhookVerifyOptions, type WebhookVerifyResult, createClient, verifyWebhookSignature };