@ows-sdk/kms-client
v1.0.0
Published
Lightweight API key verification client for Opendex KMS. Protects any SDK with a single line of code.
Maintainers
Readme
@ows-sdk/kms-client
API Key Verification for Opendex SDKs
Zero-dependency client to protect any Opendex SDK with API key verification.
Install
npm install @ows-sdk/kms-clientpnpm add @ows-sdk/kms-clientyarn add @ows-sdk/kms-clientQuick Start
Option 1: Guard (recommended for SDKs)
The simplest way to protect your SDK. Two lines: init() to verify, requireInit() to enforce.
import { createGuard, KMSError } from '@ows-sdk/kms-client';
class MySDK {
private guard = createGuard(apiKey, {
sdkName: 'my-awesome-sdk',
sdkVersion: '1.0.0',
});
async init() {
await this.guard.init(); // Verifies API key against KMS
}
doSomething() {
this.guard.requireInit(); // Throws if not verified
// ... your SDK logic here
}
async doSomethingAsync() {
this.guard.requireInit();
// ... your async SDK logic here
}
}Option 2: Client (for custom flows)
Full control over when and how verification happens.
import { KMSClient, KMSError } from '@ows-sdk/kms-client';
const kms = new KMSClient({
sdkName: 'my-sdk',
sdkVersion: '2.0.0',
});
// Verify with full details
const result = await kms.verify('kms_abc123...');
console.log(result.scopes); // ['verify', 'read']
console.log(result.environment); // 'production'
console.log(result.keyId); // 'key_xxx'
// Simple boolean check (no throw)
const valid = await kms.isValid('kms_abc123...');End User's Code
This is what your SDK users write:
import { MySDK } from 'my-awesome-sdk';
const sdk = new MySDK({ apiKey: 'kms_abc123...' });
try {
await sdk.init();
sdk.doSomething(); // Works — key is verified
} catch (error) {
if (error instanceof KMSError) {
console.error(`[${error.code}] ${error.userMessage}`);
}
}Full SDK Example
Here's a complete example of how to integrate @ows-sdk/kms-client into an SDK:
// my-sdk/src/index.ts
import { createGuard, KMSError, type KMSVerification } from '@ows-sdk/kms-client';
export interface MySDKOptions {
apiKey: string;
region?: string;
}
export class MySDK {
private guard;
constructor(options: MySDKOptions) {
this.guard = createGuard(options.apiKey, {
sdkName: 'my-sdk',
sdkVersion: '1.0.0',
requiredScope: 'verify', // Key must have 'verify' scope
});
}
/**
* Initialize the SDK. Must be called before any other method.
*/
async init(): Promise<void> {
await this.guard.init();
}
/**
* Check if the SDK is ready to use.
*/
get isReady(): boolean {
return this.guard.isVerified;
}
/**
* Get the verified key details.
*/
get keyInfo(): KMSVerification | null {
return this.guard.verification;
}
/**
* Your SDK methods — all protected by requireInit()
*/
async doSomething(): Promise<string> {
const key = this.guard.requireInit();
// key.scopes, key.environment, key.projectId are available
return `Hello from ${key.environment}!`;
}
}
// Re-export for user convenience
export { KMSError } from '@ows-sdk/kms-client';API Reference
KMSClient
const client = new KMSClient(options?: KMSClientOptions);| Option | Type | Default | Description |
|--------|------|---------|-------------|
| endpoint | string | https://kms.opendexapis.com | KMS API URL |
| timeout | number | 5000 | Request timeout (ms) |
| retries | number | 2 | Retry attempts on network errors |
| retryDelay | number | 500 | Base retry delay (ms, doubles each retry) |
| sdkName | string | 'unknown-sdk' | Your SDK name (for analytics) |
| sdkVersion | string | '0.0.0' | Your SDK version |
| cache | boolean | true | Cache verification results in memory |
| cacheTtl | number | 300000 | Cache TTL (ms, default 5 min) |
Methods:
| Method | Returns | Description |
|--------|---------|-------------|
| verify(apiKey, scope?) | Promise<KMSVerification> | Verify key (throws on invalid) |
| isValid(apiKey, scope?) | Promise<boolean> | Check validity (no throw) |
| clearCache() | void | Clear cached verifications |
createGuard()
const guard = createGuard(apiKey: string, options?: KMSGuardOptions);Extends KMSClientOptions with:
| Option | Type | Description |
|--------|------|-------------|
| requiredScope | string | Scope the key must have |
Properties & Methods:
| Member | Type | Description |
|--------|------|-------------|
| verification | KMSVerification \| null | Cached result |
| isVerified | boolean | Whether init() has been called successfully |
| init() | Promise<KMSVerification> | Verify the key (safe to call multiple times) |
| requireInit() | KMSVerification | Assert initialized (throws if not) |
KMSVerification
interface KMSVerification {
valid: true;
keyId: string; // 'key_abc123'
projectId: string; // 'proj_xyz789'
name: string; // 'Production Key'
scopes: string[]; // ['verify', 'read']
environment: string; // 'production'
rateLimit?: {
remaining: number;
reset: number;
limit: number;
};
}Error Classes
import {
KMSError, // Base error (has .code and .userMessage)
KMSValidationError, // Invalid key (non-retryable)
KMSNetworkError, // Network failure (retryable)
KMSTimeoutError, // Timeout (retryable)
} from '@ows-sdk/kms-client';| Error | Codes | Retryable |
|-------|-------|-----------|
| KMSValidationError | INVALID_FORMAT, NOT_FOUND, DISABLED, EXPIRED, SCOPE_DENIED, IP_BLOCKED, ROTATION_REQUIRED | No |
| KMSNetworkError | NETWORK_ERROR | Yes |
| KMSTimeoutError | TIMEOUT | Yes |
| KMSError | RATE_LIMITED, UNKNOWN | Yes |
Error Handling
import { KMSError, KMSValidationError, KMSTimeoutError } from '@ows-sdk/kms-client';
try {
await sdk.init();
} catch (error) {
if (error instanceof KMSValidationError) {
// Key is definitely invalid — show error.userMessage to user
console.error(error.userMessage);
// error.code: 'EXPIRED', 'NOT_FOUND', 'DISABLED', etc.
} else if (error instanceof KMSTimeoutError) {
// Network issue — maybe retry later
console.warn('KMS is unreachable, retrying...');
} else if (error instanceof KMSError) {
// Other KMS error (rate limited, unknown)
console.error(`KMS [${error.code}]: ${error.userMessage}`);
}
}Compatibility
- Node.js 18+ (uses native
fetch) - Bun — fully supported
- Deno — fully supported
- Browsers — works in modern browsers (uses
fetch+AbortController) - Cloudflare Workers — works in Workers/Pages
- Edge runtimes — any runtime with
fetchsupport
License
MIT © Opendex, Inc.
